Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: added mise module #5747

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
79 changes: 79 additions & 0 deletions .github/config-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1022,6 +1022,29 @@
}
]
},
"mise": {
"default": {
"detect_extensions": [],
"detect_files": [
".mise.toml",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mise also supports .config/mise.toml, among others: https://mise.jdx.dev/configuration.html

Note in particular environment-specifig config files, which may be of particular interest here.

".mise.local.toml"
],
"detect_folders": [
".mise"
],
"disabled": true,
"format": "[$symbol$health]($style) ",
"healthy_symbol": "healthy",
"style": "bold purple",
"symbol": "mise ",
"unhealthy_symbol": "unhealthy"
},
"allOf": [
{
"$ref": "#/definitions/MiseConfig"
}
]
},
"nim": {
"default": {
"detect_extensions": [
Expand Down Expand Up @@ -4339,6 +4362,62 @@
},
"additionalProperties": false
},
"MiseConfig": {
"type": "object",
"properties": {
"format": {
"default": "[$symbol$health]($style) ",
"type": "string"
},
"symbol": {
"default": "mise ",
"type": "string"
},
"style": {
"default": "bold purple",
"type": "string"
},
"disabled": {
"default": true,
"type": "boolean"
},
"detect_extensions": {
"default": [],
"type": "array",
"items": {
"type": "string"
}
},
"detect_files": {
"default": [
".mise.toml",
".mise.local.toml"
],
"type": "array",
"items": {
"type": "string"
}
},
"detect_folders": {
"default": [
".mise"
],
"type": "array",
"items": {
"type": "string"
}
},
"healthy_symbol": {
"default": "healthy",
"type": "string"
},
"unhealthy_symbol": {
"default": "unhealthy",
"type": "string"
}
},
"additionalProperties": false
},
"NimConfig": {
"type": "object",
"properties": {
Expand Down
37 changes: 37 additions & 0 deletions docs/config/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,7 @@ $openstack\
$azure\
$direnv\
$env_var\
$mise\
$crystal\
$custom\
$sudo\
Expand Down Expand Up @@ -2883,6 +2884,42 @@ truncation_length = 4
truncation_symbol = ''
```

## Mise

The `mise` module shows the current mise health as reported by running `mise doctor`.

### Options

| Option | Default | Description |
| ------------------ | -------------------------------- | ------------------------------------------------ |
| `symbol` | `'mise '` | The symbol used before displaying _mise_ health. |
| `style` | `'bold purple'` | The style for the module. |
| `format` | `'on [$symbol$health]($style) '` | The format for the module. |
| `healthy_symbol` | `healthy` | The message displayed when _mise_ is healthy. |
| `unhealthy_symbol` | `unhealthy` | The message displayed when _mise_ is unhealthy. |
| `disabled` | `true` | Disables the `mise` module. |

### Variables

| Variable | Example | Description |
| -------- | --------- | ------------------------------------ |
| health | `healthy` | The health of _mise_ |
| 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

[hg_branch]
format = 'on [🌱 $branch](bold purple)'
truncation_length = 4
truncation_symbol = ''
```

## Nim

The `nim` module shows the currently installed version of [Nim](https://nim-lang.org/).
Expand Down
36 changes: 36 additions & 0 deletions src/configs/mise.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
use serde::{Deserialize, Serialize};

#[derive(Clone, Deserialize, Serialize)]
#[cfg_attr(
feature = "config-schema",
derive(schemars::JsonSchema),
schemars(deny_unknown_fields)
)]
#[serde(default)]
pub struct MiseConfig<'a> {
pub 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>,
pub healthy_symbol: &'a str,
pub unhealthy_symbol: &'a str,
}

impl<'a> Default for MiseConfig<'a> {
fn default() -> Self {
Self {
format: "[$symbol$health]($style) ",
symbol: "mise ",
style: "bold purple",
disabled: true,
detect_extensions: vec![],
detect_files: vec![".mise.toml", ".mise.local.toml"],
detect_folders: vec![".mise"],
healthy_symbol: "healthy",
unhealthy_symbol: "unhealthy",
}
}
}
3 changes: 3 additions & 0 deletions src/configs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ pub mod localip;
pub mod lua;
pub mod memory_usage;
pub mod meson;
pub mod mise;
pub mod nim;
pub mod nix_shell;
pub mod nodejs;
Expand Down Expand Up @@ -213,6 +214,8 @@ pub struct FullConfig<'a> {
#[serde(borrow)]
meson: meson::MesonConfig<'a>,
#[serde(borrow)]
mise: mise::MiseConfig<'a>,
#[serde(borrow)]
nim: nim::NimConfig<'a>,
#[serde(borrow)]
nix_shell: nix_shell::NixShellConfig<'a>,
Expand Down
1 change: 1 addition & 0 deletions src/configs/starship_root.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ pub const PROMPT_ORDER: &[&str] = &[
"azure",
"direnv",
"env_var",
"mise",
"crystal",
"custom",
"sudo",
Expand Down
1 change: 1 addition & 0 deletions src/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ pub const ALL_MODULES: &[&str] = &[
"lua",
"memory_usage",
"meson",
"mise",
"nim",
"nix_shell",
"nodejs",
Expand Down
144 changes: 144 additions & 0 deletions src/modules/mise.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
use super::{Context, Module, ModuleConfig};

use crate::configs::mise::MiseConfig;
use crate::formatter::StringFormatter;

/// Creates a module with the current mise config
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
let mut module = context.new_module("mise");
let config = MiseConfig::try_load(module.config);

let mise_applies = !config.disabled
&& context
.try_begin_scan()?
.set_extensions(&config.detect_extensions)
.set_files(&config.detect_files)
.set_folders(&config.detect_folders)
.is_match();

if !mise_applies {
return None;
}

let parsed = StringFormatter::new(config.format).and_then(|formatter| {
formatter
.map_style(|variable| match variable {
"style" => Some(Ok(config.style)),
_ => None,

Check warning on line 27 in src/modules/mise.rs

View check run for this annotation

Codecov / codecov/patch

src/modules/mise.rs#L27

Added line #L27 was not covered by tests
})
.map(|variable| match variable {
"symbol" => Some(Ok(config.symbol)),
"health" => match context.exec_cmd("mise", &["doctor"]) {
Some(_) => Some(Ok(config.healthy_symbol)),
None => Some(Ok(config.unhealthy_symbol)),
},
_ => None,

Check warning on line 35 in src/modules/mise.rs

View check run for this annotation

Codecov / codecov/patch

src/modules/mise.rs#L35

Added line #L35 was not covered by tests
})
.parse(None, Some(context))
});

module.set_segments(match parsed {
Ok(segments) => segments,
Err(e) => {
log::warn!("{e}");

Check warning on line 43 in src/modules/mise.rs

View check run for this annotation

Codecov / codecov/patch

src/modules/mise.rs#L42-L43

Added lines #L42 - L43 were not covered by tests

return None;

Check warning on line 45 in src/modules/mise.rs

View check run for this annotation

Codecov / codecov/patch

src/modules/mise.rs#L45

Added line #L45 was not covered by tests
}
});

Some(module)
}

#[cfg(test)]
mod tests {
use crate::test::ModuleRenderer;
use crate::utils::CommandOutput;
use nu_ansi_term::Color;

use std::io;

#[test]
fn folder_without_mise_config() {
let renderer = ModuleRenderer::new("mise").config(toml::toml! {
[mise]
disabled = false
});

assert_eq!(None, renderer.collect());
}

#[test]
fn folder_with_mise_config_file_healthy() -> io::Result<()> {
let dir = tempfile::tempdir()?;
let config_path = dir.path().join(".mise.toml");

std::fs::File::create(config_path)?.sync_all()?;

let renderer = ModuleRenderer::new("mise")
.path(dir.path())
.config(toml::toml! {
[mise]
disabled = false
})
.cmd(
"mise doctor",
Some(CommandOutput {
stdout: String::default(),
stderr: String::default(),
}),
);

let expected = Some(format!("{} ", Color::Purple.bold().paint("mise healthy")));
assert_eq!(expected, renderer.collect());

dir.close()
}

#[test]
fn folder_with_mise_config_folder_healthy() -> io::Result<()> {
let dir = tempfile::tempdir()?;
let config_dir = dir.path().join(".mise");

std::fs::create_dir_all(config_dir)?;

let renderer = ModuleRenderer::new("mise")
.path(dir.path())
.config(toml::toml! {
[mise]
disabled = false
})
.cmd(
"mise doctor",
Some(CommandOutput {
stdout: String::default(),
stderr: String::default(),
}),
);

let expected = Some(format!("{} ", Color::Purple.bold().paint("mise healthy")));
assert_eq!(expected, renderer.collect());

dir.close()
}

#[test]
fn folder_with_mise_config_file_unhealthy() -> io::Result<()> {
let dir = tempfile::tempdir()?;
let config_path = dir.path().join(".mise.toml");

std::fs::File::create(config_path)?.sync_all()?;

let renderer = ModuleRenderer::new("mise")
.path(dir.path())
.config(toml::toml! {
[mise]
disabled = false
})
.cmd("mise doctor", None);

let expected = Some(format!("{} ", Color::Purple.bold().paint("mise unhealthy")));
assert_eq!(expected, renderer.collect());

dir.close()
}
}
3 changes: 3 additions & 0 deletions src/modules/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ mod localip;
mod lua;
mod memory_usage;
mod meson;
mod mise;
mod nim;
mod nix_shell;
mod nodejs;
Expand Down Expand Up @@ -158,6 +159,7 @@ pub fn handle<'a>(module: &str, context: &'a Context) -> Option<Module<'a>> {
"lua" => lua::module(context),
"memory_usage" => memory_usage::module(context),
"meson" => meson::module(context),
"mise" => mise::module(context),
"nim" => nim::module(context),
"nix_shell" => nix_shell::module(context),
"nodejs" => nodejs::module(context),
Expand Down Expand Up @@ -278,6 +280,7 @@ pub fn description(module: &str) -> &'static str {
"meson" => {
"The current Meson environment, if $MESON_DEVENV and $MESON_PROJECT_NAME are set"
}
"mise" => "The current mise status",
"nim" => "The currently installed version of Nim",
"nix_shell" => "The nix-shell environment",
"nodejs" => "The currently installed version of NodeJS",
Expand Down