From 74ba060f55e3ceff305caf0745313a8541eafb6c Mon Sep 17 00:00:00 2001 From: Texas Toland Date: Tue, 12 Mar 2024 10:55:07 -0500 Subject: [PATCH] [stdlib-candidate] set-env (#787) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rewrite of nushell/nushell#12156 for jdx/mise#1763. ### Why? Nushell philosophically omits a `set` list mutation. But `$env` is inherently mutable leading to issues described in nushell/nushell#12148. `set-env` provides such an operation exclusively for `$env`. ### What changed? 1. Explicit flag instead of implicit list concatenation 2. Expands updates to any `$env` field not only `$env.config` ### How is it used? ```yaml ❯ set-env -h Gracefully set an environment variable or merge a nested option. Examples: Set $env.NUPM_HOME > set-env NUPM_HOME $'($nu.home-path)/.local/share/nupm' Add to $env.NU_LIB_DIRS > set-env --append NU_LIB_DIRS $'($env.NUPM_HOME)/modules' Set a nested config option > set-env config.filesize.metric true Add a config hook > set-env -a config.hooks.pre_prompt 'ellie | print' Usage: > main {flags} Flags: -a, --append - Append to the previous value or wrap in a new list -h, --help - Display the help message for this command Parameters: field : The environment variable name or nested option cell path value : The value to set or append Input/output types: ╭───┬─────────┬─────────╮ │ # │ input │ output │ ├───┼─────────┼─────────┤ │ 0 │ nothing │ nothing │ ╰───┴─────────┴─────────╯ ``` ### How does it work? ```nushell export def --env main [ field: cell-path value: any --append (-a) ]: nothing -> nothing { # just an alias def 'get or' [default field] { get --ignore-errors $field | default $default } let value = if $append { # append to the previous value or empty list $env | get or [] $field | append $value } else { $value } # work around nushell/nushell#12168 let field = $field | to text | split row . let value = match $field { [_] => $value # if cell path is nested [$root, ..$field] => { let field = $field | into cell-path # reassigning $env would be an error # merging reserved names like PWD would be an error # so merge from 1 level deep instead $env | get or {} $root | upsert $field $value } } # avoid issues noted above load-env { ($field | first): $value } } ``` ### Where are the tests? Pending next PR for nupm integration. --- stdlib-candidate/set-env.nu | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 stdlib-candidate/set-env.nu diff --git a/stdlib-candidate/set-env.nu b/stdlib-candidate/set-env.nu new file mode 100644 index 00000000..1e0b3c49 --- /dev/null +++ b/stdlib-candidate/set-env.nu @@ -0,0 +1,37 @@ +# Gracefully set an environment variable or merge a nested option. +# +# Examples: +# Set $env.NUPM_HOME +# > set-env NUPM_HOME $'($nu.home-path)/.local/share/nupm' +# +# Add to $env.NU_LIB_DIRS +# > set-env --append NU_LIB_DIRS $'($env.NUPM_HOME)/modules' +# +# Set a nested config option +# > set-env config.filesize.metric true +# +# Add a config hook +# > set-env -a config.hooks.pre_prompt 'ellie | print' +export def --env main [ + field: cell-path # The environment variable name or nested option cell path + value: any # The value to set or append + --append (-a) # Append to the previous value or wrap in a new list +]: nothing -> nothing { + def 'get or' [default field] { + get --ignore-errors $field | default $default + } + let value = if $append { + $env | get or [] $field | append $value + } else { + $value + } + let field = $field | to text | split row . + let value = match $field { + [_] => $value + [$root, ..$field] => { + let field = $field | into cell-path + $env | get or {} $root | upsert $field $value + } + } + load-env { ($field | first): $value } +}