diff options
Diffstat (limited to 'content')
-rw-r--r-- | content/post/repository-management-with-ghq.md | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/content/post/repository-management-with-ghq.md b/content/post/repository-management-with-ghq.md new file mode 100644 index 0000000..6006605 --- /dev/null +++ b/content/post/repository-management-with-ghq.md | |||
@@ -0,0 +1,75 @@ | |||
1 | +++ | ||
2 | Tags = ["development","git"] | ||
3 | date = "2017-05-06T23:31:51+02:00" | ||
4 | title = "Repository management with ghq" | ||
5 | +++ | ||
6 | |||
7 | I recently encountered [ghq][], a tool for automatically organising VCS-backed | ||
8 | projects automatically. Give it a repository URL, it will clone a project to | ||
9 | your projects dir (set by `$GHQ_ROOT`) like so: | ||
10 | |||
11 | {{< highlight sh >}} | ||
12 | $ ghq get https://github.com/motemen/ghq | ||
13 | # Runs `git clone https://github.com/motemen/ghq ~/.ghq/github.com/motemen/ghq` | ||
14 | {{< /highlight >}} | ||
15 | |||
16 | I don't like the idea of having projects hidden away, so I set | ||
17 | `$GHQ_ROOT` to `$HOME/projects`. | ||
18 | |||
19 | From there, the `list` and `look` subcommands allow listing | ||
20 | repositories and visiting them in the shell (actually a subshell). | ||
21 | |||
22 | I wanted a nicer way to visit project directories. Since I'm | ||
23 | using [fzf][] as a fuzzy-finder, I thought it would be nice to use it | ||
24 | for this. I created a simple function, `fp` (find project) to do that: | ||
25 | |||
26 | {{< highlight sh >}} | ||
27 | fp () { | ||
28 | ghq look $(ghq list | fzf +m) | ||
29 | } | ||
30 | {{< /highlight >}} | ||
31 | |||
32 | I ran into some issues with the subshell of `ghq look` and wondered | ||
33 | whether it might be possible to create a zsh command to remove the | ||
34 | need for a subshell. | ||
35 | |||
36 | I found that `fzf` includes a [cd-widget function][fzf-cd-widget] and created | ||
37 | something similar that uses `ghq` instead of `find`: | ||
38 | |||
39 | {{< highlight sh >}} | ||
40 | cd-project-widget () { | ||
41 | local cmd="ghq list" | ||
42 | setopt localoptions pipefail 2> /dev/null | ||
43 | local dir="$(eval "$cmd" | FZF_DEFAULT_OPTS="--height ${FZF_TMUX_HEIGHT:-40%} --reverse $FZF_DEFAULT_OPTS $FZF_ALT_C_OPTS" fzf +m)" | ||
44 | if [[ -z "$dir" ]]; then | ||
45 | zle redisplay | ||
46 | return 0 | ||
47 | fi | ||
48 | cd $(ghq list --full-path | grep "$dir") | ||
49 | local ret=$? | ||
50 | zle reset-prompt | ||
51 | typeset -f zle-line-init >/dev/null && zle zle-line-init | ||
52 | return $ret | ||
53 | } | ||
54 | zle -N cd-project-widget | ||
55 | {{< /highlight >}} | ||
56 | |||
57 | It should be quite simple to modify it to work with other | ||
58 | fuzzy-finders. The basic idea is to show the output of `ghq list` for | ||
59 | selection, and use `ghq list --full-path` with the selected candidate | ||
60 | to print the correct directory for `cd`. | ||
61 | |||
62 | What's really nice about this, is that I can bind it to a key | ||
63 | sequence: | ||
64 | |||
65 | {{< highlight sh >}} | ||
66 | bindkey '\es' cd-project-widget | ||
67 | {{< /highlight >}} | ||
68 | |||
69 | Now I can press `M-s` in a shell, start typing "dotfiles" and press enter to `cd` | ||
70 | to my [dotfiles][] project. Pretty neat! | ||
71 | |||
72 | [ghq]:https://github.com/motemen/ghq | ||
73 | [fzf]:https://github.com/junegunn/fzf | ||
74 | [fzf-cd-widget]:https://github.com/junegunn/fzf/blob/337cdbb37c1efc49b09b4cacc6e9ee1369c7d76d/shell/key-bindings.zsh#L40-L54 | ||
75 | [dotfiles]:https://git.alanpearce.eu/dotfiles | ||