fish-shell/share/completions/env.fish
Mahmoud Al-Qudsi ee4d578171 completions/env: Fix errant loud string match
This was vexing me for a while because the extraneous output presented as a
valid (but unwanted) completion, i.e. with RUSTC_WRAPPER exported, `env RUSTC_W`
would offer `RUSTC_W=` and `RUSTC_WRAPPER=` as completions (when only the latter
should have been offered up).
2024-06-26 19:10:51 -05:00

124 lines
5.2 KiB
Fish

set -l is_gnu
if env --version &>/dev/null
set is_gnu --is-gnu
end
# Returns 0 if we're after `env` and all previous tokens have an equal sign or were switches
function __fish_env_defining_vars
set last ""
for token in (commandline -cxp)[2..] # 2.. excludes `env`. -cx already ignores the variable being completed.
# Is a switch, defined an env variable, or was a variable name to unset (after -u)
string match -r -- '^-|=' $token || string match -rq -- '^(-u|--unset)$' "$last" || return 1
set last $token
end
end
# Returns 0 if we're after `env` and all previous tokens have not yet contained an equal sign
# Prevents `env` completions from completing payload completions.
function __fish_env_not_yet_vars
not string match -qe = (commandline -c)
end
# Generate a list of possible variable names to redefine, excluding any already redefined.
function __fish_env_redefine_vars
set -l vars (set --names -x)
set cmdline "$(commandline -xp)"
for var in $vars
if not string match -eq -- $var= $cmdline
echo $var=
end
end
end
# Generate a list of possible variable names to define from completion history
function __fish_env_names_from_history
set -l token (commandline -ct)
# Since this is always going to be a best-effort kind of thing, limit this to uppercased variables by convention.
# This prevents us from having to parse quotes to figure out what was part of the payload and what wasn't.
for var in (history search --prefix "env " | string match -ra '\b([A-Z0-9_]+)=' --groups-only)
echo $var=
end
end
# Generate a list of possible completions for the current variable name from history
function __fish_env_values_from_history
string match -rq "(?<name>.+)=(?<value>.*)" (commandline -ct); or return 1
# Caveat lector: very crude multi-word tokenization handling below!
set -l rname (string escape --style=regex -- $name)
set -l search (string trim -c \'\" "$value")
set -l rsearch "$(string escape --style=regex -- $search)"
# Search multi-word values with quotes
set -l query '.*\b'$name'=([\'"])('$rsearch'.+?)\1.*'
set -l matches (history search --prefix "env " | string replace -rfa $query '$2')
# Search multi-word values without quotes
set -l query '.*\b'$name'=('$rsearch'[^\'" ]+).*'
set -a matches (history search --prefix "env " | string replace -rfa $query '$1')
# Display results without quotes
set matches (printf "%s\n" $matches | sort -u)
printf "$name=%s\n" $matches
end
# Get the text after all env arguments and variables, so we can complete it as a regular command
function __fish_env_remaining_args -V is_gnu
set -l argv (commandline -xpc) (commandline -ct)
if set -q is_gnu[1]
argparse -s i/ignore-environment u/unset= help version -- $argv 2>/dev/null
or return 0
else
argparse -s 0 i P= S= u= v -- $argv 2>/dev/null
or return 0
end
# argv[1] is `env` or an alias.
set -e argv[1]
# Remove all VAR=VAL arguments up to the first that isn't
while set -q argv[1]
if string match -q '*=*' -- $argv[1]
or string match -q -- '-*' $argv[1]
set -e argv[1]
else
break
end
end
string join \n -- $argv
# Return true if there is a subcommand.
test -n "$argv[1]"
end
# Generate a completion for the executable to execute under `env`
function __fish_complete_env_subcommand
if set -l argv (__fish_env_remaining_args)
complete -C "$argv"
end
end
# Complete the name of the variable from current definitions
complete -c env -n '__fish_env_defining_vars; and not string match -eq = -- (commandline -ct)' -a "(__fish_env_redefine_vars)" -f -d "Redefine variable"
# Complete the name of the variable from history
complete -c env -n '__fish_env_defining_vars; and not string match -eq = -- (commandline -ct)' -a "(__fish_env_names_from_history)" -f -d Historical
# Complete the value for FOO= from history
# TODO: NO_ESCAPE when that becomes available
complete -c env -n '__fish_env_defining_vars; and string match -eq = -- (commandline -ct)' -a "(__fish_env_values_from_history)" -f
# Complete normally after we are done with `env` stuff
complete -c env -fa "(__fish_complete_env_subcommand)"
if set -q is_gnu
complete -c env -n __fish_env_not_yet_vars -s i -l ignore-environment -d "Start with an empty environment"
complete -c env -n __fish_env_not_yet_vars -s u -l unset -d "Unset environment variable" -x -a "(set --names -x)"
complete -c env -n __fish_env_not_yet_vars -l help -d "Display help and exit"
complete -c env -n __fish_env_not_yet_vars -l version -d "Display version and exit"
else
complete -c env -n __fish_env_not_yet_vars -s 0 -d "End output lines with NUL"
complete -c env -n __fish_env_not_yet_vars -s i -d "Start with empty environment"
complete -c env -n __fish_env_not_yet_vars -s P -d "Provide an alternate PATH"
complete -c env -n __fish_env_not_yet_vars -s S -d "Split argument into args on ' '"
complete -c env -n __fish_env_not_yet_vars -s u -d "Unset environment variable" -x -a "(set --names -x)"
complete -c env -n __fish_env_not_yet_vars -s v -d "Verbose output on processing"
end