# cvs(1) completion -*- shell-script -*- _cvs_entries() { local prefix=${cur%/*}/ IFS=$'\n' [[ -e ${prefix:-}CVS/Entries ]] || prefix="" entries=( $( cut -d/ -f2 -s ${prefix:-}CVS/Entries 2>/dev/null ) ) if [[ $entries ]]; then entries=( "${entries[@]/#/${prefix:-}}" ) compopt -o filenames fi } _cvs_modules() { if [[ -n $prefix ]]; then COMPREPLY=( $( command ls -d ${cvsroot}/${prefix}/!(CVSROOT) ) ) else COMPREPLY=( $( command ls -d ${cvsroot}/!(CVSROOT) ) ) fi } _cvs_commands() { cvs --help-commands 2>&1 | awk '/^( *|\t)/ { print $1 }' } _cvs_command_options() { COMPREPLY=( $( compgen -W '$( _parse_help "$1" "--help $2" )' -- "$cur" ) ) } _cvs_kflags() { COMPREPLY=( $( compgen -W 'kv kvl k o b v' -- "$cur" ) ) } _cvs_roots() { local -a cvsroots cvsroots=( $CVSROOT ) [[ -r ~/.cvspass ]] && cvsroots+=( $( awk '{ print $2 }' ~/.cvspass ) ) [[ -r CVS/Root ]] && mapfile -tO ${#cvsroots[@]} cvsroots < CVS/Root COMPREPLY=( $( compgen -W '${cvsroots[@]}' -- "$cur" ) ) __ltrim_colon_completions "$cur" } _cvs() { local cur prev words cword _init_completion -n : || return local count mode i cvsroot cvsroots pwd local -a flags files entries changed newremoved count=0 for i in "${words[@]}"; do [[ $count -eq $cword ]] && break # Last parameter was the CVSROOT, now go back to mode selection if [[ "${words[((count))]}" == "$cvsroot" && "$mode" == cvsroot ]]; then mode="" fi if [[ -z $mode ]]; then case $i in -H|--help) COMPREPLY=( $( compgen -W "$( _cvs_commands )" -- "$cur" ) ) return 0 ;; -d) mode=cvsroot cvsroot=${words[((count+1))]} ;; add|ad|new) mode=add ;; admin|adm|rcs) mode=admin ;; annotate|ann|blame|rannotate|rann|ra) mode=annotate ;; checkout|co|get) mode=checkout ;; commit|ci|com) mode=commit ;; diff|di|dif) mode=diff ;; export|ex|exp) mode=export ;; edit|unedit|editors|logout|pserver|server|watch|watchers) mode=$i ;; history|hi|his) mode=history ;; import|im|imp) mode=import ;; log|lo|rlog|rl) mode=log ;; login|logon|lgn) mode=login ;; rdiff|patch|pa) mode=rdiff ;; release|re|rel) mode=release ;; remove|rm|delete) mode=remove ;; rtag|rt|rfreeze) mode=rtag ;; status|st|stat) mode=status ;; tag|ta|freeze) mode=tag ;; update|up|upd) mode=update ;; version|ve|ver) mode=version ;; esac elif [[ "$i" == -* ]]; then flags+=( $i ) fi count=$((++count)) done case $mode in add) case $prev in -m) return 0 ;; -k) _cvs_kflags return 0 ;; esac if [[ "$cur" != -* ]]; then _cvs_entries [[ -z $cur ]] && files=( !(CVS) ) || \ files=( $( command ls -d ${cur}* 2>/dev/null ) ) local f for i in ${!files[@]}; do if [[ ${files[i]} == ?(*/)CVS ]]; then unset 'files[i]' else for f in "${entries[@]}"; do if [[ ${files[i]} == $f && ! -d $f ]]; then unset 'files[i]' break fi done fi done COMPREPLY=( $( compgen -X "$_backup_glob" -W '${files[@]}' \ -- "$cur" ) ) else _cvs_command_options "$1" $mode fi ;; admin) case $prev in -a|-A|-b|-c|-e|-l|-m|-n|-N|-o|-s|-t-|-u) return 0 ;; -t) _filedir return 0 ;; -k) _cvs_kflags return 0 ;; esac if [[ "$cur" == -* ]]; then _cvs_command_options "$1" $mode else _cvs_entries COMPREPLY=( $( compgen -W '${entries[@]}' -- "$cur" ) ) fi ;; annotate) [[ "$prev" == -[rD] ]] && return 0 if [[ "$cur" == -* ]]; then _cvs_command_options "$1" $mode else _cvs_entries COMPREPLY=( $( compgen -W '${entries[@]}' -- "$cur" ) ) fi ;; checkout) case $prev in -r|-D|-j) return 0 ;; -d) _filedir -d return 0 ;; -k) _cvs_kflags return 0 ;; esac 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 _cvs_command_options "$1" $mode fi ;; commit) case $prev in -m|-r) return 0 ;; -F) _filedir return 0 ;; esac if [[ "$cur" != -* ]]; 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 _cvs_entries COMPREPLY=( $( compgen -W '${entries[@]}' -- "$cur" ) ) fi else _cvs_command_options "$1" $mode fi ;; cvsroot) _cvs_roots ;; diff) if [[ "$cur" == -* ]]; then _cvs_command_options "$1" $mode [[ $COMPREPLY == *= ]] && compopt -o nospace else _cvs_entries COMPREPLY=( $( compgen -W '${entries[@]:-}' -- "$cur" ) ) fi ;; editors|watchers) if [[ "$cur" == -* ]]; then _cvs_command_options "$1" $mode else _cvs_entries COMPREPLY=( $( compgen -W '${entries[@]}' -- "$cur" ) ) fi ;; export) case $prev in -r|-D) return 0 ;; -d) _filedir -d return 0 ;; -k) _cvs_kflags return 0 ;; esac if [[ "$cur" != -* ]]; then [[ -z $cvsroot ]] && cvsroot=$CVSROOT COMPREPLY=( $( cvs -d "$cvsroot" co -c | awk '{print $1}' ) ) COMPREPLY=( $( compgen -W '${COMPREPLY[@]}' -- "$cur" ) ) else _cvs_command_options "$1" $mode fi ;; import) case $prev in -I|-b|-m|-W) return 0 ;; -k) _cvs_kflags return 0 ;; esac if [[ "$cur" != -* ]]; then # starts with same algorithm as checkout [[ -z $cvsroot ]] && cvsroot=$CVSROOT local prefix=${cur%/*} if [[ -r ${cvsroot}/${prefix} ]]; then _cvs_modules COMPREPLY=( ${COMPREPLY[@]#$cvsroot} ) COMPREPLY=( ${COMPREPLY[@]#\/} ) fi pwd=$( pwd ) pwd=${pwd##*/} COMPREPLY=( $( compgen -W '${COMPREPLY[@]} $pwd' -- "$cur" ) ) else _cvs_command_options "$1" $mode fi ;; remove) if [[ "$cur" != -* ]]; then _cvs_entries if [[ "$prev" != -f ]]; then # find out what files are missing for i in ${!entries[@]}; do [[ -r "${entries[i]}" ]] && unset 'entries[i]' done fi COMPREPLY=( $( compgen -W '${entries[@]:-}' -- "$cur" ) ) else _cvs_command_options "$1" $mode fi ;; update) case $prev in -r|-D|-j|-I|-W) return 0 ;; -k) _cvs_kflags return 0 ;; esac if [[ "$cur" == -* ]]; then _cvs_command_options "$1" $mode else _cvs_entries COMPREPLY=( $( compgen -W '${entries[@]}' -- "$cur" ) ) fi ;; "") case $prev in -T) _filedir -d return 0 ;; -e|-s) return 0 ;; -z) COMPREPLY=( $( compgen -W '{1..9}' -- "$cur" ) ) return 0 ;; esac COMPREPLY=( $( compgen -W '$( _cvs_commands ) $( _parse_help "$1" --help-options ) --help --help-commands --help-options --version' -- "$cur" ) ) ;; esac return 0 } && complete -F _cvs cvs # ex: ts=4 sw=4 et filetype=sh