{"thread":{"id":"15671","subject":"[TG RFC PATCH] Add bash completion script for TopGit","startedAt":"2008-09-25T11:06:56Z","lastAt":"2008-09-25T13:47:06Z","messageCount":2,"participants":["Jonas Fonseca"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"91576","messageId":"20080925110656.GB12949@diku.dk","threadId":"15671","inReplyTo":null,"subject":"[TG RFC PATCH] Add bash completion script for TopGit","fromName":"Jonas Fonseca","fromEmail":"fonseca@diku.dk","sentAt":"2008-09-25T11:06:56Z","receivedAt":"2008-09-25T11:06:56Z","isPatch":true,"sender":{"key":"fonseca@diku.dk","avatar":"https://gravatar.com/avatar/f82f3ad698717c51873b020c750a92438c820a24056dc39fe4d07baa10a92264?d=mp&s=160"},"body":"The script is based on git's bash completion script.\n\nSigned-off-by: Jonas Fonseca <fonseca@diku.dk>\n---\n contrib/tg-completion.bash |  438 ++++++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 438 insertions(+), 0 deletions(-)\n create mode 100755 contrib/tg-completion.bash\n\n I have RFC'd this because I am still a topgit noob.\n \ndiff --git a/contrib/tg-completion.bash b/contrib/tg-completion.bash\nnew file mode 100755\nindex 0000000..35eabe9\n--- /dev/null\n+++ b/contrib/tg-completion.bash\n@@ -0,0 +1,438 @@\n+#\n+# bash completion support for TopGit.\n+#\n+# Copyright (C) 2008 Jonas Fonseca <fonseca@diku.dk>\n+# Copyright (C) 2006,2007 Shawn O. Pearce <spearce@spearce.org>\n+# Based git's git-completion.sh: http://repo.or.cz/w/git/fastimport.git\n+# Conceptually based on gitcompletion (http://gitweb.hawaga.org.uk/).\n+# Distributed under the GNU General Public License, version 2.0.\n+#\n+# The contained completion routines provide support for completing:\n+#\n+#    *) local and remote branch names\n+#    *) local and remote tag names\n+#    *) .git/remotes file names\n+#    *) git 'subcommands'\n+#    *) tree paths within 'ref:path/to/file' expressions\n+#    *) common --long-options\n+#\n+# To use these routines:\n+#\n+#    1) Copy this file to somewhere (e.g. ~/.git-completion.sh).\n+#    2) Added the following line to your .bashrc:\n+#        source ~/.git-completion.sh\n+#\n+#    3) You may want to make sure the git executable is available\n+#       in your PATH before this script is sourced, as some caching\n+#       is performed while the script loads.  If git isn't found\n+#       at source time then all lookups will be done on demand,\n+#       which may be slightly slower.\n+#\n+#    4) Consider changing your PS1 to also show the current branch:\n+#        PS1='[\\u@\\h \\W$(__tg_ps1 \" (%s)\")]\\$ '\n+#\n+#       The argument to __tg_ps1 will be displayed only if you\n+#       are currently in a git repository.  The %s token will be\n+\n+case \"$COMP_WORDBREAKS\" in\n+*:*) : great ;;\n+*)   COMP_WORDBREAKS=\"$COMP_WORDBREAKS:\"\n+esac\n+\n+### {{{ Utilities\n+\n+__tgdir ()\n+{\n+\tif [ -z \"$1\" ]; then\n+\t\tif [ -n \"$__tg_dir\" ]; then\n+\t\t\techo \"$__tg_dir\"\n+\t\telif [ -d .git ]; then\n+\t\t\techo .git\n+\t\telse\n+\t\t\tgit rev-parse --git-dir 2>/dev/null\n+\t\tfi\n+\telif [ -d \"$1/.git\" ]; then\n+\t\techo \"$1/.git\"\n+\telse\n+\t\techo \"$1\"\n+\tfi\n+}\n+\n+__tgcomp_1 ()\n+{\n+\tlocal c IFS=' '$'\\t'$'\\n'\n+\tfor c in $1; do\n+\t\tcase \"$c$2\" in\n+\t\t--*=*) printf %s$'\\n' \"$c$2\" ;;\n+\t\t*.)    printf %s$'\\n' \"$c$2\" ;;\n+\t\t*)     printf %s$'\\n' \"$c$2 \" ;;\n+\t\tesac\n+\tdone\n+}\n+\n+__tgcomp ()\n+{\n+\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\tif [ $# -gt 2 ]; then\n+\t\tcur=\"$3\"\n+\tfi\n+\tcase \"$cur\" in\n+\t--*=)\n+\t\tCOMPREPLY=()\n+\t\t;;\n+\t*)\n+\t\tlocal IFS=$'\\n'\n+\t\tCOMPREPLY=($(compgen -P \"$2\" \\\n+\t\t\t-W \"$(__tgcomp_1 \"$1\" \"$4\")\" \\\n+\t\t\t-- \"$cur\"))\n+\t\t;;\n+\tesac\n+}\n+\n+__tg_heads ()\n+{\n+\tlocal cmd i is_hash=y dir=\"$(__tgdir \"$1\")\"\n+\tif [ -d \"$dir\" ]; then\n+\t\tgit --git-dir=\"$dir\" for-each-ref --format='%(refname:short)' \\\n+\t\t\trefs/heads\n+\t\treturn\n+\tfi\n+\tfor i in $(git ls-remote \"$1\" 2>/dev/null); do\n+\t\tcase \"$is_hash,$i\" in\n+\t\ty,*) is_hash=n ;;\n+\t\tn,*^{}) is_hash=y ;;\n+\t\tn,refs/heads/*) is_hash=y; echo \"${i#refs/heads/}\" ;;\n+\t\tn,*) is_hash=y; echo \"$i\" ;;\n+\t\tesac\n+\tdone\n+}\n+\n+__tg_refs ()\n+{\n+\tlocal cmd i is_hash=y dir=\"$(__tgdir \"$1\")\"\n+\tif [ -d \"$dir\" ]; then\n+\t\tif [ -e \"$dir/HEAD\" ]; then echo HEAD; fi\n+\t\tgit --git-dir=\"$dir\" for-each-ref --format='%(refname:short)' \\\n+\t\t\trefs/tags refs/heads refs/remotes\n+\t\treturn\n+\tfi\n+\tfor i in $(git ls-remote \"$dir\" 2>/dev/null); do\n+\t\tcase \"$is_hash,$i\" in\n+\t\ty,*) is_hash=n ;;\n+\t\tn,*^{}) is_hash=y ;;\n+\t\tn,refs/tags/*) is_hash=y; echo \"${i#refs/tags/}\" ;;\n+\t\tn,refs/heads/*) is_hash=y; echo \"${i#refs/heads/}\" ;;\n+\t\tn,refs/remotes/*) is_hash=y; echo \"${i#refs/remotes/}\" ;;\n+\t\tn,*) is_hash=y; echo \"$i\" ;;\n+\t\tesac\n+\tdone\n+}\n+\n+__tg_refs2 ()\n+{\n+\tlocal i\n+\tfor i in $(__tg_refs \"$1\"); do\n+\t\techo \"$i:$i\"\n+\tdone\n+}\n+\n+__tg_refs_remotes ()\n+{\n+\tlocal cmd i is_hash=y\n+\tfor i in $(git ls-remote \"$1\" 2>/dev/null); do\n+\t\tcase \"$is_hash,$i\" in\n+\t\tn,refs/heads/*)\n+\t\t\tis_hash=y\n+\t\t\techo \"$i:refs/remotes/$1/${i#refs/heads/}\"\n+\t\t\t;;\n+\t\ty,*) is_hash=n ;;\n+\t\tn,*^{}) is_hash=y ;;\n+\t\tn,refs/tags/*) is_hash=y;;\n+\t\tn,*) is_hash=y; ;;\n+\t\tesac\n+\tdone\n+}\n+\n+__tg_remotes ()\n+{\n+\tlocal i ngoff IFS=$'\\n' d=\"$(__tgdir)\"\n+\tshopt -q nullglob || ngoff=1\n+\tshopt -s nullglob\n+\tfor i in \"$d/remotes\"/*; do\n+\t\techo ${i#$d/remotes/}\n+\tdone\n+\t[ \"$ngoff\" ] && shopt -u nullglob\n+\tfor i in $(git --git-dir=\"$d\" config --list); do\n+\t\tcase \"$i\" in\n+\t\tremote.*.url=*)\n+\t\t\ti=\"${i#remote.}\"\n+\t\t\techo \"${i/.url=*/}\"\n+\t\t\t;;\n+\t\tesac\n+\tdone\n+}\n+\n+__tg_complete_revlist ()\n+{\n+\tlocal pfx cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\tcase \"$cur\" in\n+\t*...*)\n+\t\tpfx=\"${cur%...*}...\"\n+\t\tcur=\"${cur#*...}\"\n+\t\t__tgcomp \"$(__tg_refs)\" \"$pfx\" \"$cur\"\n+\t\t;;\n+\t*..*)\n+\t\tpfx=\"${cur%..*}..\"\n+\t\tcur=\"${cur#*..}\"\n+\t\t__tgcomp \"$(__tg_refs)\" \"$pfx\" \"$cur\"\n+\t\t;;\n+\t*)\n+\t\t__tgcomp \"$(__tg_refs)\"\n+\t\t;;\n+\tesac\n+}\n+\n+__tg_topics ()\n+{\n+\ttg summary | cut -f 2\n+}\n+\n+__tg_commands ()\n+{\n+\tif [ -n \"$__tg_all_commandlist\" ]; then\n+\t\techo \"$__tg_all_commandlist\"\n+\t\treturn\n+\tfi\n+\tlocal i IFS=\" \"$'\\n'\n+\tfor i in $(tg help | sed -n 's/^Usage:.*(\\(.*\\)).*/\\1/p' | tr '|' ' ')\n+\tdo\n+\t\tcase $i in\n+\t\t*--*)             : helper pattern;;\n+\t\t*) echo $i;;\n+\t\tesac\n+\tdone\n+}\n+__tg_all_commandlist=\n+__tg_all_commandlist=\"$(__tg_commands 2>/dev/null)\"\n+\n+__tg_complete_arg ()\n+{\n+\tif [ $COMP_CWORD -gt 2 ] && [ \"${COMP_WORDS[$COMP_CWORD - 1]}\" = \"$1\" ]; then\n+\t\treturn 0\n+\tfi\n+\treturn 1\n+}\n+\n+### }}}\n+### {{{ Commands\n+\n+_tg_create ()\n+{\n+\tlocal cmd=\"$1\"\n+\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\n+\t# Name must be the first arg after the create command\n+\tif [ $((cmd + 1)) = $COMP_CWORD ]; then\n+\t\t__tgcomp \"$(__tg_topics)\"\n+\t\treturn\n+\tfi\n+\n+\t__tg_complete_arg \"-r\" && {\n+\t\t__tgcomp \"$(__tg_remotes)\"\n+\t\treturn\n+\t}\n+\n+\tcase \"$cur\" in\n+\t-*)\n+\t\t__tgcomp \"\n+\t\t\t-r\n+\t\t\"\n+\t\t;;\n+\t*)\n+\t\t__tgcomp \"$(__tg_refs)\"\n+\tesac\n+}\n+\n+_tg_delete ()\n+{\n+\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\n+\tcase \"$cur\" in\n+\t-*)\n+\t\t__tgcomp \"\n+\t\t\t-f\n+\t\t\"\n+\t\t;;\n+\t*)\n+\t\t__tgcomp \"$(__tg_topics)\"\n+\tesac\n+}\n+\n+_tg_export ()\n+{\n+\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\n+\t__tg_complete_arg \"--collapse\" && {\n+\t\t__tgcomp \"$(__tg_heads)\"\n+\t\treturn\n+\t}\n+\n+\t__tg_complete_arg \"--quilt\" && {\n+\t\treturn\n+\t}\n+\n+\tcase \"$cur\" in\n+\t*)\n+\t\t__tgcomp \"\n+\t\t\t--collapse\n+\t\t\t--quilt\n+\t\t\"\n+\tesac\n+}\n+\n+_tg_help ()\n+{\n+\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\tcase \"$cur\" in\n+\t-*)\n+\t\tCOMPREPLY=()\n+\t\treturn\n+\t\t;;\n+\tesac\n+\t__tgcomp \"$(__tg_commands)\"\n+}\n+\n+_tg_import ()\n+{\n+\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\n+\t__tg_complete_arg \"-p\" && {\n+\t\tCOMPREPLY=()\n+\t\treturn\n+\t}\n+\n+\tcase \"$cur\" in\n+\t-*)\n+\t\t__tgcomp \"\n+\t\t\t-p\n+\t\t\"\n+\t\t;;\n+\t*)\n+\t\t__tg_complete_revlist\n+\tesac\n+}\n+\n+_tg_info ()\n+{\n+\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\n+\tcase \"$cur\" in\n+\t*)\n+\t\t__tgcomp \"$(__tg_topics)\"\n+\tesac\n+}\n+\n+_tg_mail ()\n+{\n+\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\n+\tcase \"$cur\" in\n+\t*)\n+\t\t__tgcomp \"$(__tg_topics)\"\n+\tesac\n+}\n+\n+_tg_patch ()\n+{\n+\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\n+\tcase \"$cur\" in\n+\t*)\n+\t\t__tgcomp \"$(__tg_topics)\"\n+\tesac\n+}\n+\n+_tg_remote ()\n+{\n+\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\n+\tcase \"$cur\" in\n+\t*)\n+\t\t__tgcomp \"$(__tg_remotes)\"\n+\tesac\n+}\n+\n+_tg_summary ()\n+{\n+\tCOMPREPLY=()\n+}\n+\n+_tg_update ()\n+{\n+\tCOMPREPLY=()\n+}\n+\n+### }}}\n+### {{{ tg completion\n+\n+_tg ()\n+{\n+\tlocal i c=1 command __tg_dir\n+\n+\twhile [ $c -lt $COMP_CWORD ]; do\n+\t\ti=\"${COMP_WORDS[c]}\"\n+\t\tcase \"$i\" in\n+\t\t-r) \n+\t\t\tc=$((++c))\n+\t\t\tif [ $c -lt $COMP_CWORD ]; then\n+\t\t\t\t__tgcomp \"$(__tg_remotes)\"\n+\t\t\t\treturn\n+\t\t\tfi\n+\t\t\t;;\n+\t\t-h|--help) command=\"help\"; break ;;\n+\t\t*) command=\"$i\"; break ;;\n+\t\tesac\n+\t\tc=$((++c))\n+\tdone\n+\n+\tif [ -z \"$command\" ]; then\n+\t\tcase \"${COMP_WORDS[COMP_CWORD]}\" in\n+\t\t-*)\t__tgcomp \"\n+\t\t\t\t-r\n+\t\t\t\t-h\n+\t\t\t\t--help\n+\t\t\t\"\n+\t\t\t;;\n+\t\t*)     __tgcomp \"$(__tg_commands)\" ;;\n+\t\tesac\n+\t\treturn\n+\tfi\n+\n+\tcase \"$command\" in\n+\tcreate)      _tg_create \"$c\" ;;\n+\tdelete)      _tg_delete ;;\n+\texport)      _tg_export ;;\n+\thelp)        _tg_help ;;\n+\timport)      _tg_import ;;\n+\tinfo)        _tg_info ;;\n+\tmail)        _tg_mail ;;\n+\tpatch)       _tg_patch ;;\n+\tremote)      _tg_remote ;;\n+\tsummary)     _tg_summary ;;\n+\tupdate)      _tg_update ;;\n+\t*)           COMPREPLY=() ;;\n+\tesac\n+}\n+\n+### }}}\n+\n+\t__tgcomp \"$(__tg_refs top-bases)\"\n+complete -o default -o nospace -F _tg tg\n+\n+# The following are necessary only for Cygwin, and only are needed\n+# when the user has tab-completed the executable name and consequently\n+# included the '.exe' suffix.\n+#\n+if [ Cygwin = \"$(uname -o 2>/dev/null)\" ]; then\n+complete -o default -o nospace -F _tg tg.exe\n+fi\n-- \n1.6.0.2.471.g47a76.dirty\n\n\n-- \nJonas Fonseca\n"},{"id":"91594","messageId":"20080925134706.GA16533@diku.dk","threadId":"15671","inReplyTo":"20080925110656.GB12949@diku.dk","subject":"[TG PATCH] Complete depend subcommand","fromName":"Jonas Fonseca","fromEmail":"fonseca@diku.dk","sentAt":"2008-09-25T13:47:06Z","receivedAt":"2008-09-25T13:47:06Z","isPatch":true,"sender":{"key":"fonseca@diku.dk","avatar":"https://gravatar.com/avatar/f82f3ad698717c51873b020c750a92438c820a24056dc39fe4d07baa10a92264?d=mp&s=160"},"body":"Also, removes a debug line and fixes the script header.\n\nSigned-off-by: Jonas Fonseca <fonseca@diku.dk>\n\n---\n contrib/tg-completion.bash |   60 ++++++++++++++++++++++++++-----------------\n 1 files changed, 36 insertions(+), 24 deletions(-)\n\n The completion of the depend command didn't make it into the first\n patch because I had a broken topgit usage. Here is a resend, which\n also amends the script header.\n\ndiff --git a/contrib/tg-completion.bash b/contrib/tg-completion.bash\nindex 35eabe9..59fbc50 100755\n--- a/contrib/tg-completion.bash\n+++ b/contrib/tg-completion.bash\n@@ -7,32 +7,13 @@\n # Conceptually based on gitcompletion (http://gitweb.hawaga.org.uk/).\n # Distributed under the GNU General Public License, version 2.0.\n #\n-# The contained completion routines provide support for completing:\n-#\n-#    *) local and remote branch names\n-#    *) local and remote tag names\n-#    *) .git/remotes file names\n-#    *) git 'subcommands'\n-#    *) tree paths within 'ref:path/to/file' expressions\n-#    *) common --long-options\n-#\n # To use these routines:\n #\n-#    1) Copy this file to somewhere (e.g. ~/.git-completion.sh).\n-#    2) Added the following line to your .bashrc:\n-#        source ~/.git-completion.sh\n-#\n-#    3) You may want to make sure the git executable is available\n-#       in your PATH before this script is sourced, as some caching\n-#       is performed while the script loads.  If git isn't found\n-#       at source time then all lookups will be done on demand,\n-#       which may be slightly slower.\n+#    1) Copy this file to somewhere (e.g. ~/.tg-completion.sh).\n+#    2) Source it from your ~/.bashrc.\n #\n-#    4) Consider changing your PS1 to also show the current branch:\n-#        PS1='[\\u@\\h \\W$(__tg_ps1 \" (%s)\")]\\$ '\n-#\n-#       The argument to __tg_ps1 will be displayed only if you\n-#       are currently in a git repository.  The %s token will be\n+# Note: Make sure the tg script is in your PATH before you source this\n+# script, so it can properly setup cached values.\n \n case \"$COMP_WORDBREAKS\" in\n *:*) : great ;;\n@@ -172,6 +153,22 @@ __tg_remotes ()\n \tdone\n }\n \n+__tg_find_subcommand ()\n+{\n+\tlocal word subcommand c=1\n+\n+\twhile [ $c -lt $COMP_CWORD ]; do\n+\t\tword=\"${COMP_WORDS[c]}\"\n+\t\tfor subcommand in $1; do\n+\t\t\tif [ \"$subcommand\" = \"$word\" ]; then\n+\t\t\t\techo \"$subcommand\"\n+\t\t\t\treturn\n+\t\t\tfi\n+\t\tdone\n+\t\tc=$((++c))\n+\tdone\n+}\n+\n __tg_complete_revlist ()\n {\n \tlocal pfx cur=\"${COMP_WORDS[COMP_CWORD]}\"\n@@ -268,6 +265,21 @@ _tg_delete ()\n \tesac\n }\n \n+_tg_depend ()\n+{\n+\tlocal subcommands=\"add\"\n+\tlocal subcommand=\"$(__git_find_subcommand \"$subcommands\")\"\n+\tif [ -z \"$subcommand\" ]; then\n+\t\t__tgcomp \"$subcommands\"\n+\t\treturn\n+\tfi\n+\n+\tcase \"$subcommand\" in\n+\tadd)\n+\t\t__tgcomp \"$(__tg_refs)\"\n+\tesac\n+}\n+\n _tg_export ()\n {\n \tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n@@ -411,6 +423,7 @@ _tg ()\n \tcase \"$command\" in\n \tcreate)      _tg_create \"$c\" ;;\n \tdelete)      _tg_delete ;;\n+\tdepend)      _tg_depend ;;\n \texport)      _tg_export ;;\n \thelp)        _tg_help ;;\n \timport)      _tg_import ;;\n@@ -426,7 +439,6 @@ _tg ()\n \n ### }}}\n \n-\t__tgcomp \"$(__tg_refs top-bases)\"\n complete -o default -o nospace -F _tg tg\n \n # The following are necessary only for Cygwin, and only are needed\n-- \ntg: (43a8db8..) jf/completion-fixes (depends on: master)\n\n-- \nJonas Fonseca\n"}]}