From fcd003785bbc0e3ce9ab1bc594ecaf20adf7c3f7 Mon Sep 17 00:00:00 2001 From: Rekihyt <43384627+Rekihyt@users.noreply.github.com> Date: Tue, 9 Jun 2020 10:14:47 -0700 Subject: [PATCH] feat(nim): Add Nim module (#1189) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Nim module and tests * Add nim to docs * parse_nim_version refactor, add nim desc * Add nim symbol to Nerd Font preset * Yellow with v prefix as default version * Nim version fmt fix * Update docs/config/README.md Co-authored-by: Dario Vladović * Update src/modules/nim.rs Co-authored-by: Dario Vladović * Nim module and tests * Add nim to docs * Yellow with v prefix as default version * Update docs/config/README.md Co-authored-by: Dario Vladović * Update src/modules/nim.rs Co-authored-by: Dario Vladović * Add nim to docs, proper version formatting. * Remove v from symbol, add to fmt string * cargo fmt Co-authored-by: Dario Vladovic --- docs/config/README.md | 28 ++++++++ docs/presets/README.md | 3 + src/configs/mod.rs | 1 + src/configs/nim.rs | 23 +++++++ src/configs/starship_root.rs | 1 + src/module.rs | 1 + src/modules/mod.rs | 3 + src/modules/nim.rs | 125 +++++++++++++++++++++++++++++++++++ src/utils.rs | 29 +++++--- 9 files changed, 205 insertions(+), 9 deletions(-) create mode 100644 src/configs/nim.rs create mode 100644 src/modules/nim.rs diff --git a/docs/config/README.md b/docs/config/README.md index d47df257d..d0380e724 100644 --- a/docs/config/README.md +++ b/docs/config/README.md @@ -115,6 +115,7 @@ prompt_order = [ "haskell", "java", "julia", + "nim", "nodejs", "ocaml", "php", @@ -1016,6 +1017,33 @@ truncation_length = 4 truncation_symbol = "" ``` +## Nim + +The `nim` module shows the currently installed version of Nim. +The module will be shown if any of the following conditions are met: +- The current directory contains a `nim.cfg` file +- The current directory contains a file with the `.nim` extension +- The current directory contains a file with the `.nims` extension +- The current directory contains a file with the `.nimble` extension + +### Options + +| Variable | Default | Description | +| ---------- | --------------- | ------------------------------------------------------ | +| `symbol` | `"👑 "` | The symbol used before displaying the version of Nim. | +| `style` | `"bold yellow"` | The style for the module. | +| `disabled` | `false` | Disables the `nim` module. | + +### Example + +```toml +# ~/.config/starship.toml + +[nim] +style = "yellow" +symbol = "🎣 " +``` + ## Nix-shell The `nix_shell` module shows the nix-shell environment. diff --git a/docs/presets/README.md b/docs/presets/README.md index 7441a3f26..a3241b09c 100644 --- a/docs/presets/README.md +++ b/docs/presets/README.md @@ -58,6 +58,9 @@ symbol = " " [memory_usage] symbol = " " +[nim] +symbol = " " + [nix_shell] symbol = " " diff --git a/src/configs/mod.rs b/src/configs/mod.rs index 1f695a66d..48badefbc 100644 --- a/src/configs/mod.rs +++ b/src/configs/mod.rs @@ -25,6 +25,7 @@ pub mod jobs; pub mod julia; pub mod kubernetes; pub mod memory_usage; +pub mod nim; pub mod nix_shell; pub mod nodejs; pub mod ocaml; diff --git a/src/configs/nim.rs b/src/configs/nim.rs new file mode 100644 index 000000000..c975656a4 --- /dev/null +++ b/src/configs/nim.rs @@ -0,0 +1,23 @@ +use crate::config::{ModuleConfig, RootModuleConfig, SegmentConfig}; + +use ansi_term::{Color, Style}; +use starship_module_config_derive::ModuleConfig; + +#[derive(Clone, ModuleConfig)] +pub struct NimConfig<'a> { + pub symbol: SegmentConfig<'a>, + pub version: SegmentConfig<'a>, + pub style: Style, + pub disabled: bool, +} + +impl<'a> RootModuleConfig<'a> for NimConfig<'a> { + fn new() -> Self { + NimConfig { + symbol: SegmentConfig::new("👑 "), + version: SegmentConfig::default(), + style: Color::Yellow.bold(), + disabled: false, + } + } +} diff --git a/src/configs/starship_root.rs b/src/configs/starship_root.rs index 18eaeee73..f42481257 100644 --- a/src/configs/starship_root.rs +++ b/src/configs/starship_root.rs @@ -39,6 +39,7 @@ impl<'a> RootModuleConfig<'a> for StarshipRootConfig<'a> { "haskell", "java", "julia", + "nim", "nodejs", "ocaml", "php", diff --git a/src/module.rs b/src/module.rs index a3784212c..aa1ad1553 100644 --- a/src/module.rs +++ b/src/module.rs @@ -37,6 +37,7 @@ pub const ALL_MODULES: &[&str] = &[ "kubernetes", "line_break", "memory_usage", + "nim", "nix_shell", "nodejs", "ocaml", diff --git a/src/modules/mod.rs b/src/modules/mod.rs index 26b69e4f6..1a73a1a22 100644 --- a/src/modules/mod.rs +++ b/src/modules/mod.rs @@ -26,6 +26,7 @@ mod julia; mod kubernetes; mod line_break; mod memory_usage; +mod nim; mod nix_shell; mod nodejs; mod ocaml; @@ -80,6 +81,7 @@ pub fn handle<'a>(module: &str, context: &'a Context) -> Option> { "kubernetes" => kubernetes::module(context), "line_break" => line_break::module(context), "memory_usage" => memory_usage::module(context), + "nim" => nim::module(context), "nix_shell" => nix_shell::module(context), "nodejs" => nodejs::module(context), "ocaml" => ocaml::module(context), @@ -131,6 +133,7 @@ pub fn description(module: &str) -> &'static str { "kubernetes" => "The current Kubernetes context name and, if set, the namespace", "line_break" => "Separates the prompt into two lines", "memory_usage" => "Current system memory and swap usage", + "nim" => "The currently installed version of Nim", "nix_shell" => "The nix-shell environment", "nodejs" => "The currently installed version of NodeJS", "ocaml" => "The currently installed version of OCaml", diff --git a/src/modules/nim.rs b/src/modules/nim.rs new file mode 100644 index 000000000..5b064bc58 --- /dev/null +++ b/src/modules/nim.rs @@ -0,0 +1,125 @@ +use super::{Context, Module, RootModuleConfig, SegmentConfig}; + +use crate::configs::nim::NimConfig; +use crate::utils; + +/// Creates a module with the current Nim version +/// +/// Will display the Nim version if any of the following criteria are met: +/// - The current directory contains a file with extension `.nim`, `.nims`, or `.nimble` +/// - The current directory contains a `nim.cfg` file +pub fn module<'a>(context: &'a Context) -> Option> { + let is_nim_project = context + .try_begin_scan()? + .set_files(&["nim.cfg"]) + .set_extensions(&["nim", "nims", "nimble"]) + .is_match(); + + if !is_nim_project { + return None; + } + + let nim_version_output = utils::exec_cmd("nim", &["--version"])?.stdout; + let formatted_nim_version = format!("v{}", parse_nim_version(&nim_version_output)?); + + let mut module = context.new_module("nim"); + let config = NimConfig::try_load(module.config); + + module.set_style(config.style); + + module.create_segment("symbol", &config.symbol); + module.create_segment("version", &SegmentConfig::new(&formatted_nim_version)); + + Some(module) +} + +fn parse_nim_version(version_cmd_output: &str) -> Option<&str> { + version_cmd_output + .lines() + // First line has the version + .next()? + .split(' ') + .find(|&s| s.chars().all(|c| c >= '0' && c <= '9' || c == '.')) +} + +#[cfg(test)] +mod tests { + use super::parse_nim_version; + use crate::modules::utils::test::render_module; + use ansi_term::Color; + use std::fs::File; + use std::io; + + #[test] + fn nim_version() { + let ok_versions = ["1.1.1", "2", "."]; + let not_ok_versions = ["abc", " \n.", ". ", "abc."]; + + let all_some = ok_versions.iter().all(|&v| parse_nim_version(v).is_some()); + let all_none = not_ok_versions + .iter() + .any(|&v| parse_nim_version(v).is_some()); + + assert_eq!(true, all_some); + assert_eq!(true, all_none); + + let sample_nimc_output = "Nim Compiler Version 1.2.0 [Linux: amd64] + Compiled at 2020-04-03 + Copyright (c) 2006-2020 by Andreas Rumpf + + git hash: 7e83adff84be5d0c401a213eccb61e321a3fb1ff + active boot switches: -d:release\n"; + + assert_eq!(Some("1.2.0"), parse_nim_version(sample_nimc_output)) + } + + #[test] + fn folder_without_nim() -> io::Result<()> { + let dir = tempfile::tempdir()?; + File::create(dir.path().join("nim.txt"))?.sync_all()?; + let actual = render_module("nim", dir.path(), None); + let expected = None; + assert_eq!(expected, actual); + dir.close() + } + + #[test] + fn folder_with_nimble_file() -> io::Result<()> { + let dir = tempfile::tempdir()?; + File::create(dir.path().join("main.nimble"))?.sync_all()?; + let actual = render_module("nim", dir.path(), None); + let expected = Some(format!("via {} ", Color::Yellow.bold().paint("👑 v1.2.0"))); + assert_eq!(expected, actual); + dir.close() + } + + #[test] + fn folder_with_nim_file() -> io::Result<()> { + let dir = tempfile::tempdir()?; + File::create(dir.path().join("main.nim"))?.sync_all()?; + let actual = render_module("nim", dir.path(), None); + let expected = Some(format!("via {} ", Color::Yellow.bold().paint("👑 v1.2.0"))); + assert_eq!(expected, actual); + dir.close() + } + + #[test] + fn folder_with_nims_file() -> io::Result<()> { + let dir = tempfile::tempdir()?; + File::create(dir.path().join("main.nims"))?.sync_all()?; + let actual = render_module("nim", dir.path(), None); + let expected = Some(format!("via {} ", Color::Yellow.bold().paint("👑 v1.2.0"))); + assert_eq!(expected, actual); + dir.close() + } + + #[test] + fn folder_with_cfg_file() -> io::Result<()> { + let dir = tempfile::tempdir()?; + File::create(dir.path().join("cfg.nim"))?.sync_all()?; + let actual = render_module("nim", dir.path(), None); + let expected = Some(format!("via {} ", Color::Yellow.bold().paint("👑 v1.2.0"))); + assert_eq!(expected, actual); + dir.close() + } +} diff --git a/src/utils.rs b/src/utils.rs index 687544d68..7687a300b 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -47,6 +47,15 @@ pub fn exec_cmd(cmd: &str, args: &[&str]) -> Option { stdout: String::from("stdout ok!"), stderr: String::from("stderr ok!"), }), + "elixir --version" => Some(CommandOutput { + stdout: String::from( + "\ +Erlang/OTP 22 [erts-10.6.4] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe] + +Elixir 1.10 (compiled with Erlang/OTP 22)", + ), + stderr: String::default(), + }), "elm --version" => Some(CommandOutput { stdout: String::from("0.19.1"), stderr: String::default(), @@ -59,6 +68,17 @@ pub fn exec_cmd(cmd: &str, args: &[&str]) -> Option { stdout: String::from("julia version 1.4.0"), stderr: String::default(), }), + "nim --version" => Some(CommandOutput { + stdout: String::from( + "\ +Nim Compiler Version 1.2.0 [Linux: amd64] +Compiled at 2020-04-03 +Copyright (c) 2006-2020 by Andreas Rumpf +git hash: 7e83adff84be5d0c401a213eccb61e321a3fb1ff +active boot switches: -d:release\n", + ), + stderr: String::default(), + }), "node --version" => Some(CommandOutput { stdout: String::from("v12.0.0"), stderr: String::default(), @@ -87,15 +107,6 @@ pub fn exec_cmd(cmd: &str, args: &[&str]) -> Option { stderr: String::default(), }) } - "elixir --version" => Some(CommandOutput { - stdout: String::from( - "\ -Erlang/OTP 22 [erts-10.6.4] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe] - -Elixir 1.10 (compiled with Erlang/OTP 22)", - ), - stderr: String::default(), - }), "zig version" => Some(CommandOutput { stdout: String::from("0.6.0"), stderr: String::default(),