2

I'm trying to set up a zsh function that will take me back to the top level git directory with an optional argument to move relative to that directory. I've currently got this which works:

alias gitdir='git rev-parse --show-toplevel'
cdgit() { cd $(gitdir)/$1 }

The issue is, tab completion doesn't work properly, it will autocomplete from whatever directory I'm in when I run cdgit, but I want it to complete from $(gitdir). If I type the following line before running cdgit, the completion will work correctly (from $(gitdir)):

compctl -W $(gitdir) -/ cdgit

However, I don't want to type that command every time before I type cdgit just to get tab completion. Is there any way that I can make a completion function for cdgit that will somehow run that command so my completion is correct?

Josh Sherick
  • 131
  • 4
  • Why the downvote? – Josh Sherick Jun 13 '16 at 14:42
  • Why don't you want to stick with the `compctl` solution? This can go to the rc file where you define the cdgit function, can't it?! – mpy Jun 14 '16 at 18:58
  • 1
    No, because I don't want it to run when my shell starts. That would change the directory that `cdgit ` completes to to whatever `$(gitdir)` evaluated to at the time that my .zshrc was run. However, I want it to autocomplete to whatever `$(gitdir)` evaluates to at the time that I type `cdgit `. So I want to type `cdgit` and press tab and get completion from where it would `cd` me to, which might not be the same place as when the shell was started. – Josh Sherick Jun 14 '16 at 20:00
  • It could potentially run on every directory change, I guess. Not the cleanest solution but it's a quick command. – Josh Sherick Jun 14 '16 at 20:01
  • Of course, my bad not realizing that `$(gitdir)` will be static then. See my answer for a suggestion. – mpy Jun 15 '16 at 16:46

1 Answers1

2

I'd suggest to write a completion function for your cdgit function.

Put this file named _cdgit into a directory which is in your $fpath, e.g. /usr/share/zsh/site-functions, then start a new shell instance:

#compdef cdgit

local expl
local ret=1

[[ CURRENT -eq 2 ]] && _wanted directories expl 'git toplevel directory' \
    _path_files -/ -W $(git rev-parse --show-toplevel) && ret=0

return ret

This is borrowed from one of the last lines in the _cd completion function itself, which is of course much more complex.

Demo:

/usr/src/linux-git/Documentation/x86> cd [TAB]
local directory
i386/    x86_64/

/usr/src/linux-git/Documentation/x86> cdgit [TAB]
git toplevel directory
Documentation/  crypto/         include/        lib/            scripts/        usr/                          
arch/           drivers/        init/           mm/             security/       virt/                         
block/          firmware/       ipc/            net/            sound/                                      
certs/          fs/             kernel/         samples/        tools/                                      
mpy
  • 27,002
  • 7
  • 85
  • 97