From 335c514e9ee5fa5bc8a8294b4804ddf198504b97 Mon Sep 17 00:00:00 2001 From: "[Error_27]" Date: Fri, 5 Apr 2024 17:56:49 -0400 Subject: [PATCH] feat(odin): Add Odin Lang module (#5873) * Add Odin lang module * add utils string and remove commit number from output * switch to new symbol because ZWJ support is rare * add config docs * add option to show the commit number * fix lack of trimming * fix formatting to comply with checks * Add trailing newline to comply with cargo fmt * Add new Odin test and add newline in cmd output --- .github/config-schema.json | 68 +++++++++++++++++++++ docs/config/README.md | 37 ++++++++++++ src/configs/mod.rs | 3 + src/configs/odin.rs | 34 +++++++++++ src/configs/starship_root.rs | 1 + src/module.rs | 1 + src/modules/mod.rs | 3 + src/modules/odin.rs | 112 +++++++++++++++++++++++++++++++++++ src/utils.rs | 4 ++ 9 files changed, 263 insertions(+) create mode 100644 src/configs/odin.rs create mode 100644 src/modules/odin.rs diff --git a/.github/config-schema.json b/.github/config-schema.json index b36ad633..bb5fdd85 100644 --- a/.github/config-schema.json +++ b/.github/config-schema.json @@ -1148,6 +1148,25 @@ } ] }, + "odin": { + "default": { + "detect_extensions": [ + "odin" + ], + "detect_files": [], + "detect_folders": [], + "disabled": false, + "format": "via [$symbol($version )]($style)", + "show_commit": false, + "style": "bold bright-blue", + "symbol": "Ø " + }, + "allOf": [ + { + "$ref": "#/definitions/OdinConfig" + } + ] + }, "opa": { "default": { "detect_extensions": [ @@ -4664,6 +4683,55 @@ }, "additionalProperties": false }, + "OdinConfig": { + "type": "object", + "properties": { + "format": { + "default": "via [$symbol($version )]($style)", + "type": "string" + }, + "show_commit": { + "default": false, + "type": "boolean" + }, + "symbol": { + "default": "Ø ", + "type": "string" + }, + "style": { + "default": "bold bright-blue", + "type": "string" + }, + "disabled": { + "default": false, + "type": "boolean" + }, + "detect_extensions": { + "default": [ + "odin" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "detect_files": { + "default": [], + "type": "array", + "items": { + "type": "string" + } + }, + "detect_folders": { + "default": [], + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false + }, "OpaConfig": { "type": "object", "properties": { diff --git a/docs/config/README.md b/docs/config/README.md index f889ca8f..794190b7 100644 --- a/docs/config/README.md +++ b/docs/config/README.md @@ -3114,6 +3114,43 @@ By default the module will be shown if any of the following conditions are met: format = 'via [🐪 $version]($style) ' ``` +## Odin + +The 'odin' module shows the currently installed version of [Odin](https://odin-lang.org/). By default the module will be shown if the current directory contains a `.odin` file. + +### Options + +| Option | Default | Description | +| ------------------- | ------------------------------------ | ----------------------------------------------------- | +| `format` | `'via [$symbol($version )]($style)'` | The format for the module. | +| `show_commit` | `false` | Shows the commit as part of the version. | +| `symbol` | `'Ø '` | The symbol used before displaying the version of Zig. | +| `style` | `'bold bright-blue'` | The style for the module. | +| `disabled` | `false` | Disables the `odin` module. | +| `detect_extensions` | `['odin']` | Which extensions should trigger this module. | +| `detect_files` | `[]` | Which filenames should trigger this module. | +| `detect_folders` | `[]` | Which folders should trigger this module. | + +### Variables + +| Variable | Example | Description | +| -------- | ------------- | ------------------------------------ | +| version | `dev-2024-03` | The version of `odin` | +| 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 + +[odin] +format = 'via [󰹩 ($version )]($style)' +show_commit = true +``` + ## Open Policy Agent The `opa` module shows the currently installed version of the OPA tool. diff --git a/src/configs/mod.rs b/src/configs/mod.rs index a4d7502a..7e7aa263 100644 --- a/src/configs/mod.rs +++ b/src/configs/mod.rs @@ -59,6 +59,7 @@ pub mod nim; pub mod nix_shell; pub mod nodejs; pub mod ocaml; +pub mod odin; pub mod opa; pub mod openstack; pub mod os; @@ -225,6 +226,8 @@ pub struct FullConfig<'a> { #[serde(borrow)] ocaml: ocaml::OCamlConfig<'a>, #[serde(borrow)] + odin: odin::OdinConfig<'a>, + #[serde(borrow)] opa: opa::OpaConfig<'a>, #[serde(borrow)] openstack: openstack::OspConfig<'a>, diff --git a/src/configs/odin.rs b/src/configs/odin.rs new file mode 100644 index 00000000..4fb1d581 --- /dev/null +++ b/src/configs/odin.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 OdinConfig<'a> { + pub format: &'a str, + pub show_commit: bool, + 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 OdinConfig<'a> { + fn default() -> Self { + OdinConfig { + format: "via [$symbol($version )]($style)", + show_commit: false, + symbol: "Ø ", + style: "bold bright-blue", + disabled: false, + detect_extensions: vec!["odin"], + detect_files: vec![], + detect_folders: vec![], + } + } +} diff --git a/src/configs/starship_root.rs b/src/configs/starship_root.rs index d809737f..f1cc181c 100644 --- a/src/configs/starship_root.rs +++ b/src/configs/starship_root.rs @@ -77,6 +77,7 @@ pub const PROMPT_ORDER: &[&str] = &[ "nim", "nodejs", "ocaml", + "odin", "opa", "perl", "php", diff --git a/src/module.rs b/src/module.rs index 4d310878..abcb25f7 100644 --- a/src/module.rs +++ b/src/module.rs @@ -66,6 +66,7 @@ pub const ALL_MODULES: &[&str] = &[ "nix_shell", "nodejs", "ocaml", + "odin", "opa", "openstack", "os", diff --git a/src/modules/mod.rs b/src/modules/mod.rs index 8bbc5f5b..e842b494 100644 --- a/src/modules/mod.rs +++ b/src/modules/mod.rs @@ -56,6 +56,7 @@ mod nim; mod nix_shell; mod nodejs; mod ocaml; +mod odin; mod opa; mod openstack; mod os; @@ -165,6 +166,7 @@ pub fn handle<'a>(module: &str, context: &'a Context) -> Option> { "nix_shell" => nix_shell::module(context), "nodejs" => nodejs::module(context), "ocaml" => ocaml::module(context), + "odin" => odin::module(context), "opa" => opa::module(context), "openstack" => openstack::module(context), "os" => os::module(context), @@ -287,6 +289,7 @@ pub fn description(module: &str) -> &'static str { "nix_shell" => "The nix-shell environment", "nodejs" => "The currently installed version of NodeJS", "ocaml" => "The currently installed version of OCaml", + "odin" => "The currently installed version of Odin", "opa" => "The currently installed version of Open Platform Agent", "openstack" => "The current OpenStack cloud and project", "os" => "The current operating system", diff --git a/src/modules/odin.rs b/src/modules/odin.rs new file mode 100644 index 00000000..8a80bf9f --- /dev/null +++ b/src/modules/odin.rs @@ -0,0 +1,112 @@ +use super::{Context, Module, ModuleConfig}; + +use crate::configs::odin::OdinConfig; +use crate::formatter::StringFormatter; + +/// Creates a module with the current Odin version +pub fn module<'a>(context: &'a Context) -> Option> { + let mut module = context.new_module("odin"); + let config = OdinConfig::try_load(module.config); + + let is_odin_project = context + .try_begin_scan()? + .set_files(&config.detect_files) + .set_extensions(&config.detect_extensions) + .set_folders(&config.detect_folders) + .is_match(); + + if !is_odin_project { + return None; + } + + let parsed = StringFormatter::new(config.format).and_then(|formatter| { + formatter + .map_meta(|variable, _| match variable { + "symbol" => Some(config.symbol), + _ => None, + }) + .map_style(|variable| match variable { + "style" => Some(Ok(config.style)), + _ => None, + }) + .map(|variable| match variable { + "version" => { + let odin_version = context.exec_cmd("odin", &["version"])?.stdout; + let trimmed_version = odin_version.split(' ').last()?.trim().to_string(); + + if config.show_commit { + return Some(Ok(trimmed_version)); + } + + let no_commit = trimmed_version.split(':').next()?.trim().to_string(); + Some(Ok(no_commit)) + } + _ => None, + }) + .parse(None, Some(context)) + }); + + module.set_segments(match parsed { + Ok(segments) => segments, + Err(error) => { + log::warn!("Error in module `odin`:\n{}", error); + return None; + } + }); + + Some(module) +} + +#[cfg(test)] +mod tests { + use crate::test::ModuleRenderer; + use crate::utils::CommandOutput; + use nu_ansi_term::Color; + use std::fs::File; + use std::io; + + #[test] + fn folder_without_odin() -> io::Result<()> { + let dir = tempfile::tempdir()?; + File::create(dir.path().join("odin.txt"))?.sync_all()?; + let actual = ModuleRenderer::new("odin").path(dir.path()).collect(); + let expected = None; + assert_eq!(expected, actual); + dir.close() + } + + #[test] + fn folder_with_odin_file() -> io::Result<()> { + let dir = tempfile::tempdir()?; + File::create(dir.path().join("main.odin"))?.sync_all()?; + let actual = ModuleRenderer::new("odin").path(dir.path()).collect(); + let expected = Some(format!( + "via {}", + Color::LightBlue.bold().paint("Ø dev-2024-03 ") + )); + assert_eq!(expected, actual); + dir.close() + } + + #[test] + fn folder_with_odin_file_without_commit() -> io::Result<()> { + let dir = tempfile::tempdir()?; + File::create(dir.path().join("main.odin"))?.sync_all()?; + let actual = ModuleRenderer::new("odin") + .cmd( + "odin version", + Some(CommandOutput { + stdout: String::from("odin version dev-2024-03\n"), + stderr: String::default(), + }), + ) + .path(dir.path()) + .collect(); + let expected = Some(format!( + "via {}", + Color::LightBlue.bold().paint("Ø dev-2024-03 ") + )); + assert_eq!(expected, actual); + dir.close() + } +} diff --git a/src/utils.rs b/src/utils.rs index 9780a2ad..eafeca54 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -330,6 +330,10 @@ active boot switches: -d:release\n", stdout: String::from("4.10.0\n"), stderr: String::default(), }), + "odin version" => Some(CommandOutput { + stdout: String::from("odin version dev-2024-03:fc587c507\n"), + stderr: String::default(), + }), "opa version" => Some(CommandOutput { stdout: String::from("Version: 0.44.0 Build Commit: e8d488f