diff --git a/.github/workflows/release-plz.yml b/.github/workflows/release-plz.yml index f1ce91f804..e7601bc6d8 100644 --- a/.github/workflows/release-plz.yml +++ b/.github/workflows/release-plz.yml @@ -37,6 +37,7 @@ jobs: with: { toolchain: nightly, components: rustfmt } - uses: actions-rust-lang/setup-rust-toolchain@v1 - run: mkdir -p "$HOME/bin" && echo "$HOME/bin" >> "$GITHUB_PATH" + - run: npm i - run: cargo build --all-features && cp target/debug/mise "$HOME"/bin - uses: actions/cache/restore@v4 with: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7fff11a37e..969fe1aaa1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -50,6 +50,7 @@ jobs: - run: | cargo build --all-features echo "$PWD/target/debug" >> "$GITHUB_PATH" + - run: npm i - run: mise install - run: mise x -- cargo nextest run --all-features - run: cargo deny check @@ -151,6 +152,7 @@ jobs: pipx \ python3-venv \ zsh + - run: npm i - run: | mkdir -p "$HOME/.local/bin" ln -s "$(which fdfind)" "$HOME/.local/bin/fd" diff --git a/.markdownlintignore b/.markdownlintignore index 1342a141e3..a08320bd7e 100644 --- a/.markdownlintignore +++ b/.markdownlintignore @@ -2,3 +2,4 @@ registry/ target/ CHANGELOG.md docs/node_modules/ +node_modules/ diff --git a/.mise.toml b/.mise.toml index 3bde574c80..ed9290a32c 100644 --- a/.mise.toml +++ b/.mise.toml @@ -22,6 +22,7 @@ jq = "latest" "npm:prettier" = "3" direnv = "latest" actionlint = "latest" +"pipx:toml-sort" = "latest" #python = { version = "latest", virtualenv = "{{env.HOME}}/.cache/venv" } #ruby = "3.1" diff --git a/.mise/tasks/lint-fix b/.mise/tasks/lint-fix index c62e1e3f76..bf62093289 100755 --- a/.mise/tasks/lint-fix +++ b/.mise/tasks/lint-fix @@ -12,6 +12,7 @@ shfmt -w -i 2 -ci -bn "${scripts_dirs[@]}" prettier -w $(git ls-files '*.yml' '*.yaml') markdownlint --fix . actionlint +toml-sort -i settings.toml --spaces-indent-inline-array 4 cat >rustfmt.toml <" || type === "HashSet" || type === "Vec") { + type = 'string[]'; + } else { + throw new Error(`Unknown type: ${type}`); + } + if (!props.description) { + console.error(`Missing description for ${key}`); + process.exit(1); + } + const ele = { + default: props.default, + description: props.description, + deprecated: props.deprecated, + type, + }; + if (props.enum) { + ele.enum = props.enum.map((e) => e[0]); + } + if (type === 'string[]') { + ele.type = 'array'; + ele.items = { + type: 'string', + }; + } + return ele; +} + +for (const key in doc) { + const props = doc[key]; + if (props.type) { + settings[key] = buildElement(key, props); + } else { + for (const subkey in props) { + settings[key] = settings[key] || { + additionalProperties: false, + description: props.description, + properties: {}, + }; + settings[key].properties[subkey] = buildElement(`${key}.${subkey}`, props[subkey]); + } + } +} + +const schema_tmpl = Handlebars.compile(fs.readFileSync('schema/mise.json.hbs', 'utf-8')); +fs.writeFileSync('schema/mise.json.tmp', schema_tmpl({ + settings_json: new Handlebars.SafeString(JSON.stringify(settings, null, 2)), +})); + +child_process.execSync('jq . < schema/mise.json.tmp > schema/mise.json'); +fs.unlinkSync('schema/mise.json.tmp'); diff --git a/Cargo.toml b/Cargo.toml index f6db760024..a2562b620d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,15 +12,16 @@ license = "MIT" keywords = ["mise"] categories = ["command-line-utilities"] include = [ - "src/**/*.rs", - "src/plugins/core/assets/**", - "src/assets/**", - "/completions/*", "/Cargo.lock", "/LICENSE", "/README.md", "/build.rs", + "/completions/*", + "/settings.toml", "/zipsign.pub", + "src/**/*.rs", + "src/assets/**", + "src/plugins/core/assets/**", ] rust-version = "1.76.0" build = "build.rs" @@ -69,7 +70,7 @@ heck = "0.5" home = "0.5.9" humantime = "2" indenter = "0.3.3" -indexmap = { version = "2.2.6", features = ["serde"] } +indexmap = { version = "2", features = ["serde"] } indicatif = { version = "0.17.8", features = ["default", "improved_unicode"] } indoc = "2.0.5" itertools = "0.13" @@ -111,8 +112,8 @@ tokio = { version = "1.37.0", features = [ "rt", "time", ] } -toml = { version = "0.8.12", features = ["parse"] } -toml_edit = { version = "0.22.12", features = ["parse"] } +toml = { version = "0.8", features = ["parse"] } +toml_edit = { version = "0.22", features = ["parse"] } url = "2.5.0" usage-lib = { version = "0.3", features = ["clap"] } versions = { version = "6.2.0", features = ["serde"] } @@ -141,6 +142,9 @@ sevenz-rust = "0.6" [build-dependencies] built = { version = "0.7", features = ["chrono", "git2"] } cfg_aliases = "0.2" +heck = "0.5" +toml = "0.8" +indexmap = "2" [dev-dependencies] assert_cmd = "2.0.14" diff --git a/build.rs b/build.rs index 53bb2590bf..44ab7c93f2 100644 --- a/build.rs +++ b/build.rs @@ -1,7 +1,96 @@ +use heck::ToUpperCamelCase; +use indexmap::IndexMap; +use std::path::Path; +use std::{env, fs}; + fn main() { cfg_aliases::cfg_aliases! { vfox: { any(feature = "vfox", target_os = "windows") }, asdf: { any(feature = "asdf", not(target_os = "windows")) }, } built::write_built_file().expect("Failed to acquire build-time information"); + + codegen_settings(); +} + +fn codegen_settings() { + let out_dir = env::var_os("OUT_DIR").unwrap(); + let dest_path = Path::new(&out_dir).join("settings.rs"); + let mut lines = vec![r#" +#[derive(Config, Default, Debug, Clone, Serialize)] +#[config(partial_attr(derive(Clone, Serialize, Default)))] +pub struct Settings {"# + .to_string()]; + + let settings: toml::Table = fs::read_to_string("settings.toml") + .unwrap() + .parse() + .unwrap(); + let props_to_code = |key: &str, props: &toml::Value| { + let mut lines = vec![]; + let props = props.as_table().unwrap(); + if let Some(description) = props.get("description") { + lines.push(format!(" /// {}", description.as_str().unwrap())); + } + if let Some(type_) = props.get("type") { + let mut opts = IndexMap::new(); + if let Some(env) = props.get("env") { + opts.insert("env".to_string(), env.to_string()); + } + if let Some(default) = props.get("default") { + opts.insert("default".to_string(), default.to_string()); + } else if type_.as_str().unwrap() == "bool" { + opts.insert("default".to_string(), "false".to_string()); + } + if let Some(parse_env) = props.get("parse_env") { + opts.insert( + "parse_env".to_string(), + parse_env.as_str().unwrap().to_string(), + ); + } + dbg!(&opts); + lines.push(format!( + " #[config({})]", + opts.iter() + .map(|(k, v)| format!("{k} = {v}")) + .collect::>() + .join(", ") + )); + lines.push(format!(" pub {}: {},", key, type_.as_str().unwrap())); + } else { + lines.push(" #[config(nested)]".to_string()); + lines.push(format!( + " pub {}: Settings{},", + key, + key.to_upper_camel_case() + )); + } + lines.join("\n") + }; + for (key, props) in &settings { + lines.push(props_to_code(key, props)); + } + lines.push("}".to_string()); + + let nested_settings = settings + .iter() + .filter(|(_, v)| !v.as_table().unwrap().contains_key("type")) + .collect::>(); + for (child, props) in nested_settings { + lines.push(format!( + r#"#[derive(Config, Default, Debug, Clone, Serialize)] +#[config(partial_attr(derive(Clone, Serialize, Default)))] +#[config(partial_attr(serde(deny_unknown_fields)))] +pub struct Settings{name} {{ +"#, + name = child.to_upper_camel_case() + )); + + for (key, props) in props.as_table().unwrap() { + lines.push(props_to_code(key, props)); + } + lines.push("}".to_string()); + } + + fs::write(&dest_path, lines.join("\n")).unwrap(); } diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 75df013b9f..9d5f5f9767 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -30,6 +30,7 @@ export default defineConfig({ {text: 'IDE Integration', link: '/ide-integration'}, {text: 'Paranoid', link: '/paranoid'}, {text: 'Registry', link: '/registry'}, + {text: 'Settings', link: '/settings'}, {text: 'Plugins', link: '/plugins'}, {text: 'Coming from rtx', link: '/rtx'}, {text: 'Team', link: '/team'}, diff --git a/docs/configuration.md b/docs/configuration.md index b602c64b68..de3d586efc 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -245,157 +245,7 @@ version files since they're version files not specific to asdf/mise and can be u ## Settings -The following is a list of all of mise's settings. These can be set via `mise settings set`, -by directly modifying `~/.config/mise/config.toml` or local config, or via environment variables. - -Some of them also can be set via global CLI flags. - -### `activate_aggressive` - -* Type: `bool` -* Env: `MISE_ACTIVATE_AGGRESSIVE` -* Default: `false` - -Pushes tools' bin-paths to the front of PATH instead of allowing modifications of PATH after -activation to take precedence. - -For example, if you have the following in your `.mise.toml`: - -```toml -[tools] -node = '20' -python = '3.12' -``` - -But you also have this in your `~/.zshrc`: - -```sh -eval "$(mise activate zsh)" -PATH="/some/other/python:$PATH" -``` - -What will happen is `/some/other/python` will be used instead of the python installed by mise. This -means -you typically want to put `mise activate` at the end of your shell config so nothing overrides it. - -If you want to always use the mise versions of tools despite what is in your shell config, set this -to `true`. -In that case, using this example again, `/some/other/python` will be after mise's python in PATH. - -### `asdf` - -* Type: `bool` -* Env: `MISE_ASDF` -* Default: `true` - -Use asdf as a default plugin backend. This means running something like `mise use cmake` will -default to using an asdf plugin for cmake. - -### `asdf_compat` - -* Type: `bool` -* Env: `MISE_ASDF_COMPAT` -* Default: `false` - -Only output `.tool-versions` files in `mise local|global` which will be usable by asdf. -This disables mise functionality that would otherwise make these files incompatible with asdf such -as non-pinned versions. - -This will also change the default global tool config to be `~/.tool-versions` instead -of `~/.config/mise/config.toml`. - -### `cache_prune_age` - -* Type: `string` -* Env: `MISE_CACHE_PRUNE_AGE` -* Default: `30d` - -The age of the cache before it is considered stale. mise will occasionally delete cache files which -have not been accessed in this amount of time. - -Set to `0` to keep cache files indefinitely. - -### `disable_tools` - -* Type: `string[]` (comma-delimited) -* Env: `MISE_DISABLE_TOOLS` -* Default: `[]` - -Disables the specified tools. Separate with `,`. Generally used for core plugins but works with any -tool. - -### `libgit2` - -* Type: `bool` -* Env: `MISE_LIBGIT2` -* Default: `true` - -Use libgit2 for git operations. This is generally faster but may not be as compatible if the -system's libgit2 is not the same version as the one used by mise. - -### `paranoid` - -* Type: `bool` -* Env: `MISE_PARANOID` -* Default: `false` - -Enables extra-secure behavior. See [Paranoid](/paranoid). - -### `status.missing_tools` - -* Type: `enum` -* Env: `MISE_STATUS_MISSING_TOOLS` -* Default: `if_other_versions_installed` - -| Choice | Description | -|-----------------------------------------|----------------------------------------------------------------------------| -| `if_other_versions_installed` [default] | Show the warning only when the tool has at least 1 other version installed | -| `always` | Always show the warning | -| `never` | Never show the warning | - -Show a warning if tools are not installed when entering a directory with a `.mise.toml` file. - -::: tip -Disable tools with [`disable_tools`](#disable_tools). -::: - -### `status.show_env` - -* Type: `bool` -* Env: `MISE_STATUS_SHOW_ENV` -* Default: `false` - -Show configured env vars when entering a directory with a `.mise.toml` file. - -### `status.show_tools` - -* Type: `bool` -* Env: `MISE_STATUS_SHOW_TOOLS` -* Default: `false` - -Show active tools when entering a directory with a `.mise.toml` file. - -### `use_versions_host` - -* Type: `bool` -* Env: `MISE_USE_VERSIONS_HOST` -* Default: `true` - -Set to "false" to disable using [mise-versions](https://mise-versions.jdx.dev) as -a quick way for mise to query for new versions. This host regularly grabs all the -latest versions of core and community plugins. It's faster than running a plugin's -`list-all` command and gets around GitHub rate limiting problems when using it. - -See [FAQ](/faq#new-version-of-a-tool-is-not-available) for more information. - -### `vfox` - -* Type: `bool` -* Env: `MISE_VFOX` -* Default: `false` - -Use vfox as a default plugin backend. This means running something like `mise use cmake` will -default to using an vfox plugin for cmake. +See [Settings](/settings) for the full list of settings. ## Environment variables @@ -464,19 +314,6 @@ Uses [dotenvy](https://crates.io/crates/dotenvy) under the hood. Set the version for a runtime. For example, `MISE_NODE_VERSION=20` will use regardless of what is set in `.tool-versions`/`.mise.toml`. -### `MISE_LEGACY_VERSION_FILE=1` - -Plugins can read the versions files used by other version managers (if enabled by the plugin) -for example, `.nvmrc` in the case of node's nvm. See [legacy version files](#legacy-version-files) -for more -information. - -Set to "0" to disable legacy version file parsing. - -### `MISE_LEGACY_VERSION_FILE_DISABLE_TOOLS=node,python` - -Disable legacy version file parsing for specific tools. Separate with `,`. - ### `MISE_USE_TOML=0` Set to `1` to default to using `.mise.toml` in `mise local` instead of `.tool-versions` for @@ -506,22 +343,6 @@ Output logs to a file. Same as `MISE_LOG_LEVEL` but for the log _file_ output level. This is useful if you want to store the logs but not have them litter your display. -### `MISE_ALWAYS_KEEP_DOWNLOAD=1` - -Set to "1" to always keep the downloaded archive. By default it is deleted after install. - -### `MISE_ALWAYS_KEEP_INSTALL=1` - -Set to "1" to always keep the install directory. By default it is deleted on failure. - -### `MISE_VERBOSE=1` - -This shows the installation output during `mise install` and `mise plugin install`. -This should likely be merged so it behaves the same as `MISE_DEBUG=1` and we don't have -2 configuration for the same thing, but for now it is its own config. - -Equivalent to `MISE_LOG_LEVEL=debug`. - ### `MISE_QUIET=1` Equivalent to `MISE_LOG_LEVEL=warn`. @@ -530,10 +351,6 @@ Equivalent to `MISE_LOG_LEVEL=warn`. Set the timeout for http requests in seconds. The default is `30`. -### `MISE_JOBS=1` - -Set the number plugins or runtimes to install in parallel. The default is `4`. - ### `MISE_RAW=1` Set to "1" to directly pipe plugin scripts to stdin/stdout/stderr. By default stdin is disabled @@ -542,77 +359,6 @@ plugin accepts input or otherwise does not seem to be installing correctly. Sets `MISE_JOBS=1` because only 1 plugin script can be executed at a time. -### `MISE_SHORTHANDS_FILE=~/.config/mise/shorthands.toml` - -Use a custom file for the shorthand aliases. This is useful if you want to share plugins within -an organization. - -Shorthands make it so when a user runs something like `mise install elixir` mise will -automatically install the [asdf-elixir](https://github.com/asdf-vm/asdf-elixir) plugin. By -default, it uses the shorthands in -[`src/default_shorthands.rs`](https://github.com/jdx/mise/blob/main/src/default_shorthands.rs). - -The file should be in this toml format: - -```toml -elixir = "https://github.com/my-org/mise-elixir.git" -node = "https://github.com/my-org/mise-node.git" -``` - -### `MISE_DISABLE_DEFAULT_SHORTHANDS=1` - -Disables the shorthand aliases for installing plugins. You will have to specify full URLs when -installing plugins, e.g.: `mise plugin install node https://github.com/asdf-vm/asdf-node.git` - -### `MISE_YES=1` - -This will automatically answer yes or no to prompts. This is useful for scripting. - -### `MISE_NOT_FOUND_AUTO_INSTALL=true` - -Set to false to disable the "command not found" handler to autoinstall missing tool versions. -Disable this -if experiencing strange behavior in your shell when a command is not found—but please submit a -ticket to -help diagnose problems. - -### `MISE_TASK_OUTPUT=prefix` - -This controls the output of `mise run`. It can be one of: - -- `prefix` - (default if jobs > 1) print by line with the prefix of the task name -- `interleave` - (default if jobs == 1) display stdout/stderr as it comes in - -### `MISE_EXPERIMENTAL=1` - -Enables experimental features. I generally will publish new features under -this config which needs to be enabled to use them. While a feature is marked -as "experimental" its behavior may change or even disappear in any release. - -The idea is experimental features can be iterated on this way so we can get -the behavior right, but once that label goes away you shouldn't expect things -to change without a proper deprecation—and even then it's unlikely. - -Also, I very often will use experimental as a beta flag as well. New -functionality that I want to test with a smaller subset of users I will often -push out under experimental mode even if it's not related to an experimental -feature. - -If you'd like to help me out, consider enabling it even if you don't have -a particular feature you'd like to try. Also, if something isn't working -right, try disabling it if you can. - -### `MISE_ALL_COMPILE=1` - -Default: false unless running NixOS or Alpine (let me know if others should be added) - -Do not use precompiled binaries for all languages. Useful if running on a Linux distribution -like Alpine that does not use glibc and therefore likely won't be able to run precompiled binaries. - -Note that this needs to be setup for each language. File a ticket if you notice a language that is -not -working with this config. - ### `MISE_FISH_AUTO_ACTIVATE=1` Configures the vendor_conf.d script for fish shell to automatically activate. diff --git a/docs/contributing.md b/docs/contributing.md index ccf95bb44a..fcc65bfa96 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -135,16 +135,7 @@ mise run render ## Adding a new setting -Settings require some boilerplate. The easiest way to find everything needed to add a new -setting is to look at the git history for [`src/config/settings.rs`](https://github.com/jdx/mise/commits/main/src/config/settings.rs). -Find a recent commit adding a new setting to find everything required. Some of the requirements are: - -* Setting added to [`src/config/settings.rs`](https://github.com/jdx/mise/commits/main/src/config/settings.rs). -* Documentation added to [`docs/configruation.md`](https://github.com/jdx/mise/commits/main/src/docs/configuration.md). -* JSON Schema added to [`schema/mise.json`](https://github.com/jdx/mise/commits/main/schema/mise.json). -* Test snapshots updated `mise run snapshots` (this updates the test snapshots so you don't need to do it manually). - -Note that code changes may alter this list so the best way to find the current requirements is to look at a recent commit. +To add a new setting, add it to [`settings.toml`](https://github.com/jdx/mise/blob/main/settings.toml) in the root of the project and run `mise run render` to update the codebase. ## Testing packaging diff --git a/docs/package.json b/docs/package.json index 8f907e44f9..401f1edf23 100644 --- a/docs/package.json +++ b/docs/package.json @@ -9,5 +9,10 @@ "docs:dev": "vitepress dev", "docs:build": "vitepress build", "docs:preview": "vitepress preview" + }, + "dependencies": { + "@types/markdown-it": "^14.1.2", + "markdown-it": "^14.1.0", + "toml": "^3.0.0" } } diff --git a/docs/settings.data.ts b/docs/settings.data.ts new file mode 100644 index 0000000000..5b672cd40d --- /dev/null +++ b/docs/settings.data.ts @@ -0,0 +1,76 @@ +import * as fs from 'node:fs'; +import * as toml from 'toml'; +import markdownit from 'markdown-it' + +const md = markdownit(); + +export default { + watch: ['./settings.toml'], + load() { + const settings = {}; + const raw = fs.readFileSync('./settings.toml', 'utf-8'); + const doc = toml.parse(raw); + + function buildElement(key, props) { + let type = props.type; + let optional = false; + if (type.startsWith('Option<')) { + type = type.slice(7, -1); + optional = true; + } + type = type.replaceAll('PathBuf', 'String'); + let default_ = props.default; + if (default_ === undefined && type === 'bool' && !optional) { + default_ = false; + } + if (default_ === undefined && optional) { + default_ = "None"; + } + if (type === 'u64' || type === 'usize') { + type = 'integer'; + } else if (type === 'String') { + type = 'string'; + } else if (type === "BTreeSet" || type === "HashSet" || type === "Vec") { + type = 'string[]'; + } + // } else if (type === "String" || type === "PathBuf") { + // type = 'string'; + // } else if (type === "usize" || type === "u64") { + // type = 'number'; + // } else { + // throw new Error(`Unknown type: ${type}`); + // } + const ele = { + key, + default: default_, + docs: md.render(props.docs ?? props.description), + deprecated: props.deprecated, + enum: props.enum, + env: props.env, + optional, + type, + }; + return ele; + } + + for (const key in doc) { + const props = doc[key]; + if (props.hide) continue; + if (props.type) { + settings[key] = buildElement(key, props); + } else { + for (const subkey in props) { + if (props.hide) continue; + settings[key] = settings[key] || { + key, + additionalProperties: false, + description: props.description, + settings: [], + }; + settings[key].settings.push(buildElement(`${key}.${subkey}`, props[subkey])); + } + } + } + return Object.values(settings); + } +} diff --git a/docs/settings.md b/docs/settings.md new file mode 100644 index 0000000000..371a73ae7c --- /dev/null +++ b/docs/settings.md @@ -0,0 +1,59 @@ +# Settings + + + +The following is a list of all of mise's settings. These can be set via `mise settings set`, +by directly modifying `~/.config/mise/config.toml` or local config, or via environment variables. + +Some of them also can be set via global CLI flags. + +
+

