# cvs(1) completion have cvs && { set_prefix() { [ -z ${prefix:-} ] || prefix=${cur%/*}/ [ -r ${prefix:-}CVS/Entries ] || prefix="" } get_entries() { local IFS=$'\n' [ -r ${prefix:-}CVS/Entries ] && \ entries=$(cut -d/ -f2 -s ${prefix:-}CVS/Entries) } get_modules() { if [ -n "$prefix" ]; then COMPREPLY=( $( command ls -d ${cvsroot}/${prefix}/!(CVSROOT) ) ) else COMPREPLY=( $( command ls -d ${cvsroot}/!(CVSROOT) ) ) fi } _cvs() { local cur count mode i cvsroot cvsroots pwd local -a flags miss files entries changed newremoved COMPREPLY=() cur=`_get_cword` count=0 for i in "${COMP_WORDS[@]}"; do [ $count -eq $COMP_CWORD ] && break # Last parameter was the CVSROOT, now go back to mode selection if [ "${COMP_WORDS[((count))]}" == "$cvsroot" -a "$mode" == "cvsroot" ]; then mode="" fi if [ -z "$mode" ]; then case $i in -d) mode=cvsroot cvsroot=${COMP_WORDS[((count+1))]} ;; @(ad?(d)|new)) mode=add ;; @(adm?(in)|rcs)) mode=admin ;; ann?(notate)) mode=annotate ;; @(checkout|co|get)) mode=checkout ;; @(com?(mit)|ci)) mode=commit ;; di?(f?(f))) mode=diff ;; ex?(p?(ort))) mode=export ;; ?(un)edit) mode=$i ;; hi?(s?(tory))) mode=history ;; im?(p?(ort))) mode=import ;; re?(l?(ease))) mode=release ;; ?(r)log) mode=log ;; @(rdiff|patch)) mode=rdiff ;; @(remove|rm|delete)) mode=remove ;; @(rtag|rfreeze)) mode=rtag ;; st?(at?(us))) mode=status ;; @(tag|freeze)) mode=tag ;; up?(d?(ate))) mode=update ;; *) ;; esac elif [[ "$i" = -* ]]; then flags=( "${flags[@]}" $i ) fi count=$((++count)) done case "$mode" in add) if [[ "$cur" != -* ]]; then set_prefix if [ $COMP_CWORD -gt 1 -a -r ${prefix:-}CVS/Entries ]; then get_entries [ -z "$cur" ] && \ files=$( command ls -Ad !(CVS) ) || \ files=$( command ls -d ${cur}* 2>/dev/null ) for i in "${entries[@]}"; do files=( ${files[@]/#$i//} ) done COMPREPLY=( $( compgen -X '*~' -W '${files[@]}' -- \ $cur ) ) fi else COMPREPLY=( $( compgen -W '-k -m' -- "$cur" ) ) fi ;; admin) if [[ "$cur" = -* ]]; then COMPREPLY=( $( compgen -W '-i -a -A -e -b -c -k -l -u \ -L -U -m -M -n -N -o -q -I \ -s -t -t- -T -V -x -z' -- \ $cur ) ) fi ;; annotate) if [[ "$cur" = -* ]]; then COMPREPLY=( $( compgen -W '-D -F -f -l -R -r' -- "$cur" ) ) else get_entries COMPREPLY=( $( compgen -W '${entries[@]}' -- "$cur" ) ) fi ;; checkout) if [[ "$cur" != -* ]]; then [ -z "$cvsroot" ] && cvsroot=$CVSROOT COMPREPLY=( $( cvs -d "$cvsroot" co -c 2> /dev/null | \ awk '{print $1}' ) ) COMPREPLY=( $( compgen -W '${COMPREPLY[@]}' -- "$cur" ) ) else COMPREPLY=( $( compgen -W '-A -N -P -R -c -f -l -n -p \ -s -r -D -d -k -j' -- "$cur" ) ) fi ;; commit) set_prefix if [[ "$cur" != -* ]] && [ -r ${prefix:-}CVS/Entries ]; then # if $COMP_CVS_REMOTE is not null, 'cvs commit' will # complete on remotely checked-out files (requires # passwordless access to the remote repository if [ -n "${COMP_CVS_REMOTE:-}" ]; then # this is the least computationally intensive # way found so far, but other changes # (something other than changed/removed/new) # may be missing changed=( $( cvs -q diff --brief 2>&1 | \ sed -ne 's/^Files [^ ]* and \([^ ]*\) differ$/\1/p' ) ) newremoved=( $( cvs -q diff --brief 2>&1 | \ sed -ne 's/^cvs diff: \([^ ]*\) .*, no comparison available$/\1/p' ) ) COMPREPLY=( $( compgen -W '${changed[@]:-} \ ${newremoved[@]:-}' -- "$cur" ) ) else COMPREPLY=( $(compgen $default -- "$cur") ) fi else COMPREPLY=( $( compgen -W '-n -R -l -f -F -m -r' -- \ $cur ) ) fi ;; cvsroot) if [ -r ~/.cvspass ]; then # Ugly escaping because of bash treating ':' specially cvsroots=$( sed 's/^[^ ]* //; s/:/\\:/g' ~/.cvspass ) COMPREPLY=( $( compgen -W '$cvsroots' -- "$cur" ) ) fi ;; export) if [[ "$cur" != -* ]]; then [ -z "$cvsroot" ] && cvsroot=$CVSROOT COMPREPLY=( $( cvs -d "$cvsroot" co -c | awk '{print $1}' ) ) COMPREPLY=( $( compgen -W '${COMPREPLY[@]}' -- "$cur" ) ) else COMPREPLY=( $( compgen -W '-N -f -l -R -n \ -r -D -d -k' -- "$cur" ) ) fi ;; diff) if [[ "$cur" == -* ]]; then _longopt diff else get_entries COMPREPLY=( $( compgen -W '${entries[@]:-}' -- "$cur" ) ) fi ;; remove) if [[ "$cur" != -* ]]; then set_prefix if [ $COMP_CWORD -gt 1 -a -r ${prefix:-}CVS/Entries ]; then get_entries # find out what files are missing for i in "${entries[@]}"; do [ ! -r "$i" ] && miss=( "${miss[@]}" $i ) done COMPREPLY=( $(compgen -W '${miss[@]:-}' -- "$cur") ) fi else COMPREPLY=( $( compgen -W '-f -l -R' -- "$cur" ) ) fi ;; import) if [[ "$cur" != -* ]]; then # starts with same algorithm as checkout [ -z "$cvsroot" ] && cvsroot=$CVSROOT prefix=${cur%/*} if [ -r ${cvsroot}/${prefix} ]; then get_modules COMPREPLY=( ${COMPREPLY[@]#$cvsroot} ) COMPREPLY=( ${COMPREPLY[@]#\/} ) fi pwd=$( pwd ) pwd=${pwd##*/} COMPREPLY=( $( compgen -W '${COMPREPLY[@]} $pwd' -- \ $cur ) ) else COMPREPLY=( $( compgen -W '-d -k -I -b -m -W' -- "$cur" )) fi ;; update) if [[ "$cur" = -* ]]; then COMPREPLY=( $( compgen -W '-A -P -C -d -f -l -R -p \ -k -r -D -j -I -W' -- \ "$cur" ) ) fi ;; "") COMPREPLY=( $( compgen -W 'add admin annotate checkout ci co \ commit diff delete edit export \ freeze get history import log new \ patch rcs rdiff release remove \ rfreeze rlog rm rtag stat status \ tag unedit up update -H -Q -q -b \ -d -e -f -l -n -t -r -v -w -x -z \ --help --version' -- "$cur" ) ) ;; *) ;; esac return 0 } complete -F _cvs $default cvs } # Local variables: # mode: shell-script # sh-basic-offset: 8 # sh-indent-comment: t # indent-tabs-mode: t # End: # ex: ts=8 sw=8 noet filetype=sh