+++ date = 2017-05-06T23:31:51+02:00 title = "Repository management with ghq" [taxonomies] tags = ["development","git"] +++ I recently encountered [ghq][], a tool for automatically organising VCS-backed projects automatically. Give it a repository URL, it will clone a project to your projects dir (set by `$GHQ_ROOT`) like so: ```sh $ ghq get https://github.com/motemen/ghq # Runs `git clone https://github.com/motemen/ghq ~/.ghq/github.com/motemen/ghq` ``` I don't like the idea of having projects hidden away, so I set `$GHQ_ROOT` to `$HOME/projects`. From there, the `list` and `look` subcommands allow listing repositories and visiting them in the shell (actually a subshell). I wanted a nicer way to visit project directories. Since I'm using [fzf][] as a fuzzy-finder, I thought it would be nice to use it for this. I created a simple function, `fp` (find project) to do that: ```sh fp () { ghq look $(ghq list | fzf +m) } ``` I ran into some issues with the subshell of `ghq look` and wondered whether it might be possible to create a zsh command to remove the need for a subshell. I found that `fzf` includes a [cd-widget function][fzf-cd-widget] and created something similar that uses `ghq` instead of `find`: ```sh cd-project-widget () { local cmd="ghq list" setopt localoptions pipefail 2> /dev/null local dir="$(eval "$cmd" | FZF_DEFAULT_OPTS="--height ${FZF_TMUX_HEIGHT:-40%} --reverse $FZF_DEFAULT_OPTS $FZF_ALT_C_OPTS" fzf +m)" if [[ -z "$dir" ]]; then zle redisplay return 0 fi cd $(ghq list --full-path | grep "$dir") local ret=$? zle reset-prompt typeset -f zle-line-init >/dev/null && zle zle-line-init return $ret } zle -N cd-project-widget ``` It should be quite simple to modify it to work with other fuzzy-finders. The basic idea is to show the output of `ghq list` for selection, and use `ghq list --full-path` with the selected candidate to print the correct directory for `cd`. What's really nice about this, is that I can bind it to a key sequence: ```sh bindkey '\es' cd-project-widget ``` Now I can press `M-s` in a shell, start typing "dotfiles" and press enter to `cd` to my [dotfiles][] project. Pretty neat! [ghq]:https://github.com/motemen/ghq [fzf]:https://github.com/junegunn/fzf [fzf-cd-widget]:https://github.com/junegunn/fzf/blob/337cdbb37c1efc49b09b4cacc6e9ee1369c7d76d/shell/key-bindings.zsh#L40-L54 [dotfiles]:https://git.alanpearce.eu/dotfiles