24

In zsh, I have a function called g which acts like this:

  • with no arguments, call git status
  • with one or more arguments, delegate to git with all given arguments - i.e. call git $@

I would like the tab completions for g to be exactly the same as for git. I can achieve this with alias g=git, but that doesn't allow me to call status by default (the first point above).

How can I delegate to the completion for git?

In bash, I simply did complete -F _git g which re-uses git's completion function. With zsh, git's completion looks much more complex, and I wan't able to find a similar solution.

I'd guess there's some function in zsh to say "pretend I typed command [x], what would you complete it to?". If I knew what that was, it should be simple enough to use a function to delegate to it. But I've found no such function in the manuals.

gfxmonk
  • 8,614
  • 5
  • 42
  • 53

2 Answers2

25

The documentation for compdef says this:

The function compdef can be used to associate existing completion functions with new commands. For example,

compdef _pids foo

But adapting it (_git is the usual completion function for git) did not produce a working result for me (even after _git had been autoloaded):

compdef _git g

I was able to get it to work via _dispatch though:

compdef '_dispatch git git' g
Chris Johnsen
  • 214,407
  • 26
  • 209
  • 186
  • 1
    That's weird. I have the same thing happening, but other completion functions work just fine with the first command. – Dennis Williamson Nov 19 '10 at 02:53
  • 1
    excellent, thank you very much! As for why the first doesn't work, Perhaps the completion for _git is sufficiently custom that just redirecting it isn't enough to get it to respond with anything useful? (i.e maybe it checks that the command starts with "git") – gfxmonk Nov 19 '10 at 03:56
  • 6
    Any idea how `compdef '_dispatch git git' g` can be adjusted to make g auto-complete like git-status, rather than just git? – Galder Zamarreño Aug 29 '12 at 09:40
  • This works for me when I run it directly in a zsh shell, but for some reason it doesn't work when I put it my `.zshrc`. – Dario Seidl Sep 25 '21 at 13:54
  • If you want to have a subcommand like `git status`, then apparently (by trial and error) I came up with `compdef '_dispatch _git-status git' gst` – Michael Jun 01 '22 at 10:06
  • @DarioSeidl If you put it into your .zshrc, make sure that it is after your call `autoload -Uz compinit && compinit` – Michael Jun 01 '22 at 10:07
0

This same function had stopped working for me after a change-around of configs.

# in ~/.zsh/functions/g.zsh

# # No arguments: `git status`
# # With arguments: acts like `git`
g() {
  if [[ $# > 0 ]]; then
    git "$@"
  else
    git status
  fi
}

It's actually important to place just the function in ~/.zsh/functions/g.zsh and create a compdef in ~/.zsh/completions/_g:

#compdef g
compdef g=git

Then, in .zshrc:

fpath=($HOME/.zsh/completions $fpath)

# load custom executable functions
for function in ~/.zsh/functions/*.zsh; do
  source $function
done

# completion
autoload -U compinit
compinit

Not sure if the order is important. I think when the compdef is in a separate folder, it works with any order.

Got the g function from here:

https://github.com/thoughtbot/dotfiles/blob/master/zsh/functions/g

https://github.com/thoughtbot/dotfiles/blob/master/zsh/completion/_g

Thanks Thoughtbot!

Martin Tomov
  • 31
  • 1
  • 5