--- misc/eselect.bashcomp.old 2009-02-15 16:44:47.000000000 -0600 +++ misc/eselect.bashcomp 2009-02-15 16:45:08.000000000 -0600 @@ -1,29 +1,108 @@ -# Copyright 1999-2005 Gentoo Foundation +# Completion for eselect [] [] +# Author: Wilke Schwiedop # Distributed under the terms of the GNU General Public License v2 -# $Id$ - -# bash command-line completion for eselect -# Author: Aaron Walker _eselect() { - local cur prev sedcmd possibles - COMPREPLY=() - cur="${COMP_WORDS[COMP_CWORD]}" - prev="${COMP_WORDS[COMP_CWORD-1]}" - sedcmd='sed -n -e s/^[[:space:]]\+.*1m\([^[:space:]][[:alnum:]-]\+\).*[[:space:]]\+.*$/\1/p' - - if [[ ${COMP_CWORD} -eq 1 ]] || [[ -n "${prev}" && ${prev} == -* ]] - then - possibles="$(eselect help | ${sedcmd})" - elif eselect ${prev} usage &>/dev/null ; then - possibles=$(eselect ${prev} usage | ${sedcmd}) - fi + local curr=${COMP_WORDS[COMP_CWORD]} possibles="" module_index=1 + + # Unset default completion + COMPREPLY=() + + # Unfortunatly we can't source eselect to get to the variables directly, so this is a bit more complicated + local ESELECT_DATA_PATH ESELECT_MODULES_PATH - [[ -n "${possibles}" ]] && \ - COMPREPLY=( $(compgen -W "${possibles}" -- ${cur}) ) + # Obtain ESELECT_DATA_PATH and ESELECT_MODULES_PATH . See eselect for more info + ESELECT_DATA_PATH=$(sed -n -e 's/^ESELECT_DATA_PATH="\(.\+\)"$/\1/p' $(which eselect)) + ESELECT_MODULES_PATH=( "${HOME}/.eselect/modules" "${ESELECT_DATA_PATH}/modules" ) + + # Hard-coded Actions. + # Note: list-modules is hardcoded aswell, but not used in the modules. list-modules is added only when needed. + ESELECT_KNOWN_ACTIONS="help usage version" + # Hard-coded Options + # TODO These could be read from ESELECT_KNOWN_OPTIONS + ESELECT_KNOWN_OPTIONS="--no-colour" + + # If any word in ${COMP_WORDS[@]} is a default-action, we don't need further completion + for i in ${COMP_WORDS[@]} ; do + [[ $i == @(${ESELECT_KNOWN_ACTIONS//[[:space:]]/"|"}|list-modules) ]] && return 0 + done + + # Skip all global-options + while [[ ${COMP_WORDS[module_index]} == -* ]] ; do + ((++module_index)) + done + + # If this is true we're looking for a module name or an eselect-option. In short: "eselect " + # Since we're skipping the global options, this may be < 0 if we have nothing but options in COMP_WORDS. + if [[ $((COMP_CWORD-module_index)) -le 0 ]] ; then + local path file + for path in "${ESELECT_MODULES_PATH[@]}" ; do + [[ -d ${path} ]] || continue + for file in ${path}/*.eselect ; do + [[ -f ${file} ]] || continue + file=${file##*/} # strip path + file=${file%%.eselect} # strip extension + possibles+=" ${file}" + done + done + + possibles+=" list-modules ${ESELECT_KNOWN_ACTIONS}" # Include default actions and list-modules + possibles+=" ${ESELECT_KNOWN_OPTIONS}" # Include default options + + # We already have a module, so we're looking for an action or even and option + # In short: "eselect somemodule " + else + local modname=${COMP_WORDS[module_index]} modpath="" modfile="" + for modpath in "${ESELECT_MODULES_PATH[@]}" ; do + modfile="${modpath}/${modname}.eselect" + [[ -f ${modfile} ]] && break + done + [[ -f ${modfile} ]] || return 1 # 404 File not found, so theres no way we get the info we need + + + # We're looking for an action; In short: "eselect somemodule " + if [[ $((COMP_CWORD-module_index)) -eq 1 ]] ; then + possibles+=" ${ESELECT_KNOWN_ACTIONS}" # Include default actions + + # module-actions are simple bash functions in the module-file. + # They follow the pattern "do_${action}()" and "do_${action} ()" respectively + possibles+=" " + possibles+=$(sed -n -e 's/^do_\([^ _\(]\+\).*/\1/p' ${modfile}) + + # We're looking for an option. + # In short: "eselect somemodule someaction " + else + local action=${COMP_WORDS[module_index+1]} + + possibles+=" " + possibles+=$( + source ${modfile} &> /dev/null + # functions describing options follow the pattern "describe_${action}_options()" + if [[ $(type -t "describe_${action}_options" ) == "function" ]] ; then + # we're only interested in --options-like-this + # TODO The regexp could be improved to match only single "-" between letters + echo $(describe_${action}_options | sed -n -e 's/^.*--\([[:alpha:]-]\+\).*/--\1/p') + fi + ) + fi + fi + + # If we already completed something, remove already used words from completion. + if [[ ${COMP_CWORD} -ge 2 ]] ; then + # Our delete candidates are ${COMP_WORDS[@] without the first ("eselect") and last word ("$curr") + local delete_candidates="${COMP_WORDS[@]:1:${COMP_CWORD}-1}" + # Convert delete candidates to regexp + delete_candidates=${delete_candidates//[[:space:]]/"|"} + # Delete candidates begone! + possibles=${possibles//@($delete_candidates)/""} + # When removing a word, the delimiting spaces remain. Remove them aswell + possibles=${possibles//" "/" "} + fi - return 0 + COMPREPLY=( $(compgen -W "${possibles}" -- ${curr}) ) + + return 0 } + complete -F _eselect eselect -# vim: set ft=sh tw=80 sw=4 et :