From 23e5ee255d2dae432f777c32a9f9fa305a251406 Mon Sep 17 00:00:00 2001 From: jdx <216188+jdx@users.noreply.github.com> Date: Fri, 27 Sep 2024 16:02:03 -0500 Subject: [PATCH] feat: added --type option to `toml set` (#2674) Fixes #2668 --- .idea/prettier.xml | 5 +- docs/.vitepress/cli_commands.ts | 19 +-- docs/cli/config/generate.md | 2 +- docs/cli/{toml => config}/get.md | 9 +- docs/cli/config/ls.md | 4 +- docs/cli/config/set.md | 30 +++++ docs/cli/index.md | 124 +++++++++--------- docs/cli/toml/set.md | 25 ---- man/man1/mise.1 | 5 +- mise.usage.kdl | 68 +++++----- src/cli/config/generate.rs | 2 +- src/cli/{toml => config}/get.rs | 22 ++-- src/cli/config/ls.rs | 9 +- src/cli/config/mod.rs | 32 ++++- src/cli/config/set.rs | 106 +++++++++++++++ ...se__cli__config__get__tests__toml_get.snap | 25 ++++ src/cli/mod.rs | 3 - src/cli/toml/mod.rs | 62 --------- src/cli/toml/set.rs | 79 ----------- src/config/config_file/mise_toml.rs | 8 +- 20 files changed, 334 insertions(+), 305 deletions(-) rename docs/cli/{toml => config}/get.md (73%) create mode 100644 docs/cli/config/set.md delete mode 100644 docs/cli/toml/set.md rename src/cli/{toml => config}/get.rs (76%) create mode 100644 src/cli/config/set.rs create mode 100644 src/cli/config/snapshots/mise__cli__config__get__tests__toml_get.snap delete mode 100644 src/cli/toml/mod.rs delete mode 100644 src/cli/toml/set.rs diff --git a/.idea/prettier.xml b/.idea/prettier.xml index ed1abca792..f89a64058a 100644 --- a/.idea/prettier.xml +++ b/.idea/prettier.xml @@ -1,8 +1,9 @@ - - + \ No newline at end of file diff --git a/docs/.vitepress/cli_commands.ts b/docs/.vitepress/cli_commands.ts index d76f76d18e..2156705d3a 100644 --- a/docs/.vitepress/cli_commands.ts +++ b/docs/.vitepress/cli_commands.ts @@ -59,10 +59,16 @@ export const commands: { [key: string]: Command } = { "config": { hide: false, subcommands: { + "generate": { + hide: false, + }, + "get": { + hide: false, + }, "ls": { hide: false, }, - "generate": { + "set": { hide: false, }, }, @@ -238,17 +244,6 @@ export const commands: { [key: string]: Command } = { }, }, }, - "toml": { - hide: false, - subcommands: { - "get": { - hide: false, - }, - "set": { - hide: false, - }, - }, - }, "trust": { hide: false, }, diff --git a/docs/cli/config/generate.md b/docs/cli/config/generate.md index 144db72d1d..ff6de06329 100644 --- a/docs/cli/config/generate.md +++ b/docs/cli/config/generate.md @@ -3,7 +3,7 @@ **Aliases:** `g` ```text -[experimental] Generate an .mise.toml file +[experimental] Generate a mise.toml file Usage: config generate [OPTIONS] diff --git a/docs/cli/toml/get.md b/docs/cli/config/get.md similarity index 73% rename from docs/cli/toml/get.md rename to docs/cli/config/get.md index 74f2e7d3f5..4b7d8166a9 100644 --- a/docs/cli/toml/get.md +++ b/docs/cli/config/get.md @@ -1,15 +1,16 @@ -## `mise toml get [FILE]` +## `mise config get [OPTIONS] [KEY]` ```text Display the value of a setting in a mise.toml file -Usage: toml get [FILE] +Usage: config get [OPTIONS] [KEY] Arguments: - + [KEY] The path of the config to display - [FILE] +Options: + -f, --file The path to the mise.toml file to edit If not provided, the nearest mise.toml file will be used diff --git a/docs/cli/config/ls.md b/docs/cli/config/ls.md index 87b988dd74..acb08860d8 100644 --- a/docs/cli/config/ls.md +++ b/docs/cli/config/ls.md @@ -1,7 +1,7 @@ -## `mise config ls [OPTIONS]` +## `mise config ls [OPTIONS]` ```text -[experimental] List config files currently in use +List config files currently in use Usage: config ls [OPTIONS] diff --git a/docs/cli/config/set.md b/docs/cli/config/set.md new file mode 100644 index 0000000000..f0510d7f2e --- /dev/null +++ b/docs/cli/config/set.md @@ -0,0 +1,30 @@ +## `mise config set [OPTIONS] ` + +```text +Display the value of a setting in a mise.toml file + +Usage: config set [OPTIONS] + +Arguments: + + The path of the config to display + + + The value to set the key to + +Options: + -f, --file + The path to the mise.toml file to edit + + If not provided, the nearest mise.toml file will be used + + -t, --type + [default: string] + [possible values: string, integer, float, bool] + +Examples: + + $ mise config set tools.python 3.12 + $ mise config set settings.always_keep_download true + $ mise config set env.TEST_ENV_VAR ABC +``` diff --git a/docs/cli/index.md b/docs/cli/index.md index 7824970390..438214be56 100644 --- a/docs/cli/index.md +++ b/docs/cli/index.md @@ -237,10 +237,52 @@ Examples: $ mise completion fish > ~/.config/fish/completions/mise.fish ``` -## `mise config ls [OPTIONS]` +## `mise config generate [OPTIONS]` + +**Aliases:** `g` ```text -[experimental] List config files currently in use +[experimental] Generate a mise.toml file + +Usage: config generate [OPTIONS] + +Options: + -o, --output + Output to file instead of stdout + +Examples: + + $ mise cf generate > .mise.toml + $ mise cf generate --output=.mise.toml +``` + +## `mise config get [OPTIONS] [KEY]` + +```text +Display the value of a setting in a mise.toml file + +Usage: config get [OPTIONS] [KEY] + +Arguments: + [KEY] + The path of the config to display + +Options: + -f, --file + The path to the mise.toml file to edit + + If not provided, the nearest mise.toml file will be used + +Examples: + + $ mise toml get tools.python + 3.12 +``` + +## `mise config ls [OPTIONS]` + +```text +List config files currently in use Usage: config ls [OPTIONS] @@ -253,23 +295,35 @@ Examples: $ mise config ls ``` -## `mise config generate [OPTIONS]` - -**Aliases:** `g` +## `mise config set [OPTIONS] ` ```text -[experimental] Generate an .mise.toml file +Display the value of a setting in a mise.toml file -Usage: config generate [OPTIONS] +Usage: config set [OPTIONS] + +Arguments: + + The path of the config to display + + + The value to set the key to Options: - -o, --output - Output to file instead of stdout + -f, --file + The path to the mise.toml file to edit + + If not provided, the nearest mise.toml file will be used + + -t, --type + [default: string] + [possible values: string, integer, float, bool] Examples: - $ mise cf generate > .mise.toml - $ mise cf generate --output=.mise.toml + $ mise config set tools.python 3.12 + $ mise config set settings.always_keep_download true + $ mise config set env.TEST_ENV_VAR ABC ``` ## `mise current [PLUGIN]` @@ -1603,54 +1657,6 @@ Examples: $ mise tasks cmd1 arg1 arg2 ::: cmd2 arg1 arg2 ``` -## `mise toml get [FILE]` - -```text -Display the value of a setting in a mise.toml file - -Usage: toml get [FILE] - -Arguments: - - The path of the config to display - - [FILE] - The path to the mise.toml file to edit - - If not provided, the nearest mise.toml file will be used - -Examples: - - $ mise toml get tools.python - 3.12 -``` - -## `mise toml set [FILE]` - -```text -Display the value of a setting in a mise.toml file - -Usage: toml set [FILE] - -Arguments: - - The path of the config to display - - - The value to set the key to - - [FILE] - The path to the mise.toml file to edit - - If not provided, the nearest mise.toml file will be used - -Examples: - - $ mise toml set tools.python 3.12 - $ mise toml set settings.always_keep_download true - $ mise toml set env.TEST_ENV_VAR ABC -``` - ## `mise trust [OPTIONS] [CONFIG_FILE]` ```text diff --git a/docs/cli/toml/set.md b/docs/cli/toml/set.md deleted file mode 100644 index 8c1e55cf1f..0000000000 --- a/docs/cli/toml/set.md +++ /dev/null @@ -1,25 +0,0 @@ -## `mise toml set [FILE]` - -```text -Display the value of a setting in a mise.toml file - -Usage: toml set [FILE] - -Arguments: - - The path of the config to display - - - The value to set the key to - - [FILE] - The path to the mise.toml file to edit - - If not provided, the nearest mise.toml file will be used - -Examples: - - $ mise toml set tools.python 3.12 - $ mise toml set settings.always_keep_download true - $ mise toml set env.TEST_ENV_VAR ABC -``` diff --git a/man/man1/mise.1 b/man/man1/mise.1 index 29451308f1..1e5457b298 100644 --- a/man/man1/mise.1 +++ b/man/man1/mise.1 @@ -57,7 +57,7 @@ mise\-completion(1) Generate shell completions .TP mise\-config(1) -[experimental] Manage config files +Manage config files .TP mise\-current(1) Shows current active and installed runtime versions @@ -134,9 +134,6 @@ Add tool versions from external tools to mise mise\-tasks(1) [experimental] Manage tasks .TP -mise\-toml(1) -Edit mise.toml files -.TP mise\-trust(1) Marks a config file as trusted .TP diff --git a/mise.usage.kdl b/mise.usage.kdl index 5bf59f21df..6363a27b3b 100644 --- a/mise.usage.kdl +++ b/mise.usage.kdl @@ -179,26 +179,56 @@ cmd "completion" help="Generate shell completions" { } arg "[SHELL]" help="Shell type to generate completions for" } -cmd "config" help="[experimental] Manage config files" { +cmd "config" help="Manage config files" { alias "cfg" + alias "toml" hide=true flag "--no-header" help="Do not print table header" - cmd "ls" help="[experimental] List config files currently in use" { + cmd "generate" help="[experimental] Generate a mise.toml file" { + alias "g" + after_long_help r"Examples: + + $ mise cf generate > .mise.toml + $ mise cf generate --output=.mise.toml +" + flag "-o --output" help="Output to file instead of stdout" { + arg "" + } + } + cmd "get" help="Display the value of a setting in a mise.toml file" { + after_long_help r"Examples: + + $ mise toml get tools.python + 3.12 +" + flag "-f --file" help="The path to the mise.toml file to edit" { + long_help "The path to the mise.toml file to edit\n\nIf not provided, the nearest mise.toml file will be used" + arg "" + } + arg "[KEY]" help="The path of the config to display" + } + cmd "ls" help="List config files currently in use" { after_long_help r"Examples: $ mise config ls " flag "--no-header" help="Do not print table header" } - cmd "generate" help="[experimental] Generate an .mise.toml file" { - alias "g" + cmd "set" help="Display the value of a setting in a mise.toml file" { after_long_help r"Examples: - $ mise cf generate > .mise.toml - $ mise cf generate --output=.mise.toml + $ mise config set tools.python 3.12 + $ mise config set settings.always_keep_download true + $ mise config set env.TEST_ENV_VAR ABC " - flag "-o --output" help="Output to file instead of stdout" { - arg "" + flag "-f --file" help="The path to the mise.toml file to edit" { + long_help "The path to the mise.toml file to edit\n\nIf not provided, the nearest mise.toml file will be used" + arg "" + } + flag "-t --type" { + arg "" } + arg "" help="The path of the config to display" + arg "" help="The value to set the key to" } } cmd "current" help="Shows current active and installed runtime versions" { @@ -1145,28 +1175,6 @@ The name of the script will be the name of the tasks. arg "[ARGS]..." help="Arguments to pass to the tasks. Use \":::\" to separate tasks" var=true } } -cmd "toml" help="Edit mise.toml files" { - cmd "get" help="Display the value of a setting in a mise.toml file" { - after_long_help r"Examples: - - $ mise toml get tools.python - 3.12 -" - arg "" help="The path of the config to display" - arg "[FILE]" help="The path to the mise.toml file to edit" long_help="The path to the mise.toml file to edit\n\nIf not provided, the nearest mise.toml file will be used" - } - cmd "set" help="Display the value of a setting in a mise.toml file" { - after_long_help r"Examples: - - $ mise toml set tools.python 3.12 - $ mise toml set settings.always_keep_download true - $ mise toml set env.TEST_ENV_VAR ABC -" - arg "" help="The path of the config to display" - arg "" help="The value to set the key to" - arg "[FILE]" help="The path to the mise.toml file to edit" long_help="The path to the mise.toml file to edit\n\nIf not provided, the nearest mise.toml file will be used" - } -} cmd "trust" help="Marks a config file as trusted" { long_help r"Marks a config file as trusted diff --git a/src/cli/config/generate.rs b/src/cli/config/generate.rs index a862ab7842..156dd2866e 100644 --- a/src/cli/config/generate.rs +++ b/src/cli/config/generate.rs @@ -7,7 +7,7 @@ use crate::config::Settings; use crate::file; use crate::file::display_path; -/// [experimental] Generate an .mise.toml file +/// [experimental] Generate a mise.toml file #[derive(Debug, clap::Args)] #[clap(visible_alias = "g", verbatim_doc_comment, after_long_help = AFTER_LONG_HELP)] pub struct ConfigGenerate { diff --git a/src/cli/toml/get.rs b/src/cli/config/get.rs similarity index 76% rename from src/cli/toml/get.rs rename to src/cli/config/get.rs index d387eeb6d8..0e6cd4047e 100644 --- a/src/cli/toml/get.rs +++ b/src/cli/config/get.rs @@ -1,4 +1,4 @@ -use crate::cli::toml::top_toml_config; +use crate::cli::config::top_toml_config; use crate::file::display_path; use eyre::bail; use std::path::PathBuf; @@ -6,17 +6,18 @@ use std::path::PathBuf; /// Display the value of a setting in a mise.toml file #[derive(Debug, clap::Args)] #[clap(after_long_help = AFTER_LONG_HELP, verbatim_doc_comment)] -pub struct TomlGet { +pub struct ConfigGet { /// The path of the config to display - pub key: String, + pub key: Option, /// The path to the mise.toml file to edit /// /// If not provided, the nearest mise.toml file will be used + #[clap(short, long)] pub file: Option, } -impl TomlGet { +impl ConfigGet { pub fn run(self) -> eyre::Result<()> { let mut file = self.file; if file.is_none() { @@ -25,10 +26,12 @@ impl TomlGet { if let Some(file) = file { let config: toml::Value = std::fs::read_to_string(&file)?.parse()?; let mut value = &config; - for key in self.key.split('.') { - value = value.get(key).ok_or_else(|| { - eyre::eyre!("Key not found: {} in {}", &self.key, display_path(&file)) - })?; + if let Some(key) = &self.key { + for k in key.split('.') { + value = value.get(k).ok_or_else(|| { + eyre::eyre!("Key not found: {} in {}", key, display_path(&file)) + })?; + } } match value { toml::Value::String(s) => miseprintln!("{}", s), @@ -65,6 +68,7 @@ mod tests { #[test] fn test_toml_get() { reset(); - assert_cli_snapshot!("toml", "get", "env.TEST_ENV_VAR", @"test-123"); + assert_cli_snapshot!("cfg", "get"); + assert_cli_snapshot!("cfg", "get", "env.TEST_ENV_VAR", @"test-123"); } } diff --git a/src/cli/config/ls.rs b/src/cli/config/ls.rs index c2584fc145..59e8993baa 100644 --- a/src/cli/config/ls.rs +++ b/src/cli/config/ls.rs @@ -6,11 +6,11 @@ use tabled::settings::{Modify, Width}; use tabled::Tabled; use crate::config::config_file::ConfigFile; -use crate::config::{Config, Settings}; +use crate::config::CONFIG; use crate::file::display_path; use crate::ui::table; -/// [experimental] List config files currently in use +/// List config files currently in use #[derive(Debug, clap::Args)] #[clap(verbatim_doc_comment, after_long_help = AFTER_LONG_HELP)] pub struct ConfigLs { @@ -21,10 +21,7 @@ pub struct ConfigLs { impl ConfigLs { pub fn run(self) -> Result<()> { - let config = Config::try_get()?; - let settings = Settings::try_get()?; - settings.ensure_experimental("`mise config ls`")?; - let rows = config + let rows = CONFIG .config_files .values() .map(|cf| cf.as_ref().into()) diff --git a/src/cli/config/mod.rs b/src/cli/config/mod.rs index 7640026c13..b14e0e1795 100644 --- a/src/cli/config/mod.rs +++ b/src/cli/config/mod.rs @@ -1,12 +1,17 @@ +use crate::config::{load_config_paths, DEFAULT_CONFIG_FILENAMES}; use clap::Subcommand; use eyre::Result; +use once_cell::sync::Lazy; +use std::path::PathBuf; mod generate; +mod get; mod ls; +mod set; -/// [experimental] Manage config files +/// Manage config files #[derive(Debug, clap::Args)] -#[clap(visible_alias = "cfg")] +#[clap(visible_alias = "cfg", alias = "toml")] pub struct Config { #[clap(subcommand)] command: Option, @@ -18,15 +23,19 @@ pub struct Config { #[derive(Debug, Subcommand)] enum Commands { - Ls(ls::ConfigLs), Generate(generate::ConfigGenerate), + Get(get::ConfigGet), + Ls(ls::ConfigLs), + Set(set::ConfigSet), } impl Commands { pub fn run(self) -> Result<()> { match self { - Self::Ls(cmd) => cmd.run(), Self::Generate(cmd) => cmd.run(), + Self::Get(cmd) => cmd.run(), + Self::Ls(cmd) => cmd.run(), + Self::Set(cmd) => cmd.run(), } } } @@ -40,3 +49,18 @@ impl Config { cmd.run() } } + +pub static TOML_CONFIG_FILENAMES: Lazy> = Lazy::new(|| { + DEFAULT_CONFIG_FILENAMES + .iter() + .filter(|s| s.ends_with(".toml")) + .map(|s| s.to_string()) + .collect() +}); + +fn top_toml_config() -> Option { + load_config_paths(&TOML_CONFIG_FILENAMES) + .iter() + .find(|p| p.to_string_lossy().ends_with(".toml")) + .map(|p| p.to_path_buf()) +} diff --git a/src/cli/config/set.rs b/src/cli/config/set.rs new file mode 100644 index 0000000000..bcac039c96 --- /dev/null +++ b/src/cli/config/set.rs @@ -0,0 +1,106 @@ +use crate::cli::config::top_toml_config; +use crate::config::config_file::mise_toml::MiseToml; +use clap::ValueEnum; +use eyre::bail; +use std::path::PathBuf; + +/// Display the value of a setting in a mise.toml file +#[derive(Debug, clap::Args)] +#[clap(after_long_help = AFTER_LONG_HELP, verbatim_doc_comment)] +pub struct ConfigSet { + /// The path of the config to display + pub key: String, + + /// The value to set the key to + pub value: String, + + /// The path to the mise.toml file to edit + /// + /// If not provided, the nearest mise.toml file will be used + #[clap(short, long)] + pub file: Option, + + #[clap(value_enum, short, long, default_value_t)] + pub type_: TomlValueTypes, +} + +#[derive(ValueEnum, Default, Clone, Debug)] +pub enum TomlValueTypes { + #[default] + #[value()] + String, + #[value()] + Integer, + #[value()] + Float, + #[value()] + Bool, +} + +impl ConfigSet { + pub fn run(self) -> eyre::Result<()> { + let mut file = self.file; + if file.is_none() { + file = top_toml_config(); + } + if let Some(file) = file { + let mut config: toml_edit::DocumentMut = std::fs::read_to_string(&file)?.parse()?; + let mut container = config.as_item_mut(); + let parts = self.key.split('.').collect::>(); + for key in parts.iter().take(parts.len() - 1) { + container = container + .as_table_mut() + .unwrap() + .entry(key) + .or_insert(toml_edit::Item::Table(toml_edit::Table::new())); + } + let last_key = parts.last().unwrap(); + + let value = match self.type_ { + TomlValueTypes::String => toml_edit::value(self.value), + TomlValueTypes::Integer => toml_edit::value(self.value.parse::()?), + TomlValueTypes::Float => toml_edit::value(self.value.parse::()?), + TomlValueTypes::Bool => toml_edit::value(self.value.parse::()?), + }; + + container.as_table_mut().unwrap().insert(last_key, value); + + let raw = config.to_string(); + MiseToml::from_str(&raw, &file)?; + std::fs::write(&file, raw)?; + } else { + bail!("No mise.toml file found"); + } + Ok(()) + } +} + +static AFTER_LONG_HELP: &str = color_print::cstr!( + r#"Examples: + + $ mise config set tools.python 3.12 + $ mise config set settings.always_keep_download true + $ mise config set env.TEST_ENV_VAR ABC +"# +); + +#[cfg(test)] +mod tests { + use crate::test::reset; + + #[test] + fn test_config_set() { + reset(); + assert_cli_snapshot!("config", "set", "env.TEST_ENV_VAR", "ABC", @""); + assert_cli_snapshot!("config", "get", "env.TEST_ENV_VAR", @"ABC"); + + assert_cli_snapshot!("config", "set", "settings.ruby.default_packages_file", "abc", @""); + assert_cli_snapshot!("config", "get", "settings.ruby.default_packages_file", @"abc"); + + assert_cli_snapshot!("config", "set", "settings.always_keep_download", "--type", "bool", "true", @""); + assert_cli_snapshot!("config", "get", "settings.always_keep_download", @"true"); + + assert_cli_snapshot!("config", "set", "settings.jobs", "--type", "integer", "4", @""); + assert_cli_snapshot!("config", "get", "settings.jobs", @"4"); + } +} diff --git a/src/cli/config/snapshots/mise__cli__config__get__tests__toml_get.snap b/src/cli/config/snapshots/mise__cli__config__get__tests__toml_get.snap new file mode 100644 index 0000000000..1515ceceb1 --- /dev/null +++ b/src/cli/config/snapshots/mise__cli__config__get__tests__toml_get.snap @@ -0,0 +1,25 @@ +--- +source: src/cli/config/get.rs +expression: output +--- +[alias.tiny] +"my/alias" = "3.0" + +[env] +TEST_ENV_VAR = "test-123" + +[settings] +always_keep_download = true +always_keep_install = true +jobs = 2 +legacy_version_file = true +plugin_autoupdate_last_check_duration = "20m" + +[tasks.configtask] +run = 'echo "configtask:"' + +[tasks.lint] +run = 'echo "linting!"' + +[tasks.test] +run = 'echo "testing!"' diff --git a/src/cli/mod.rs b/src/cli/mod.rs index 77b33f0208..67d7bcc6b8 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -48,7 +48,6 @@ mod settings; mod shell; mod sync; mod tasks; -mod toml; mod trust; mod uninstall; mod unset; @@ -101,7 +100,6 @@ pub enum Commands { Shell(shell::Shell), Sync(sync::Sync), Tasks(tasks::Tasks), - Toml(toml::Toml), Trust(trust::Trust), Uninstall(uninstall::Uninstall), Unset(unset::Unset), @@ -160,7 +158,6 @@ impl Commands { Self::Shell(cmd) => cmd.run(), Self::Sync(cmd) => cmd.run(), Self::Tasks(cmd) => cmd.run(), - Self::Toml(cmd) => cmd.run(), Self::Trust(cmd) => cmd.run(), Self::Uninstall(cmd) => cmd.run(), Self::Unset(cmd) => cmd.run(), diff --git a/src/cli/toml/mod.rs b/src/cli/toml/mod.rs deleted file mode 100644 index 6ce44cd0dd..0000000000 --- a/src/cli/toml/mod.rs +++ /dev/null @@ -1,62 +0,0 @@ -use crate::config::{load_config_paths, DEFAULT_CONFIG_FILENAMES}; -use crate::file; -use clap::Subcommand; -use eyre::{bail, Result}; -use once_cell::sync::Lazy; -use std::path::PathBuf; - -mod get; -mod set; - -#[derive(Debug, clap::Args)] -#[clap(about = "Edit mise.toml files")] -pub struct Toml { - #[clap(subcommand)] - command: Option, -} - -#[derive(Debug, Subcommand)] -enum Commands { - Get(get::TomlGet), - Set(set::TomlSet), -} - -pub static TOML_CONFIG_FILENAMES: Lazy> = Lazy::new(|| { - DEFAULT_CONFIG_FILENAMES - .iter() - .filter(|s| s.ends_with(".toml")) - .map(|s| s.to_string()) - .collect() -}); - -fn top_toml_config() -> Option { - load_config_paths(&TOML_CONFIG_FILENAMES) - .iter() - .find(|p| p.to_string_lossy().ends_with(".toml")) - .map(|p| p.to_path_buf()) -} - -impl Commands { - pub fn run(self) -> Result<()> { - match self { - // TODO: implement add for appending to arrays - Self::Get(cmd) => cmd.run(), - Self::Set(cmd) => cmd.run(), - } - } -} - -impl Toml { - pub fn run(self) -> Result<()> { - if let Some(cmd) = self.command { - return cmd.run(); - } - if let Some(toml_config) = top_toml_config() { - miseprintln!("{}", file::read_to_string(&toml_config)?); - } else { - bail!("No mise.toml file found"); - } - - Ok(()) - } -} diff --git a/src/cli/toml/set.rs b/src/cli/toml/set.rs deleted file mode 100644 index 95bf391437..0000000000 --- a/src/cli/toml/set.rs +++ /dev/null @@ -1,79 +0,0 @@ -use crate::cli::toml::top_toml_config; -use eyre::bail; -use std::path::PathBuf; - -/// Display the value of a setting in a mise.toml file -#[derive(Debug, clap::Args)] -#[clap(after_long_help = AFTER_LONG_HELP, verbatim_doc_comment)] -pub struct TomlSet { - /// The path of the config to display - pub key: String, - - /// The value to set the key to - pub value: String, - - /// The path to the mise.toml file to edit - /// - /// If not provided, the nearest mise.toml file will be used - pub file: Option, -} - -impl TomlSet { - pub fn run(self) -> eyre::Result<()> { - let mut file = self.file; - if file.is_none() { - file = top_toml_config(); - } - if let Some(file) = file { - let mut config: toml_edit::DocumentMut = std::fs::read_to_string(&file)?.parse()?; - let mut value = config.as_item_mut(); - let parts = self.key.split('.').collect::>(); - for key in parts.iter().take(parts.len() - 1) { - value = value - .as_table_mut() - .unwrap() - .entry(key) - .or_insert(toml_edit::Item::Table(toml_edit::Table::new())); - } - let last_key = parts.last().unwrap(); - // TODO: support data types other than strings - value - .as_table_mut() - .unwrap() - .insert(last_key, self.value.into()); - - // TODO: validate by parsing the config - std::fs::write(&file, config.to_string())?; - } else { - bail!("No mise.toml file found"); - } - Ok(()) - } -} - -static AFTER_LONG_HELP: &str = color_print::cstr!( - r#"Examples: - - $ mise toml set tools.python 3.12 - $ mise toml set settings.always_keep_download true - $ mise toml set env.TEST_ENV_VAR ABC -"# -); - -#[cfg(test)] -mod tests { - use crate::test::reset; - - #[test] - fn test_toml_set() { - reset(); - assert_cli_snapshot!("toml", "set", "env.TEST_ENV_VAR", "ABC", @""); - assert_cli_snapshot!("toml", "get", "env.TEST_ENV_VAR", @"ABC"); - - assert_cli_snapshot!("toml", "set", "foo", "1", @""); - assert_cli_snapshot!("toml", "get", "foo", @"1"); - - assert_cli_snapshot!("toml", "set", "a.b.c.d.e.f", "2", @""); - assert_cli_snapshot!("toml", "get", "a.b.c.d.e.f", @"2"); - } -} diff --git a/src/config/config_file/mise_toml.rs b/src/config/config_file/mise_toml.rs index 58d8dcc81c..b4dc86f896 100644 --- a/src/config/config_file/mise_toml.rs +++ b/src/config/config_file/mise_toml.rs @@ -82,9 +82,13 @@ impl MiseToml { } pub fn from_file(path: &Path) -> eyre::Result { - trace!("parsing: {}", display_path(path)); let body = file::read_to_string(path)?; - let des = toml::Deserializer::new(&body); + Self::from_str(&body, path) + } + + pub fn from_str(body: &str, path: &Path) -> eyre::Result { + trace!("parsing: {}", display_path(path)); + let des = toml::Deserializer::new(body); let mut rf: MiseToml = serde_ignored::deserialize(des, |p| { warn!("unknown field in {}: {p}", display_path(path)); })?;