Skip to content

Commit 3202292

Browse files
karan925helizaga
authored andcommitted
feat(init): add ctrl-n keybinding to create new worktree from fzf picker
1 parent b64edc6 commit 3202292

File tree

2 files changed

+102
-8
lines changed

2 files changed

+102
-8
lines changed

lib/commands/init.sh

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -89,24 +89,31 @@ __FUNC__() {
8989
echo "No worktrees to pick from. Create one with: git gtr new <branch>" >&2
9090
return 0
9191
fi
92-
local _gtr_selection _gtr_key _gtr_line
92+
local _gtr_selection _gtr_key _gtr_line _gtr_branch
9393
_gtr_selection="$(printf '%s\n' "$_gtr_porcelain" | fzf \
9494
--delimiter=$'\t' \
9595
--with-nth=2 \
9696
--ansi \
9797
--layout=reverse \
9898
--border \
9999
--prompt='Worktree> ' \
100-
--header='enter:cd │ ctrl-e:editor │ ctrl-a:ai │ ctrl-d:delete │ ctrl-y:copy │ ctrl-r:refresh' \
100+
--header='enter:cd │ ctrl-n:new │ ctrl-e:editor │ ctrl-a:ai │ ctrl-d:delete │ ctrl-y:copy │ ctrl-r:refresh' \
101+
--expect=ctrl-n,ctrl-a,ctrl-e \
101102
--preview='git -C {1} log --oneline --graph --color=always -15 2>/dev/null; echo "---"; git -C {1} status --short 2>/dev/null' \
102103
--preview-window=right:50% \
103-
--expect=ctrl-a,ctrl-e \
104104
--bind='ctrl-d:execute(git gtr rm {2} > /dev/tty 2>&1 < /dev/tty)+reload(git gtr list --porcelain)' \
105105
--bind='ctrl-y:execute(git gtr copy {2} > /dev/tty 2>&1 < /dev/tty)' \
106106
--bind='ctrl-r:reload(git gtr list --porcelain)')" || return 0
107107
[ -z "$_gtr_selection" ] && return 0
108108
_gtr_key="$(head -1 <<< "$_gtr_selection")"
109109
_gtr_line="$(sed -n '2p' <<< "$_gtr_selection")"
110+
if [ "$_gtr_key" = "ctrl-n" ]; then
111+
printf "Branch name: " >&2
112+
read -r _gtr_branch
113+
[ -z "$_gtr_branch" ] && return 0
114+
command git gtr new "$_gtr_branch"
115+
return $?
116+
fi
110117
[ -z "$_gtr_line" ] && return 0
111118
# ctrl-a/ctrl-e: run after fzf exits (needs full terminal for TUI apps)
112119
if [ "$_gtr_key" = "ctrl-a" ]; then
@@ -205,24 +212,31 @@ __FUNC__() {
205212
echo "No worktrees to pick from. Create one with: git gtr new <branch>" >&2
206213
return 0
207214
fi
208-
local _gtr_selection _gtr_key _gtr_line
215+
local _gtr_selection _gtr_key _gtr_line _gtr_branch
209216
_gtr_selection="$(printf '%s\n' "$_gtr_porcelain" | fzf \
210217
--delimiter=$'\t' \
211218
--with-nth=2 \
212219
--ansi \
213220
--layout=reverse \
214221
--border \
215222
--prompt='Worktree> ' \
216-
--header='enter:cd │ ctrl-e:editor │ ctrl-a:ai │ ctrl-d:delete │ ctrl-y:copy │ ctrl-r:refresh' \
223+
--header='enter:cd │ ctrl-n:new │ ctrl-e:editor │ ctrl-a:ai │ ctrl-d:delete │ ctrl-y:copy │ ctrl-r:refresh' \
224+
--expect=ctrl-n,ctrl-a,ctrl-e \
217225
--preview='git -C {1} log --oneline --graph --color=always -15 2>/dev/null; echo "---"; git -C {1} status --short 2>/dev/null' \
218226
--preview-window=right:50% \
219-
--expect=ctrl-a,ctrl-e \
220227
--bind='ctrl-d:execute(git gtr rm {2} > /dev/tty 2>&1 < /dev/tty)+reload(git gtr list --porcelain)' \
221228
--bind='ctrl-y:execute(git gtr copy {2} > /dev/tty 2>&1 < /dev/tty)' \
222229
--bind='ctrl-r:reload(git gtr list --porcelain)')" || return 0
223230
[ -z "$_gtr_selection" ] && return 0
224231
_gtr_key="$(head -1 <<< "$_gtr_selection")"
225232
_gtr_line="$(sed -n '2p' <<< "$_gtr_selection")"
233+
if [ "$_gtr_key" = "ctrl-n" ]; then
234+
printf "Branch name: " >&2
235+
read -r _gtr_branch
236+
[ -z "$_gtr_branch" ] && return 0
237+
command git gtr new "$_gtr_branch"
238+
return $?
239+
fi
226240
[ -z "$_gtr_line" ] && return 0
227241
# ctrl-a/ctrl-e: run after fzf exits (needs full terminal for TUI apps)
228242
if [ "$_gtr_key" = "ctrl-a" ]; then
@@ -331,10 +345,10 @@ function __FUNC__
331345
--layout=reverse \
332346
--border \
333347
--prompt='Worktree> ' \
334-
--header='enter:cd │ ctrl-e:editor │ ctrl-a:ai │ ctrl-d:delete │ ctrl-y:copy │ ctrl-r:refresh' \
348+
--header='enter:cd │ ctrl-n:new │ ctrl-e:editor │ ctrl-a:ai │ ctrl-d:delete │ ctrl-y:copy │ ctrl-r:refresh' \
349+
--expect=ctrl-n,ctrl-a,ctrl-e \
335350
--preview='git -C {1} log --oneline --graph --color=always -15 2>/dev/null; echo "---"; git -C {1} status --short 2>/dev/null' \
336351
--preview-window=right:50% \
337-
--expect=ctrl-a,ctrl-e \
338352
--bind='ctrl-d:execute(git gtr rm {2} > /dev/tty 2>&1 < /dev/tty)+reload(git gtr list --porcelain)' \
339353
--bind='ctrl-y:execute(git gtr copy {2} > /dev/tty 2>&1 < /dev/tty)' \
340354
--bind='ctrl-r:reload(git gtr list --porcelain)')
@@ -350,6 +364,12 @@ function __FUNC__
350364
set -l _gtr_key "$_gtr_selection[1]"
351365
set -l _gtr_line "$_gtr_selection[2]"
352366
end
367+
if test "$_gtr_key" = "ctrl-n"
368+
read -P "Branch name: " _gtr_branch
369+
test -z "$_gtr_branch"; and return 0
370+
command git gtr new "$_gtr_branch"
371+
return $status
372+
end
353373
test -z "$_gtr_line"; and return 0
354374
# ctrl-a/ctrl-e: run after fzf exits (needs full terminal for TUI apps)
355375
if test "$_gtr_key" = "ctrl-a"

