Skip to content
This repository was archived by the owner on Jan 22, 2026. It is now read-only.

Commit 95bd9f8

Browse files
authored
Merge pull request #9 from andrew/completions
Add completions command for bash/zsh and update documentation
2 parents c5e58af + ddc530b commit 95bd9f8

File tree

6 files changed

+386
-1
lines changed

6 files changed

+386
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
- Fix N+1 queries in `blame`, `stale`, `stats`, and `log` commands
77
- Configuration via git config: `pkgs.ecosystems`, `pkgs.ignoredDirs`, `pkgs.ignoredFiles`
88
- `git pkgs info --ecosystems` to show available ecosystems and their status
9+
- `git pkgs completions` command for bash/zsh tab completion
910
- `-q, --quiet` flag to suppress informational messages
1011
- `git pkgs diff` now supports `commit..commit` range syntax
1112
- `--git-dir` and `--work-tree` global options (also respects `GIT_WORK_TREE` env var)

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,21 @@ diff --git a/Gemfile.lock b/Gemfile.lock
371371

372372
Use `git diff --no-textconv` to see the raw lockfile diff. To remove: `git pkgs diff-driver --uninstall`
373373

374+
### Shell completions
375+
376+
Enable tab completion for commands:
377+
378+
```bash
379+
# Bash: add to ~/.bashrc
380+
eval "$(git pkgs completions bash)"
381+
382+
# Zsh: add to ~/.zshrc
383+
eval "$(git pkgs completions zsh)"
384+
385+
# Or auto-install to standard completion directories
386+
git pkgs completions install
387+
```
388+
374389
## Configuration
375390

