123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350 |
- # GNU Guix --- Functional package management for GNU
- # Copyright © 2015-2022 Ludovic Courtès <ludo@gnu.org>
- # Copyright © 2021 Tobias Geerinck-Rice <me@tobias.gr>
- #
- # This file is part of GNU Guix.
- #
- # GNU Guix is free software; you can redistribute it and/or modify it
- # under the terms of the GNU General Public License as published by
- # the Free Software Foundation; either version 3 of the License, or (at
- # your option) any later version.
- #
- # GNU Guix is distributed in the hope that it will be useful, but
- # WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- # You should have received a copy of the GNU General Public License
- # along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
- # Bash completion for Guix commands.
- declare _guix_available_packages
- declare _guix_commands
- _guix_complete_command ()
- {
- local word_at_point="${COMP_WORDS[$COMP_CWORD]}"
- if [ -z "$_guix_commands" ]
- then
- # Cache the list of commands to speed things up.
- _guix_commands="$(${COMP_WORDS[0]} --help 2> /dev/null \
- | grep '^ ' \
- | sed '-es/^ *\([a-z-]\+\).*$/\1/g')"
- fi
- COMPREPLY+=($(compgen -W "$_guix_commands" -- "$word_at_point"))
- }
- _guix_complete_subcommand ()
- {
- local command="${COMP_WORDS[1]}"
- local subcommands="$(${COMP_WORDS[0]} $command --help 2> /dev/null \
- | grep '^ [a-z]' \
- | sed -e's/^ \+\([a-z-]\+\).*$/\1/g')"
- COMPREPLY+=($(compgen -W "$subcommands" -- "${COMP_WORDS[$COMP_CWORD]}"))
- }
- _guix_complete_available_package ()
- {
- local prefix="$1"
- if [ -z "$_guix_available_packages" ]
- then
- # Cache the complete list because it rarely changes and makes
- # completion much faster.
- _guix_available_packages="$(${COMP_WORDS[0]} package -A 2> /dev/null \
- | cut -f1)"
- fi
- COMPREPLY+=($(compgen -W "$_guix_available_packages" -- "$prefix"))
- }
- _guix_complete_installed_package ()
- {
- # Here we do not cache the list of installed packages because that
- # may change over time and the list is relatively small anyway.
- local prefix="$1"
- local packages="$(${COMP_WORDS[0]} package -I "^$prefix" 2> /dev/null \
- | cut -f1)"
- COMPREPLY+=($(compgen -W "$packages" -- "$prefix"))
- }
- _guix_complete_option ()
- {
- local command="${COMP_WORDS[$1]}"
- local subcommand="${COMP_WORDS[$(($1 + 1))]}"
- if [ $1 -eq 0 ]
- then
- command=""
- subcommand=""
- elif _guix_is_option "$subcommand"
- then
- subcommand=""
- fi
- local options="$(${COMP_WORDS[0]} $command $subcommand --help 2> /dev/null \
- | grep '^ \+-' \
- | sed -e's/^.*--\([a-zA-Z0-9_-]\+\)\(=\?\).*/--\1\2/g')"
- compopt -o nospace
- COMPREPLY+=($(compgen -W "$options" -- "$2"))
- }
- _guix_is_option ()
- {
- case "$1" in
- -*)
- true
- ;;
- *)
- false
- ;;
- esac
- }
- _guix_is_removing ()
- {
- local word
- local result="false"
- for word in ${COMP_WORDS[*]}
- do
- case "$word" in
- --remove|--remove=*|-r)
- result=true
- break
- ;;
- esac
- done
- $result
- }
- _guix_is_short_option ()
- {
- case "${COMP_WORDS[$COMP_CWORD - 1]}" in
- --*) false;;
- -*$1) true ;;
- *) false ;;
- esac
- }
- _guix_is_long_option ()
- {
- # Don't handle (non-GNU?) ‘--long-option VALUE’, as Guix doesn't either.
- case "${COMP_WORDS[$COMP_CWORD]}" in
- --$1=*) true ;;
- *) false ;;
- esac
- }
- _guix_is_dash_f ()
- {
- _guix_is_short_option f ||
- _guix_is_long_option file ||
- _guix_is_long_option install-from-file
- }
- _guix_is_dash_l ()
- {
- _guix_is_short_option l ||
- _guix_is_long_option load
- }
- _guix_is_dash_L ()
- {
- _guix_is_short_option L ||
- _guix_is_long_option load-path
- }
- _guix_is_dash_m ()
- {
- _guix_is_short_option m ||
- _guix_is_long_option manifest
- }
- _guix_is_dash_C ()
- {
- _guix_is_short_option C ||
- _guix_is_long_option channels
- }
- _guix_is_dash_p ()
- {
- _guix_is_short_option p ||
- _guix_is_long_option profile
- }
- _guix_complete_file ()
- {
- # Let Readline complete file names.
- compopt -o default
- COMPREPLY=()
- }
- _guix_complete_available_package_or_store_file ()
- {
- _guix_complete_available_package "$@"
- # The current _guix_complete_file implementation doesn't compose (append to
- # COMPREPLY), so we suggest file names only if no package names matched.
- if [[ -z "$COMPREPLY" ]]
- then
- _guix_complete_file # TODO: restrict to store files
- fi
- }
- _guix_complete_pid ()
- {
- local pids="$(cd /proc; echo [0-9]*)"
- COMPREPLY+=($(compgen -W "$pids" -- "$1"))
- }
- _guix_complete ()
- {
- local word_count=${#COMP_WORDS[*]}
- local word_at_point="${COMP_WORDS[$COMP_CWORD]}"
- # Find the innermost command at point, e.g. "build" in the case of
- # "guix time-machine OPTIONS -- build<Tab>" -- but "time-machine" if
- # point is moved before "build".
- local command_index=0
- local command
- local word_index=0
- local word
- local expect_command="true"
- while [[ $((++word_index)) -le COMP_CWORD ]]
- do
- word="${COMP_WORDS[$word_index]}"
- if $expect_command
- then
- command_index=$word_index
- command="$word"
- expect_command="false"
- continue
- fi
- if [[ "$word" = "--" ]]
- then
- case "$command" in
- environment|shell)
- break
- ;;
- time-machine)
- expect_command="true"
- ;;
- esac
- fi
- done
- case $COMP_CWORD in
- $command_index)
- _guix_complete_command
- _guix_complete_option 0 "$word_at_point"
- ;;
- *)
- if [[ "$command" = "package" ]]
- then
- if _guix_is_dash_L || _guix_is_dash_m || _guix_is_dash_p || _guix_is_dash_f
- then
- _guix_complete_file
- elif _guix_is_removing
- then
- _guix_complete_installed_package "$word_at_point"
- else
- _guix_complete_available_package "$word_at_point"
- fi
- elif [[ "$command" = "install" ]]
- then
- if _guix_is_dash_L || _guix_is_dash_m || _guix_is_dash_p
- then
- _guix_complete_file
- else
- _guix_complete_available_package "$word_at_point"
- fi
- elif [[ "$command" = "upgrade" || "$command" = "remove" ]]
- then
- if _guix_is_dash_L || _guix_is_dash_m || _guix_is_dash_p
- then
- _guix_complete_file
- else
- _guix_complete_installed_package "$word_at_point"
- fi
- elif [[ "$command" = "build" ]]
- then
- if _guix_is_dash_L || _guix_is_dash_m || _guix_is_dash_f
- then
- _guix_complete_file
- else
- _guix_complete_available_package_or_store_file "$word_at_point"
- fi
- elif [[ "$command" = "environment" || "$command" = "shell" ]]
- then
- if _guix_is_dash_f && [[ "$command" = "shell" ]]
- then
- # The otherwise identical ‘guix environment’ lacks the ‘-f’ option.
- _guix_complete_file
- elif _guix_is_dash_L || _guix_is_dash_m || _guix_is_dash_p || _guix_is_dash_l
- then
- _guix_complete_file
- elif _guix_is_option "$word_at_point"
- then
- _guix_complete_option "$command_index" "$word_at_point"
- else
- _guix_complete_available_package "$word_at_point"
- fi
- elif [[ "$command" = "download" || "$command" = "gc" || "$command" = "hash" ]]
- then
- _guix_complete_file
- elif [[ "$command" = "size" ]]
- then
- _guix_complete_available_package_or_store_file "$word_at_point"
- elif [[ "$command" = "system" || "$command" = "home" ]]
- then
- case $((COMP_CWORD - command_index)) in
- 1) _guix_complete_subcommand;;
- *) _guix_complete_file;; # TODO: restrict to *.scm
- esac
- elif [[ "$command" = "pull" ]]
- then
- if _guix_is_dash_C || _guix_is_dash_p
- then
- _guix_complete_file
- fi
- elif [[ "$command" = "time-machine" ]]
- then
- if _guix_is_dash_C
- then
- _guix_complete_file
- else
- _guix_complete_option "$command_index" "$word_at_point"
- fi
- elif [[ "$command" = "container" ]]
- then
- case $((COMP_CWORD - command_index)) in
- 1) _guix_complete_subcommand;;
- 2) _guix_complete_pid "$word_at_point";;
- *) _guix_complete_file;;
- esac
- elif [[ "$command" = "import" ]]
- then
- _guix_complete_subcommand
- elif [[ "$command" = "weather" ]]
- then
- if _guix_is_dash_m
- then
- _guix_complete_file
- else
- _guix_complete_available_package "$word_at_point"
- fi
- else
- _guix_complete_available_package "$word_at_point"
- fi
- ;;
- esac
- if [[ -z "$COMPREPLY" && COMP_CWORD -gt command_index ]] &&
- _guix_is_option "$word_at_point"
- then
- _guix_complete_option "$command_index" "$word_at_point"
- fi
- }
- complete -F _guix_complete guix
|