Skip to content

Commit 22ac181

Browse files
authored
fix(completion): support Homebrew-installed completion assets (#155)
1 parent 23c3f59 commit 22ac181

File tree

5 files changed

+182
-12
lines changed

5 files changed

+182
-12
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,10 @@ git gtr config set gtr.ui.color never
397397

398398
## Shell Completions (Optional)
399399

400+
Homebrew installs native Bash, Zsh, and Fish completion files automatically.
401+
Use the commands below for manual setup when installing from source or when you
402+
want to load completions explicitly.
403+
400404
```bash
401405
# Bash (~/.bashrc)
402406
source <(git gtr completion bash)

docs/configuration.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,8 @@ The `NO_COLOR` environment variable ([no-color.org](https://no-color.org)) alway
364364
## Shell Completions
365365

366366
Enable tab completion using the built-in `completion` command.
367+
Homebrew installs native Bash, Zsh, and Fish completion files automatically, so
368+
manual setup is mainly for source installs or explicit shell configuration.
367369

368370
### Bash
369371

lib/commands/completion.sh

Lines changed: 58 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,45 @@
11
#!/usr/bin/env bash
22

3+
# Resolve a completion asset from supported install layouts.
4+
_completion_asset_path() {
5+
local shell="$1"
6+
shift
7+
8+
local candidate
9+
for candidate in "$@"; do
10+
if [ -f "$candidate" ]; then
11+
printf '%s\n' "$candidate"
12+
return 0
13+
fi
14+
done
15+
16+
log_error "Could not find $shell completion asset under: $GTR_DIR"
17+
log_error "Expected either a source checkout (completions/) or a Homebrew install layout."
18+
return 1
19+
}
20+
21+
_completion_bash_path() {
22+
_completion_asset_path "bash" \
23+
"$GTR_DIR/completions/gtr.bash" \
24+
"$GTR_DIR/etc/bash_completion.d/git-gtr"
25+
}
26+
27+
_completion_zsh_path() {
28+
_completion_asset_path "zsh" \
29+
"$GTR_DIR/completions/_git-gtr" \
30+
"$GTR_DIR/share/zsh/site-functions/_git-gtr"
31+
}
32+
33+
_completion_fish_path() {
34+
_completion_asset_path "fish" \
35+
"$GTR_DIR/completions/git-gtr.fish" \
36+
"$GTR_DIR/share/fish/vendor_completions.d/git-gtr.fish"
37+
}
38+
39+
_completion_single_quote() {
40+
printf "'%s'" "$(printf '%s' "$1" | sed "s/'/'\\\\''/g")"
41+
}
42+
343
# Completion command (generate shell completions)
444
cmd_completion() {
545
if [ "${1:-}" = "-h" ] || [ "${1:-}" = "--help" ]; then
@@ -10,9 +50,15 @@ cmd_completion() {
1050

1151
case "$shell" in
1252
bash)
13-
cat "$GTR_DIR/completions/gtr.bash"
53+
local bash_path
54+
bash_path="$(_completion_bash_path)" || return 1
55+
cat "$bash_path"
1456
;;
1557
zsh)
58+
local zsh_path zsh_dir zsh_dir_quoted
59+
zsh_path="$(_completion_zsh_path)" || return 1
60+
zsh_dir="$(dirname "$zsh_path")"
61+
zsh_dir_quoted="$(_completion_single_quote "$zsh_dir")"
1662
# Output zstyle registration + completion loading
1763
# The zstyle MUST run before compinit to register gtr as a git subcommand
1864
cat <<EOF
@@ -25,7 +71,7 @@ cmd_completion() {
2571
zstyle ':completion:*:*:git:*' user-commands gtr:'Git worktree management'
2672
2773
# Add completions to fpath and initialize
28-
fpath=($GTR_DIR/completions \$fpath)
74+
fpath=($zsh_dir_quoted \$fpath)
2975
3076
# Note: If you already have compinit in your .zshrc, you may want to
3177
# source this file before your existing compinit call and remove the
@@ -34,7 +80,9 @@ autoload -Uz compinit && compinit -C
3480
EOF
3581
;;
3682
fish)
37-
cat "$GTR_DIR/completions/git-gtr.fish"
83+
local fish_path
84+
fish_path="$(_completion_fish_path)" || return 1
85+
cat "$fish_path"
3886
;;
3987
""|--help|-h)
4088
echo "Generate shell completions for git gtr"
@@ -46,14 +94,17 @@ EOF
4694
echo " zsh Generate Zsh completions"
4795
echo " fish Generate Fish completions"
4896
echo ""
97+
echo "Homebrew installs native shell completions automatically."
98+
echo ""
4999
echo "Examples:"
50-
echo " # Bash: add to ~/.bashrc"
100+
echo " # Bash: manual setup (~/.bashrc)"
51101
echo " source <(git gtr completion bash)"
52102
echo ""
53-
echo " # Zsh: add to ~/.zshrc (BEFORE any existing compinit call)"
103+
echo " # Zsh: manual setup (~/.zshrc, BEFORE any existing compinit call)"
54104
echo " eval \"\$(git gtr completion zsh)\""
55105
echo ""
56-
echo " # Fish: save to completions directory"
106+
echo " # Fish: manual setup"
107+
echo " mkdir -p ~/.config/fish/completions"
57108
echo " git gtr completion fish > ~/.config/fish/completions/git-gtr.fish"
58109
return 0
59110
;;
@@ -64,4 +115,4 @@ EOF
64115
return 1
65116
;;
66117
esac
67-
}
118+
}

lib/commands/help.sh

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -326,14 +326,17 @@ shell configuration for tab completion of git gtr commands and options.
326326
Supported shells: bash, zsh, fish
327327
328328
Setup:
329-
# Bash (add to ~/.bashrc)
330-
eval "$(git gtr completion bash)"
329+
Homebrew installs native shell completions automatically.
330+
331+
# Bash (manual setup, add to ~/.bashrc)
332+
source <(git gtr completion bash)
331333
332-
# Zsh (add to ~/.zshrc BEFORE compinit)
334+
# Zsh (manual setup, add to ~/.zshrc BEFORE compinit)
333335
eval "$(git gtr completion zsh)"
334336
335-
# Fish (symlink to completions dir)
336-
ln -s /path/to/completions/git-gtr.fish ~/.config/fish/completions/
337+
# Fish (manual setup)
338+
mkdir -p ~/.config/fish/completions
339+
git gtr completion fish > ~/.config/fish/completions/git-gtr.fish
337340
EOF
338341
}
339342

tests/completion.bats

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
#!/usr/bin/env bats
2+
# Tests for completion path resolution in lib/commands/completion.sh
3+
4+
load test_helper
5+
6+
log_error() { printf '%s\n' "$*" >&2; }
7+
log_info() { printf '%s\n' "$*" >&2; }
8+
9+
setup() {
10+
TEST_ROOT="$(mktemp -d)"
11+
TEST_GTR_DIR="$TEST_ROOT/prefix with spaces"
12+
mkdir -p "$TEST_GTR_DIR"
13+
export GTR_DIR="$TEST_GTR_DIR"
14+
# shellcheck disable=SC1091
15+
. "$PROJECT_ROOT/lib/commands/completion.sh"
16+
}
17+
18+
teardown() {
19+
rm -rf "$TEST_ROOT"
20+
}
21+
22+
write_test_file() {
23+
local path="$1" content="$2"
24+
mkdir -p "$(dirname "$path")"
25+
printf '%s\n' "$content" > "$path"
26+
}
27+
28+
setup_source_layout() {
29+
write_test_file "$TEST_GTR_DIR/completions/gtr.bash" "# source bash completion"
30+
write_test_file "$TEST_GTR_DIR/completions/_git-gtr" "#compdef git-gtr"
31+
write_test_file "$TEST_GTR_DIR/completions/git-gtr.fish" "# fish source completion"
32+
}
33+
34+
setup_homebrew_layout() {
35+
write_test_file "$TEST_GTR_DIR/etc/bash_completion.d/git-gtr" "# brew bash completion"
36+
write_test_file "$TEST_GTR_DIR/share/zsh/site-functions/_git-gtr" "#compdef git-gtr"
37+
write_test_file "$TEST_GTR_DIR/share/fish/vendor_completions.d/git-gtr.fish" "# fish brew completion"
38+
}
39+
40+
@test "cmd_completion bash uses source checkout asset when present" {
41+
setup_source_layout
42+
43+
run cmd_completion bash
44+
45+
[ "$status" -eq 0 ]
46+
[ "$output" = "# source bash completion" ]
47+
}
48+
49+
@test "cmd_completion zsh uses source checkout completions directory when present" {
50+
setup_source_layout
51+
52+
run cmd_completion zsh
53+
54+
[ "$status" -eq 0 ]
55+
[[ "$output" == *"fpath=('$TEST_GTR_DIR/completions' \$fpath)"* ]]
56+
}
57+
58+
@test "cmd_completion fish uses source checkout asset when present" {
59+
setup_source_layout
60+
61+
run cmd_completion fish
62+
63+
[ "$status" -eq 0 ]
64+
[ "$output" = "# fish source completion" ]
65+
}
66+
67+
@test "cmd_completion bash falls back to Homebrew asset layout" {
68+
setup_homebrew_layout
69+
70+
run cmd_completion bash
71+
72+
[ "$status" -eq 0 ]
73+
[ "$output" = "# brew bash completion" ]
74+
}
75+
76+
@test "cmd_completion zsh falls back to Homebrew site-functions directory" {
77+
setup_homebrew_layout
78+
79+
run cmd_completion zsh
80+
81+
[ "$status" -eq 0 ]
82+
[[ "$output" == *"fpath=('$TEST_GTR_DIR/share/zsh/site-functions' \$fpath)"* ]]
83+
}
84+
85+
@test "cmd_completion fish falls back to Homebrew vendor completions" {
86+
setup_homebrew_layout
87+
88+
run cmd_completion fish
89+
90+
[ "$status" -eq 0 ]
91+
[ "$output" = "# fish brew completion" ]
92+
}
93+
94+
@test "cmd_completion prefers source checkout assets over Homebrew assets" {
95+
setup_source_layout
96+
setup_homebrew_layout
97+
98+
run cmd_completion bash
99+
100+
[ "$status" -eq 0 ]
101+
[ "$output" = "# source bash completion" ]
102+
}
103+
104+
@test "cmd_completion returns a clear error when completion assets are missing" {
105+
run cmd_completion bash
106+
107+
[ "$status" -eq 1 ]
108+
[[ "$output" == *"Could not find bash completion asset under:"* ]]
109+
[[ "$output" == *"Expected either a source checkout (completions/) or a Homebrew install layout."* ]]
110+
}

0 commit comments

Comments
 (0)