376391
git-pkgs respects [standard git configuration](https://git-scm.com/docs/git-config).

lib/git/pkgs.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
require_relative "pkgs/commands/upgrade"
3737
require_relative "pkgs/commands/schema"
3838
require_relative "pkgs/commands/diff_driver"
39+
require_relative "pkgs/commands/completions"
3940

4041
module Git
4142
module Pkgs

lib/git/pkgs/cli.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ class CLI
1414
"info" => "Show database size and row counts",
1515
"branch" => "Manage tracked branches",
1616
"schema" => "Show database schema",
17-
"diff-driver" => "Install git textconv driver for lockfile diffs"
17+
"diff-driver" => "Install git textconv driver for lockfile diffs",
18+
"completions" => "Generate shell completions"
1819
},
1920
"Query" => {
2021
"list" => "List dependencies at a commit",
Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
# frozen_string_literal: true
2+
3+
module Git
4+
module Pkgs
5+
module Commands
6+
class Completions
7+
COMMANDS = CLI::COMMANDS
8+
SUBCOMMAND_OPTIONS = {
9+
"hooks" => %w[--install --uninstall],
10+
"branch" => %w[--add --remove --list],
11+
"diff" => %w[--format],
12+
"list" => %w[--format --type],
13+
"tree" => %w[--format],
14+
"history" => %w[--format --limit],
15+
"search" => %w[--format --limit],
16+
"blame" => %w[--format],
17+
"stale" => %w[--days --format],
18+
"stats" => %w[--format],
19+
"log" => %w[--limit --format],
20+
"show" => %w[--format],
21+
"where" => %w[--format],
22+
"why" => %w[--format]
23+
}.freeze
24+
25+
BASH_SCRIPT = <<~'BASH'
26+
_git_pkgs() {
27+
local cur prev commands
28+
COMPREPLY=()
29+
cur="${COMP_WORDS[COMP_CWORD]}"
30+
prev="${COMP_WORDS[COMP_CWORD-1]}"
31+
32+
commands="init update hooks info list tree history search where why blame stale stats diff branch show log upgrade schema completions"
33+
34+
if [[ ${COMP_CWORD} -eq 2 && ${COMP_WORDS[1]} == "pkgs" ]]; then
35+
COMPREPLY=( $(compgen -W "${commands}" -- ${cur}) )
36+
return 0
37+
fi
38+
39+
if [[ ${COMP_CWORD} -eq 1 ]]; then
40+
COMPREPLY=( $(compgen -W "${commands}" -- ${cur}) )
41+
return 0
42+
fi
43+
44+
case "${prev}" in
45+
hooks)
46+
COMPREPLY=( $(compgen -W "--install --uninstall --help" -- ${cur}) )
47+
;;
48+
branch)
49+
COMPREPLY=( $(compgen -W "--add --remove --list --help" -- ${cur}) )
50+
;;
51+
completions)
52+
COMPREPLY=( $(compgen -W "bash zsh install --help" -- ${cur}) )
53+
;;
54+
diff|list|tree|history|search|blame|stale|stats|log|show|where|why)
55+
COMPREPLY=( $(compgen -W "--format --help" -- ${cur}) )
56+
;;
57+
esac
58+
59+
return 0
60+
}
61+
62+
# Support both 'git pkgs' and 'git-pkgs' invocations
63+
complete -F _git_pkgs git-pkgs
64+
65+
# For 'git pkgs' subcommand completion
66+
if declare -F _git >/dev/null 2>&1; then
67+
_git_pkgs_git_wrapper() {
68+
if [[ ${COMP_WORDS[1]} == "pkgs" ]]; then
69+
_git_pkgs
70+
fi
71+
}
72+
fi
73+
BASH
74+
75+
ZSH_SCRIPT = <<~'ZSH'
76+
#compdef git-pkgs
77+
78+
_git-pkgs() {
79+
local -a commands
80+
commands=(
81+
'init:Initialize the package database'
82+
'update:Update the database with new commits'
83+
'hooks:Manage git hooks for auto-updating'
84+
'info:Show database size and row counts'
85+
'branch:Manage tracked branches'
86+
'list:List dependencies at a commit'
87+
'tree:Show dependency tree grouped by type'
88+
'history:Show the history of a package'
89+
'search:Find a dependency across all history'
90+
'where:Show where a package appears in manifest files'
91+
'why:Explain why a dependency exists'
92+
'blame:Show who added each dependency'
93+
'stale:Show dependencies that have not been updated'
94+
'stats:Show dependency statistics'
95+
'diff:Show dependency changes between commits'
96+
'show:Show dependency changes in a commit'
97+
'log:List commits with dependency changes'
98+
'upgrade:Upgrade database after git-pkgs update'
99+
'schema:Show database schema'
100+
'completions:Generate shell completions'
101+
)
102+
103+
_arguments -C \
104+
'1: :->command' \
105+
'*:: :->args'
106+
107+
case $state in
108+
command)
109+
_describe -t commands 'git-pkgs commands' commands
110+
;;
111+
args)
112+
case $words[1] in
113+
hooks)
114+
_arguments \
115+
'--install[Install git hooks]' \
116+
'--uninstall[Remove git hooks]' \
117+
'--help[Show help]'
118+
;;
119+
branch)
120+
_arguments \
121+
'--add[Add a branch to track]' \
122+
'--remove[Remove a tracked branch]' \
123+
'--list[List tracked branches]' \
124+
'--help[Show help]'
125+
;;
126+
completions)
127+
_arguments '1:shell:(bash zsh install)'
128+
;;
129+
diff|list|tree|history|search|blame|stale|stats|log|show|where|why)
130+
_arguments \
131+
'--format[Output format]:format:(table json csv)' \
132+
'--help[Show help]'
133+
;;
134+
esac
135+
;;
136+
esac
137+
}
138+
139+
_git-pkgs "$@"
140+
ZSH
141+
142+
def initialize(args)
143+
@args = args
144+
end
145+
146+
def run
147+
shell = @args.first
148+
149+
case shell
150+
when "bash"
151+
puts BASH_SCRIPT
152+
when "zsh"
153+
puts ZSH_SCRIPT
154+
when "install"
155+
install_completions
156+
when "-h", "--help", nil
157+
print_help
158+
else
159+
$stderr.puts "Unknown shell: #{shell}"
160+
$stderr.puts "Supported: bash, zsh, install"
161+
exit 1
162+
end
163+
end
164+
165+
def install_completions
166+
shell = detect_shell
167+
168+
case shell
169+
when "zsh"
170+
install_zsh_completions
171+
when "bash"
172+
install_bash_completions
173+
else
174+
$stderr.puts "Could not detect shell. Please run one of:"
175+
$stderr.puts " eval \"$(git pkgs completions bash)\""
176+
$stderr.puts " eval \"$(git pkgs completions zsh)\""
177+
exit 1
178+
end
179+
end
180+
181+
def detect_shell
182+
shell_env = ENV["SHELL"] || ""
183+
if shell_env.include?("zsh")
184+
"zsh"
185+
elsif shell_env.include?("bash")
186+
"bash"
187+
end
188+
end
189+
190+
def install_bash_completions
191+
dir = File.expand_path("~/.local/share/bash-completion/completions")
192+
FileUtils.mkdir_p(dir)
193+
path = File.join(dir, "git-pkgs")
194+
File.write(path, BASH_SCRIPT)
195+
puts "Installed bash completions to #{path}"
196+
puts "Restart your shell or run: source #{path}"
197+
end
198+
199+
def install_zsh_completions
200+
dir = File.expand_path("~/.zsh/completions")
201+
FileUtils.mkdir_p(dir)
202+
path = File.join(dir, "_git-pkgs")
203+
File.write(path, ZSH_SCRIPT)
204+
puts "Installed zsh completions to #{path}"
205+
puts ""
206+
puts "Add to your ~/.zshrc if not already present:"
207+
puts " fpath=(~/.zsh/completions $fpath)"
208+
puts " autoload -Uz compinit && compinit"
209+
puts ""
210+
puts "Then restart your shell or run: source ~/.zshrc"
211+
end
212+
213+
def print_help
214+
puts <<~HELP
215+
Usage: git pkgs completions <shell>
216+
217+
Generate shell completion scripts.
218+
219+
Shells:
220+
bash Output bash completion script
221+
zsh Output zsh completion script
222+
install Auto-install completions for your shell
223+
224+
Examples:
225+
git pkgs completions bash > ~/.local/share/bash-completion/completions/git-pkgs
226+
git pkgs completions zsh > ~/.zsh/completions/_git-pkgs
227+
eval "$(git pkgs completions bash)"
228+
git pkgs completions install
229+
HELP
230+
end
231+
end
232+
end
233+
end
234+
end

0 commit comments

Comments
 (0)