diff --git a/.github/config-schema.json b/.github/config-schema.json index c3a6f70c..b36ad633 100644 --- a/.github/config-schema.json +++ b/.github/config-schema.json @@ -667,6 +667,27 @@ } ] }, + "gleam": { + "default": { + "detect_extensions": [ + "gleam" + ], + "detect_files": [ + "gleam.toml" + ], + "detect_folders": [], + "disabled": false, + "format": "via [$symbol($version )]($style)", + "style": "bold #FFAFF3", + "symbol": "⭐ ", + "version_format": "v${raw}" + }, + "allOf": [ + { + "$ref": "#/definitions/GleamConfig" + } + ] + }, "golang": { "default": { "detect_extensions": [ @@ -3534,6 +3555,57 @@ }, "additionalProperties": false }, + "GleamConfig": { + "type": "object", + "properties": { + "format": { + "default": "via [$symbol($version )]($style)", + "type": "string" + }, + "version_format": { + "default": "v${raw}", + "type": "string" + }, + "symbol": { + "default": "⭐ ", + "type": "string" + }, + "style": { + "default": "bold #FFAFF3", + "type": "string" + }, + "disabled": { + "default": false, + "type": "boolean" + }, + "detect_extensions": { + "default": [ + "gleam" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "detect_files": { + "default": [ + "gleam.toml" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "detect_folders": { + "default": [], + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false + }, "GoConfig": { "type": "object", "properties": { diff --git a/docs/config/README.md b/docs/config/README.md index 0c08d076..f889ca8f 100644 --- a/docs/config/README.md +++ b/docs/config/README.md @@ -295,6 +295,7 @@ $elixir\ $elm\ $erlang\ $fennel\ +$gleam\ $golang\ $guix_shell\ $haskell\ @@ -2058,6 +2059,45 @@ Use Windows Starship executable on Windows paths in WSL windows_starship = '/mnt/c/Users/username/scoop/apps/starship/current/starship.exe' ``` +## Gleam + +The `gleam` module shows the currently installed version of [Gleam](https://gleam.run/). +By default the module will be shown if any of the following conditions are met: + +- The current directory contains a `gleam.toml` file +- The current directory contains a file with the `.gleam` extension + +### Options + +| Option | Default | Description | +| ------------------- | ------------------------------------ | ------------------------------------------------------------------------- | +| `format` | `'via [$symbol($version )]($style)'` | The format for the module. | +| `version_format` | `'v${raw}'` | The version format. Available vars are `raw`, `major`, `minor`, & `patch` | +| `symbol` | `'⭐ '` | A format string representing the symbol of Go. | +| `detect_extensions` | `['gleam']` | Which extensions should trigger this module. | +| `detect_files` | `['gleam.toml']` | Which filenames should trigger this module. | +| `style` | `'bold #FFAFF3'` | The style for the module. | +| `disabled` | `false` | Disables the `gleam` module. | + +### Variables + +| Variable | Example | Description | +| -------- | -------- | ------------------------------------ | +| version | `v1.0.0` | The version of `gleam` | +| symbol | | Mirrors the value of option `symbol` | +| style\* | | Mirrors the value of option `style` | + +*: This variable can only be used as a part of a style string + +### Example + +```toml +# ~/.config/starship.toml + +[gleam] +format = 'via [⭐ $version](bold red) ' +``` + ## Go The `golang` module shows the currently installed version of [Go](https://golang.org/). diff --git a/docs/public/presets/toml/no-empty-icons.toml b/docs/public/presets/toml/no-empty-icons.toml index 174c9dcb..ad97b703 100644 --- a/docs/public/presets/toml/no-empty-icons.toml +++ b/docs/public/presets/toml/no-empty-icons.toml @@ -40,6 +40,9 @@ format = '(via [$symbol($version )]($style))' [fennel] format = '(via [$symbol($version )]($style))' +[gleam] +format = '(via [$symbol($version )]($style))' + [golang] format = '(via [$symbol($version )]($style))' diff --git a/docs/public/presets/toml/no-runtime-versions.toml b/docs/public/presets/toml/no-runtime-versions.toml index df3a1ff4..529fe8da 100644 --- a/docs/public/presets/toml/no-runtime-versions.toml +++ b/docs/public/presets/toml/no-runtime-versions.toml @@ -37,6 +37,9 @@ format = 'via [$symbol]($style)' [fennel] format = 'via [$symbol]($style)' +[gleam] +format = 'via [$symbol]($style)' + [golang] format = 'via [$symbol]($style)' diff --git a/docs/public/presets/toml/plain-text-symbols.toml b/docs/public/presets/toml/plain-text-symbols.toml index 244dc3a7..0c200eec 100644 --- a/docs/public/presets/toml/plain-text-symbols.toml +++ b/docs/public/presets/toml/plain-text-symbols.toml @@ -73,6 +73,9 @@ symbol = "gcp " [git_branch] symbol = "git " +[gleam] +symbol = "gleam " + [golang] symbol = "go " diff --git a/src/configs/gleam.rs b/src/configs/gleam.rs new file mode 100644 index 00000000..8d70e985 --- /dev/null +++ b/src/configs/gleam.rs @@ -0,0 +1,34 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Deserialize, Serialize)] +#[cfg_attr( + feature = "config-schema", + derive(schemars::JsonSchema), + schemars(deny_unknown_fields) +)] +#[serde(default)] +pub struct GleamConfig<'a> { + pub format: &'a str, + pub version_format: &'a str, + pub symbol: &'a str, + pub style: &'a str, + pub disabled: bool, + pub detect_extensions: Vec<&'a str>, + pub detect_files: Vec<&'a str>, + pub detect_folders: Vec<&'a str>, +} + +impl<'a> Default for GleamConfig<'a> { + fn default() -> Self { + GleamConfig { + format: "via [$symbol($version )]($style)", + version_format: "v${raw}", + symbol: "⭐ ", + style: "bold #FFAFF3", + disabled: false, + detect_extensions: vec!["gleam"], + detect_files: vec!["gleam.toml"], + detect_folders: vec![], + } + } +} diff --git a/src/configs/mod.rs b/src/configs/mod.rs index 591b350d..a4d7502a 100644 --- a/src/configs/mod.rs +++ b/src/configs/mod.rs @@ -36,6 +36,7 @@ pub mod git_commit; pub mod git_metrics; pub mod git_state; pub mod git_status; +pub mod gleam; pub mod go; pub mod gradle; pub mod guix_shell; @@ -179,6 +180,8 @@ pub struct FullConfig<'a> { #[serde(borrow)] git_status: git_status::GitStatusConfig<'a>, #[serde(borrow)] + gleam: gleam::GleamConfig<'a>, + #[serde(borrow)] golang: go::GoConfig<'a>, #[serde(borrow)] gradle: gradle::GradleConfig<'a>, diff --git a/src/configs/starship_root.rs b/src/configs/starship_root.rs index 7612a550..d809737f 100644 --- a/src/configs/starship_root.rs +++ b/src/configs/starship_root.rs @@ -64,6 +64,7 @@ pub const PROMPT_ORDER: &[&str] = &[ "elm", "erlang", "fennel", + "gleam", "golang", "gradle", "haskell", diff --git a/src/module.rs b/src/module.rs index 3a8533f3..4d310878 100644 --- a/src/module.rs +++ b/src/module.rs @@ -43,6 +43,7 @@ pub const ALL_MODULES: &[&str] = &[ "git_metrics", "git_state", "git_status", + "gleam", "golang", "gradle", "guix_shell", diff --git a/src/modules/gleam.rs b/src/modules/gleam.rs new file mode 100644 index 00000000..fa9a1e9b --- /dev/null +++ b/src/modules/gleam.rs @@ -0,0 +1,122 @@ +use super::{Context, Module, ModuleConfig}; + +use crate::configs::gleam::GleamConfig; +use crate::formatter::StringFormatter; +use crate::formatter::VersionFormatter; + +/// Creates a module with the current Gleam version +pub fn module<'a>(context: &'a Context) -> Option> { + let mut module = context.new_module("gleam"); + let config = GleamConfig::try_load(module.config); + + let is_gleam_project = context + .try_begin_scan()? + .set_files(&config.detect_files) + .set_extensions(&config.detect_extensions) + .set_folders(&config.detect_folders) + .is_match(); + + if !is_gleam_project { + return None; + } + + let parsed = StringFormatter::new(config.format).and_then(|formatter| { + formatter + .map_meta(|var, _| match var { + "symbol" => Some(config.symbol), + _ => None, + }) + .map_style(|variable| match variable { + "style" => Some(Ok(config.style)), + _ => None, + }) + .map(|variable| match variable { + "version" => { + let gleam_version = + parse_gleam_version(&context.exec_cmd("gleam", &["--version"])?.stdout)?; + VersionFormatter::format_module_version( + module.get_name(), + &gleam_version, + config.version_format, + ) + .map(Ok) + } + _ => None, + }) + .parse(None, Some(context)) + }); + + module.set_segments(match parsed { + Ok(segments) => segments, + Err(error) => { + log::warn!("Error in module `gleam`:\n{}", error); + return None; + } + }); + + Some(module) +} + +fn parse_gleam_version(version: &str) -> Option { + let version = version.split_whitespace().last()?; + Some(version.to_string()) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::test::ModuleRenderer; + use nu_ansi_term::Color; + use std::fs::File; + use std::io; + + #[test] + fn test_folder_without_gleam_file() -> io::Result<()> { + let dir = tempfile::tempdir()?; + + let actual = ModuleRenderer::new("gleam").path(dir.path()).collect(); + + let expected = None; + + assert_eq!(actual, expected); + dir.close() + } + + #[test] + fn test_folder_with_gleam_file() -> io::Result<()> { + let dir = tempfile::tempdir()?; + File::create(dir.path().join("hello.gleam"))?.sync_all()?; + + let actual = ModuleRenderer::new("gleam").path(dir.path()).collect(); + + let expected = Some(format!( + "via {}", + Color::Rgb(255, 175, 243).bold().paint("⭐ v1.0.0 ") + )); + + assert_eq!(actual, expected); + dir.close() + } + + #[test] + fn test_folder_with_gleam_toml() -> io::Result<()> { + let dir = tempfile::tempdir()?; + File::create(dir.path().join("gleam.toml"))?.sync_all()?; + + let actual = ModuleRenderer::new("gleam").path(dir.path()).collect(); + + let expected = Some(format!( + "via {}", + Color::Rgb(255, 175, 243).bold().paint("⭐ v1.0.0 ") + )); + + assert_eq!(actual, expected); + dir.close() + } + + #[test] + fn test_parse_gleam_version() { + let version = "gleam 1.0.0"; + assert_eq!(parse_gleam_version(version), Some("1.0.0".to_string())); + } +} diff --git a/src/modules/mod.rs b/src/modules/mod.rs index a219cd0d..8bbc5f5b 100644 --- a/src/modules/mod.rs +++ b/src/modules/mod.rs @@ -33,6 +33,7 @@ mod git_commit; mod git_metrics; mod git_state; mod git_status; +mod gleam; mod golang; mod gradle; mod guix_shell; @@ -141,6 +142,7 @@ pub fn handle<'a>(module: &str, context: &'a Context) -> Option> { "git_metrics" => git_metrics::module(context), "git_state" => git_state::module(context), "git_status" => git_status::module(context), + "gleam" => gleam::module(context), "golang" => golang::module(context), "gradle" => gradle::module(context), "guix_shell" => guix_shell::module(context), @@ -260,6 +262,7 @@ pub fn description(module: &str) -> &'static str { "git_metrics" => "The currently added/deleted lines in your repo", "git_state" => "The current git operation, and it's progress", "git_status" => "Symbol representing the state of the repo", + "gleam" => "The currently installed version of Gleam", "golang" => "The currently installed version of Golang", "gradle" => "The currently installed version of Gradle", "guix_shell" => "The guix-shell environment", diff --git a/src/utils.rs b/src/utils.rs index aa1819b5..9780a2ad 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -267,6 +267,10 @@ Elixir 1.10 (compiled with Erlang/OTP 22)\n", stdout: String::default(), stderr: String::default(), }), + "gleam --version" => Some(CommandOutput { + stdout: String::from("gleam 1.0.0\n"), + stderr: String::default(), + }), "go version" => Some(CommandOutput { stdout: String::from("go version go1.12.1 linux/amd64\n"), stderr: String::default(),