10

I would like to allow completion for --flags after other input in my gradle completion script, but _arguments seems to require that

specs that describe option flags must precede specs that describe non-option ("positional" or "normal") arguments of the analyzed line (from the zsh completion docs)

In other words: command foo --o[TAB] does nothing, but command --o[TAB] works fine. Is there any way to configure _arguments or do I need to use other control functions?

NOTE: Separate completion functions do not seem like an option in my case as the inputs are not in a fixed list (gradle tasks are arbitrary and multiple can be specified, gradle myfoo mybar --o[TAB] must work).

Eric Wendelin
  • 43,147
  • 9
  • 68
  • 92
  • 1
    Have a look at the git completion functions, they work like that (`git clone --[TAB]` for example (`--bare, --branch, ...`)) – Tom Regner Feb 01 '17 at 09:31
  • @TomRegner that's a good idea — I'll give that a shot. – Eric Wendelin Feb 01 '17 at 16:31
  • Git completion (https://github.com/zsh-users/zsh/blob/master/Completion/Unix/Command/_git) uses completion functions per subcommand (e.g. `_git_clone()`). In my case, the Gradle task list is dynamic, and multiple tasks can be specified, so using the same approach doesn't seem feasible. I shall add that to the question. – Eric Wendelin Feb 01 '17 at 16:38
  • @TomRegner after taking another look, your suggestion was correct. Git allows arbitrary branch names (after `git checkout`, say) and will provide completion of options afterward. I could use the logic from git completion to achieve my answer below. Thank you! – Eric Wendelin Feb 10 '17 at 04:51
  • Very cool! I like that ;-) – Tom Regner Feb 10 '17 at 08:29
  • @TomRegner If you submit an answer with you comment, I'll award you the bounty. – Eric Wendelin Feb 10 '17 at 15:13
  • Nah, the comment is not really worth that much -- seems to be too late anyway (If I had extracted the info from the git-stuff, but I didn't) ;-) – Tom Regner Feb 10 '17 at 15:39

2 Answers2

1

So you want to be able to type something like vim foo -[TAB] and have a list auto expand to show flags and switches, where currently you have to type vim -[TAB] to get your flags and switches and then type foo, yes?

Hopefully I am understanding your question correctly.

My current zsh completion options might be able to help with this, as I can do what I described, which seems to be what you are asking for? It has been quite a while sense I set these up so I don't remember precisely what each one does. What I belive you want though is the setopt COMPLETE_IN_WORD , unset LIST_AMBIGUOUS, as well as the zstyle ':completion::approximate*:*' prefix-needed false options. If I am wrong someone please correct me.

I have included what I use in my zsh as my completion section. I have tested this as standalone and it works on my zsh as is.

#{{{ Completion Stuff
zmodload -i zsh/complist
zstyle ':completion:*' list-colors ${(s.:.)LS_COLORS}
bindkey -M viins '\C-i' complete-word
# Faster! (?)
zstyle ':completion::complete:*' use-cache 1
# case insensitive completion
zstyle ':completion:*' matcher-list 'm:{a-z}={A-Z}' \
  'r:|[._-]=* r:|=*' 'l:|=* r:|=*'
zstyle ':completion:*' verbose yes
zstyle ':completion:*:descriptions' format '%B%d%b'
zstyle ':completion:*:messages' format '%d'
zstyle ':completion:*:warnings' format 'No matches for: %d'
zstyle ':completion:*' group-name ''
# generate descriptions with magic.
zstyle ':completion:*' auto-description 'specify: %d'
# Don't prompt for a huge list, page it!
zstyle ':completion:*:default' list-prompt '%S%M matches%s'
# Don't prompt for a huge list, menu it!
zstyle ':completion:*:default' menu 'select=0'
# Have the newer files last so I see them first
zstyle ':completion:*' file-sort modification reverse
# color code completion
zstyle ':completion:*' list-colors "=(#b) #([0-9]#)*=36=31"
unsetopt LIST_AMBIGUOUS
setopt  COMPLETE_IN_WORD
# Separate man page sections.
zstyle ':completion:*:manuals' separate-sections true
#
zstyle ':completion:*' list-separator 'fREW'
# complete with a menu for xwindow ids
zstyle ':completion:*:windows' menu on=0
zstyle ':completion:*:expand:*' tag-order all-expansions
# more errors allowed for large words and fewer for small words
zstyle ':completion:*:approximate:*' max-errors 'reply=(  $((  ($#PREFIX+$#SUFFIX)/3  ))  )'
# Errors format
zstyle ':completion:*:corrections' format '%B%d (errors %e)%b'
# Don't complete stuff already on the line
zstyle ':completion::*:(rm|vi):*' ignore-line true
# Don't complete directory we are already in (../here)
zstyle ':completion:*' ignore-parents parent pwd
zstyle ':completion::approximate*:*' prefix-needed false
Tropical_Peach
  • 1,143
  • 3
  • 16
  • 29
  • 1
    I think you're partially understanding my question. It sounds like you're suggesting that I configure my completion script using `setopt` and `zstyle` commands, but I get the sense that you think I'm approaching this for my personal zsh configuration. My intent is to provide a better completion script for our Gradle users. I don't want to configure this for just any completion, I specifically want to address this for gradle-completion. – Eric Wendelin Feb 08 '17 at 18:56
1

I was able to solve this with this commit at least to allow options after 1 task is specified.

The trick is to set the state within _arguments with :->statename, reset the context to the next word, and provide a wildcard matcher that matches non-command words and use _arguments again.

There's almost certainly a way to allow options specified after an arbitrary number of words and avoid some duplication, but this is a workable start.

Eric Wendelin
  • 43,147
  • 9
  • 68
  • 92