tests/init.bats

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,80 @@ setup() {
408408
[[ "$output" == *'Usage: gwtr cd <branch>'* ]]
409409
}
410410
411+
# ── ctrl-n (new worktree) in fzf picker ────────────────────────────────────
412+
413+
@test "bash output includes --expect=ctrl-n in fzf args" {
414+
run cmd_init bash
415+
[ "$status" -eq 0 ]
416+
[[ "$output" == *"--expect=ctrl-n"* ]]
417+
}
418+
419+
@test "zsh output includes --expect=ctrl-n in fzf args" {
420+
run cmd_init zsh
421+
[ "$status" -eq 0 ]
422+
[[ "$output" == *"--expect=ctrl-n"* ]]
423+
}
424+
425+
@test "fish output includes --expect=ctrl-n in fzf args" {
426+
run cmd_init fish
427+
[ "$status" -eq 0 ]
428+
[[ "$output" == *"--expect=ctrl-n"* ]]
429+
}
430+
431+
@test "bash output includes ctrl-n:new in fzf header" {
432+
run cmd_init bash
433+
[ "$status" -eq 0 ]
434+
[[ "$output" == *"ctrl-n:new"* ]]
435+
}
436+
437+
@test "zsh output includes ctrl-n:new in fzf header" {
438+
run cmd_init zsh
439+
[ "$status" -eq 0 ]
440+
[[ "$output" == *"ctrl-n:new"* ]]
441+
}
442+
443+
@test "fish output includes ctrl-n:new in fzf header" {
444+
run cmd_init fish
445+
[ "$status" -eq 0 ]
446+
[[ "$output" == *"ctrl-n:new"* ]]
447+
}
448+
449+
@test "bash output includes git gtr new in ctrl-n handler" {
450+
run cmd_init bash
451+
[ "$status" -eq 0 ]
452+
[[ "$output" == *'git gtr new "$_gtr_branch"'* ]]
453+
}
454+
455+
@test "zsh output includes git gtr new in ctrl-n handler" {
456+
run cmd_init zsh
457+
[ "$status" -eq 0 ]
458+
[[ "$output" == *'git gtr new "$_gtr_branch"'* ]]
459+
}
460+
461+
@test "fish output includes git gtr new in ctrl-n handler" {
462+
run cmd_init fish
463+
[ "$status" -eq 0 ]
464+
[[ "$output" == *'git gtr new "$_gtr_branch"'* ]]
465+
}
466+
467+
@test "bash output prompts for branch name on ctrl-n" {
468+
run cmd_init bash
469+
[ "$status" -eq 0 ]
470+
[[ "$output" == *'Branch name: '* ]]
471+
}
472+
473+
@test "zsh output prompts for branch name on ctrl-n" {
474+
run cmd_init zsh
475+
[ "$status" -eq 0 ]
476+
[[ "$output" == *'Branch name: '* ]]
477+
}
478+
479+
@test "fish output prompts for branch name on ctrl-n" {
480+
run cmd_init fish
481+
[ "$status" -eq 0 ]
482+
[[ "$output" == *'Branch name: '* ]]
483+
}
484+
411485
# ── git gtr passthrough preserved ────────────────────────────────────────────
412486
413487
@test "bash output passes non-cd commands to git gtr" {

0 commit comments

Comments
 (0)