Skip to contentSkip to conversation

StGIT bash completion

PATCH In review Karl Hasselström 3 participants 6 messages Aug 11, 2016

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 StGIT bash completion

From: Karl Hasselström <[email protected]>

A minimal bash completion script for StGIT. It completes the subcommand names, and options and patch names for some subcommands.

---

I'm not good at all at bash programming -- this script was basically put together by pattern-matching Shawns git completion code -- so comments are even more welcome than usual.

 contrib/stgit-completion.bash |  156 +++++++++++++++++++++++++++++++++++++++++
 1 files changed, 156 insertions(+), 0 deletions(-)
contrib/stgit-completion.bash new file +155 -0
new file mode 100644
index 0000000..25549fb
@@ -0,0 +1,156 @@
+# bash completion support for StGIT                        -*- shell-script -*-
+#
+# Copyright (C) 2006, Karl Hasselström <[email protected]>
+# Based on git-completion.sh
+#
+# To use these routines:
+#
+#    1. Copy this file to somewhere (e.g. ~/.stgit-completion.bash).
+#
+#    2. Add the following line to your .bashrc:
+#         . ~/.stgit-completion.bash
+
+# The path to .git, or empty if we're not in a repository.
+_gitdir ()
+{
+    echo "$(git rev-parse --git-dir 2>/dev/null)"
+}
+
+# Name of the current branch, or empty if there isn't one.
+_current_branch ()
+{
+    local b=$(git symbolic-ref HEAD 2>/dev/null)
+    echo ${b#refs/heads/}
+}
+
+# List of all applied patches.
+_applied_patches ()
+{
+    local g=$(_gitdir)
+    [ "$g" ] && cat "$g/patches/$(_current_branch)/applied"
+}
+
+# List of all unapplied patches.
+_unapplied_patches ()
+{
+    local g=$(_gitdir)
+    [ "$g" ] && cat "$g/patches/$(_current_branch)/unapplied"
+}
+
+# List of all patches.
+_all_patches ()
+{
+    local b=$(_current_branch)
+    local g=$(_gitdir)
+    [ "$g" ] && cat "$g/patches/$b/applied" "$g/patches/$b/unapplied"
+}
+
+# List of all patches except the current patch.
+_all_other_patches ()
+{
+    local b=$(_current_branch)
+    local g=$(_gitdir)
+    [ "$g" ] && cat "$g/patches/$b/applied" "$g/patches/$b/unapplied" \
+        | grep -v "^$(< $g/patches/$b/current)$"
+}
+
+# Generate completions for patches and patch ranges from the given
+# patch list function, and options from the given list.
+_complete_patch_range ()
+{
+    local patchlist="$1" options="$2"
+    local pfx cur="${COMP_WORDS[COMP_CWORD]}"
+    case "$cur" in
+        *..*)
+            pfx="${cur%..*}.."
+            cur="${cur#*..}"
+            COMPREPLY=($(compgen -P "$pfx" -W "$($patchlist)" -- "$cur"))
+            ;;
+        *)
+            COMPREPLY=($(compgen -W "$options $($patchlist)" -- "$cur"))
+            ;;
+    esac
+}
+
+# Generate completions for options from the given list.
+_complete_options ()
+{
+    local options="$1"
+    COMPREPLY=($(compgen -W "$options" -- "${COMP_WORDS[COMP_CWORD]}"))
+}
+
+_stg_delete ()
+{
+    _complete_patch_range _all_patches "--branch --help"
+}
+
+_stg_goto ()
+{
+    _complete_patch_range _all_other_patches "--help"
+}
+
+_stg_mail ()
+{
+    _complete_patch_range _all_patches \
+        "--all --to --cc --bcc --auto --noreply --version --prefix --template \
+         --cover --edit-cover --edit-patches --sleep --refid --smtp-user \
+         --smtp-password --branch --mbox --help"
+}
+
+_stg_new ()
+{
+    _complete_options "--message --showpatch --author --authname --authemail \
+                       --authdate --commname --commemail --help"
+}
+
+_stg_pop ()
+{
+    _complete_patch_range _applied_patches "--all --number --keep --help"
+}
+
+_stg_push ()
+{
+    _complete_patch_range _unapplied_patches "--all --number --reverse \
+                                              --merged --undo --help"
+}
+
+_stg_status ()
+{
+    _complete_options "--modified --new --deleted --conflict --unknown \
+                       --noexclude --reset --help"
+}
+
+_stg ()
+{
+    local i c=1 command
+
+    while [ $c -lt $COMP_CWORD ]; do
+        if [ $c == 1 ]; then
+            command="${COMP_WORDS[c]}"
+        fi
+        c=$((++c))
+    done
+
+    # Complete name of subcommand.
+    if [ $c -eq $COMP_CWORD -a -z "$command" ]; then
+        COMPREPLY=($(compgen \
+            -W "--help --version \
+                $(stg help|grep '^ '|sed 's/ *\([^ ]\) .*/\1/')" \
+            -- "${COMP_WORDS[COMP_CWORD]}"))
+        return;
+    fi
+
+    # Complete arguments to subcommands.
+    case "$command" in
+        delete) _stg_delete ;;
+        goto)   _stg_goto ;;
+        mail)   _stg_mail ;;
+        new)    _stg_new ;;
+        pop)    _stg_pop ;;
+        push)   _stg_push ;;
+        status) _stg_status ;;
+        *)      COMPREPLY=() ;;
+    esac
+}
+
#1 lore raw
Quoted 2 lines · Karl Hasselström

