diff --git a/.github/config-schema.json b/.github/config-schema.json index 0e062b41..5a0c7838 100644 --- a/.github/config-schema.json +++ b/.github/config-schema.json @@ -620,6 +620,19 @@ } ] }, + "guix_shell": { + "default": { + "disabled": false, + "format": "via [$symbol]($style) ", + "style": "yellow bold", + "symbol": "🐃 " + }, + "allOf": [ + { + "$ref": "#/definitions/GuixShellConfig" + } + ] + }, "haskell": { "default": { "detect_extensions": [ @@ -3091,6 +3104,28 @@ }, "additionalProperties": false }, + "GuixShellConfig": { + "type": "object", + "properties": { + "format": { + "default": "via [$symbol]($style) ", + "type": "string" + }, + "symbol": { + "default": "🐃 ", + "type": "string" + }, + "style": { + "default": "yellow bold", + "type": "string" + }, + "disabled": { + "default": false, + "type": "boolean" + } + }, + "additionalProperties": false + }, "HaskellConfig": { "type": "object", "properties": { diff --git a/docs/.vuepress/public/presets/toml/bracketed-segments.toml b/docs/.vuepress/public/presets/toml/bracketed-segments.toml index b8138d79..cdd48cf9 100644 --- a/docs/.vuepress/public/presets/toml/bracketed-segments.toml +++ b/docs/.vuepress/public/presets/toml/bracketed-segments.toml @@ -58,6 +58,9 @@ format = '([\[$all_status$ahead_behind\]]($style))' [golang] format = '\[[$symbol($version)]($style)\]' +[guix_shell] +format = '\[[$symbol]($style)\]' + [haskell] format = '\[[$symbol($version)]($style)\]' diff --git a/docs/.vuepress/public/presets/toml/nerd-font-symbols.toml b/docs/.vuepress/public/presets/toml/nerd-font-symbols.toml index 7d8adfb5..f8f2700b 100644 --- a/docs/.vuepress/public/presets/toml/nerd-font-symbols.toml +++ b/docs/.vuepress/public/presets/toml/nerd-font-symbols.toml @@ -31,6 +31,9 @@ symbol = " " [golang] symbol = " " +[guix_shell] +symbol = " " + [haskell] symbol = " " diff --git a/docs/.vuepress/public/presets/toml/plain-text-symbols.toml b/docs/.vuepress/public/presets/toml/plain-text-symbols.toml index 5360d793..bc555349 100644 --- a/docs/.vuepress/public/presets/toml/plain-text-symbols.toml +++ b/docs/.vuepress/public/presets/toml/plain-text-symbols.toml @@ -64,6 +64,9 @@ symbol = "git " [golang] symbol = "go " +[guix_shell] +symbol = "guix " + [hg_branch] symbol = "hg " diff --git a/docs/config/README.md b/docs/config/README.md index 0c2d863e..b1adce8e 100644 --- a/docs/config/README.md +++ b/docs/config/README.md @@ -250,6 +250,7 @@ $elixir\ $elm\ $erlang\ $golang\ +$guix_shell\ $haskell\ $helm\ $java\ @@ -1842,6 +1843,39 @@ By default the module will be shown if any of the following conditions are met: format = "via [🏎💨 $version](bold cyan) " ``` +## Guix-shell + +The `guix_shell` module shows the [guix-shell](https://guix.gnu.org/manual/devel/en/html_node/Invoking-guix-shell.html) environment. +The module will be shown when inside a guix-shell environment. + +### Options + +| Option | Default | Description | +| ---------- | -------------------------- | ------------------------------------------------------ | +| `format` | `'via [$symbol]($style) '` | The format for the module. | +| `symbol` | `"🐃 "` | A format string representing the symbol of guix-shell. | +| `style` | `"yellow bold"` | The style for the module. | +| `disabled` | `false` | Disables the `guix_shell` module. | + +### Variables + +| Variable | Example | Description | +| -------- | ------- | ------------------------------------ | +| 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 + +[guix_shell] +disabled = true +format = 'via [🐂](yellow bold) ' +``` + ## Haskell The `haskell` module finds the current selected GHC version and/or the selected Stack snapshot. diff --git a/src/configs/guix_shell.rs b/src/configs/guix_shell.rs new file mode 100644 index 00000000..8bedc706 --- /dev/null +++ b/src/configs/guix_shell.rs @@ -0,0 +1,26 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Deserialize, Serialize)] +#[cfg_attr( + feature = "config-schema", + derive(schemars::JsonSchema), + schemars(deny_unknown_fields) +)] +#[serde(default)] +pub struct GuixShellConfig<'a> { + pub format: &'a str, + pub symbol: &'a str, + pub style: &'a str, + pub disabled: bool, +} + +impl<'a> Default for GuixShellConfig<'a> { + fn default() -> Self { + GuixShellConfig { + format: "via [$symbol]($style) ", + symbol: "🐃 ", + style: "yellow bold", + disabled: false, + } + } +} diff --git a/src/configs/mod.rs b/src/configs/mod.rs index 582d56c5..035b09e0 100644 --- a/src/configs/mod.rs +++ b/src/configs/mod.rs @@ -33,6 +33,7 @@ pub mod git_metrics; pub mod git_state; pub mod git_status; pub mod go; +pub mod guix_shell; pub mod haskell; pub mod helm; pub mod hg_branch; @@ -161,6 +162,8 @@ pub struct FullConfig<'a> { #[serde(borrow)] golang: go::GoConfig<'a>, #[serde(borrow)] + guix_shell: guix_shell::GuixShellConfig<'a>, + #[serde(borrow)] haskell: haskell::HaskellConfig<'a>, #[serde(borrow)] helm: helm::HelmConfig<'a>, diff --git a/src/configs/starship_root.rs b/src/configs/starship_root.rs index 11f6627a..48116eb2 100644 --- a/src/configs/starship_root.rs +++ b/src/configs/starship_root.rs @@ -86,6 +86,7 @@ pub const PROMPT_ORDER: &[&str] = &[ "zig", // ↑ Toolchain version modules ↑ "buf", + "guix_shell", "nix_shell", "conda", "meson", diff --git a/src/module.rs b/src/module.rs index 31881ee7..871c2f9d 100644 --- a/src/module.rs +++ b/src/module.rs @@ -41,6 +41,7 @@ pub const ALL_MODULES: &[&str] = &[ "git_state", "git_status", "golang", + "guix_shell", "haskell", "helm", "hg_branch", diff --git a/src/modules/guix_shell.rs b/src/modules/guix_shell.rs new file mode 100644 index 00000000..6ee0a7b5 --- /dev/null +++ b/src/modules/guix_shell.rs @@ -0,0 +1,69 @@ +use super::{Context, Module, ModuleConfig}; + +use crate::configs::guix_shell::GuixShellConfig; +use crate::formatter::StringFormatter; + +/// Creates a module showing if inside a guix-shell +/// +/// The module will use the `$GUIX_ENVIRONMENT` environment variable to determine if it's +/// inside a guix-shell and the name of it. +pub fn module<'a>(context: &'a Context) -> Option> { + let mut module = context.new_module("guix_shell"); + let config: GuixShellConfig = GuixShellConfig::try_load(module.config); + + let is_guix_shell = context.get_env("GUIX_ENVIRONMENT").is_some(); + + if !is_guix_shell { + 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, + }) + .parse(None, Some(context)) + }); + + module.set_segments(match parsed { + Ok(segments) => segments, + Err(error) => { + log::warn!("Error in module `guix_shell`:\n{}", error); + return None; + } + }); + + Some(module) +} + +#[cfg(test)] +mod tests { + use crate::test::ModuleRenderer; + use nu_ansi_term::Color; + + #[test] + fn no_env_variables() { + let actual = ModuleRenderer::new("guix_shell").collect(); + let expected = None; + + assert_eq!(expected, actual); + } + + #[test] + fn env_variables() { + let actual = ModuleRenderer::new("guix_shell") + .env( + "GUIX_ENVIRONMENT", + "/gnu/store/7vmfs4khf4fllsh83kqkxssbw3437qsh-profile", + ) + .collect(); + let expected = Some(format!("via {} ", Color::Yellow.bold().paint("🐃 "))); + + assert_eq!(expected, actual); + } +} diff --git a/src/modules/mod.rs b/src/modules/mod.rs index 62de0ec6..06a4fe04 100644 --- a/src/modules/mod.rs +++ b/src/modules/mod.rs @@ -30,6 +30,7 @@ mod git_metrics; mod git_state; mod git_status; mod golang; +mod guix_shell; mod haskell; mod helm; mod hg_branch; @@ -126,6 +127,7 @@ pub fn handle<'a>(module: &str, context: &'a Context) -> Option> { "git_state" => git_state::module(context), "git_status" => git_status::module(context), "golang" => golang::module(context), + "guix_shell" => guix_shell::module(context), "haskell" => haskell::module(context), "helm" => helm::module(context), "hg_branch" => hg_branch::module(context), @@ -233,6 +235,7 @@ pub fn description(module: &str) -> &'static str { "git_state" => "The current git operation, and it's progress", "git_status" => "Symbol representing the state of the repo", "golang" => "The currently installed version of Golang", + "guix_shell" => "The guix-shell environment", "haskell" => "The selected version of the Haskell toolchain", "helm" => "The currently installed version of Helm", "hg_branch" => "The active branch of the repo in your current directory",