#!/usr/bin/env bash # # Based on the programmed completion for bash to use quilt. # Copyright 2003-2004 Martin Quinson (martin quinson#debian org) # # This file is part of the distribution of quilt, and is distributed under # the same licence than quilt itself # # Apart from that it looks like it contains stuff from /etc/bash_completion. # Adopted to Cogito by Jonas Fonseca , 2006-02-03 if type cg &> /dev/null ; then _cg() { local __cg_path="$(type -P cg)" local __cg_dir="$(git-rev-parse --git-dir)" || return 0 local __cg_cmd= local cur=${COMP_WORDS[COMP_CWORD]} local prev=${COMP_WORDS[COMP_CWORD-1]} local specs= COMPREPLY=() __cg_cmd_lookup() { for words in ${COMP_WORDS[@]}; do for cmd in $(__cg_cmds); do if [ "$words" = "$cmd" ]; then echo "$cmd" return fi done done } # Grab the arguments from the USAGE line. __cg_raw_usage() { # __cg_cmd is empty for the cg program local path="$__cg_path${__cg_cmd:+-$__cg_cmd}" sed -n '/^USAGE=/,0s/.*"cg-[^ ]* \(.*\)"/\1/p' < "$path" } # Convert the argument synopsis from USAGE to argument list __cg_opts() { __cg_raw_usage | tr '[|]' '\n' | \ sed -n 's/^\(-[^ ]*\).*/\1/p' | sed 's/-uUSERNAME/-u/' echo "-h --help" } # List args and file, if USAGE contains "FILE" __cg_usage() { __cg_raw_usage | grep -q "FILE" && __cg_compfile __cg_opts } # List all Cogito commands __cg_cmds() { ls "$__cg_path"-* | sed "s#$__cg_path-##"; } __cg_objtype() { echo commit tree blob tag; } __cg_groups() { compgen -g -- "$cur"; } # List files in the $GIT_DIR/ sub directory. __cg_list() { local path="$__cg_dir/$1/" find "$path" -type f | while read line; do echo ${line#$path} done } # List first line of files in $GIT_DIR/ sub directory. __cg_list_content() { find "$__cg_dir/$1/" -type f | while read line; do head -n 1 ${line} done } # All of these should maybe be rate limited but only tags # is a problem for me. ;) --jonas __cg_tags() { __cg_list refs/tags | head -n 15; } __cg_heads() { __cg_list refs/heads; } __cg_refs() { __cg_heads; __cg_tags; echo HEAD; } __cg_branches() { __cg_list branches; } # FIXME: For interaction with GIT repos? __cg_remotes() { __cg_list remotes; } __cg_location() { # FIXME needs work, maybe pull in _known_hosts # if it is defined echo "git:// git+ssh:// http:// rsync://" __cg_dir __cg_list_content branches } # List directories. __cg_dir() { # FIXME: Tilde expansion _expand compgen -d -- "$cur" | sed '/^.git$/d' echo "~" # | while read dir; do # echo "$dir/" #done } # Complete on files, not on directories # # Directories are shown in completion, but with their trailing / so that # user can go in them. It ought to be a more standard way to achieve this. __cg_file() { # ignore compgen -f -- "$cur" echo $( compgen -d -- "$cur" ) | while read d ; do echo "$d/" done } __cg_newfile() { cg status -s '?' -n -w \ | sed "s,\($cur[^/]*\)/.*,\1," | sort -u | while read i; do compgen -f "$i" -- "$cur" done } __cg_complete() { for i in "$@"; do COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W "$(__cg_$i)" -- $cur ) ) done } __cg_cmd="$(__cg_cmd_lookup)" if [ "$COMP_CWORD" -eq 1 ]; then __cg_complete cmds opts return 0 fi # Complete depending on the this tiny specification: # # Syntax Example Completes # ------------------------------------------------------ # - -r=refs refs after -r # = 2=branches branches as 2nd arg # ... file|opts file and opts # # The last one is the default completion combo. case "$__cg_cmd" in "") specs="cmds|opts" ;; add) specs="newfile|opts" ;; admin-cat) specs="-r=refs file|opts" ;; admin-lsobj) specs="objtype|opts" ;; admin-ls) specs="-t=refs file|opts" ;; admin-setuprepo) specs="-g=groups dir|opts" ;; admin-uncommit) specs="refs|opts" ;; branch-add) specs="2=branches 3=location" ;; branch-chg) specs="2=branches 3=location" ;; clone) specs="location|opts" ;; commit) specs="-m= -c=refs file|opts" ;; diff) specs="-r=refs file|opts" ;; export) specs="-r=refs file" ;; fetch) specs="branches|opts" ;; help) specs="cmds|opts" ;; init) specs="-e= opts" ;; log) specs="-u= -d= -r=refs file|opts" ;; merge) specs="-b=refs branches|opts" ;; mkpatch) specs="-r=refs -d=dir opts" ;; object-id) specs="refs|opts" ;; patch) specs="opts" ;; push) specs="-t=tags -r=heads branches|opts" ;; reset) specs="opts" ;; restore) specs="-r=refs file|opts" ;; rm) specs="file|opts" ;; switch) specs="-r=refs refs|opts" ;; tag) specs="-d= -k= opts" ;; update) specs="branches|opts" ;; *) specs="usage" esac # The completion "parser". for spec in $specs; do local -a comps # First match options, both exact and catch all. Then look for # numeric position markers. Finally, just assume we hit the # default completion. case "$spec,$prev" in -*,"${spec%=*}") comps=("${spec#*=}") ;; -*) continue ;; "$COMP_CWORD"=*) comps=("${spec#*=}") ;; [0-9]*) continue ;; *) comps=(${spec//|/ }) esac __cg_complete ${comps[@]} return 0 done return 0 } fi # Enable proper file name completion if available. [ ${BASH_VERSINFO[0]} '>' 2 -o \ ${BASH_VERSINFO[0]} = 2 -a ${BASH_VERSINFO[1]} '>' 04 ] \ && __cg_complete_opt="-o filenames" complete -F _cg $__cg_complete_opt cg unset -v __cg_complete_opt