zsh: use completions for command X when I type command Y
Asked Answered
A

2

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.

Agrarian answered 19/11, 2010 at 1:4 Comment(2)
Thank you for the tip on how to make it work in bash!Jacey
If you can change your function to conditionally print the commands it would execute instead of actually executing them, see this answer by yut23: https://mcmap.net/q/583453/-complete-a-command-with-arguments-like-another-command-with-other-argumentsMeaganmeager
M
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
Menhir answered 19/11, 2010 at 2:35 Comment(6)
That's weird. I have the same thing happening, but other completion functions work just fine with the first command.Heterodoxy
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")Agrarian
Any idea how compdef '_dispatch git git' g can be adjusted to make g auto-complete like git-status, rather than just git?Whydah
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.Disjoined
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' gstCooker
@DarioSeidl If you put it into your .zshrc, make sure that it is after your call autoload -Uz compinit && compinitCooker
P
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!

Polite answered 20/8, 2021 at 22:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.