Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: tag-order with git refs



Peter wrote:
> How do I limit completion after "git checkout" to showing local heads
> first (i.e. branches I actually use)?
> 
> zstyle ':completion:*:complete:git-checkout:*' tag-order heads-local

There are several nested tag loops in _git. In such cases, I find it
works better to list all tags along the path:
  zstyle ':completion:*:complete:git-checkout:*' tag-order 'tree-ishs heads heads-local'
This has limitations. _next_tags will advance within inner tag loops
first before tracking back to outer ones. There are other irritations here
like ORIG_HEAD making it hard to complete origin/ given case-insensitive
matching control.

It also doesn't help that in a couple of cases functions are called
sequentially instead of using _alternative. The following patch helps a
tiny bit with this.

The tag loop structure for git checkout looks something like the
following:
  tree-ishs
    heads           - sequentially calls:
      heads-local 
      heads-remote
    commit-tags
      commit-tags
    commit-objects  - sequentially calls:
      commit-tags
      heads
      commits
  modified-files
    modified-files
  remote branches  - the space looks like a mistake
    remote-branch-names-noprefix

In general, it is better to avoid nesting. If you look at many of the
simpler functions in Completion/Unix/Type, you'll see that they don't
call _wanted but just use _description. This is sensible for functions
that are likely always called from another tag loop. It'd be worth
thinking about how we might further flatten this. Maybe _alternative
could take a special action style for functions that call a nested
_alternative that should be incorporated as a single tag loop.

I've not done anything about the lack of a tag loop in
__git_recent_commits because that looks like it needs wider refactoring.
On the subject of that function, I'd prefer if it used things like
HEAD~3 (or even @~3 which is an abbreviation for the same thing) instead
of the hashes for the matches. That gives them a common prefix so you
can type git checkout @<tab> if you know you want recent commits.
Looking at the history, it seems those were added to the description to
avoid grouping of matches if two commits have the same comment. I'd be
inclined to not use _describe and handle the descriptions more manually.

Also __git_heads should avoid duplicating local heads in the remote list.

Oliver

diff --git a/Completion/Unix/Command/_git b/Completion/Unix/Command/_git
index 1fcde90..2cfe636 100644
--- a/Completion/Unix/Command/_git
+++ b/Completion/Unix/Command/_git
@@ -457,7 +457,7 @@ _git-checkout () {
       if (( CURRENT == 1 )) && [[ -z $opt_args[(I)--] ]]; then
         # TODO: Allow A...B
         local branch_arg='' \
-              remote_branch_noprefix_arg='remote branches::__git_remote_branch_names_noprefix' \
+              remote_branch_noprefix_arg='remote-branches::__git_remote_branch_names_noprefix' \
               tree_ish_arg='tree-ishs::__git_tree_ishs' \
               file_arg='modified-files::__git_modified_files'
 
@@ -5587,8 +5587,9 @@ __git_commits () {
 
 (( $+functions[__git_heads] )) ||
 __git_heads () {
-  __git_heads_local
-  __git_heads_remote
+  _alternative \
+    'heads-local::__git_heads_local' \
+    'heads-remote::__git_heads_remote'
 }
 
 (( $+functions[__git_heads_local] )) ||



Messages sorted by: Reverse Date, Date, Thread, Author