A minimal bash completion script for StGIT. It completes the subcommand names, and options and patch names for some subcommands.

Thanks for the patch. I modified it slightly to automatically generate the options for other commands as well (by invoking "stg help <command>" and it doesn't seem to be slow). I'll try to push it tonight.

Thanks for the other patches as well. I included some but haven't finished them yet.

#2 lore raw
Quoted 10 lines · Catalin Marinas
Quoted 3 lines · Karl Hasselström

A minimal bash completion script for StGIT. It completes the subcommand names, and options and patch names for some subcommands.

Thanks for the patch. I modified it slightly to automatically generate the options for other commands as well (by invoking "stg help <command>" and it doesn't seem to be slow). I'll try to push it tonight.

Hmm. I'll have to try it, but I was half planning to hard-code the list of subcommands instead of calling "stg help" since it causes a tangible delay. On the machines I've tried, it easily takes 0.2 seconds to run "stg help" (with hot caches; with cold caches, it's _really_ bad), and that's bad for interactive behavior.

There's also the point that some switches need (or can benefit from) the tab completion machinery, and thus can't just be automatically extracted and used. But autocompleting the switch names shouldn't interfere with that, and hard-coding stuff that changes every now and then is both morally wrong and a lot of work.

Quoted 1 line

Thanks for the other patches as well. I included some

Ah, thanks!

Quoted 1 line

but haven't finished them yet.

No problem. Thanks to the power of modern version control systems, I'm able to use my own branch of StGIT in the meantime, on all the various computers that I use. :-)

Signature · 1 line
Karl Hasselström, [email protected]
#3 lore raw
Quoted 11 lines · Karl Hasselström
Quoted 4 lines · Catalin Marinas

Thanks for the patch. I modified it slightly to automatically generate the options for other commands as well (by invoking "stg help <command>" and it doesn't seem to be slow). I'll try to push it tonight.

Hmm. I'll have to try it, but I was half planning to hard-code the list of subcommands instead of calling "stg help" since it causes a tangible delay. On the machines I've tried, it easily takes 0.2 seconds to run "stg help" (with hot caches; with cold caches, it's _really_ bad), and that's bad for interactive behavior.

Indeed, stg help takes over 200ms on my machine as well, with hot caches but this is mainly because it imports all the stgit.commands.* modules in order to read the short description. The 'stg help <command>' takes around 90ms on my machine since it only imports one module (I actually reduced it to 85ms by minimizing the imports even further).

I could actually hard-code the commands only in the script. At the moment I removed the _stg_* functions and added some common _stg_all_patches() to avoid duplicating the code (see attached).

Signature · 1 line
Catalin

IyBiYXNoIGNvbXBsZXRpb24gc3VwcG9ydCBmb3IgU3RHSVQgICAgICAgICAgICAgICAgICAgICAg ICAtKi0gc2hlbGwtc2NyaXB0IC0qLQojCiMgQ29weXJpZ2h0IChDKSAyMDA2LCBLYXJsIEhhc3Nl bHN0csO2bSA8a2hhQHRyZXNrYWwuY29tPgojIEJhc2VkIG9uIGdpdC1jb21wbGV0aW9uLnNoCiMK IyBUbyB1c2UgdGhlc2Ugcm91dGluZXM6CiMKIyAgICAxLiBDb3B5IHRoaXMgZmlsZSB0byBzb21l d2hlcmUgKGUuZy4gfi8uc3RnaXQtY29tcGxldGlvbi5iYXNoKS4KIwojICAgIDIuIEFkZCB0aGUg Zm9sbG93aW5nIGxpbmUgdG8geW91ciAuYmFzaHJjOgojICAgICAgICAgLiB+Ly5zdGdpdC1jb21w bGV0aW9uLmJhc2gKCnN0Z19jb21tYW5kcz0iCiAgICAtLWhlbHAKICAgIC0tdmVyc2lvbgogICAg YWRkCiAgICBhcHBsaWVkCiAgICBhc3NpbWlsYXRlCiAgICBicmFuY2gKICAgIGRlbGV0ZQogICAg ZGlmZgogICAgY2xlYW4KICAgIGNsb25lCiAgICBjb21taXQKICAgIGV4cG9ydAogICAgZmlsZXMK ICAgIGZsb2F0CiAgICBmb2xkCiAgICBnb3RvCiAgICBoZWxwCiAgICBpZAogICAgaW1wb3J0CiAg ICBpbml0CiAgICBsb2cKICAgIG1haWwKICAgIG5ldwogICAgcGF0Y2hlcwogICAgcGljawogICAg cG9wCiAgICBwdWxsCiAgICBwdXNoCiAgICByZWZyZXNoCiAgICByZW5hbWUKICAgIHJlc29sdmVk CiAgICBybQogICAgc2VyaWVzCiAgICBzaG93CiAgICBzdGF0dXMKICAgIHRvcAogICAgdW5hcHBs aWVkCiAgICB1bmNvbW1pdAoiCgojIFRoZSBwYXRoIHRvIC5naXQsIG9yIGVtcHR5IGlmIHdlJ3Jl IG5vdCBpbiBhIHJlcG9zaXRvcnkuCl9naXRkaXIgKCkKewogICAgZWNobyAiJChnaXQgcmV2LXBh cnNlIC0tZ2l0LWRpciAyPi9kZXYvbnVsbCkiCn0KCiMgTmFtZSBvZiB0aGUgY3VycmVudCBicmFu Y2gsIG9yIGVtcHR5IGlmIHRoZXJlIGlzbid0IG9uZS4KX2N1cnJlbnRfYnJhbmNoICgpCnsKICAg IGxvY2FsIGI9JChnaXQgc3ltYm9saWMtcmVmIEhFQUQgMj4vZGV2L251bGwpCiAgICBlY2hvICR7 YiNyZWZzL2hlYWRzL30KfQoKIyBMaXN0IG9mIGFsbCBhcHBsaWVkIHBhdGNoZXMuCl9hcHBsaWVk X3BhdGNoZXMgKCkKewogICAgbG9jYWwgZz0kKF9naXRkaXIpCiAgICBbICIkZyIgXSAmJiBjYXQg IiRnL3BhdGNoZXMvJChfY3VycmVudF9icmFuY2gpL2FwcGxpZWQiCn0KCiMgTGlzdCBvZiBhbGwg dW5hcHBsaWVkIHBhdGNoZXMuCl91bmFwcGxpZWRfcGF0Y2hlcyAoKQp7CiAgICBsb2NhbCBnPSQo X2dpdGRpcikKICAgIFsgIiRnIiBdICYmIGNhdCAiJGcvcGF0Y2hlcy8kKF9jdXJyZW50X2JyYW5j aCkvdW5hcHBsaWVkIgp9CgojIExpc3Qgb2YgYWxsIHBhdGNoZXMuCl9hbGxfcGF0Y2hlcyAoKQp7 CiAgICBsb2NhbCBiPSQoX2N1cnJlbnRfYnJhbmNoKQogICAgbG9jYWwgZz0kKF9naXRkaXIpCiAg ICBbICIkZyIgXSAmJiBjYXQgIiRnL3BhdGNoZXMvJGIvYXBwbGllZCIgIiRnL3BhdGNoZXMvJGIv dW5hcHBsaWVkIgp9CgojIExpc3Qgb2YgYWxsIHBhdGNoZXMgZXhjZXB0IHRoZSBjdXJyZW50IHBh dGNoLgpfYWxsX290aGVyX3BhdGNoZXMgKCkKewogICAgbG9jYWwgYj0kKF9jdXJyZW50X2JyYW5j aCkKICAgIGxvY2FsIGc9JChfZ2l0ZGlyKQogICAgWyAiJGciIF0gJiYgY2F0ICIkZy9wYXRjaGVz LyRiL2FwcGxpZWQiICIkZy9wYXRjaGVzLyRiL3VuYXBwbGllZCIgXAogICAgICAgIHwgZ3JlcCAt diAiXiQoPCAkZy9wYXRjaGVzLyRiL2N1cnJlbnQpJCIKfQoKIyBMaXN0IHRoZSBjb21tYW5kIG9w dGlvbnMKX2NtZF9vcHRpb25zICgpCnsKICAgIHN0ZyAkMSAtLWhlbHAgfCBncmVwIC1lICIgLS1b QS1aYS16XSIgfCBzZWQgLWUgInMvLipcKC0tW0EtWmEtel1cK1wpLiovXDEvIgp9CgojIEdlbmVy YXRlIGNvbXBsZXRpb25zIGZvciBwYXRjaGVzIGFuZCBwYXRjaCByYW5nZXMgZnJvbSB0aGUgZ2l2 ZW4KIyBwYXRjaCBsaXN0IGZ1bmN0aW9uLCBhbmQgb3B0aW9ucyBmcm9tIHRoZSBnaXZlbiBsaXN0 LgpfY29tcGxldGVfcGF0Y2hfcmFuZ2UgKCkKewogICAgbG9jYWwgcGF0Y2hsaXN0PSIkMSIgb3B0 aW9ucz0iJDIiCiAgICBsb2NhbCBwZnggY3VyPSIke0NPTVBfV09SRFNbQ09NUF9DV09SRF19Igog ICAgY2FzZSAiJGN1ciIgaW4KICAgICAgICAqLi4qKQogICAgICAgICAgICBwZng9IiR7Y3VyJS4u Kn0uLiIKICAgICAgICAgICAgY3VyPSIke2N1ciMqLi59IgogICAgICAgICAgICBDT01QUkVQTFk9 KCQoY29tcGdlbiAtUCAiJHBmeCIgLVcgIiQoJHBhdGNobGlzdCkiIC0tICIkY3VyIikpCiAgICAg ICAgICAgIDs7CiAgICAgICAgKikKICAgICAgICAgICAgQ09NUFJFUExZPSgkKGNvbXBnZW4gLVcg IiRvcHRpb25zICQoJHBhdGNobGlzdCkiIC0tICIkY3VyIikpCiAgICAgICAgICAgIDs7CiAgICBl c2FjCn0KCiMgR2VuZXJhdGUgY29tcGxldGlvbnMgZm9yIG9wdGlvbnMgZnJvbSB0aGUgZ2l2ZW4g bGlzdC4KX2NvbXBsZXRlX29wdGlvbnMgKCkKewogICAgbG9jYWwgb3B0aW9ucz0iJDEiCiAgICBD T01QUkVQTFk9KCQoY29tcGdlbiAtVyAiJG9wdGlvbnMiIC0tICIke0NPTVBfV09SRFNbQ09NUF9D V09SRF19IikpCn0KCl9zdGdfY29tbW9uICgpCnsKICAgIF9jb21wbGV0ZV9vcHRpb25zICIkKF9j bWRfb3B0aW9ucyAkMSkiCn0KCl9zdGdfYWxsX3BhdGNoZXMgKCkKewogICAgX2NvbXBsZXRlX3Bh dGNoX3JhbmdlIF9hbGxfcGF0Y2hlcyAiJChfY21kX29wdGlvbnMgJDEpIgp9Cgpfc3RnX290aGVy X3BhdGNoZXMgKCkKewogICAgX2NvbXBsZXRlX3BhdGNoX3JhbmdlIF9hbGxfb3RoZXJfcGF0Y2hl cyAiJChfY21kX29wdGlvbnMgJDEpIgp9Cgpfc3RnX2FwcGxpZWRfcGF0Y2hlcyAoKQp7CiAgICBf Y29tcGxldGVfcGF0Y2hfcmFuZ2UgX2FwcGxpZWRfcGF0Y2hlcyAiJChfY21kX29wdGlvbnMgJDEp Igp9Cgpfc3RnX3VuYXBwbGllZF9wYXRjaGVzICgpCnsKICAgIF9jb21wbGV0ZV9wYXRjaF9yYW5n ZSBfdW5hcHBsaWVkX3BhdGNoZXMgIiQoX2NtZF9vcHRpb25zICQxKSIKfQoKX3N0ZyAoKQp7CiAg ICBsb2NhbCBpIGM9MSBjb21tYW5kCgogICAgd2hpbGUgWyAkYyAtbHQgJENPTVBfQ1dPUkQgXTsg ZG8KICAgICAgICBpZiBbICRjID09IDEgXTsgdGhlbgogICAgICAgICAgICBjb21tYW5kPSIke0NP TVBfV09SRFNbY119IgogICAgICAgIGZpCiAgICAgICAgYz0kKCgrK2MpKQogICAgZG9uZQoKICAg ICMgQ29tcGxldGUgbmFtZSBvZiBzdWJjb21tYW5kLgogICAgaWYgWyAkYyAtZXEgJENPTVBfQ1dP UkQgLWEgLXogIiRjb21tYW5kIiBdOyB0aGVuCiAgICAgICAgQ09NUFJFUExZPSgkKGNvbXBnZW4g XAogICAgICAgICAgICAtVyAiJHN0Z19jb21tYW5kcyIgXAogICAgICAgICAgICAtLSAiJHtDT01Q X1dPUkRTW0NPTVBfQ1dPUkRdfSIpKQogICAgICAgIHJldHVybjsKICAgIGZpCgogICAgIyBDb21w bGV0ZSBhcmd1bWVudHMgdG8gc3ViY29tbWFuZHMuCiAgICBjYXNlICIkY29tbWFuZCIgaW4KICAg ICAgICAjIHJlcG9zaXRvcnkgY29tbWFuZHMKICAgICAgICBpZCkgICAgIF9zdGdfYWxsX3BhdGNo ZXMgJGNvbW1hbmQgOzsKICAgICAgICAjIHN0YWNrIGNvbW1hbmRzCiAgICAgICAgZmxvYXQpICBf c3RnX2FsbF9wYXRjaGVzICRjb21tYW5kIDs7CiAgICAgICAgZ290bykgICBfc3RnX290aGVyX3Bh dGNoZXMgJGNvbW1hbmQgOzsKICAgICAgICBwb3ApICAgIF9zdGdfYXBwbGllZF9wYXRjaGVzICRj b21tYW5kIDs7CiAgICAgICAgcHVzaCkgICBfc3RnX3VuYXBwbGllZF9wYXRjaGVzICRjb21tYW5k IDs7CiAgICAgICAgIyBwYXRjaCBjb21tYW5kcwogICAgICAgIGRlbGV0ZSkgX3N0Z19hbGxfcGF0 Y2hlcyAkY29tbWFuZCA7OwogICAgICAgIGV4cG9ydCkgX3N0Z19hcHBsaWVkX3BhdGNoZXMgJGNv bW1hbmQgOzsKICAgICAgICBmaWxlcykgIF9zdGdfYWxsX3BhdGNoZXMgJGNvbW1hbmQgOzsKICAg ICAgICBsb2cpICAgIF9zdGdfYWxsX3BhdGNoZXMgJGNvbW1hbmQgOzsKICAgICAgICBtYWlsKSAg IF9zdGdfYXBwbGllZF9wYXRjaGVzICRjb21tYW5kIDs7CiAgICAgICAgcGljaykgICBfc3RnX3Vu YXBwbGllZF9wYXRjaGVzICRjb21tYW5kIDs7CiAgICAgICAgcmVuYW1lKSBfc3RnX2FsbF9wYXRj aGVzICRjb21tYW5kIDs7CiAgICAgICAgc2hvdykgICBfc3RnX2FsbF9wYXRjaGVzICRjb21tYW5k IDs7CiAgICAgICAgIyBhbGwgdGhlIG90aGVyIGNvbW1hbmRzCiAgICAgICAgKikgICAgICBfc3Rn X2NvbW1vbiAkY29tbWFuZCA7OwogICAgZXNhYwp9Cgpjb21wbGV0ZSAtbyBkZWZhdWx0IC1GIF9z dGcgc3RnCg==

#4 lore raw
Quoted 5 lines · Catalin Marinas

Indeed, stg help takes over 200ms on my machine as well, with hot caches but this is mainly because it imports all the stgit.commands.* modules in order to read the short description. The 'stg help <command>' takes around 90ms on my machine since it only imports one module

Excellent. However, this suggests that an option should be added to stg that makes it print just the subcommand names, without importing anything, to get this kind of speed there as well. Call it --generate-tab-completion or something, and don't print it in the help output.

Quoted 2 lines

(I actually reduced it to 85ms by minimizing the imports even further).

Goodie. For reference, I think git was able to list its subcommands in about 20 ms. Just so you know what to aim for. :-)

Quoted 3 lines

I could actually hard-code the commands only in the script. At the moment I removed the _stg_* functions and added some common _stg_all_patches() to avoid duplicating the code (see attached).

Seems reasonable.

Next time I do some StGIT hacking (not this weekend, unfortunately), I was planning to build more tab-completion stuff. On top of my list are fixing basic completion for all subcommands, and fixing some kind of filename completion. But do feel free to do it first if you like. :-)

Signature · 1 line
Karl Hasselström, [email protected]
#5 lore raw
In reply to Karl Hasselström
Quoted 11 lines · Karl Hasselstr?m

From: Karl Hasselström <[email protected]>

A minimal bash completion script for StGIT. It completes the subcommand names, and options and patch names for some subcommands.

---

I'm not good at all at bash programming -- this script was basically put together by pattern-matching Shawns git completion code -- so comments are even more welcome than usual.

I'm not an StGIT user, but this looks pretty good.