From 6a2fb889dbab335d0358dfa1f4dcd43804bb9cff Mon Sep 17 00:00:00 2001 From: jdx <216188+jdx@users.noreply.github.com> Date: Fri, 25 Oct 2024 13:18:56 -0500 Subject: [PATCH] fix: read choices from clap args (#136) Fixes #27 --- cli/tests/complete_word.rs | 6 + examples/mise.usage.kdl | 618 ++++++++++++++---- lib/src/docs/markdown/cmd.rs | 12 +- lib/src/docs/markdown/spec.rs | 8 +- .../markdown/templates/arg_template.md.tera | 10 +- .../markdown/templates/flag_template.md.tera | 10 +- lib/src/spec/arg.rs | 14 +- lib/src/spec/flag.rs | 22 +- 8 files changed, 535 insertions(+), 165 deletions(-) diff --git a/cli/tests/complete_word.rs b/cli/tests/complete_word.rs index 6235376..be57e6c 100644 --- a/cli/tests/complete_word.rs +++ b/cli/tests/complete_word.rs @@ -59,6 +59,12 @@ fn complete_word_kitchen_sink() { assert_cmd("kitchen-sink.usage.kdl", &["--", "--shell", ""]).stdout("bash\nzsh\nfish\n"); } +#[test] +fn complete_word_choices() { + assert_cmd("mise.usage.kdl", &["--", "env", "--shell", ""]) + .stdout("bash\nfish\nnu\nxonsh\nzsh\n"); +} + #[test] fn complete_word_shebang() { assert_cmd("example.sh", &["--", "-"]).stdout("--bar\n--defaulted\n--foo\n"); diff --git a/examples/mise.usage.kdl b/examples/mise.usage.kdl index 06d56e3..ed97c5a 100644 --- a/examples/mise.usage.kdl +++ b/examples/mise.usage.kdl @@ -13,9 +13,14 @@ usage "Usage: mise [OPTIONS] " flag "-C --cd" help="Change directory before running command" global=true { arg "" } +flag "-P --profile" help="Set the profile (environment)" global=true { + arg "" +} flag "--debug" help="Sets log level to debug" hide=true global=true flag "--log-level" help="Set the log output verbosity" hide=true global=true { - arg "" + arg "" { + choices "error" "warn" "info" "debug" "trace" + } } flag "-q --quiet" help="Suppress non-error messages" global=true flag "--trace" help="Sets log level to trace" hide=true global=true @@ -50,12 +55,18 @@ Customize status output with `status` settings."# $ execx($(mise activate xonsh)) "# flag "-s --shell" help="Shell type to generate the script for" hide=true { - arg "" + arg "" { + choices "bash" "fish" "nu" "xonsh" "zsh" + } } flag "--status" help="Show \"mise: @\" message when changing directories" hide=true - flag "--shims" help="Use shims instead of modifying PATH\nEffectively the same as:\n PATH=\"$HOME/.local/share/mise/shims:$PATH\"" + flag "--shims" help="Use shims instead of modifying PATH\nEffectively the same as:" { + long_help "Use shims instead of modifying PATH\nEffectively the same as:\n\n PATH=\"$HOME/.local/share/mise/shims:$PATH\"" + } flag "-q --quiet" help="Suppress non-error messages" - arg "[SHELL_TYPE]" help="Shell type to generate the script for" + arg "[SHELL_TYPE]" help="Shell type to generate the script for" { + choices "bash" "fish" "nu" "xonsh" "zsh" + } } cmd "alias" help="Manage aliases" { alias "a" @@ -69,6 +80,7 @@ cmd "alias" help="Manage aliases" { This is the contents of an alias. entry in ~/.config/mise/config.toml" after_long_help r"Examples: + $ mise alias get node lts-hydrogen 20.0.0 " @@ -83,8 +95,8 @@ These can come from user config or from plugins in `bin/list-aliases`. For user config, aliases are defined like the following in `~/.config/mise/config.toml`: - [alias.node] - lts = "20.0.0""# + [alias.node] + lts = "20.0.0""# after_long_help r"Examples: $ mise aliases @@ -122,6 +134,23 @@ This modifies the contents of ~/.config/mise/config.toml" cmd "asdf" hide=true help="[internal] simulates asdf for plugins that call \"asdf\" internally" { arg "[ARGS]..." help="all arguments" var=true } +cmd "backends" help="Manage backends" { + alias "b" + alias "backend" "backend-list" hide=true + cmd "ls" help="List built-in backends" { + alias "list" + after_long_help r"Examples: + + $ mise backends ls + cargo + go + npm + pipx + spm + ubi +" + } +} cmd "bin-paths" help="List all the active runtime bin paths" cmd "cache" help="Manage the mise cache" { long_help r"Manage the mise cache @@ -132,6 +161,16 @@ Run `mise cache` with no args to view the current cache directory." alias "clean" hide=true arg "[PLUGIN]..." help="Plugin(s) to clear cache for e.g.: node, python" var=true } + cmd "prune" help="Removes stale mise cache files" { + alias "p" + long_help r"Removes stale mise cache files + +By default, this command will remove files that have not been accessed in 30 days. +Change this with the MISE_CACHE_PRUNE_AGE environment variable." + flag "--dry-run" help="Just show what would be pruned" + flag "-v --verbose" help="Show pruned files" var=true count=true + arg "[PLUGIN]..." help="Plugin(s) to clear cache for e.g.: node, python" var=true + } } cmd "completion" help="Generate shell completions" { alias "complete" "completions" hide=true @@ -142,33 +181,71 @@ cmd "completion" help="Generate shell completions" { $ mise completion fish > ~/.config/fish/completions/mise.fish " flag "-s --shell" help="Shell type to generate completions for" hide=true { - arg "" + arg "" { + choices "bash" "fish" "zsh" + } } - flag "--usage" help="Always use usage for completions.\nCurrently, usage is the default for fish and bash but not zsh since it has a few quirks\nto work out first." { + flag "--usage" help="Always use usage for completions.\nCurrently, usage is the default for fish and bash but not zsh since it has a few quirks\nto work out first." hide=true { long_help "Always use usage for completions.\nCurrently, usage is the default for fish and bash but not zsh since it has a few quirks\nto work out first.\n\nThis requires the `usage` CLI to be installed.\nhttps://usage.jdx.dev" } - arg "[SHELL]" help="Shell type to generate completions for" + arg "[SHELL]" help="Shell type to generate completions for" { + choices "bash" "fish" "zsh" + } } -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" { + flag "-J --json" help="Output in JSON format" + 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" + flag "-J --json" help="Output in JSON format" } - 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 "" { + choices "string" "integer" "float" "bool" + } + } + 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" { @@ -177,16 +254,17 @@ cmd "current" help="Shows current active and installed runtime versions" { This is similar to `mise ls --current`, but this only shows the runtime and/or version. It's designed to fit into scripts more easily." after_long_help r"Examples: + # outputs `.tool-versions` compatible format $ mise current python 3.11.0 3.10.0 shfmt 3.6.0 shellcheck 0.9.0 node 20.0.0 - + $ mise current node 20.0.0 - + # can output multiple versions $ mise current python 3.11.0 3.10.0 @@ -199,10 +277,7 @@ cmd "deactivate" help="Disable mise for current shell session" { This can be used to temporarily disable mise in a shell session." after_long_help r"Examples: - $ mise deactivate bash - $ mise deactivate zsh - $ mise deactivate fish - $ execx($(mise deactivate xonsh)) + $ mise deactivate " } cmd "direnv" help="Output direnv function to use mise inside direnv" { @@ -254,7 +329,9 @@ use this if you have `mise activate` in your shell rc file." "# flag "-J --json" help="Output in JSON format" flag "-s --shell" help="Shell type to generate environment variables for" { - arg "" + arg "" { + choices "bash" "fish" "nu" "xonsh" "zsh" + } } arg "[TOOL@VERSION]..." help="Tool(s) to use" var=true } @@ -264,8 +341,8 @@ cmd "exec" help="Execute a command with tool(s) set" { use this to avoid modifying the shell session or running ad-hoc commands with mise tools set. -Tools will be loaded from .mise.toml/.tool-versions, though they can be overridden with args -Note that only the plugin specified will be overridden, so if a `.tool-versions` file +Tools will be loaded from mise.toml, though they can be overridden with args +Note that only the plugin specified will be overridden, so if a `mise.toml` file includes "node 20" but you run `mise exec python@3.11`; it will still load node@20. The "--" separates runtimes from the commands to pass along to the subprocess."# @@ -290,13 +367,75 @@ The "--" separates runtimes from the commands to pass along to the subprocess."# arg "[TOOL@VERSION]..." help="Tool(s) to start e.g.: node@20 python@3.10" var=true arg "[COMMAND]..." help="Command string to execute (same as --command)" var=true } +cmd "generate" subcommand_required=true help="[experimental] Generate files for various tools/services" { + alias "g" + cmd "git-pre-commit" help="[experimental] Generate a git pre-commit hook" { + alias "pre-commit" + long_help r"[experimental] Generate a git pre-commit hook + +This command generates a git pre-commit hook that runs a mise task like `mise run pre-commit` +when you commit changes to your repository." + after_long_help r#"Examples: + + $ mise generate git-pre-commit --write --task=pre-commit + $ git commit -m "feat: add new feature" # runs `mise run pre-commit` +"# + flag "--hook" help="Which hook to generate (saves to .git/hooks/$hook)" { + arg "" + } + flag "-t --task" help="The task to run when the pre-commit hook is triggered" { + arg "" + } + flag "-w --write" help="write to .git/hooks/pre-commit and make it executable" + } + cmd "github-action" help="[experimental] Generate a GitHub Action workflow file" { + long_help r"[experimental] Generate a GitHub Action workflow file + +This command generates a GitHub Action workflow file that runs a mise task like `mise run ci` +when you push changes to your repository." + after_long_help r#"Examples: + + $ mise generate github-action --write --task=ci + $ git commit -m "feat: add new feature" + $ git push # runs `mise run ci` on GitHub +"# + flag "-n --name" help="the name of the workflow to generate" { + arg "" + } + flag "-t --task" help="The task to run when the workflow is triggered" { + arg "" + } + flag "-w --write" help="write to .github/workflows/$name.yml" + } + cmd "task-docs" help="[experimental] Generate documentation for tasks in a project" { + after_long_help r"Examples: + + $ mise generate task-docs +" + flag "-I --index" help="write only an index of tasks, intended for use with `--multi`" + flag "-i --inject" help="inserts the documentation into an existing file" { + long_help "inserts the documentation into an existing file\n\nThis will look for a special comment, , and replace it with the generated documentation.\nIt will replace everything between the comment and the next comment, so it can be\nrun multiple times on the same file to update the documentation." + } + flag "-m --multi" help="render each task as a separate document, requires `--output` to be a directory" + flag "-o --output" help="writes the generated docs to a file/directory" { + arg "" + } + flag "-r --root" help="root directory to search for tasks" { + arg "" + } + flag "-s --style" { + arg "