+ {{ setting.key }} + deprecated +

+ +
    +
  • + Type: {{ setting.type }} + (optional) +
  • +
  • Env: {{ setting.env }}
  • +
  • Default: {{ setting.default }}
  • +
  • Choices: +
      +
    • {{ choice[0] }} – {{choice[1]}}
    • +
    +
  • +
+ + +
+ +
+

+ {{ child.key }} +

+
+

+ {{ setting.key }} + deprecated +

+
    +
  • + Type: {{ setting.type }} + (optional) +
  • +
  • Env: {{ setting.env }}
  • +
  • Default: {{ setting.default }}
  • +
  • Choices: +
      +
    • {{ choice[0] }} – {{choice[1]}}
    • +
    +
  • +
+ +
+
diff --git a/docs/settings.toml b/docs/settings.toml new file mode 120000 index 0000000000..71746d3b6a --- /dev/null +++ b/docs/settings.toml @@ -0,0 +1 @@ +../settings.toml \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000000..8e4c9cc335 --- /dev/null +++ b/package.json @@ -0,0 +1,20 @@ +{ + "name": "mise", + "version": "1.0.0", + "description": "", + "main": "index.js", + "directories": { + "doc": "docs", + "man": "man", + "test": "tests" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "handlebars": "^4.7.8", + "toml": "^3.0.0" + } +} diff --git a/schema/mise.json b/schema/mise.json index 8050534589..735bec1a02 100644 --- a/schema/mise.json +++ b/schema/mise.json @@ -1,4 +1,8 @@ { + "$id": "https://mise.jdx.dev/schema/mise.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "mise", + "type": "object", "$defs": { "env": { "additionalProperties": { @@ -111,7 +115,7 @@ "settings": { "properties": { "activate_aggressive": { - "description": "push tools to the front of PATH instead of allowing modifications of PATH after activation to take precedence", + "description": "Pushes tools' bin-paths to the front of PATH instead of allowing modifications of PATH after activation to take precedence.", "type": "boolean" }, "all_compile": { @@ -137,255 +141,306 @@ }, "cache_prune_age": { "default": "30d", - "description": "age to keep cached files, e.g.: 30d", + "description": "Delete files in cache that have not been accessed in this duration", "type": "string" }, "cargo_binstall": { "default": true, - "description": "use cargo-binstall to install rust tools if available", + "description": "Use cargo-binstall instead of cargo install if available", + "type": "boolean" + }, + "cd": { + "description": "Path to change to after launching mise", + "type": "string" + }, + "ci": { + "description": "Set to true if running in a CI environment", "type": "boolean" }, "color": { "default": true, - "description": "colorize output", + "description": "Use color in mise terminal output", + "type": "boolean" + }, + "debug": { + "description": "Sets log level to debug", "type": "boolean" }, "disable_default_shorthands": { - "description": "disables built-in shorthands", + "description": "Disables built-in shorthands to asdf/vfox plugins", "type": "boolean" }, "disable_hints": { - "description": "disable hints for mise commands", + "default": [], + "description": "Turns off helpful hints when using different mise features", + "type": "array", "items": { - "description": "command name or * for all commands", "type": "string" - }, - "type": "array" + } }, "disable_tools": { - "description": "tools that should not be used", + "default": [], + "description": "Tools defined in mise.toml that should be ignored", + "type": "array", "items": { - "description": "tool name", "type": "string" - }, - "type": "array" + } + }, + "env_file": { + "description": "Path to a file containing environment variables.", + "type": "string" }, "experimental": { - "description": "enable experimental features", + "description": "Enable experimental mise features which are incomplete or unstable—breakings changes may occur", "type": "boolean" }, "go_default_packages_file": { - "description": "path to file containing default go packages", + "default": "~/.default-go-packages", + "description": "Path to a file containing default go packages to install when installing go", "type": "string" }, "go_download_mirror": { - "description": "url to use as a mirror for go downloads", + "default": "https://dl.google.com/go", + "description": "Mirror to download go sdk tarballs from.", "type": "string" }, "go_repo": { - "description": "url to use as a mirror for go modules", + "default": "https://github.com/golang/go", + "description": "URL to fetch go from.", "type": "string" }, + "go_set_gobin": { + "description": "Changes where `go install` installs binaries to.", + "type": "boolean" + }, "go_set_gopath": { - "description": "set GOPATH to the directory containing the go tool", + "description": "[deprecated] Set to true to set GOPATH=~/.local/share/mise/installs/go/.../packages.", + "deprecated": "Use env._go.set_goroot instead.", "type": "boolean" }, "go_set_goroot": { - "description": "set GOROOT to the directory containing the go tool", + "default": true, + "description": "Sets GOROOT=~/.local/share/mise/installs/go/.../.", "type": "boolean" }, "go_skip_checksum": { - "description": "skip checksum verification for go downloads", + "description": "Set to true to skip checksum verification when downloading go sdk tarballs.", "type": "boolean" }, "http_timeout": { - "description": "timeout for http requests in seconds", - "type": "integer" + "default": 30, + "description": "Timeout in seconds for all HTTP requests in mise.", + "type": "number" }, "jobs": { - "description": "number of tools to install in parallel, default is 4", - "type": "integer" + "default": 4, + "description": "How many jobs to run concurrently such as tool installs.", + "type": "number" }, "legacy_version_file": { - "description": "should mise parse legacy version files (e.g. .node-version)", + "default": true, + "description": "Set to false to disable the idiomatic version files such as .node-version, .ruby-version, etc.", "type": "boolean" }, "legacy_version_file_disable_tools": { - "description": "tools that should not have their legacy version files parsed", + "default": [], + "description": "Specific tools to disable idiomatic version files for.", + "type": "array", "items": { - "description": "tool name", "type": "string" - }, - "type": "array" + } }, "libgit2": { "default": true, - "description": "use libgit2 for git operations", + "description": "Use libgit2 for git operations, set to false to shell out to git.", "type": "boolean" }, + "log_level": { + "default": "info", + "description": "Show more/less output.", + "type": "string", + "enum": [ + "trace", + "debug", + "info", + "warn", + "error" + ] + }, "node": { "additionalProperties": false, - "description": "settings specific to node", "properties": { "compile": { - "description": "do not use precompiled binaries for node", + "description": "Compile node from source.", "type": "boolean" }, "flavor": { - "description": "node flavor to use, generally used for unofficial builds", + "description": "Install a specific node flavor like glibc-217 or musl. Use with unofficial node build repo.", "type": "string" }, "mirror_url": { - "default": "https://nodejs.org/dist", - "description": "url to use as a mirror for node downloads", + "description": "Mirror to download node tarballs from.", "type": "string" } - }, - "type": "object" - }, - "node_compile": { - "description": "do not use precompiled binaries for node", - "type": "boolean" + } }, "not_found_auto_install": { "default": true, - "description": "adds a shell hook to `mise activate` and shims to automatically install tools when they need to be installed", + "description": "Set to false to disable the \"command not found\" handler to autoinstall missing tool versions.", "type": "boolean" }, "paranoid": { - "description": "extra-security mode, see https://mise.jdx.dev/paranoid.html for details", + "description": "Enables extra-secure behavior.", "type": "boolean" }, "pipx_uvx": { - "default": false, - "description": "use uv to install python tools if available", + "description": "Use uvx instead of pipx if uv is installed and on PATH.", "type": "boolean" }, "plugin_autoupdate_last_check_duration": { - "description": "how often to check for plugin updates", + "default": "7d", + "description": "How long to wait before updating plugins automatically (note this isn't currently implemented).", "type": "string" }, "python_compile": { - "description": "do not use precompiled binaries for python", + "description": "If true, compile python from source. If false, use precompiled binaries. If not set, use precompiled binaries if available.", "type": "boolean" }, "python_default_packages_file": { - "description": "path to file containing default python packages", + "description": "Path to a file containing default python packages to install when installing python.", + "type": "string" + }, + "python_patch_url": { + "description": "URL to fetch python patches from.", + "type": "string" + }, + "python_patches_directory": { + "description": "Directory to fetch python patches from.", + "type": "string" + }, + "python_precompiled_arch": { + "description": "Specify the architecture to use for precompiled binaries.", + "type": "string" + }, + "python_precompiled_os": { + "description": "Specify the OS to use for precompiled binaries.", + "type": "string" + }, + "python_pyenv_repo": { + "default": "https://github.com/pyenv/pyenv.git", + "description": "URL to fetch pyenv from for compiling python.", "type": "string" }, "python_venv_auto_create": { - "description": "automatically create a virtualenv for python tools", + "description": "Automatically create virtualenvs for python tools.", + "deprecated": "Use env._python.venv instead.", "type": "boolean" }, "quiet": { - "description": "suppress all non-error output", + "description": "Suppress all output except errors.", "type": "boolean" }, "raw": { - "description": "directly connect plugin scripts to stdin/stdout, implies --jobs=1", + "description": "Connect stdin/stdout/stderr to child processes.", "type": "boolean" }, "ruby": { "additionalProperties": false, - "description": "settings specific to ruby", "properties": { "apply_patches": { - "description": "A list of patches (files or URLs) to apply to Ruby source code before building", + "description": "A list of patch files or URLs to apply to ruby source.", "type": "string" }, "default_packages_file": { - "description": "Location of file containing a list of gems to install after installing a new ruby version.", + "default": "~/.default-gems", + "description": "Path to a file containing default ruby gems to install when installing ruby.", "type": "string" }, "ruby_build_opts": { - "description": "Command line options to pass to ruby-build when installing", + "description": "Options to pass to ruby-build.", "type": "string" }, "ruby_build_repo": { - "description": "The git repository to use for getting ruby-build", + "default": "https://github.com/rbenv/ruby-build.git", + "description": "URL to fetch ruby-build from.", "type": "string" }, "ruby_install": { - "description": "Build with ruby-install instead of ruby-build", + "description": "Use ruby-install instead of ruby-build.", "type": "boolean" }, "ruby_install_opts": { - "description": "Command line options to pass to ruby-install when installing (if MISE_RUBY_INSTALL=1)", + "description": "Options to pass to ruby-install.", "type": "string" }, "ruby_install_repo": { - "description": "The git repository to use for getting ruby-install", + "default": "https://github.com/postmodern/ruby-install.git", + "description": "URL to fetch ruby-install from.", "type": "string" }, "verbose_install": { - "description": "Show verbose output during installation (passes --verbose to ruby-build)", + "description": "Set to true to enable verbose output during ruby installation.", "type": "boolean" } - }, - "type": "object" + } }, "shorthands_file": { - "description": "path to file containing shorthand mappings", + "description": "Path to a file containing custom tool shorthands.", "type": "string" }, "status": { "additionalProperties": false, - "description": "configure messages displayed when changing directories or executing tools", "properties": { "missing_tools": { "default": "if_other_versions_installed", - "description": "display warning when a tool is not installed", - "enum": [ - "if_other_versions_installed", - "always", - "never" - ], + "description": "Show a warning if tools are not installed when entering a directory with a mise.toml file.", "type": "string" }, "show_env": { - "description": "display configured mise environment variables", + "description": "Show configured env vars when entering a directory with a mise.toml file.", "type": "boolean" }, "show_tools": { - "description": "display active tools", + "description": "Show configured env vars when entering a directory with a mise.toml file.", "type": "boolean" } - }, - "type": "object" + } }, "task_output": { - "default": "prefix", - "description": "how to display task output", + "description": "Change output style when executing tasks.", + "type": "string", "enum": [ "prefix", "interleave" - ], - "type": "string" + ] + }, + "trace": { + "description": "Sets log level to trace", + "type": "boolean" }, "trusted_config_paths": { - "description": "config files with these prefixes will be trusted by default", + "default": [], + "description": "This is a list of config paths that mise will automatically mark as trusted.", + "type": "array", "items": { - "description": "a path to add to PATH", "type": "string" - }, - "type": "array" + } }, "use_versions_host": { "default": true, - "description": "set to false to disable using mise-versions.jdx.dev to quickly fetch versions rather than listing them with the plugin", + "description": "Set to false to disable using the mise-versions API as a quick way for mise to query for new versions.", "type": "boolean" }, "verbose": { - "description": "display extra output", + "description": "Shows more verbose output such as installation logs when installing tools.", "type": "boolean" }, "vfox": { - "default": false, - "description": "use vfox as a default plugin backend", + "description": "Use vfox as a default plugin backend instead of asdf.", "type": "boolean" }, "yes": { - "description": "assume yes for all prompts", + "description": "This will automatically answer yes or no to prompts. This is useful for scripting.", "type": "boolean" } } @@ -529,8 +584,6 @@ ] } }, - "$id": "https://mise.jdx.dev/schema/mise.json", - "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "description": "config file for mise version manager (.mise.toml)", "properties": { @@ -592,7 +645,5 @@ "description": "dev tools to use", "type": "object" } - }, - "title": "mise", - "type": "object" + } } diff --git a/schema/mise.json.hbs b/schema/mise.json.hbs new file mode 100644 index 0000000000..907b8552d5 --- /dev/null +++ b/schema/mise.json.hbs @@ -0,0 +1,319 @@ +{ + "$id": "https://mise.jdx.dev/schema/mise.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "mise", + "type": "object", + "$defs": { + "env": { + "additionalProperties": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "enum": [ + false + ], + "type": "boolean" + } + ] + }, + "description": "environment variables", + "properties": { + "_": { + "description": "environment modules", + "properties": { + "file": { + "oneOf": [ + { + "description": "dotenv file to load", + "type": "string" + }, + { + "description": "dotenv files to load", + "items": { + "description": "dotenv file to load", + "type": "string" + }, + "type": "array" + } + ] + }, + "path": { + "oneOf": [ + { + "description": "PATH entry to add", + "type": "string" + }, + { + "description": "PATH entries to add", + "items": { + "description": "PATH entry to add", + "type": "string" + }, + "type": "array" + } + ] + }, + "python": { + "description": "python environment", + "properties": { + "venv": { + "oneOf": [ + { + "description": "path to python virtual environment to use", + "type": "string" + }, + { + "description": "virtualenv options", + "properties": { + "create": { + "default": false, + "description": "create a new virtual environment if one does not exist", + "type": "boolean" + }, + "path": { + "description": "path to python virtual environment to use", + "type": "string" + } + }, + "required": [ + "path" + ], + "type": "object" + } + ] + } + }, + "type": "object" + }, + "source": { + "oneOf": [ + { + "description": "bash script to load", + "type": "string" + }, + { + "description": "bash scripts to load", + "items": { + "description": "bash script to load", + "type": "string" + }, + "type": "array" + } + ] + } + }, + "type": "object" + } + }, + "type": "object" + }, + "settings": { + "properties": {{settings_json}} + }, + "task": { + "oneOf": [ + { + "description": "script to run", + "type": "string" + }, + { + "description": "script to run", + "items": { + "description": "script to run", + "type": "string" + }, + "type": "array" + }, + { + "additionalProperties": false, + "properties": { + "alias": { + "oneOf": [ + { + "description": "alias for this task", + "type": "string" + }, + { + "description": "alias for this task", + "items": { + "description": "alias for this task", + "type": "string" + }, + "type": "array" + } + ] + }, + "depends": { + "description": "other tasks to run before this task", + "items": { + "description": "task to run before this task", + "type": "string" + }, + "type": "array" + }, + "description": { + "description": "description of task", + "type": "string" + }, + "dir": { + "description": "directory to run script in, default is current working directory", + "type": "string" + }, + "env": { + "additionalProperties": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "enum": [ + false + ], + "type": "boolean" + } + ] + }, + "description": "environment variables", + "type": "object" + }, + "hide": { + "description": "do not display this task", + "type": "boolean" + }, + "outputs": { + "description": "files created by this task", + "items": { + "description": "glob pattern or path to files created by this task", + "type": "string" + }, + "type": "array" + }, + "quiet": { + "description": "do not display mise information for this task", + "type": "boolean" + }, + "raw": { + "description": "directly connect task to stdin/stdout/stderr", + "type": "boolean" + }, + "run": { + "oneOf": [ + { + "description": "script to run", + "type": "string" + }, + { + "description": "script to run", + "items": { + "description": "script to run", + "type": "string" + }, + "type": "array" + } + ] + }, + "sources": { + "description": "files that this task depends on", + "items": { + "description": "glob pattern or path to files that this task depends on", + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + } + ] + }, + "tool": { + "oneOf": [ + { + "description": "version of the tool to install", + "type": "string" + }, + { + "properties": { + "version": { + "description": "version of the tool to install", + "type": "string" + } + }, + "required": [ + "version" + ], + "type": "object" + } + ] + } + }, + "additionalProperties": false, + "description": "config file for mise version manager (.mise.toml)", + "properties": { + "alias": { + "additionalProperties": { + "additionalProperties": { + "description": "version alias points to", + "type": "string" + }, + "description": "plugin to set aliases for", + "type": "object" + }, + "description": "custom shorthands for versions", + "type": "object" + }, + "env": { + "$ref": "#/$defs/env" + }, + "min_version": { + "description": "minimum version of mise required to use this config", + "pattern": "^\\d+\\.\\d+\\.\\d+$", + "type": "string" + }, + "plugins": { + "additionalProperties": { + "description": "url to plugin repository", + "type": "string" + }, + "description": "plugins to use", + "type": "object" + }, + "settings": { + "$ref": "#/$defs/settings", + "additionalProperties": false, + "description": "mise settings", + "type": "object" + }, + "tasks": { + "additionalProperties": { + "$ref": "#/$defs/task" + }, + "description": "task runner tasks", + "type": "object" + }, + "tools": { + "additionalProperties": { + "oneOf": [ + { + "items": { + "$ref": "#/$defs/tool" + }, + "type": "array" + }, + { + "$ref": "#/$defs/tool" + } + ] + }, + "description": "dev tools to use", + "type": "object" + } + } +} diff --git a/settings.toml b/settings.toml new file mode 100644 index 0000000000..c9fb2b9f74 --- /dev/null +++ b/settings.toml @@ -0,0 +1,528 @@ +# This file generates code and documentation for settings in mise +# When this file is updated, run `mise run render` to update generated files + +[activate_aggressive] +env = "MISE_ACTIVATE_AGGRESSIVE" +type = "bool" +description = "Pushes tools' bin-paths to the front of PATH instead of allowing modifications of PATH after activation to take precedence." +docs = """ +Pushes tools' bin-paths to the front of PATH instead of allowing modifications of PATH after activation to take precedence. For example, if you have the following in your `mise.toml`: + +```toml +[tools] +node = '20' +python = '3.12' +``` + +But you also have this in your `~/.zshrc`: + +```sh +eval "$(mise activate zsh)" +PATH="/some/other/python:$PATH" +``` + +What will happen is `/some/other/python` will be used instead of the python installed by mise. This +means +you typically want to put `mise activate` at the end of your shell config so nothing overrides it. + +If you want to always use the mise versions of tools despite what is in your shell config, set this +to `true`. +In that case, using this example again, `/some/other/python` will be after mise's python in PATH. +""" + +[all_compile] +env = "MISE_ALL_COMPILE" +type = "bool" +description = "do not use precompiled binaries for any tool" +docs = """ +Default: false unless running NixOS or Alpine (let me know if others should be added) + +Do not use precompiled binaries for all languages. Useful if running on a Linux distribution +like Alpine that does not use glibc and therefore likely won't be able to run precompiled binaries. + +Note that this needs to be setup for each language. File a ticket if you notice a language that is +not +working with this config. +""" + +[always_keep_download] +env = "MISE_ALWAYS_KEEP_DOWNLOAD" +type = "bool" +description = "should mise keep downloaded files after installation" + +[always_keep_install] +env = "MISE_ALWAYS_KEEP_INSTALL" +type = "bool" +description = "should mise keep install files after installation even if the installation fails" + +[asdf] +env = "MISE_ASDF" +type = "bool" +default = true +description = "use asdf as a default plugin backend" +docs = """ +Use asdf as a default plugin backend. This means running something like `mise use cmake` will +default to using an asdf plugin for cmake. +""" + +[asdf_compat] +env = "MISE_ASDF_COMPAT" +type = "bool" +description = "set to true to ensure .tool-versions will be compatible with asdf" +docs = """ +Only output `.tool-versions` files in `mise local|global` which will be usable by asdf. +This disables mise functionality that would otherwise make these files incompatible with asdf such +as non-pinned versions. + +This will also change the default global tool config to be `~/.tool-versions` instead +of `~/.config/mise/config.toml`. +""" + +[cache_prune_age] +env = "MISE_CACHE_PRUNE_AGE" +type = "String" +default = "30d" +description = "Delete files in cache that have not been accessed in this duration" +docs = """ +The age of the cache before it is considered stale. mise will occasionally delete cache files which +have not been accessed in this amount of time. + +Set to `0` to keep cache files indefinitely. +""" + +[cargo_binstall] +env = "MISE_CARGO_BINSTALL" +type = "bool" +default = true +description = "Use cargo-binstall instead of cargo install if available" + +[cd] +env = "MISE_CD" +type = "Option" +description = "Path to change to after launching mise" +hide = true + +[ci] +env = "CI" +type = "bool" +description = "Set to true if running in a CI environment" +hide = true + +[color] +env = "MISE_COLOR" +type = "bool" +default = true +description = "Use color in mise terminal output" + +[debug] +env = "MISE_DEBUG" +type = "bool" +hide = true +description = "Sets log level to debug" + +[disable_default_shorthands] +env = "MISE_DISABLE_DEFAULT_SHORTHANDS" +type = "bool" +description = "Disables built-in shorthands to asdf/vfox plugins" +docs = """ +Disables the shorthand aliases for installing plugins. You will have to specify full URLs when +installing plugins, e.g.: `mise plugin install node https://github.com/asdf-vm/asdf-node.git` +""" + +[disable_hints] +env = "MISE_DISABLE_HINTS" +type = "BTreeSet" +default = [] +parse_env = "list_by_comma" +description = "Turns off helpful hints when using different mise features" + +[disable_tools] +env = "MISE_DISABLE_TOOLS" +type = "BTreeSet" +default = [] +parse_env = "list_by_comma" +description = "Tools defined in mise.toml that should be ignored" + +[env_file] +env = "MISE_ENV_FILE" +type = "Option" +description = "Path to a file containing environment variables." +hide = true + +[experimental] +env = "MISE_EXPERIMENTAL" +type = "bool" +description = "Enable experimental mise features which are incomplete or unstable—breakings changes may occur" +docs = """ +Enables experimental features. I generally will publish new features under +this config which needs to be enabled to use them. While a feature is marked +as "experimental" its behavior may change or even disappear in any release. + +The idea is experimental features can be iterated on this way so we can get +the behavior right, but once that label goes away you shouldn't expect things +to change without a proper deprecation—and even then it's unlikely. + +Also, I very often will use experimental as a beta flag as well. New +functionality that I want to test with a smaller subset of users I will often +push out under experimental mode even if it's not related to an experimental +feature. + +If you'd like to help me out, consider enabling it even if you don't have +a particular feature you'd like to try. Also, if something isn't working +right, try disabling it if you can. +""" + +[go_default_packages_file] +env = "MISE_GO_DEFAULT_PACKAGES_FILE" +type = "PathBuf" +default = "~/.default-go-packages" +description = "Path to a file containing default go packages to install when installing go" + +[go_download_mirror] +env = "MISE_GO_DOWNLOAD_MIRROR" +type = "String" +default = "https://dl.google.com/go" +description = "Mirror to download go sdk tarballs from." + +[go_repo] +env = "MISE_GO_REPO" +type = "String" +default = "https://github.com/golang/go" +description = "URL to fetch go from." + +[go_set_gobin] +env = "MISE_GO_SET_GOBIN" +type = "Option" +description = "Changes where `go install` installs binaries to." +docs = """ +Defaults to `~/.local/share/mise/installs/go/.../bin`. +Set to `true` to override GOBIN if previously set. +Set to `false` to not set GOBIN (default is `${GOPATH:-$HOME/go}/bin`). +""" + +[go_set_gopath] +env = "MISE_GO_SET_GOPATH" +type = "bool" +description = "[deprecated] Set to true to set GOPATH=~/.local/share/mise/installs/go/.../packages." +deprecated = "Use env._go.set_goroot instead." + +[go_set_goroot] +env = "MISE_GO_SET_GOROOT" +type = "bool" +default = true +description = "Sets GOROOT=~/.local/share/mise/installs/go/.../." + +[go_skip_checksum] +env = "MISE_GO_SKIP_CHECKSUM" +type = "bool" +description = "Set to true to skip checksum verification when downloading go sdk tarballs." + +[http_timeout] +env = "MISE_HTTP_TIMEOUT" +type = "u64" +default = 30 +description = "Timeout in seconds for all HTTP requests in mise." + +[jobs] +env = "MISE_JOBS" +type = "usize" +default = 4 +description = "How many jobs to run concurrently such as tool installs." + +# TODO: rename to "idiomatic_version_file" +[legacy_version_file] +env = "MISE_LEGACY_VERSION_FILE" +type = "bool" +default = true +description = "Set to false to disable the idiomatic version files such as .node-version, .ruby-version, etc." +docs = """ +Plugins can read the versions files used by other version managers (if enabled by the plugin) +for example, `.nvmrc` in the case of node's nvm. See [legacy version files](#legacy-version-files) +for more +information. + +Set to "0" to disable legacy version file parsing. +""" + +[legacy_version_file_disable_tools] +env = "MISE_LEGACY_VERSION_FILE_DISABLE_TOOLS" +type = "BTreeSet" +default = [] +parse_env = "list_by_comma" +description = "Specific tools to disable idiomatic version files for." + +[libgit2] +env = "MISE_LIBGIT2" +type = "bool" +default = true +description = "Use libgit2 for git operations, set to false to shell out to git." +docs = """ +Use libgit2 for git operations. This is generally faster but may not be as compatible if the +system's libgit2 is not the same version as the one used by mise. +""" + +[log_level] +env = "MISE_LOG_LEVEL" +type = "String" +default = "info" +hide = true +description = "Show more/less output." +enum = [ + ["trace"], + ["debug"], + ["info"], + ["warn"], + ["error"] +] + +[node.compile] +env = "MISE_NODE_COMPILE" +type = "Option" +description = "Compile node from source." + +[node.flavor] +env = "MISE_NODE_FLAVOR" +type = "Option" +description = "Install a specific node flavor like glibc-217 or musl. Use with unofficial node build repo." + +[node.mirror_url] +env = "MISE_NODE_MIRROR_URL" +type = "Option" +description = "Mirror to download node tarballs from." + +[not_found_auto_install] +env = "MISE_NOT_FOUND_AUTO_INSTALL" +type = "bool" +default = true +description = "Set to false to disable the \"command not found\" handler to autoinstall missing tool versions." +docs = """ +Set to false to disable the "command not found" handler to autoinstall missing tool versions. +Disable this if experiencing strange behavior in your shell when a command is not found—but please submit a +ticket to help diagnose problems. +""" + +[paranoid] +env = "MISE_PARANOID" +type = "bool" +description = "Enables extra-secure behavior." +docs = """ +Enables extra-secure behavior. See [Paranoid](/paranoid). +""" + +[pipx_uvx] +env = "MISE_PIPX_UVX" +type = "bool" +description = "Use uvx instead of pipx if uv is installed and on PATH." + +[plugin_autoupdate_last_check_duration] +env = "MISE_PLUGIN_AUTOUPDATE_LAST_CHECK_DURATION" +type = "String" +default = "7d" +description = "How long to wait before updating plugins automatically (note this isn't currently implemented)." + +[python_compile] +env = "MISE_PYTHON_COMPILE" +type = "Option" +description = "If true, compile python from source. If false, use precompiled binaries. If not set, use precompiled binaries if available." + +[python_default_packages_file] +env = "MISE_PYTHON_DEFAULT_PACKAGES_FILE" +type = "Option" +description = "Path to a file containing default python packages to install when installing python." + +[python_patch_url] +env = "MISE_PYTHON_PATCH_URL" +type = "Option" +description = "URL to fetch python patches from." + +[python_patches_directory] +env = "MISE_PYTHON_PATCHES_DIRECTORY" +type = "Option" +description = "Directory to fetch python patches from." + +[python_precompiled_arch] +env = "MISE_PYTHON_PRECOMPILED_ARCH" +type = "Option" +description = "Specify the architecture to use for precompiled binaries." +default_docs = '"apple-darwin" | "unknown-linux-gnu" | "unknown-linux-musl"' + +[python_precompiled_os] +env = "MISE_PYTHON_PRECOMPILED_OS" +type = "Option" +default_docs = '"x86_64_v3" | "aarch64"' +description = "Specify the OS to use for precompiled binaries." + +[python_pyenv_repo] +env = "MISE_PYENV_REPO" +type = "String" +default = "https://github.com/pyenv/pyenv.git" +description = "URL to fetch pyenv from for compiling python." + +[python_venv_auto_create] +env = "MISE_PYTHON_VENV_AUTO_CREATE" +type = "bool" +hide = true +deprecated = "Use env._python.venv instead." +description = "Automatically create virtualenvs for python tools." + +[quiet] +env = "MISE_QUIET" +type = "bool" +description = "Suppress all output except errors." + +[raw] +env = "MISE_RAW" +type = "bool" +description = "Connect stdin/stdout/stderr to child processes." + +[ruby.apply_patches] +env = "MISE_RUBY_APPLY_PATCHES" +type = "Option" +description = "A list of patch files or URLs to apply to ruby source." + +[ruby.default_packages_file] +env = "MISE_RUBY_DEFAULT_PACKAGES_FILE" +type = "String" +default = "~/.default-gems" +description = "Path to a file containing default ruby gems to install when installing ruby." + +[ruby.ruby_build_opts] +env = "MISE_RUBY_BUILD_OPTS" +type = "Option" +description = "Options to pass to ruby-build." + +[ruby.ruby_build_repo] +env = "MISE_RUBY_BUILD_REPO" +type = "String" +default = "https://github.com/rbenv/ruby-build.git" +description = "URL to fetch ruby-build from." + +[ruby.ruby_install] +env = "MISE_RUBY_INSTALL" +type = "bool" +description = "Use ruby-install instead of ruby-build." + +[ruby.ruby_install_opts] +env = "MISE_RUBY_INSTALL_OPTS" +type = "Option" +description = "Options to pass to ruby-install." + +[ruby.ruby_install_repo] +env = "MISE_RUBY_INSTALL_REPO" +type = "String" +default = "https://github.com/postmodern/ruby-install.git" +description = "URL to fetch ruby-install from." + +[ruby.verbose_install] +env = "MISE_RUBY_VERBOSE_INSTALL" +type = "Option" +description = "Set to true to enable verbose output during ruby installation." + +[shorthands_file] +env = "MISE_SHORTHANDS_FILE" +type = "Option" +description = "Path to a file containing custom tool shorthands." +docs = """ +Use a custom file for the shorthand aliases. This is useful if you want to share plugins within +an organization. + +Shorthands make it so when a user runs something like `mise install elixir` mise will +automatically install the [asdf-elixir](https://github.com/asdf-vm/asdf-elixir) plugin. By +default, it uses the shorthands in +[`src/default_shorthands.rs`](https://github.com/jdx/mise/blob/main/src/default_shorthands.rs). + +The file should be in this toml format: + +```toml +elixir = "https://github.com/my-org/mise-elixir.git" +node = "https://github.com/my-org/mise-node.git" +``` + +""" + +[status.missing_tools] +env = "MISE_STATUS_MESSAGE_MISSING_TOOLS" +type = "String" +default = "if_other_versions_installed" +description = "Show a warning if tools are not installed when entering a directory with a mise.toml file." +docs = """ +| Choice | Description | +|-----------------------------------------|----------------------------------------------------------------------------| +| `if_other_versions_installed` [default] | Show the warning only when the tool has at least 1 other version installed | +| `always` | Always show the warning | +| `never` | Never show the warning | + +Show a warning if tools are not installed when entering a directory with a `mise.toml` file. + +::: tip +Disable tools with [`disable_tools`](#disable_tools). +::: +""" + +[status.show_env] +env = "MISE_STATUS_MESSAGE_SHOW_ENV" +type = "bool" +description = "Show configured env vars when entering a directory with a mise.toml file." + +[status.show_tools] +env = "MISE_STATUS_MESSAGE_SHOW_TOOLS" +type = "bool" +description = "Show configured env vars when entering a directory with a mise.toml file." + +[task_output] +env = "MISE_TASK_OUTPUT" +type = "Option" +description = "Change output style when executing tasks." +enum = [ + ["prefix", "(default if jobs > 1) print by line with the prefix of the task name"], + ["interleave", "(default if jobs > 1) print by line with the prefix of the task name"] +] +docs = """ +Change output style when executing tasks. This controls the output of `mise run`. +""" + +[trace] +env = "MISE_TRACE" +type = "bool" +hide = true +description = "Sets log level to trace" + +[trusted_config_paths] +env = "MISE_TRUSTED_CONFIG_PATHS" +type = "BTreeSet" +default = [] +parse_env = "list_by_colon" +description = "This is a list of config paths that mise will automatically mark as trusted." + +[use_versions_host] +env = "MISE_USE_VERSIONS_HOST" +type = "bool" +default = true +description = "Set to false to disable using the mise-versions API as a quick way for mise to query for new versions." +docs = """ +Set to "false" to disable using [mise-versions](https://mise-versions.jdx.dev) as +a quick way for mise to query for new versions. This host regularly grabs all the +latest versions of core and community plugins. It's faster than running a plugin's +`list-all` command and gets around GitHub rate limiting problems when using it. + +See [FAQ](/faq#new-version-of-a-tool-is-not-available) for more information. +""" + +[verbose] +env = "MISE_VERBOSE" +type = "bool" +description = "Shows more verbose output such as installation logs when installing tools." + +[vfox] +env = "MISE_VFOX" +type = "bool" +description = "Use vfox as a default plugin backend instead of asdf." +docs = """ +Use vfox as a default plugin backend. This means running something like `mise use cmake` will +default to using an vfox plugin for cmake. +""" + +[yes] +env = "MISE_YES" +type = "bool" +description = "This will automatically answer yes or no to prompts. This is useful for scripting." diff --git a/src/backend/mod.rs b/src/backend/mod.rs index 8bcdcb4dbd..69deac3de6 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -85,10 +85,10 @@ fn load_tools() -> BackendMap { .map(|(_, p)| p.clone()) .collect::>(); let settings = Settings::get(); - if settings.asdf { + if !cfg!(windows) || settings.asdf { tools.extend(asdf::AsdfBackend::list().expect("failed to list asdf plugins")); } - if settings.vfox { + if cfg!(windows) || settings.vfox { tools.extend(vfox::VfoxBackend::list().expect("failed to list vfox plugins")); } tools.extend(list_installed_backends().expect("failed to list backends")); diff --git a/src/config/settings.rs b/src/config/settings.rs index 67f7ef8e3f..4480862d20 100644 --- a/src/config/settings.rs +++ b/src/config/settings.rs @@ -12,213 +12,16 @@ use std::collections::{BTreeSet, HashSet}; use std::fmt::{Debug, Display, Formatter}; use std::iter::once; use std::path::PathBuf; +use std::str::FromStr; use std::sync::{Arc, Mutex, RwLock}; use std::time::Duration; use url::Url; pub static SETTINGS: Lazy> = Lazy::new(Settings::get); -#[rustfmt::skip] -#[derive(Config, Default, Debug, Clone, Serialize)] -#[config(partial_attr(derive(Clone, Serialize, Default)))] -pub struct Settings { - /// push tools to the front of PATH instead of allowing modifications of PATH after activation to take precedence - #[config(env = "MISE_ACTIVATE_AGGRESSIVE", default = false)] - pub activate_aggressive: bool, - #[config(env = "MISE_ALL_COMPILE", default = false)] - pub all_compile: bool, - #[config(env = "MISE_ALWAYS_KEEP_DOWNLOAD", default = false)] - pub always_keep_download: bool, - #[config(env = "MISE_ALWAYS_KEEP_INSTALL", default = false)] - pub always_keep_install: bool, - #[cfg(asdf)] - #[config(env = "MISE_ASDF", default = true)] - pub asdf: bool, - #[cfg(not(asdf))] - #[config(env = "MISE_ASDF", default = false)] - pub asdf: bool, - /// default to asdf-compatible behavior - /// this means that the global config file will be ~/.tool-versions - /// also, the default behavior of `mise global` will be --pin - #[config(env = "MISE_ASDF_COMPAT", default = false)] - pub asdf_compat: bool, - /// delete files in cache that have not been accessed in this duration - #[config(env = "MISE_CACHE_PRUNE_AGE", default = "30d")] - pub cache_prune_age: String, - /// use cargo-binstall instead of cargo install if available - #[config(env = "MISE_CARGO_BINSTALL", default = true)] - pub cargo_binstall: bool, - #[config(env = "MISE_COLOR", default = true)] - pub color: bool, - #[config(env = "MISE_DISABLE_DEFAULT_SHORTHANDS", default = false)] - pub disable_default_shorthands: bool, - #[config(env = "MISE_DISABLE_HINTS", default = [], parse_env = list_by_comma)] - pub disable_hints: BTreeSet, - #[config(env = "MISE_DISABLE_TOOLS", default = [], parse_env = list_by_comma)] - pub disable_tools: BTreeSet, - #[config(env = "MISE_EXPERIMENTAL", default = false)] - pub experimental: bool, - /// after installing a go version, run `go install` on packages listed in this file - #[config(env = "MISE_GO_DEFAULT_PACKAGES_FILE", default = "~/.default-go-packages")] - pub go_default_packages_file: PathBuf, - /// url to fetch go sdks from - #[config(env = "MISE_GO_DOWNLOAD_MIRROR", default = "https://dl.google.com/go")] - pub go_download_mirror: String, - /// used for fetching go versions - #[config(env = "MISE_GO_REPO", default = "https://github.com/golang/go")] - pub go_repo: String, - /// changes where `go install` installs binaries to - /// defaults to ~/.local/share/mise/installs/go/.../bin - /// set to true to override GOBIN if previously set - /// set to false to not set GOBIN (default is ${GOPATH:-$HOME/go}/bin) - #[config(env = "MISE_GO_SET_GOBIN")] - pub go_set_gobin: Option, - /// [deprecated] set to true to set GOPATH=~/.local/share/mise/installs/go/.../packages - /// use to make mise behave like asdf but there are no known use-cases where this is necessary. - /// See https://github.com/jdx/mise/discussions/1638 - #[config(env = "MISE_GO_SET_GOPATH", default = false)] - pub go_set_gopath: bool, - /// sets GOROOT=~/.local/share/mise/installs/go/.../ - /// you probably always want this set to be set unless you want GOROOT to point to something - /// other than the sdk mise is currently set to - #[config(env = "MISE_GO_SET_GOROOT", default = true)] - pub go_set_goroot: bool, - /// set to true to skip checksum verification when downloading go sdk tarballs - #[config(env = "MISE_GO_SKIP_CHECKSUM", default = false)] - pub go_skip_checksum: bool, - #[config(env = "MISE_HTTP_TIMEOUT", default = 30)] - pub http_timeout: u64, - #[config(env = "MISE_JOBS", default = 4)] - pub jobs: usize, - #[config(env = "MISE_LEGACY_VERSION_FILE", default = true)] - pub legacy_version_file: bool, - #[config(env = "MISE_LEGACY_VERSION_FILE_DISABLE_TOOLS", default = [], parse_env = list_by_comma)] - pub legacy_version_file_disable_tools: BTreeSet, - #[config(env = "MISE_LIBGIT2", default = true)] - pub libgit2: bool, - #[config(nested)] - pub node: SettingsNode, - #[config(env = "MISE_NOT_FOUND_AUTO_INSTALL", default = true)] - pub not_found_auto_install: bool, - #[config(env = "MISE_PARANOID", default = false)] - pub paranoid: bool, - /// use uvx instead of pipx if available - #[config(env = "MISE_PIPX_UVX", default = false)] - pub pipx_uvx: bool, - #[config(env = "MISE_PLUGIN_AUTOUPDATE_LAST_CHECK_DURATION", default = "7d")] - pub plugin_autoupdate_last_check_duration: String, - #[config(env = "MISE_PYTHON_COMPILE")] - pub python_compile: Option, - #[config(env = "MISE_PYTHON_DEFAULT_PACKAGES_FILE")] - pub python_default_packages_file: Option, - #[config(env = "MISE_PYTHON_PATCH_URL")] - pub python_patch_url: Option, - #[config(env = "MISE_PYTHON_PATCHES_DIRECTORY")] - pub python_patches_directory: Option, - #[config(env = "MISE_PYTHON_PRECOMPILED_ARCH")] - pub python_precompiled_arch: Option, - #[config(env = "MISE_PYTHON_PRECOMPILED_OS")] - pub python_precompiled_os: Option, - #[config(env = "MISE_PYENV_REPO", default = "https://github.com/pyenv/pyenv.git")] - pub python_pyenv_repo: String, - #[config(env = "MISE_RAW", default = false)] - pub raw: bool, - #[config(nested)] - pub ruby: SettingsRuby, - #[config(env = "MISE_SHORTHANDS_FILE")] - pub shorthands_file: Option, - /// what level of status messages to display when entering directories - #[config(nested)] - pub status: SettingsStatus, - #[config(env = "MISE_TASK_OUTPUT")] - pub task_output: Option, - #[config(env = "MISE_TRUSTED_CONFIG_PATHS", default = [], parse_env = list_by_colon)] - pub trusted_config_paths: BTreeSet, - #[config(env = "MISE_QUIET", default = false)] - pub quiet: bool, - #[config(env = "MISE_USE_VERSIONS_HOST", default = true)] - pub use_versions_host: bool, - #[config(env = "MISE_VERBOSE", default = false)] - pub verbose: bool, - #[cfg(vfox)] - #[config(env = "MISE_VFOX", default = true)] - pub vfox: bool, - #[cfg(not(vfox))] - #[config(env = "MISE_VFOX", default = false)] - pub vfox: bool, - #[config(env = "MISE_YES", default = false)] - pub yes: bool, - - // hidden settings - #[config(env = "CI", default = false)] - pub ci: bool, - #[config(env = "MISE_CD")] - pub cd: Option, - #[config(env = "MISE_DEBUG", default = false)] - pub debug: bool, - #[config(env = "MISE_ENV_FILE")] - pub env_file: Option, - #[config(env = "MISE_TRACE", default = false)] - pub trace: bool, - #[config(env = "MISE_LOG_LEVEL", default = "info")] - pub log_level: String, - #[config(env = "MISE_PYTHON_VENV_AUTO_CREATE", default = false)] - pub python_venv_auto_create: bool, -} - -#[derive(Config, Default, Debug, Clone, Serialize)] -#[config(partial_attr(derive(Clone, Serialize, Default)))] -#[config(partial_attr(serde(deny_unknown_fields)))] -#[rustfmt::skip] -pub struct SettingsNode { - #[config(env = "MISE_NODE_COMPILE")] - pub compile: Option, - #[config(env = "MISE_NODE_FLAVOR")] - pub flavor: Option, - #[config(env = "MISE_NODE_MIRROR_URL")] - pub mirror_url: Option -} - -#[derive(Config, Default, Debug, Clone, Serialize)] -#[config(partial_attr(derive(Clone, Serialize, Default)))] -#[config(partial_attr(serde(deny_unknown_fields)))] -#[rustfmt::skip] -pub struct SettingsRuby { - #[config(env = "MISE_RUBY_APPLY_PATCHES")] - pub apply_patches: Option, - #[config(env = "MISE_RUBY_DEFAULT_PACKAGES_FILE", default = "~/.default-gems")] - pub default_packages_file: String, - #[config(env = "MISE_RUBY_BUILD_REPO", default = "https://github.com/rbenv/ruby-build.git")] - pub ruby_build_repo: String, - #[config(env = "MISE_RUBY_BUILD_OPTS")] - pub ruby_build_opts: Option, - #[config(env = "MISE_RUBY_INSTALL", default = false)] - pub ruby_install: bool, - #[config(env = "MISE_RUBY_INSTALL_REPO", default = "https://github.com/postmodern/ruby-install.git")] - pub ruby_install_repo: String, - #[config(env = "MISE_RUBY_INSTALL_OPTS")] - pub ruby_install_opts: Option, - #[config(env = "MISE_RUBY_VERBOSE_INSTALL")] - pub verbose_install: Option, -} - -#[derive(Config, Default, Debug, Clone, Serialize)] -#[config(partial_attr(derive(Clone, Serialize, Default)))] -#[config(partial_attr(serde(deny_unknown_fields)))] -pub struct SettingsStatus { - /// warn if a tool is missing - #[config( - env = "MISE_STATUS_MESSAGE_MISSING_TOOLS", - default = "if_other_versions_installed" - )] - pub missing_tools: SettingsStatusMissingTools, - /// show env var keys when entering directories - #[config(env = "MISE_STATUS_MESSAGE_SHOW_ENV", default = false)] - pub show_env: bool, - /// show active tools when entering directories - #[config(env = "MISE_STATUS_MESSAGE_SHOW_TOOLS", default = false)] - pub show_tools: bool, -} +// settings are generated from settings.toml in the project root +// make sure you run `mise run render` after updating settings.toml +include!(concat!(env!("OUT_DIR"), "/settings.rs")); #[derive( Debug, Clone, Copy, Serialize, Deserialize, Default, strum::EnumString, strum::Display, @@ -523,3 +326,9 @@ impl SettingsNode { Url::parse(&s).unwrap() } } + +impl SettingsStatus { + pub fn missing_tools(&self) -> SettingsStatusMissingTools { + SettingsStatusMissingTools::from_str(&self.missing_tools).unwrap() + } +} diff --git a/src/registry.rs b/src/registry.rs index f56142fa7e..78dece7942 100644 --- a/src/registry.rs +++ b/src/registry.rs @@ -45,7 +45,7 @@ const _REGISTRY_VFOX: &[(&str, &str)] = &[ pub static REGISTRY: Lazy> = Lazy::new(|| { let settings = Settings::get(); - let registry = if settings.vfox { + let registry = if cfg!(windows) || settings.vfox { _REGISTRY.iter().chain(_REGISTRY_VFOX.iter()).collect_vec() } else { _REGISTRY.iter().collect_vec() diff --git a/src/toolset/mod.rs b/src/toolset/mod.rs index 0cf2b1b0a9..41258b70f8 100644 --- a/src/toolset/mod.rs +++ b/src/toolset/mod.rs @@ -472,7 +472,7 @@ impl Toolset { let missing = self .list_missing_versions() .into_iter() - .filter(|tv| match settings.status.missing_tools { + .filter(|tv| match settings.status.missing_tools() { SettingsStatusMissingTools::Never => false, SettingsStatusMissingTools::Always => true, SettingsStatusMissingTools::IfOtherVersionsInstalled => tv