mirror of
https://github.com/fish-shell/fish-shell.git
synced 2024-12-13 09:24:03 +08:00
9354dd6971
This is a function you can either execute once, interactively, or stick in config.fish, and it will do the right thing. Some options are included to choose some slightly different behavior, like setting $PATH directly instead of $fish_user_paths, or moving already existing components to the front/back instead of ignoring them, or appending new components instead of prepending them. The defaults were chosen because they are the most safe, and especially because they allow it to be idempotent - running it again and again and again won't change anything, it won't even run the actual `set` because it skips that if all components are already in. Fixes #6960.
86 lines
3.3 KiB
Fish
86 lines
3.3 KiB
Fish
function fish_add_path --description "Add paths to the PATH"
|
|
# This is meant to be the easy one-stop shop to adding stuff to $PATH.
|
|
# By default it'll prepend the given paths to a universal $fish_user_paths, excluding the already-included ones.
|
|
#
|
|
# That means it can be executed once in an interactive session, or stuffed in config.fish,
|
|
# and it will do The Right Thing.
|
|
#
|
|
# The options:
|
|
# --prepend or --append to select whether to put the new paths first or last
|
|
# --global or --universal to decide whether to use a universal or global fish_user_paths
|
|
# --path to set $PATH instead
|
|
# --move to move existing entries instead of ignoring them
|
|
# --verbose to print the set-command used
|
|
# --dry-run to print the set-command without running it
|
|
# We do not allow setting $PATH universally.
|
|
#
|
|
# It defaults to keeping $fish_user_paths or creating a universal, prepending and ignoring existing entries.
|
|
argparse -x g,U -x P,U -x a,p g/global U/universal P/path p/prepend a/append h/help m/move v/verbose n/dry-run -- $argv
|
|
or return
|
|
|
|
if set -q _flag_help
|
|
__fish_print_help fish_add_path
|
|
return 0
|
|
end
|
|
|
|
set -l scope $_flag_global $_flag_universal
|
|
if not set -q scope[1]; and not set -q fish_user_paths
|
|
set scope -U
|
|
end
|
|
|
|
set -l var fish_user_paths
|
|
set -q _flag_path; and set var PATH
|
|
set -l mode $_flag_prepend $_flag_append
|
|
set -q mode[1]; or set mode -p
|
|
|
|
# To keep the order of our arguments, go through and save the ones we want to keep.
|
|
set -l newpaths
|
|
set -l indexes
|
|
for path in $argv
|
|
# Realpath allows us to canonicalize the path, which is needed for deduplication.
|
|
# We could add a non-canonical version of the given path if no duplicate exists, but tbh that's a recipe for disaster.
|
|
|
|
# realpath complains if a parent directory does not exist, so we silence stderr.
|
|
set -l p (builtin realpath -- $path 2>/dev/null)
|
|
|
|
# Ignore non-existing paths
|
|
test -d "$p"; or continue
|
|
|
|
if set -l ind (contains -i -- $p $$var)
|
|
# In move-mode, we remove it from its current position and add it back.
|
|
if set -q _flag_move
|
|
set -a indexes $ind
|
|
set -a newpaths $p
|
|
end
|
|
else
|
|
# Without move, we only add it if it's not in.
|
|
set -a newpaths $p
|
|
end
|
|
end
|
|
|
|
# Ensure the variable is only set once, by constructing a new variable before.
|
|
# This is to stop any handlers or anything from firing more than once.
|
|
set -l newvar $$var
|
|
if set -q _flag_move; and set -q indexes[1]
|
|
# We remove in one step, so the indexes don't move.
|
|
set -e newvar[$indexes]
|
|
end
|
|
set $mode newvar $newpaths
|
|
|
|
# Finally, only set if there is anything *to* set.
|
|
# This saves us from setting, especially in the common case of someone putting this in config.fish
|
|
# to ensure a path is in $PATH.
|
|
if set -q newpaths[1]; or set -q indexes[1]
|
|
if set -q _flag_verbose; or set -q _flag_n
|
|
# The escape helps make it unambiguous - so you see whether an argument includes a space or something.
|
|
echo (string escape -- set $scope $var $newvar)
|
|
end
|
|
|
|
not set -q _flag_n
|
|
and set $scope $var $newvar
|
|
return 0
|
|
else
|
|
return 1
|
|
end
|
|
end
|