On 12.03.2017 23:27, Bart Schaefer wrote: > On Mar 12, 5:37pm, Daniel Hahler wrote: > } > } I am using a helper method to setup completion for functions that are > } used as extended aliases. > } > } # Helper to setup completion for functions, e.g. > } # "complete_function gcf git commit --fixup" will setup completion for > } # "gcf" => "git commit --fixup". > } complete_function() { > } local f=$1; shift > } compdef -e "words=($* \"${(@)words[2,-1]}\"); ((CURRENT+=$(( $#*-1 )))); _normal" $f > } } > > This can't be right. Because of the double quotes around the argument > of compdef -e, ${(@)words[2,-1]} will expand when complete_function > is executed, not when the compdef value is needed. Same for $(( $#*-1 )) > which by the way is the same as $(( $# - 1 )). Also as you are already > inside (( )) you don't need $(( )). > > Try it this way: > > complete_function() { > local f=$1; shift > compdef -e "words[1]=( ${${(qq)@}} ); (( CURRENT += $# )); _normal" $f > } > > There's a bit of magic there using an extra ${...} around ${(qq)@} to > force the multi-word expansion of $@ back into a single string so that > the outer double-quotes won't split it the way "$@" is normally split. Thank you! It did not work initially, but luckily it seems to be just an off-by-one error when incrementing CURRENT. The following works: complete_function() { local f=$1; shift compdef -e "words[1]=( ${${(qq)@}} ); (( CURRENT += $# - 1 )); _normal" $f } complete_function gsta git stash gsta drop <tab> > } Additionally, I think that zsh itself should provide a way to more > } easily setup completion for functions (i.e. something like my wrapper > } function above). > > How would you envision this to work? How does "zsh itself" know what > someone is going to do inside a function body? > > There's already (compdef cmd=service) e.g. > > compdef gsta=git > > for wrappers that don't insert things into their argument words to act > exactly like a pre-existing completion. Yes, I am aware of that, and what I mean is more or less something in this regard, e.g. by making it handle command+arguments. compdef gsta='git stash' Since that would be incompatible with commands that contain spaces, maybe a list could be used: compdef gsta=(git stash) > Also, using an alias instead of a function wrapper, i.e., > > alias gsta='git stash' > > should "just work" because completion will expand the alias before it > builds $words and looks up the completion. I am using it with the following to automatically update a ctags tags file, but I have other, more involving functions-as-aliases - so using an alias directly is not feasible: gsta() { $_git_cmd stash "$@" local ret=$? if [[ -z "$1" || "$1" == 'pop' || "$1" == 'apply' ]]; then _update_git_ctags $ret fi return $ret } complete_function gsta git stash btw: Daniel Shahaf suggested on IRC to use a wrapper function for "git" altogether: alias gsta='git stash drop' git() { if [[ $1 == stash && $2 == drop ]]; then ... else command git "$@"; fi } Thanks, Daniel.
Attachment:
signature.asc
Description: OpenPGP digital signature