diff --git a/docs/cli/edit.md b/docs/cli/edit.md index fcb4a42d0a..07a4f2e829 100644 --- a/docs/cli/edit.md +++ b/docs/cli/edit.md @@ -1,7 +1,7 @@ # `mise edit` -- **Usage**: `mise edit [-n --dry-run] [-t --tool-versions ] [PATH]` +- **Usage**: `mise edit [FLAGS] [PATH]` - **Source code**: [`src/cli/edit.rs`](https://github.com/jdx/mise/blob/main/src/cli/edit.rs) Edit mise.toml interactively @@ -14,6 +14,10 @@ Path to the config file to create ## Flags +### `-g --global` + +Edit the global config file (~/.config/mise/config.toml) + ### `-n --dry-run` Show what would be generated without writing to file @@ -27,6 +31,7 @@ Examples: ``` mise edit # edit mise.toml interactively mise edit .mise.toml # edit a specific file +mise edit -g # edit the global config file mise edit -y # skip interactive editor mise edit -n # preview without writing ``` diff --git a/docs/cli/generate.md b/docs/cli/generate.md index 821fe8235a..5e223e1114 100644 --- a/docs/cli/generate.md +++ b/docs/cli/generate.md @@ -10,7 +10,7 @@ Generate files for various tools/services ## Subcommands - [`mise generate bootstrap [FLAGS]`](/cli/generate/bootstrap.md) -- [`mise generate config [-n --dry-run] [-t --tool-versions ] [PATH]`](/cli/generate/config.md) +- [`mise generate config [FLAGS] [PATH]`](/cli/generate/config.md) - [`mise generate devcontainer [FLAGS]`](/cli/generate/devcontainer.md) - [`mise generate git-pre-commit [FLAGS]`](/cli/generate/git-pre-commit.md) - [`mise generate github-action [FLAGS]`](/cli/generate/github-action.md) diff --git a/docs/cli/generate/config.md b/docs/cli/generate/config.md index 2130aa5ddc..9799226f0e 100644 --- a/docs/cli/generate/config.md +++ b/docs/cli/generate/config.md @@ -1,7 +1,7 @@ # `mise generate config` -- **Usage**: `mise generate config [-n --dry-run] [-t --tool-versions ] [PATH]` +- **Usage**: `mise generate config [FLAGS] [PATH]` - **Source code**: [`src/cli/generate/config.rs`](https://github.com/jdx/mise/blob/main/src/cli/generate/config.rs) Generate a mise.toml file @@ -14,6 +14,10 @@ Path to the config file to create ## Flags +### `-g --global` + +Generate the global config file (~/.config/mise/config.toml) + ### `-n --dry-run` Show what would be generated without writing to file @@ -25,8 +29,9 @@ Path to a .tool-versions file to import tools from Examples: ``` -mise edit # edit mise.toml interactively -mise edit .mise.toml # edit a specific file -mise edit -y # skip interactive editor -mise edit -n # preview without writing +mise generate config # generate mise.toml interactively +mise generate config .mise.toml # generate a specific file +mise generate config -g # generate the global config file +mise generate config -y # skip interactive editor +mise generate config -n # preview without writing ``` diff --git a/docs/cli/index.md b/docs/cli/index.md index cd78522758..06ee921e14 100644 --- a/docs/cli/index.md +++ b/docs/cli/index.md @@ -106,7 +106,7 @@ Can also use `MISE_NO_HOOKS=1` - [`mise fmt [FLAGS]`](/cli/fmt.md) - [`mise generate `](/cli/generate.md) - [`mise generate bootstrap [FLAGS]`](/cli/generate/bootstrap.md) -- [`mise generate config [-n --dry-run] [-t --tool-versions ] [PATH]`](/cli/generate/config.md) +- [`mise generate config [FLAGS] [PATH]`](/cli/generate/config.md) - [`mise generate devcontainer [FLAGS]`](/cli/generate/devcontainer.md) - [`mise generate git-pre-commit [FLAGS]`](/cli/generate/git-pre-commit.md) - [`mise generate github-action [FLAGS]`](/cli/generate/github-action.md) @@ -114,7 +114,7 @@ Can also use `MISE_NO_HOOKS=1` - [`mise generate task-stubs [-d --dir ] [-m --mise-bin ]`](/cli/generate/task-stubs.md) - [`mise generate tool-stub [FLAGS] `](/cli/generate/tool-stub.md) - [`mise implode [-n --dry-run] [--config]`](/cli/implode.md) -- [`mise edit [-n --dry-run] [-t --tool-versions ] [PATH]`](/cli/edit.md) +- [`mise edit [FLAGS] [PATH]`](/cli/edit.md) - [`mise install [FLAGS] [TOOL@VERSION]…`](/cli/install.md) - [`mise install-into `](/cli/install-into.md) - [`mise latest [-i --installed] [--before ] `](/cli/latest.md) diff --git a/e2e/cli/test_edit_global b/e2e/cli/test_edit_global new file mode 100644 index 0000000000..247c73b59e --- /dev/null +++ b/e2e/cli/test_edit_global @@ -0,0 +1,29 @@ +#!/usr/bin/env bash + +# `mise edit --global` writes to the global config file path. + +export MISE_GLOBAL_CONFIG_FILE="$PWD/global-config.toml" + +assert_contains "mise edit --global --dry-run 2>&1" "global-config.toml" +assert_contains "mise edit -g -n 2>&1" "global-config.toml" + +# A positional path overrides --global regardless of argument order. +assert_contains "mise edit --global custom.toml --dry-run 2>&1" "custom.toml" +assert_not_contains "mise edit --global custom.toml --dry-run 2>&1" "global-config.toml" +assert_contains "mise edit custom.toml --global --dry-run 2>&1" "custom.toml" +assert_not_contains "mise edit custom.toml --global --dry-run 2>&1" "global-config.toml" + +# Without --global, the default config filename is used (regression guard). +assert_contains "mise edit --dry-run 2>&1" "mise.toml" +assert_not_contains "mise edit --dry-run 2>&1" "global-config.toml" + +# --tool-versions merges into the resolved target file, not the local mise.toml. +cat >preexisting.toml <.tool-versions <&1" 'go = "1.22"' +assert_contains "mise edit preexisting.toml --tool-versions .tool-versions --dry-run 2>&1" 'node = "22"' diff --git a/man/man1/mise.1 b/man/man1/mise.1 index 43ff59701c..a7c297cdfc 100644 --- a/man/man1/mise.1 +++ b/man/man1/mise.1 @@ -1039,6 +1039,9 @@ Generate a mise.toml file \fBOptions:\fR .PP .TP +\fB\-g, \-\-global\fR +Generate the global config file (~/.config/mise/config.toml) +.TP \fB\-n, \-\-dry\-run\fR Show what would be generated without writing to file .TP @@ -1281,6 +1284,9 @@ Edit mise.toml interactively \fBOptions:\fR .PP .TP +\fB\-g, \-\-global\fR +Edit the global config file (~/.config/mise/config.toml) +.TP \fB\-n, \-\-dry\-run\fR Show what would be generated without writing to file .TP diff --git a/mise.usage.kdl b/mise.usage.kdl index dd74da1901..6cb526f8e6 100644 --- a/mise.usage.kdl +++ b/mise.usage.kdl @@ -321,7 +321,8 @@ cmd generate subcommand_required=#true help="Generate files for various tools/se } } cmd config help="Generate a mise.toml file" { - after_long_help "Examples:\n\n $ mise edit # edit mise.toml interactively\n $ mise edit .mise.toml # edit a specific file\n $ mise edit -y # skip interactive editor\n $ mise edit -n # preview without writing\n" + after_long_help "Examples:\n\n $ mise generate config # generate mise.toml interactively\n $ mise generate config .mise.toml # generate a specific file\n $ mise generate config -g # generate the global config file\n $ mise generate config -y # skip interactive editor\n $ mise generate config -n # preview without writing\n" + flag "-g --global" help="Generate the global config file (~/.config/mise/config.toml)" flag "-n --dry-run" help="Show what would be generated without writing to file" flag "-t --tool-versions" help="Path to a .tool-versions file to import tools from" { arg @@ -482,7 +483,8 @@ cmd implode help="Removes mise CLI and all related data" { flag --config help="Also remove config directory" } cmd edit help="Edit mise.toml interactively" { - after_long_help "Examples:\n\n $ mise edit # edit mise.toml interactively\n $ mise edit .mise.toml # edit a specific file\n $ mise edit -y # skip interactive editor\n $ mise edit -n # preview without writing\n" + after_long_help "Examples:\n\n $ mise edit # edit mise.toml interactively\n $ mise edit .mise.toml # edit a specific file\n $ mise edit -g # edit the global config file\n $ mise edit -y # skip interactive editor\n $ mise edit -n # preview without writing\n" + flag "-g --global" help="Edit the global config file (~/.config/mise/config.toml)" flag "-n --dry-run" help="Show what would be generated without writing to file" flag "-t --tool-versions" help="Path to a .tool-versions file to import tools from" { arg diff --git a/src/cli/edit.rs b/src/cli/edit.rs index 836d39b446..0fdef2c82e 100644 --- a/src/cli/edit.rs +++ b/src/cli/edit.rs @@ -16,7 +16,7 @@ use crate::backend::backend_type::BackendType; use crate::cli::args::BackendArg; use crate::cli::version::VERSION_PLAIN; use crate::config::config_file; -use crate::config::{Config, Settings}; +use crate::config::{Config, Settings, global_config_path}; use crate::file::display_path; use crate::plugins::PluginType; use crate::registry::REGISTRY; @@ -122,6 +122,9 @@ impl BackendProvider for MiseBackendProvider { #[derive(Debug, clap::Args)] #[clap(verbatim_doc_comment, after_long_help = AFTER_LONG_HELP)] pub struct Edit { + /// Edit the global config file (~/.config/mise/config.toml) + #[clap(long, short = 'g')] + global: bool, /// Show what would be generated without writing to file #[clap(long, short = 'n')] dry_run: bool, @@ -143,15 +146,32 @@ struct DetectedTool { } impl Edit { + pub(crate) fn new( + global: bool, + dry_run: bool, + path: Option, + tool_versions: Option, + ) -> Self { + Self { + global, + dry_run, + path, + tool_versions, + } + } + pub async fn run(self) -> Result<()> { - let path = self - .path - .clone() - .unwrap_or_else(|| PathBuf::from(&*env::MISE_DEFAULT_CONFIG_FILENAME)); + let path = if let Some(path) = self.path.clone() { + path + } else if self.global { + global_config_path() + } else { + PathBuf::from(&*env::MISE_DEFAULT_CONFIG_FILENAME) + }; if let Some(tool_versions) = &self.tool_versions { // Import from .tool-versions file - let doc = self.tool_versions(tool_versions).await?; + let doc = self.tool_versions(tool_versions, &path).await?; if self.dry_run { info!("would write to {}", display_path(&path)); @@ -250,9 +270,8 @@ impl Edit { Ok(()) } - async fn tool_versions(&self, tool_versions: &Path) -> Result { - let to = - config_file::parse_or_init(&PathBuf::from(&*env::MISE_DEFAULT_CONFIG_FILENAME)).await?; + async fn tool_versions(&self, tool_versions: &Path, path: &Path) -> Result { + let to = config_file::parse_or_init(path).await?; let from = config_file::parse(tool_versions).await?; let tools = from.to_tool_request_set()?.tools; for (ba, tools) in tools { @@ -364,11 +383,12 @@ fn extract_version(tool: &str, path: &Path) -> Option { } } -pub static AFTER_LONG_HELP: &str = color_print::cstr!( +static AFTER_LONG_HELP: &str = color_print::cstr!( r#"Examples: $ mise edit # edit mise.toml interactively $ mise edit .mise.toml # edit a specific file + $ mise edit -g # edit the global config file $ mise edit -y # skip interactive editor $ mise edit -n # preview without writing "# diff --git a/src/cli/generate/config.rs b/src/cli/generate/config.rs index ad7c652f58..19a714b814 100644 --- a/src/cli/generate/config.rs +++ b/src/cli/generate/config.rs @@ -1,16 +1,43 @@ +use std::path::PathBuf; + +use clap::ValueHint; + use crate::Result; -use crate::cli::edit; +use crate::cli::edit::Edit; /// Generate a mise.toml file #[derive(Debug, clap::Args)] -#[clap(verbatim_doc_comment, after_long_help = edit::AFTER_LONG_HELP)] +#[clap(verbatim_doc_comment, after_long_help = AFTER_LONG_HELP)] pub struct Config { - #[clap(flatten)] - edit: edit::Edit, + /// Generate the global config file (~/.config/mise/config.toml) + #[clap(long, short = 'g')] + global: bool, + /// Show what would be generated without writing to file + #[clap(long, short = 'n')] + dry_run: bool, + /// Path to the config file to create + #[clap(verbatim_doc_comment, value_hint = ValueHint::FilePath)] + path: Option, + /// Path to a .tool-versions file to import tools from + #[clap(long, short, verbatim_doc_comment, value_hint = ValueHint::FilePath)] + tool_versions: Option, } impl Config { pub async fn run(self) -> Result<()> { - self.edit.run().await + Edit::new(self.global, self.dry_run, self.path, self.tool_versions) + .run() + .await } } + +static AFTER_LONG_HELP: &str = color_print::cstr!( + r#"Examples: + + $ mise generate config # generate mise.toml interactively + $ mise generate config .mise.toml # generate a specific file + $ mise generate config -g # generate the global config file + $ mise generate config -y # skip interactive editor + $ mise generate config -n # preview without writing +"# +); diff --git a/xtasks/fig/src/mise.ts b/xtasks/fig/src/mise.ts index 8ea529e863..0e82ffb3bd 100644 --- a/xtasks/fig/src/mise.ts +++ b/xtasks/fig/src/mise.ts @@ -1155,6 +1155,12 @@ const completionSpec: Fig.Spec = { name: "config", description: "Generate a mise.toml file", options: [ + { + name: ["-g", "--global"], + description: + "Generate the global config file (~/.config/mise/config.toml)", + isRepeatable: false, + }, { name: ["-n", "--dry-run"], description: @@ -1455,6 +1461,12 @@ const completionSpec: Fig.Spec = { name: "edit", description: "Edit mise.toml interactively", options: [ + { + name: ["-g", "--global"], + description: + "Edit the global config file (~/.config/mise/config.toml)", + isRepeatable: false, + }, { name: ["-n", "--dry-run"], description: "Show what would be generated without writing to file",