# ghc-pkg command line completion for bash # # Copyright 2006-2007 Lennart Kolmodin _ghc-pkg-get-ghc-pkg() { echo ghc-pkg } _ghc-pkg-pkg-fields() { # usage: _ghc-pkg-pkg-fields pkg-id # # list all fields of the pkg-id # same fields for all packages but different in different versions of # ghc-pkg? this can probably be done better/faster if [[ -z "$1" ]]; then echo "usage: _ghc-pkg-pkg-fields pkg-id" return 1 fi local fields fields="$( $(_ghc-pkg-get-ghc-pkg) describe $1 )" #if [[ fields != *"cannot find package"* ]]; then echo "$fields" | grep ".*:.*" | sed "s/^\(.*\):.*\$/\1/" #fi } _ghc-pkg-pkg-ids() { # usage: _ghc-pkg-pkg-ids # # simply lists all package ids known by ghc-pkg. $(_ghc-pkg-get-ghc-pkg) list --simple-output } _ghc-pkg-pkgs() { # usage: _ghc-pkg-pkgs [include-pkgs] [include-ids] # # with optional parameter include-pkgs it will list all packages known # to ghc-pkg. # with optional parameter include-ids it will list all package-ids known # to ghc-pkg. local pkgs local result pkgs=( $( _ghc-pkg-pkg-ids ) ) result=( ) local withPkgs="no" withIds="no" while [[ -n "$1" ]]; do case "$1" in include-pkgs) withPkgs="yes" ;; include-ids) withIds="yes" ;; *) echo "unknown parameter '$1' to _ghc-pkg-pkgs" return 1 ;; esac shift done # user must supply either include-pkgs, include-ids or both if [[ $withPkgs != "yes" && $withIds != "yes" ]]; then echo "usage: _ghc-pkg-pkgs [include-pkgs] [include-ids]" return 1 fi # find all packages if the user requested them if [[ $withPkgs == "yes" ]]; then # O(n^2) algorithm to exclude duplicates for p in ${pkgs[*]}; do p="${p//-[0-9.]*/}" for existing in ${result[*]}; do if [[ "$existing" == "$p" ]]; then continue 2 fi done result=( "${result[@]}" "${p}" ) done fi # include all pkg-ids if requested if [[ $withIds == "yes" ]]; then result=( "${result[@]}" "${pkgs[@]}" ) fi # we are finished, echo the result echo "${result[*]}" # happy ending return 0 } _ghc-pkg() { local cur cur=${COMP_WORDS[COMP_CWORD]} COMPREPLY=() local actions flags actions='register update unregister expose hide list latest describe field' dbflags="--user \ --global \ -f --package-conf= \ --global-conf=" registerflags="--force \ -g --auto-ghci-libs \ -D --define-name=" listflags="--simple-output" flags="$dbflags \ $registerflags \ $listflags \ -? --help \ -V --version" # if it's the users first word; complete it and return if (($COMP_CWORD == 1)); then COMPREPLY=( $( compgen -W "$actions $flags" -- $cur ) ) return 0 fi # now we know we have at least one word written local action="unknown" \ prev numwords \ cword act prev=${COMP_WORDS[COMP_CWORD-1]} numwords=${#COMP_WORDS[@]} # find the action with O(n*m) algorithm # where n = ${#COMP_WORDS[*]} # m = number of actions for cword in ${COMP_WORDS[*]}; do for act in $actions; do if [[ "$cword" == "$act" ]]; then action=$cword fi done done case $action in register|update) # we want to complete both flags and paths, how? # we do it by checking if the user has started to write a flag # or a path, and then decide what to complete. # that is, to complete a flag, the user must start to write a '-' if [[ "$cur" == -* ]]; then # (we assume) it's the start of a flag # set COMPREPLY to flags relevant to these actions COMPREPLY=( $( compgen -W "$dbflags $registerflags" -- $cur ) ) fi ;; unregister|expose|hide|list|describe) # all these actions can be completed with exactly one argument, # a pkg-id. COMPREPLY=( $( compgen -W "$dbflags" -- $cur ) ) # add special flags for some actions if [[ "$action" == "list" ]]; then COMPREPLY+=( $( compgen -W "$listflags" -- $cur ) ) fi COMPREPLY+=( $( compgen -W "$( _ghc-pkg-pkgs include-ids )" -- $cur ) ) ;; latest) # complete only packages, not package ids COMPREPLY=( $( compgen -W "$( _ghc-pkg-pkgs include-pkgs )" -- $cur ) ) ;; field) # we should always complete on the flags... COMPREPLY=( $( compgen -W "$dbflags" -- $cur ) ) # then, we should either complete the package name or the field # lets find out which one # find the number of words in COMP_WORDS before COMP_CWORD that # isn't flags. it should be 2 or 3 for us to complete it, # exactly 2 if we should complete the package name # exactly 3 if we should complete the field name # otherwise, don't do any additional completion except the # flags # count the number of non flags up till the current word local numnonflags=0 lastword i for (( i=0 ; $i < $COMP_CWORD ; i++ )); do if [[ ${COMP_WORDS[$i]} != -* ]]; then lastword=${COMP_WORDS[$i]} numnonflags=$(( ++numnonflags )) fi done case $numnonflags in 2) # complete on pkg-ids COMPREPLY+=( $( compgen -W "$( _ghc-pkg-pkgs include-ids )" -- $cur ) ) ;; 3) # complete on fields COMPREPLY+=( $( compgen -W "$( _ghc-pkg-pkg-fields $lastword )" -- $cur ) ) ;; esac ;; *) # unknown action, not yet given by the user # return all possible completions COMPREPLY=( $( compgen -W "$actions $flags" -- $cur ) ) ;; esac } complete -F _ghc-pkg -o default ghc-pkg # vim: set ft=sh tw=80 sw=4 et :