summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md1
-rw-r--r--docs/config/README.md28
-rw-r--r--src/configs/crystal.rs21
-rw-r--r--src/configs/mod.rs1
-rw-r--r--src/module.rs1
-rw-r--r--src/modules/crystal.rs86
-rw-r--r--src/modules/mod.rs2
-rw-r--r--src/utils.rs4
8 files changed, 144 insertions, 0 deletions
diff --git a/README.md b/README.md
index 8de4201b5..0621d8080 100644
--- a/README.md
+++ b/README.md
@@ -97,6 +97,7 @@ The prompt shows information you need while you're working, while staying sleek
- Current Ruby version (`💎`)
- Current Rust version (`🦀`)
- Current .NET version (`•NET`)
+- Current Crystal version (`🔮 `).
- Current version of package in current directory (`📦`)
- npm (Node.js)
- cargo (Rust)
diff --git a/docs/config/README.md b/docs/config/README.md
index 1c2ca272e..d40e09da2 100644
--- a/docs/config/README.md
+++ b/docs/config/README.md
@@ -116,6 +116,7 @@ prompt_order = [
"memory_usage",
"aws",
"env_var",
+ "crystal",
"cmd_duration",
"line_break",
"jobs",
@@ -858,6 +859,33 @@ separator = "/"
style = "bold dimmed green"
```
+## Crystal
+
+The `crystal` module shows the currently installed version of Crystal.
+The module will be shown if any of the following conditions are met:
+
+- The current directory contains a `shard.yml` file
+- The current directory contains a `.cr` file
+
+### Options
+
+| Variable | Default | Description |
+| ---------- | ------------ | ------------------------------------------------------------ |
+| `symbol` | `"🔮 "` | The symbol used before displaying the version of crystal. |
+| `style` | `"bold red"` | The style for the module. |
+| `disabled` | `false` | Disables the `crystal` module. |
+
+### Example
+
+```toml
+# ~/.config/starship.toml
+
+[crystal]
+symbol = "🔮 "
+style = "bold red"
+disabled = false
+```
+
## NodeJS
The `nodejs` module shows the currently installed version of NodeJS.
diff --git a/src/configs/crystal.rs b/src/configs/crystal.rs
new file mode 100644
index 000000000..58455e8e5
--- /dev/null
+++ b/src/configs/crystal.rs
@@ -0,0 +1,21 @@
+use crate::config::{ModuleConfig, RootModuleConfig, SegmentConfig};
+
+use ansi_term::{Color, Style};
+use starship_module_config_derive::ModuleConfig;
+
+#[derive(Clone, ModuleConfig)]
+pub struct CrystalConfig<'a> {
+ pub symbol: SegmentConfig<'a>,
+ pub style: Style,
+ pub disabled: bool,
+}
+
+impl<'a> RootModuleConfig<'a> for CrystalConfig<'a> {
+ fn new() -> Self {
+ CrystalConfig {
+ symbol: SegmentConfig::new("🔮 "),
+ style: Color::Red.bold(),
+ disabled: false,
+ }
+ }
+}
diff --git a/src/configs/mod.rs b/src/configs/mod.rs
index 02ee00ef7..b3950b50a 100644
--- a/src/configs/mod.rs
+++ b/src/configs/mod.rs
@@ -3,6 +3,7 @@ pub mod battery;
pub mod character;
pub mod cmd_duration;
pub mod conda;
+pub mod crystal;
pub mod directory;
pub mod dotnet;
pub mod env_var;
diff --git a/src/module.rs b/src/module.rs
index 1768d6b2f..c3d283d88 100644
--- a/src/module.rs
+++ b/src/module.rs
@@ -36,6 +36,7 @@ pub const ALL_MODULES: &[&str] = &[
"package",
"python",
"ruby",
+ "crystal",
"rust",
"php",
"terraform",
diff --git a/src/modules/crystal.rs b/src/modules/crystal.rs
new file mode 100644
index 000000000..a215369cb
--- /dev/null
+++ b/src/modules/crystal.rs
@@ -0,0 +1,86 @@
+use super::{Context, Module, RootModuleConfig, SegmentConfig};
+
+use crate::configs::crystal::CrystalConfig;
+use crate::utils;
+
+/// Creates a module with the current Crystal version
+///
+/// Will display the Crystal version if any of the following criteria are met:
+/// - Current directory contains a `.cr` file
+/// - Current directory contains a `shard.yml` file
+pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
+ let is_crystal_project = context
+ .try_begin_scan()?
+ .set_files(&["shard.yml"])
+ .set_extensions(&["cr"])
+ .is_match();
+
+ if !is_crystal_project {
+ return None;
+ }
+
+ let crystal_version = utils::exec_cmd("crystal", &["--version"])?.stdout;
+ let formatted_version = format_crystal_version(&crystal_version)?;
+
+ let mut module = context.new_module("crystal");
+ let config: CrystalConfig = CrystalConfig::try_load(module.config);
+ module.set_style(config.style);
+
+ module.create_segment("symbol", &config.symbol);
+ module.create_segment("version", &SegmentConfig::new(&formatted_version));
+
+ Some(module)
+}
+
+fn format_crystal_version(crystal_version: &str) -> Option<String> {
+ let version = crystal_version
+ // split into ["Crystal", "0.32.1", ...]
+ .split_whitespace()
+ // return "0.32.1"
+ .nth(1)?;
+
+ let mut formatted_version = String::with_capacity(version.len() + 1);
+ formatted_version.push('v');
+ formatted_version.push_str(version);
+ Some(formatted_version)
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::modules::utils::test::render_module;
+ use ansi_term::Color;
+ use std::fs::File;
+ use std::io;
+ use tempfile;
+
+ #[test]
+ fn folder_without_crystal_files() -> io::Result<()> {
+ let dir = tempfile::tempdir()?;
+ let actual = render_module("crystal", dir.path());
+ let expected = None;
+ assert_eq!(expected, actual);
+ Ok(())
+ }
+
+ #[test]
+ fn folder_with_shard_file() -> io::Result<()> {
+ let dir = tempfile::tempdir()?;
+ File::create(dir.path().join("shard.yml"))?.sync_all()?;
+
+ let actual = render_module("crystal", dir.path());
+ let expected = Some(format!("via {} ", Color::Red.bold().paint("🔮 v0.32.1")));
+ assert_eq!(expected, actual);
+ Ok(())
+ }
+
+ #[test]
+ fn folder_with_cr_file() -> io::Result<()> {
+ let dir = tempfile::tempdir()?;
+ File::create(dir.path().join("main.cr"))?.sync_all()?;
+
+ let actual = render_module("crystal", dir.path());
+ let expected = Some(format!("via {} ", Color::Red.bold().paint("🔮 v0.32.1")));
+ assert_eq!(expected, actual);
+ Ok(())
+ }
+}
diff --git a/src/modules/mod.rs b/src/modules/mod.rs
index 74b11b946..2852d169b 100644
--- a/src/modules/mod.rs
+++ b/src/modules/mod.rs
@@ -3,6 +3,7 @@ mod aws;
mod character;
mod cmd_duration;
mod conda;
+mod crystal;
mod directory;
mod dotnet;
mod env_var;
@@ -73,6 +74,7 @@ pub fn handle<'a>(module: &str, context: &'a Context) -> Option<Module<'a>> {
"rust" => rust::module(context),
"terraform" => terraform::module(context),
"time" => time::module(context),
+ "crystal" => crystal::module(context),
"username" => username::module(context),
_ => {
eprintln!("Error: Unknown module {}. Use starship module --list to list out all supported modules.", module);
diff --git a/src/utils.rs b/src/utils.rs
index 0aae93da9..01039093d 100644
--- a/src/utils.rs
+++ b/src/utils.rs
@@ -41,6 +41,10 @@ pub fn exec_cmd(cmd: &str, args: &[&str]) -> Option<CommandOutput> {
stdout: String::from("v12.0.0"),
stderr: String::default(),
}),
+ "crystal --version" => Some(CommandOutput {
+ stdout: String::from("Crystal 0.32.1 (2019-12-18)"),
+ stderr: String::default(),
+ }),
"dummy_command" => Some(CommandOutput {
stdout: String::from("stdout ok!"),
stderr: String::from("stderr ok!"),