mirror of
https://github.com/fish-shell/fish-shell.git
synced 2024-12-03 08:23:51 +08:00
0072367512
The case for symlinked directories being duplicated a lot isn't there, but there *is* a usecase for adding the symlink rather than the target, and that's homebrew. E.g. homebrew installs ruby into /usr/local/Cellar/ruby/2.7.1_2/bin, and links to it from /usr/local/opt/ruby/bin. If we add the target, we would miss updates. Having path entries that point to the same location isn't a big problem - it's a path lookup, so it takes a teensy bit longer. The canonicalization is mainly so paths don't end up duplicated via weird spelling and so relative paths can be used.
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 -s -- $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
|