diff --git a/share/completions/npm.fish b/share/completions/npm.fish index ff9731c8d..8fdb03d1d 100644 --- a/share/completions/npm.fish +++ b/share/completions/npm.fish @@ -4,21 +4,8 @@ # see also Fish's large set of completions for examples: # https://github.com/fish-shell/fish-shell/tree/master/share/completions -# If all-the-package-names is installed, it will be used to generate npm completions. -# Install globally with `sudo npm install -g all-the-package-names`. Keep it up to date. -function __npm_list_packages - if not type -q all-the-package-names - return - end - - all-the-package-names -end - -# Entire list of packages is too long to be used in a `complete` subcommand -# Search it for matches instead -function __npm_filtered_list_packages - __npm_list_packages | grep (commandline -ct) | head -n 50 -end +source $__fish_data_dir/functions/fish_npm_helper.fish +set -l npm_install "npm install --global" function __fish_npm_needs_command set cmd (commandline -opc) @@ -156,7 +143,7 @@ complete -f -c npm -n '__fish_npm_using_command owner' -a 'rm' -d 'Remove an own # remove for c in 'r' 'remove' 'rm' 'un' 'uninstall' 'unlink' - complete -f -c npm -n '__fish_npm_needs_command' -a "$c" -d 'remove package' + complete -f -c npm -n '__fish_npm_needs_command' -a "$c" -d 'remove package' -xa '(__yarn_installed_packages)' complete -x -c npm -n "__fish_npm_using_command $c" -s g -l global -d 'remove global package' complete -x -c npm -n "__fish_npm_using_command $c" -l save -d 'Package will be removed from your dependencies' complete -x -c npm -n "__fish_npm_using_command $c" -l save-dev -d 'Package will be removed from your devDependencies' @@ -208,4 +195,4 @@ complete -f -c npm -n '__fish_npm_needs_command' -a 'unpublish' -d 'Remove a pac complete -f -c npm -n '__fish_npm_needs_command' -a 'unstar' -d 'Remove star from a package' complete -f -c npm -n '__fish_npm_needs_command' -a 'version' -d 'Bump a package version' complete -f -c npm -n '__fish_npm_needs_command' -a 'whoami' -d 'Display npm username' -complete -f -c npm -n '__fish_seen_subcommand_from install' -a '(__npm_filtered_list_packages)' +complete -f -c npm -n '__fish_seen_subcommand_from install; and not __fish_is_switch' -a "(__yarn_filtered_list_packages \"$npm_install\")" diff --git a/share/completions/yarn.fish b/share/completions/yarn.fish index bd7b40228..378d466d8 100644 --- a/share/completions/yarn.fish +++ b/share/completions/yarn.fish @@ -1,95 +1,12 @@ -# NOTE: Fish helper functions are your best friend here! -# see https://github.com/fish-shell/fish-shell/blob/master/share/functions/__fish_seen_subcommand_from.fish -# and https://github.com/fish-shell/fish-shell/blob/master/share/functions/__fish_use_subcommand.fish - -# If all-the-package-names is installed, it will be used to generate npm completions. -# Install globally with `sudo npm install -g all-the-package-names`. Keep it up to date. -function __yarn_helper_installed - if not type -q all-the-package-names - if not set -qg __fish_yarn_pkg_info_shown - set -l old (commandline) - commandline -r "" - echo \nfish: Run `yarn global add all-the-package-names` to gain intelligent \ - package completion > /dev/stderr - commandline -f repaint - commandline -r $old - set -g __fish_yarn_pkg_info_shown 1 - end - return 1 - end -end - -# Entire list of packages is too long to be used efficiently in a `complete` subcommand. -# Search it for matches instead. -function __yarn_filtered_list_packages - if not __yarn_helper_installed - return - end - - # Do not provide any completions if nothing has been entered yet to avoid long hang. - if string match -r . (commandline -ct) - # Filter the results here rather than in the C++ code due to #5267 - all-the-package-names | string match -er -- "(?:\\b|_)"(commandline -ct | - string escape --style=regex) | head -n1000 - end -end - -function __yarn_find_package_json - set parents (__fish_parent_directories (pwd)) - - for p in $parents - if test -f "$p/package.json" - echo "$p/package.json" - return 0 - end - end - - return 1 -end - -function __yarn_installed_packages - set -l package_json (__yarn_find_package_json) - if not test $status -eq 0 - # no package.json in tree - return 1 - end - - if type -q jq - jq -r '.dependencies as $a1 | .devDependencies as $a2 | ($a1 + $a2) | to_entries[] | .key' $package_json - else - set -l depsFound 0 - for line in (cat $package_json) - # echo "evaluating $line" - if test $depsFound -eq 0 - # echo "mode: noDeps" - if string match -qr '(devD|d)ependencies"' -- $line - # echo "switching to mode: deps" - set depsFound 1 - continue - end - continue - end - - if string match -qr '\}' -- $line - # echo "switching to mode: noDeps" - set depsFound 0 - continue - end - - # echo "mode: deps" - - string replace -r '^\s*"([^"]+)".*' '$1' -- $line - end - end -end - +source $__fish_data_dir/functions/fish_npm_helper.fish +set -l yarn_add "yarn global add" # Typically there is no need to check if (commandline -ct) begins with `--` # because it won't be matched. But we can prevent the slowdown from getting # a list of all packages and filtering through it if we only do that when # completing what seems to be a package name. complete -f -c yarn -n '__fish_seen_subcommand_from remove; and not __fish_is_switch' -xa '(__yarn_installed_packages)' -complete -f -c yarn -n '__fish_seen_subcommand_from add; and not __fish_is_switch' -xa '(__yarn_filtered_list_packages)' +complete -f -c yarn -n '__fish_seen_subcommand_from add; and not __fish_is_switch' -xa "(__yarn_filtered_list_packages \"$yarn_add\")" complete -f -c yarn -n '__fish_use_subcommand' -a help diff --git a/share/functions/fish_npm_helper.fish b/share/functions/fish_npm_helper.fish new file mode 100644 index 000000000..f6eb1efc9 --- /dev/null +++ b/share/functions/fish_npm_helper.fish @@ -0,0 +1,89 @@ +# This file is explicitly sourced by the npm and fish completions +# It is used to enumerate entries from the npm registry, interact with a locally installed +# package.json file, and more. +# Other completions that would depend on this include jspm, pnpm, etc. + +# If all-the-package-names is installed, it will be used to generate npm completions. +# Install globally with `sudo npm install -g all-the-package-names`. Keep it up to date. +function __yarn_helper_installed + # This function takes the command to globally install a package as $argv[1] + if not type -q all-the-package-namesS + if not set -qg __fish_yarn_pkg_info_shown + set -l old (commandline) + commandline -r "" + echo \nfish: Run `$argv[1] all-the-package-names` to gain intelligent \ + package completion > /dev/stderr + commandline -f repaint + commandline -r $old + set -g __fish_yarn_pkg_info_shown 1 + end + return 1 + end +end + +# Entire list of packages is too long to be used efficiently in a `complete` subcommand. +# Search it for matches instead. +function __yarn_filtered_list_packages + # This function takes the command to globally install a package as $argv[1] + if not __yarn_helper_installed $argv[1] + return + end + + # Do not provide any completions if nothing has been entered yet to avoid long hang. + if string match -r . (commandline -ct) + # Filter the results here rather than in the C++ code due to #5267 + all-the-package-names | string match -er -- "(?:\\b|_)"(commandline -ct | + string escape --style=regex) | head -n1000 + end +end + +function __yarn_find_package_json + set parents (__fish_parent_directories (pwd)) + + for p in $parents + if test -f "$p/package.json" + echo "$p/package.json" + return 0 + end + end + + return 1 +end + +function __yarn_installed_packages + set -l package_json (__yarn_find_package_json) + if not test $status -eq 0 + # no package.json in tree + return 1 + end + + if type -q jq + jq -r '.dependencies as $a1 | .devDependencies as $a2 | ($a1 + $a2) | to_entries[] | .key' $package_json + else + set -l depsFound 0 + for line in (cat $package_json) + # echo "evaluating $line" + if test $depsFound -eq 0 + # echo "mode: noDeps" + if string match -qr '(devD|d)ependencies"' -- $line + # echo "switching to mode: deps" + set depsFound 1 + continue + end + continue + end + + if string match -qr '\}' -- $line + # echo "switching to mode: noDeps" + set depsFound 0 + continue + end + + # echo "mode: deps" + + string replace -r '^\s*"([^"]+)".*' '$1' -- $line + end + end +end + +