chiark / gitweb /
Add bash completion script for TopGit
authorJonas Fonseca <fonseca@diku.dk>
Thu, 25 Sep 2008 11:06:56 +0000 (13:06 +0200)
committerPetr Baudis <pasky@suse.cz>
Thu, 25 Sep 2008 13:21:45 +0000 (15:21 +0200)
The script is based on git's bash completion script.

Signed-off-by: Jonas Fonseca <fonseca@diku.dk>
contrib/tg-completion.bash [new file with mode: 0755]

diff --git a/contrib/tg-completion.bash b/contrib/tg-completion.bash
new file mode 100755 (executable)
index 0000000..35eabe9
--- /dev/null
@@ -0,0 +1,438 @@
+#
+# bash completion support for TopGit.
+#
+# Copyright (C) 2008 Jonas Fonseca <fonseca@diku.dk>
+# Copyright (C) 2006,2007 Shawn O. Pearce <spearce@spearce.org>
+# Based git's git-completion.sh: http://repo.or.cz/w/git/fastimport.git
+# Conceptually based on gitcompletion (http://gitweb.hawaga.org.uk/).
+# Distributed under the GNU General Public License, version 2.0.
+#
+# The contained completion routines provide support for completing:
+#
+#    *) local and remote branch names
+#    *) local and remote tag names
+#    *) .git/remotes file names
+#    *) git 'subcommands'
+#    *) tree paths within 'ref:path/to/file' expressions
+#    *) common --long-options
+#
+# To use these routines:
+#
+#    1) Copy this file to somewhere (e.g. ~/.git-completion.sh).
+#    2) Added the following line to your .bashrc:
+#        source ~/.git-completion.sh
+#
+#    3) You may want to make sure the git executable is available
+#       in your PATH before this script is sourced, as some caching
+#       is performed while the script loads.  If git isn't found
+#       at source time then all lookups will be done on demand,
+#       which may be slightly slower.
+#
+#    4) Consider changing your PS1 to also show the current branch:
+#        PS1='[\u@\h \W$(__tg_ps1 " (%s)")]\$ '
+#
+#       The argument to __tg_ps1 will be displayed only if you
+#       are currently in a git repository.  The %s token will be
+
+case "$COMP_WORDBREAKS" in
+*:*) : great ;;
+*)   COMP_WORDBREAKS="$COMP_WORDBREAKS:"
+esac
+
+### {{{ Utilities
+
+__tgdir ()
+{
+       if [ -z "$1" ]; then
+               if [ -n "$__tg_dir" ]; then
+                       echo "$__tg_dir"
+               elif [ -d .git ]; then
+                       echo .git
+               else
+                       git rev-parse --git-dir 2>/dev/null
+               fi
+       elif [ -d "$1/.git" ]; then
+               echo "$1/.git"
+       else
+               echo "$1"
+       fi
+}
+
+__tgcomp_1 ()
+{
+       local c IFS=' '$'\t'$'\n'
+       for c in $1; do
+               case "$c$2" in
+               --*=*) printf %s$'\n' "$c$2" ;;
+               *.)    printf %s$'\n' "$c$2" ;;
+               *)     printf %s$'\n' "$c$2 " ;;
+               esac
+       done
+}
+
+__tgcomp ()
+{
+       local cur="${COMP_WORDS[COMP_CWORD]}"
+       if [ $# -gt 2 ]; then
+               cur="$3"
+       fi
+       case "$cur" in
+       --*=)
+               COMPREPLY=()
+               ;;
+       *)
+               local IFS=$'\n'
+               COMPREPLY=($(compgen -P "$2" \
+                       -W "$(__tgcomp_1 "$1" "$4")" \
+                       -- "$cur"))
+               ;;
+       esac
+}
+
+__tg_heads ()
+{
+       local cmd i is_hash=y dir="$(__tgdir "$1")"
+       if [ -d "$dir" ]; then
+               git --git-dir="$dir" for-each-ref --format='%(refname:short)' \
+                       refs/heads
+               return
+       fi
+       for i in $(git ls-remote "$1" 2>/dev/null); do
+               case "$is_hash,$i" in
+               y,*) is_hash=n ;;
+               n,*^{}) is_hash=y ;;
+               n,refs/heads/*) is_hash=y; echo "${i#refs/heads/}" ;;
+               n,*) is_hash=y; echo "$i" ;;
+               esac
+       done
+}
+
+__tg_refs ()
+{
+       local cmd i is_hash=y dir="$(__tgdir "$1")"
+       if [ -d "$dir" ]; then
+               if [ -e "$dir/HEAD" ]; then echo HEAD; fi
+               git --git-dir="$dir" for-each-ref --format='%(refname:short)' \
+                       refs/tags refs/heads refs/remotes
+               return
+       fi
+       for i in $(git ls-remote "$dir" 2>/dev/null); do
+               case "$is_hash,$i" in
+               y,*) is_hash=n ;;
+               n,*^{}) is_hash=y ;;
+               n,refs/tags/*) is_hash=y; echo "${i#refs/tags/}" ;;
+               n,refs/heads/*) is_hash=y; echo "${i#refs/heads/}" ;;
+               n,refs/remotes/*) is_hash=y; echo "${i#refs/remotes/}" ;;
+               n,*) is_hash=y; echo "$i" ;;
+               esac
+       done
+}
+
+__tg_refs2 ()
+{
+       local i
+       for i in $(__tg_refs "$1"); do
+               echo "$i:$i"
+       done
+}
+
+__tg_refs_remotes ()
+{
+       local cmd i is_hash=y
+       for i in $(git ls-remote "$1" 2>/dev/null); do
+               case "$is_hash,$i" in
+               n,refs/heads/*)
+                       is_hash=y
+                       echo "$i:refs/remotes/$1/${i#refs/heads/}"
+                       ;;
+               y,*) is_hash=n ;;
+               n,*^{}) is_hash=y ;;
+               n,refs/tags/*) is_hash=y;;
+               n,*) is_hash=y; ;;
+               esac
+       done
+}
+
+__tg_remotes ()
+{
+       local i ngoff IFS=$'\n' d="$(__tgdir)"
+       shopt -q nullglob || ngoff=1
+       shopt -s nullglob
+       for i in "$d/remotes"/*; do
+               echo ${i#$d/remotes/}
+       done
+       [ "$ngoff" ] && shopt -u nullglob
+       for i in $(git --git-dir="$d" config --list); do
+               case "$i" in
+               remote.*.url=*)
+                       i="${i#remote.}"
+                       echo "${i/.url=*/}"
+                       ;;
+               esac
+       done
+}
+
+__tg_complete_revlist ()
+{
+       local pfx cur="${COMP_WORDS[COMP_CWORD]}"
+       case "$cur" in
+       *...*)
+               pfx="${cur%...*}..."
+               cur="${cur#*...}"
+               __tgcomp "$(__tg_refs)" "$pfx" "$cur"
+               ;;
+       *..*)
+               pfx="${cur%..*}.."
+               cur="${cur#*..}"
+               __tgcomp "$(__tg_refs)" "$pfx" "$cur"
+               ;;
+       *)
+               __tgcomp "$(__tg_refs)"
+               ;;
+       esac
+}
+
+__tg_topics ()
+{
+       tg summary | cut -f 2
+}
+
+__tg_commands ()
+{
+       if [ -n "$__tg_all_commandlist" ]; then
+               echo "$__tg_all_commandlist"
+               return
+       fi
+       local i IFS=" "$'\n'
+       for i in $(tg help | sed -n 's/^Usage:.*(\(.*\)).*/\1/p' | tr '|' ' ')
+       do
+               case $i in
+               *--*)             : helper pattern;;
+               *) echo $i;;
+               esac
+       done
+}
+__tg_all_commandlist=
+__tg_all_commandlist="$(__tg_commands 2>/dev/null)"
+
+__tg_complete_arg ()
+{
+       if [ $COMP_CWORD -gt 2 ] && [ "${COMP_WORDS[$COMP_CWORD - 1]}" = "$1" ]; then
+               return 0
+       fi
+       return 1
+}
+
+### }}}
+### {{{ Commands
+
+_tg_create ()
+{
+       local cmd="$1"
+       local cur="${COMP_WORDS[COMP_CWORD]}"
+
+       # Name must be the first arg after the create command
+       if [ $((cmd + 1)) = $COMP_CWORD ]; then
+               __tgcomp "$(__tg_topics)"
+               return
+       fi
+
+       __tg_complete_arg "-r" && {
+               __tgcomp "$(__tg_remotes)"
+               return
+       }
+
+       case "$cur" in
+       -*)
+               __tgcomp "
+                       -r
+               "
+               ;;
+       *)
+               __tgcomp "$(__tg_refs)"
+       esac
+}
+
+_tg_delete ()
+{
+       local cur="${COMP_WORDS[COMP_CWORD]}"
+
+       case "$cur" in
+       -*)
+               __tgcomp "
+                       -f
+               "
+               ;;
+       *)
+               __tgcomp "$(__tg_topics)"
+       esac
+}
+
+_tg_export ()
+{
+       local cur="${COMP_WORDS[COMP_CWORD]}"
+
+       __tg_complete_arg "--collapse" && {
+               __tgcomp "$(__tg_heads)"
+               return
+       }
+
+       __tg_complete_arg "--quilt" && {
+               return
+       }
+
+       case "$cur" in
+       *)
+               __tgcomp "
+                       --collapse
+                       --quilt
+               "
+       esac
+}
+
+_tg_help ()
+{
+       local cur="${COMP_WORDS[COMP_CWORD]}"
+       case "$cur" in
+       -*)
+               COMPREPLY=()
+               return
+               ;;
+       esac
+       __tgcomp "$(__tg_commands)"
+}
+
+_tg_import ()
+{
+       local cur="${COMP_WORDS[COMP_CWORD]}"
+
+       __tg_complete_arg "-p" && {
+               COMPREPLY=()
+               return
+       }
+
+       case "$cur" in
+       -*)
+               __tgcomp "
+                       -p
+               "
+               ;;
+       *)
+               __tg_complete_revlist
+       esac
+}
+
+_tg_info ()
+{
+       local cur="${COMP_WORDS[COMP_CWORD]}"
+
+       case "$cur" in
+       *)
+               __tgcomp "$(__tg_topics)"
+       esac
+}
+
+_tg_mail ()
+{
+       local cur="${COMP_WORDS[COMP_CWORD]}"
+
+       case "$cur" in
+       *)
+               __tgcomp "$(__tg_topics)"
+       esac
+}
+
+_tg_patch ()
+{
+       local cur="${COMP_WORDS[COMP_CWORD]}"
+
+       case "$cur" in
+       *)
+               __tgcomp "$(__tg_topics)"
+       esac
+}
+
+_tg_remote ()
+{
+       local cur="${COMP_WORDS[COMP_CWORD]}"
+
+       case "$cur" in
+       *)
+               __tgcomp "$(__tg_remotes)"
+       esac
+}
+
+_tg_summary ()
+{
+       COMPREPLY=()
+}
+
+_tg_update ()
+{
+       COMPREPLY=()
+}
+
+### }}}
+### {{{ tg completion
+
+_tg ()
+{
+       local i c=1 command __tg_dir
+
+       while [ $c -lt $COMP_CWORD ]; do
+               i="${COMP_WORDS[c]}"
+               case "$i" in
+               -r) 
+                       c=$((++c))
+                       if [ $c -lt $COMP_CWORD ]; then
+                               __tgcomp "$(__tg_remotes)"
+                               return
+                       fi
+                       ;;
+               -h|--help) command="help"; break ;;
+               *) command="$i"; break ;;
+               esac
+               c=$((++c))
+       done
+
+       if [ -z "$command" ]; then
+               case "${COMP_WORDS[COMP_CWORD]}" in
+               -*)     __tgcomp "
+                               -r
+                               -h
+                               --help
+                       "
+                       ;;
+               *)     __tgcomp "$(__tg_commands)" ;;
+               esac
+               return
+       fi
+
+       case "$command" in
+       create)      _tg_create "$c" ;;
+       delete)      _tg_delete ;;
+       export)      _tg_export ;;
+       help)        _tg_help ;;
+       import)      _tg_import ;;
+       info)        _tg_info ;;
+       mail)        _tg_mail ;;
+       patch)       _tg_patch ;;
+       remote)      _tg_remote ;;
+       summary)     _tg_summary ;;
+       update)      _tg_update ;;
+       *)           COMPREPLY=() ;;
+       esac
+}
+
+### }}}
+
+       __tgcomp "$(__tg_refs top-bases)"
+complete -o default -o nospace -F _tg tg
+
+# The following are necessary only for Cygwin, and only are needed
+# when the user has tab-completed the executable name and consequently
+# included the '.exe' suffix.
+#
+if [ Cygwin = "$(uname -o 2>/dev/null)" ]; then
+complete -o default -o nospace -F _tg tg.exe
+fi