# Gentoo Linux Bash Shell Command Completion # # Copyright 1999-2013 Gentoo Authors # Distributed under the terms of the GNU General Public License, v2 or later source "@helpersdir@/gentoo-common.sh" # # emerge completion command # _emerge() { local c cur prev cond prepend local words stophere i x local action actionpos sysactions pkgpos local portdir=$(_portdir -o) COMPREPLY=() local cur=${COMP_WORDS[COMP_CWORD]} local prev=${COMP_WORDS[COMP_CWORD-1]} local numwords=${#COMP_WORDS[*]} local curword=${COMP_CWORD} local opts=() if [[ ${prev} == '>' || ${prev} == '<' ]] ; then COMPREPLY=($(compgen -f -- ${cur})) return 0 fi if [[ ${cur} =~ ^@ ]] ; then local SET_LIST=($(emerge --list-sets)) COMPREPLY=($(compgen -W '${SET_LIST[@]/#/@}' ${cur})) return 0 fi # find action for x in ${COMP_LINE} ; do if [[ ${x} =~ ^(system|world)$ ]] || [[ ${x} =~ -[CPcs] ]] || \ [[ ${x} =~ --(clean|config|depclean|deselect|info|metadata|prune|rage-clean|regen|resume|search|sync|unmerge) ]] then action=${x} break fi done if [[ -n ${action} ]]; then for ((i = 0; i < ${numwords}; i++ )); do if [[ ${COMP_WORDS[${i}]} == "${action}" ]]; then actionpos=${i} pkgpos=$((actionpos + 1)) break fi done if [[ ${action} == -* && ${action} != --* ]] ; then case "${action}" in -*C*) action='--unmerge' ;; -*P*) action='--prune' ;; -*c*) action='--clean' ;; -*s*) action='--search' ;; esac fi else for ((i = 1; i < ${numwords}; i++ )); do if [[ ! ${COMP_WORDS[$i]} == -* ]]; then pkgpos=${i} break fi done [[ -z ${pkgpos} ]] && pkgpos=${numwords} fi # Handle special cases. if [[ ${action} == "--search" ]] || [[ ${COMP_LINE} == *" "-@(S|-searchdesc)* ]] || \ [[ ${COMP_LINE} == *" "-@(V|-version)* ]] || [[ ${action} == "--metadata" ]] then unset COMPREPLY return 0 elif [[ ${COMP_LINE} == *" "-@(h|-help)* ]] ; then unset COMPREPLY [[ ${curword} -eq 2 ]] && COMPREPLY=($(compgen -W 'system world --sync' -- ${cur})) return 0 fi # Complete on options. if [[ ${cur} == -* ]]; then # If a resume option was specified, it needs special handling. if [[ ${COMP_LINE} =~ --(resume|skipfirst) ]] ; then if [[ ${cur} == --* ]]; then opts=( --ask --pretend --resume --skipfirst ) elif [[ ${cur} == -* ]]; then [[ ${COMP_LINE} =~ --(ask|pretend) ]] && opts=( -a -p ) fi elif [[ ${cur} == --* ]]; then # Complete on long options. opts=( --alphabetical --ask --autounmask-write --autounmask-keep-keywords --autounmask-continue={y,n} --autounmask-backtrack --autounmask-only --autounmask-unrestricted-atoms --autounmask-keep-masks --autounmask-license={y,n} --autounmask-use={y,n} --accept-properties --accept-restrict --alert --alert={y,n} --ask-enter-invalid --binpkg-changed-deps --binpkg-respect-use --buildpkg-exclude --buildpkg --buildpkgonly --backtrack= --changelog --clean --color={y,n} --columns --complete-graph --config --check-news --complete-graph-if-new-use={y,n} --complete-graph-if-new-ver={y,n} --config-root --changed-deps --changed-deps-report --changed-slot --changed-use --debug --deep --depclean --deselect --depclean-lib-check --dynamic-deps={y,n} --emptytree --exclude --fail-clean --fetch-all-uri --fetchonly --fuzzy-search --getbinpkg --getbinpkgonly --ignore-default-opts --ignore-built-slot-operator-deps={y,n} --ignore-soname-deps={y,n} --ignore-world --implicit-system-deps={y,n} --info --jobs= --load-average= --keep-going --misspell-suggestions={y,n} --metadata --newrepo --newuse --noconfmem --nodeps --noreplace --nospinner --oneshot --onlydeps --onlydeps-with-ideps --onlydeps-with-rdeps --pretend --prune --package-moves --pkg-format --quiet --quiet-build --quiet-fail --quiet-repo-display --quiet-unmerge-warn --rage-clean --regex-search-auto={y,n} --read-news --reinstall=changed-use --reinstall-atoms --regen --rebuild-exclude --rebuild-ignore --rebuild-if-new-slot --rebuild-if-new-rev --rebuild-if-new-ver --rebuild-if-unbuilt --rebuilt-binaries --search --search-index --search-similarity --sync --select --selective --sync-submodule={glsa,news,profiles} --tree --unordered-display --use-ebuild-visibility --useoldpkg-atoms --usepkg-exclude-live --unmerge --update --update-if-installed --upgradeonly --usepkg --usepkgonly --usepkg-exclude --verbose --verbose-conflicts --verbose-slot-rebuilds --with-bdeps={y,n} --with-bdeps-auto={y,n} --with-test-deps ) if [[ ${curword} -eq 1 ]] && [[ ${numwords} -eq 2 ]] ; then opts+=( --help --resume --searchdesc --version ) fi elif [[ ${cur} == -* ]]; then # Complete on short options. opts+=( -B -D -G -K -N -O -a -b -d -e -f -g -k -l -n -o -p -q -t -u -v ) if [[ ${curword} -eq 1 ]] && [[ ${numwords} -eq 2 ]] ; then opts+=( -h -S -V ) fi if [[ -z ${action} ]] && [[ ${curword} -eq $((pkgpos - 1)) ]] ; then opts+=( -C -P -c -s ) fi fi COMPREPLY=($(compgen -W '${opts[*]}' -- ${cur})) # NOTE: This slows things down! # (Adapted from bash_completion by Ian Macdonald ) # This removes any options from the list of completions that have # already been specified on the command line. COMPREPLY=($(echo "${COMP_WORDS[@]}" | \ (while read -d ' ' i; do [[ -z ${i} ]] && continue # flatten array with spaces on either side, # otherwise we cannot grep on word boundaries of # first and last word COMPREPLY=" ${COMPREPLY[@]} " # remove word from list of completions COMPREPLY=(${COMPREPLY/ ${i%% *} / }) done echo ${COMPREPLY[@]}))) return 0 fi # options # Stop completion if a special case is encountered. if [[ ${action} =~ (system|world) ]] || \ [[ ${COMP_LINE} =~ --(depclean|metadata|regen|resume|skipfirst|sync) ]] then unset COMPREPLY return 0 fi # Complete on installed packages when unmerging. if [[ "${action}" =~ --(rage-clean|unmerge) ]]; then if [[ -n "${cur}" ]] ; then if [[ "${cur}" == */* ]]; then words=$(builtin cd @GENTOO_PORTAGE_EPREFIX@/var/db/pkg; compgen -G "${cur}*") else words=$(builtin cd @GENTOO_PORTAGE_EPREFIX@/var/db/pkg; compgen -S '/' -G "${cur}*") local n=0 for i in ${words} ; do [[ ${i} == ${cur}* ]] && n=$((n+1)) done if [[ ${n} -eq 1 ]] ; then words="$(builtin cd @GENTOO_PORTAGE_EPREFIX@/var/db/pkg ; compgen -G "*-*/*")" fi fi COMPREPLY=($(for i in ${words} ; do \ [[ ${i} == ${cur}* ]] && echo ${i} ; \ done)) else COMPREPLY=($(builtin cd @GENTOO_PORTAGE_EPREFIX@/var/db/pkg ; compgen -S '/' -G "*-*")) fi [[ -z "${COMPREPLY}" ]] && _pkgname_only ${cur} @GENTOO_PORTAGE_EPREFIX@/var/db/pkg return 0 fi # Check for conditional. cond="${cur%%[A-Za-z0-9]*}" cur="${cur:${#cond}}" if [[ ${cond:0:1} == "'" || ${cond:0:1} == '"' ]] ; then prepend="-P ${cond:1}" c="${cond:1}" else c="${cond}" fi # Handle cases where a conditional is specified. if [[ -n "${cond}" ]]; then if [[ -n "${cur}" ]]; then if [[ ${cur} == */* ]]; then if [[ ${cur} == *-[0-9]* ]] ; then words="$(\ for pd in ${portdir} ; do \ builtin cd ${pd} ; \ local cat="${cur%/*}" ; \ local pkg="$(echo ${cur%-[0-9]*})" ; \ pkg="${pkg##*/}" ; \ for x in ${cat}/${pkg}/*.ebuild ; do \ [[ -f ${x} ]] || continue ; \ x="${x/${pkg}\/}" ; \ echo "${x%*.ebuild}" ; \ done ; \ done)" else words="$(\ for pd in ${portdir} ; do \ builtin cd ${pd}; \ compgen -X "*metadata.xml" -G "${cur}*" -- ${cur} ; \ done)" fi local w for x in $words ; do w="${x}\n${w}" done words=$(echo -ne ${w} | sort | uniq) COMPREPLY=( ${words} ) # Complete on the specific versions (if appropriate). # TODO - see if we can use _pkgname if [[ ${#COMPREPLY[@]} -le 1 ]]; then COMPREPLY=($( for pd in ${portdir}; do if [[ -d ${pd}/metadata/md5-cache ]]; then builtin cd ${pd}/metadata/md5-cache compgen ${prepend} -G "${cur}*" -- "${cur}" elif [[ -d ${pd}/metadata/cache ]]; then builtin cd ${pd}/metadata/cache compgen ${prepend} -G "${cur}*" -- "${cur}" else builtin cd ${pd} local cat="${cur%/*}" local pkg="$(echo ${cur%-[0-9]*}*)" pkg="${pkg##*/}" for x in ${cat}/${pkg}/*.ebuild; do [[ -f "${x}" ]] || continue x="${x/${pkg}\/}" if [[ ${cond:0:1} == "'" ]] || [[ ${cond:0:1} == '"' ]]; then echo "${c}${x%*.ebuild}" else echo "${x%*.ebuild}" fi done fi done )) else COMPREPLY=($(compgen ${prepend} -W "${words}" -- $cur)) fi else words="$(\ for pd in ${portdir} ; do \ builtin cd ${pd} ; \ compgen ${prepend} -S '/' -G "${cur}*" -- "${cur}" ; \ done)" local w for x in words ; do w="${x}\n${w}" done COMPREPLY=($(echo -e ${w} | uniq)) [[ ${#COMPREPLY[@]} = 1 ]] && \ COMPREPLY=($(\ for pd in ${portdir} ; do \ builtin cd ${pd} ; \ compgen ${prepend} -G "${cur}*/*" -- "${cur}" ; \ done)) fi else words="$(\ for pd in ${portdir} ; do \ builtin cd ${pd}; \ compgen -G "*-*"; \ done)" COMPREPLY=($(compgen -W "${words}" -- "${cur}")) fi # If all else fails, try to complete on package names without the # category being specified. if [[ -z "${COMPREPLY}" ]]; then words="$(\ for pd in ${portdir} ; do \ builtin cd ${pd}; \ for i in *-*/${cur}*; do \ [[ -d $i ]] && echo ${i##*/}; \ done ; \ done)" COMPREPLY=($(compgen ${prepend} -W "${words}" -- ${cur})) if [[ ${#COMPREPLY[@]} -le 1 ]]; then # Now complete on the specific versions. words="$( for pd in ${portdir}; do if [[ -d ${pd}/metadata/md5-cache ]]; then builtin cd ${pd}/metadata/md5-cache for i in */${cur}*; do [[ -f $i ]] && echo ${i##*/} done elif [[ -d ${pd}/metadata/cache ]]; then builtin cd ${pd}/metadata/cache for i in */${cur}*; do [[ -f $i ]] && echo ${i##*/} done fi done )" COMPREPLY=($(compgen ${prepend} -W "${words}" -- "${cur}")) fi fi return 0 fi # Complete on packages. # # Only allow these actions if no packages have been specified. # # TODO: This doesn't block these actions if no categories are # specified. Please fix me. # # e.g. emerge -a gentoo-dev-sources # # will still allow system and world actions to be specified, # as opposed to # # emerge -a sys-kernel/gentoo-dev-sources # if [[ ${COMP_CWORD} -eq 1 ]] || [[ ! " ${COMP_LINE} " == *" "*[/]*" "* ]] ; then sysactions=$'\n'"system"$'\n'"world" else sysactions='' fi if [[ -n "${cur}" ]] ; then if [[ ${cur} == */* ]] ; then words=$(\ for pd in ${portdir} ; do \ builtin cd ${pd}; \ compgen -X "*metadata.xml" -G "${cur}*" ; \ done)"${sysactions}" else local ww=$(\ for pd in ${portdir} ; do \ builtin cd ${pd} ; \ compgen -X "!@(*-*|virtual)" -S '/' -G "${cur}*"; \ done)"${sysactions}" # complete on virtuals ww="${ww} $(\ for pd in ${portdir} ; do \ if [[ -d ${pd}/profiles ]] ; then find ${pd}/profiles -name virtuals -exec \ sed -n -e 's|^\(virtual/[[:alnum:]]\+\).*$|\1|p' {} \; | \ sort -u fi ; \ done)" local w for x in ${ww} ; do w="${x}\n${w}" ; done words=$(echo -e ${w} | sort -u) local n=0 for i in ${words} ; do [[ ${i} == ${cur}* ]] && n=$((n+1)) done if [[ ${n} -eq 1 ]] ; then words=$(for pd in ${portdir} ; do \ builtin cd ${pd} ; \ compgen -G "*-*/*" ; \ done)"${sysactions}" fi fi COMPREPLY=($(for i in ${words} ; do \ [[ ${i} == ${cur}* ]] && echo ${i} ; \ done)) else words="$(\ for pd in ${portdir} ; do \ builtin cd ${pd} ; \ compgen -S '/' -G "*-*" ; \ done)""${sysactions}" COMPREPLY=($(compgen -W "${words}" -- ${cur})) fi # If all else fails, try to complete on package names without the # category being specified. if [[ -z "${COMPREPLY}" ]]; then words="$(\ for pd in ${portdir} ; do \ builtin cd ${pd}; \ for i in [a-z]*-[a-z0-9]*/${cur}*; do \ [[ -d $i ]] && echo ${i##*/}; \ done ; \ done)" COMPREPLY=($(compgen -W "${words}" -- ${cur})) fi return 0 } && complete -o filenames -F _emerge emerge # vim: ft=sh:et:ts=4:sw=4:tw=80