Skip to content

Commit b5b3dcb

Browse files
committed
feat: add shell completion support for pingu command
- Implement completion command for bash, zsh, and fish shells. - Update README with usage instructions for shell completions. - Create utility functions for generating completion scripts.
1 parent 5f83571 commit b5b3dcb

File tree

3 files changed

+288
-0
lines changed

3 files changed

+288
-0
lines changed

README.md

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,19 +152,26 @@ pingu -e --count 20 cloudflare.com
152152
```
153153
Usage
154154
$ pingu <host>
155+
$ pingu completion <shell>
155156
156157
Options
157158
--count, -c Number of ping packets to send (default: unlimited)
159+
--chart, -ch Display chart (default: false)
160+
--display, -d Number of ping packets to display (default: 8)
158161
--interval, -i Wait interval seconds between sending each packet (default: 1)
159162
--timeout, -t Time to wait for a response, in seconds (default: 5)
160163
--size, -s Number of data bytes to be sent (default: 56)
161164
--export, -e Export results to JSON file after completion
162165
166+
Commands
167+
completion <shell> Generate shell completion script (bash, zsh, fish)
168+
163169
Examples
164170
$ pingu google.com
165171
$ pingu -c 10 8.8.8.8
166172
$ pingu --count 5 --interval 2 example.com
167173
$ pingu -e -c 100 cloudflare.com
174+
$ pingu completion bash > ~/.local/share/bash-completion/completions/pingu
168175
```
169176

170177
### Interface Overview
@@ -199,6 +206,62 @@ Pingu analyzes your network connection and provides detailed metrics:
199206
- **Response Time Distribution**: Categorized latency analysis
200207
- **Streak Tracking**: Success/failure pattern analysis
201208

209+
## 🐚 Shell Completions
210+
211+
Pingu includes built-in shell completion support for bash, zsh, and fish shells, providing intelligent tab completion for all commands and options.
212+
213+
### Quick Setup
214+
215+
The installer automatically sets up completions, but you can also configure them manually:
216+
217+
**Bash:**
218+
```bash
219+
# Generate and install completion
220+
pingu completion bash > ~/.local/share/bash-completion/completions/pingu
221+
222+
# Add to ~/.bashrc
223+
source ~/.local/share/bash-completion/completions/pingu
224+
```
225+
226+
**Zsh:**
227+
```bash
228+
# Generate and install completion
229+
pingu completion zsh > ~/.local/share/zsh/site-functions/_pingu
230+
231+
# Add to ~/.zshrc
232+
fpath=(~/.local/share/zsh/site-functions $fpath)
233+
autoload -U compinit && compinit
234+
```
235+
236+
**Fish:**
237+
```bash
238+
# Generate and install completion (auto-loaded)
239+
pingu completion fish > ~/.config/fish/completions/pingu.fish
240+
```
241+
242+
### Completion Features
243+
244+
- **🎯 Smart option completion** - Tab complete all flags and options
245+
- **🔢 Value suggestions** - Intelligent suggestions for numeric options (count, interval, timeout)
246+
- **🌐 Hostname completion** - Common hosts like `google.com`, `8.8.8.8`, `1.1.1.1`
247+
- **📝 Contextual help** - Descriptions for all options and commands
248+
- **⚡ Subcommand support** - Complete the `completion` command and shell types
249+
250+
### Usage Examples
251+
252+
```bash
253+
# Tab completion for options
254+
pingu --c<TAB> # → --count --chart
255+
pingu --count <TAB> # → 1 2 3 4 5 10 20 50 100
256+
257+
# Hostname completion
258+
pingu goo<TAB> # → google.com
259+
pingu 8.<TAB> # → 8.8.8.8
260+
261+
# Completion command
262+
pingu completion <TAB> # → bash zsh fish
263+
```
264+
202265
## 🛠️ Development
203266

204267
### Prerequisites

src/cli.tsx

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import meow from "meow";
66
import App from "./app";
77
import figlet from "figlet";
88
import gradient from "gradient-string";
9+
import { generateCompletion, printCompletionHelp } from "./utils/completions";
910

1011
console.log();
1112
console.log(
@@ -23,6 +24,7 @@ const cli = meow(
2324
`
2425
Usage
2526
$ pingu <host>
27+
$ pingu completion <shell>
2628
2729
Options
2830
--count, -c Number of ping packets to send (default: unlimited)
@@ -33,10 +35,15 @@ const cli = meow(
3335
--size, -s Number of data bytes to be sent (default: 56)
3436
--export, -e Export results to JSON file after completion
3537
38+
Commands
39+
completion <shell> Generate shell completion script (bash, zsh, fish)
40+
3641
Examples
3742
$ pingu google.com
3843
$ pingu -c 10 8.8.8.8
3944
$ pingu --count 5 --interval 2 example.com
45+
$ pingu completion bash > /usr/local/etc/bash_completion.d/pingu
46+
$ pingu completion zsh > ~/.local/share/zsh/site-functions/_pingu
4047
`,
4148
{
4249
importMeta: import.meta,
@@ -79,6 +86,26 @@ const cli = meow(
7986
},
8087
);
8188

89+
// Handle completion command
90+
if (cli.input[0] === "completion") {
91+
const shell = cli.input[1];
92+
93+
if (!shell) {
94+
printCompletionHelp();
95+
process.exit(0);
96+
}
97+
98+
try {
99+
const completionScript = generateCompletion(shell);
100+
console.log(completionScript);
101+
process.exit(0);
102+
} catch (error) {
103+
console.error(`Error: ${(error as Error).message}`);
104+
printCompletionHelp();
105+
process.exit(1);
106+
}
107+
}
108+
82109
const host = cli.input[0];
83110

84111
if (!host) {

src/utils/completions.ts

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
export const bashCompletion = `# Bash completion for pingu
2+
_pingu() {
3+
local cur prev opts commands
4+
COMPREPLY=()
5+
cur="\${COMP_WORDS[COMP_CWORD]}"
6+
prev="\${COMP_WORDS[COMP_CWORD-1]}"
7+
8+
commands="completion"
9+
opts="--count -c --chart -ch --display -d --interval -i --timeout -t --size -s --export -e --help -h --version -v"
10+
11+
# Handle completion command
12+
if [[ \${COMP_WORDS[1]} == "completion" ]]; then
13+
if [[ \${COMP_CWORD} == 2 ]]; then
14+
COMPREPLY=( \$(compgen -W "bash zsh fish" -- \${cur}) )
15+
return 0
16+
fi
17+
return 0
18+
fi
19+
20+
# Handle regular commands
21+
case "\${prev}" in
22+
--count|-c|--display|-d|--interval|-i|--timeout|-t|--size|-s)
23+
case "\${prev}" in
24+
--count|-c)
25+
COMPREPLY=( \$(compgen -W "1 2 3 4 5 10 20 50 100" -- \${cur}) )
26+
;;
27+
--display|-d)
28+
COMPREPLY=( \$(compgen -W "1 2 3 4 5 8 10 15 20" -- \${cur}) )
29+
;;
30+
--interval|-i)
31+
COMPREPLY=( \$(compgen -W "0.2 0.5 1 2 5" -- \${cur}) )
32+
;;
33+
--timeout|-t)
34+
COMPREPLY=( \$(compgen -W "1 2 5 10 30" -- \${cur}) )
35+
;;
36+
--size|-s)
37+
COMPREPLY=( \$(compgen -W "32 56 64 128 256 512 1024" -- \${cur}) )
38+
;;
39+
esac
40+
return 0
41+
;;
42+
*)
43+
;;
44+
esac
45+
46+
# Complete commands if first argument
47+
if [[ \${COMP_CWORD} == 1 ]]; then
48+
if [[ \${cur} == -* ]]; then
49+
COMPREPLY=( \$(compgen -W "\${opts}" -- \${cur}) )
50+
else
51+
local words="\${commands} google.com 8.8.8.8 1.1.1.1 cloudflare.com localhost 127.0.0.1"
52+
COMPREPLY=( \$(compgen -W "\${words}" -- \${cur}) )
53+
fi
54+
return 0
55+
fi
56+
57+
# Complete options
58+
if [[ \${cur} == -* ]]; then
59+
COMPREPLY=( \$(compgen -W "\${opts}" -- \${cur}) )
60+
return 0
61+
fi
62+
63+
# Complete hostnames/IPs for second+ arguments
64+
COMPREPLY=( \$(compgen -W "google.com 8.8.8.8 1.1.1.1 cloudflare.com localhost 127.0.0.1" -- \${cur}) )
65+
}
66+
67+
complete -F _pingu pingu`;
68+
69+
export const zshCompletion = `#compdef pingu
70+
71+
_pingu() {
72+
local context state state_descr line
73+
typeset -A opt_args
74+
75+
_arguments -C \\
76+
'1: :_pingu_commands' \\
77+
'*::arg:->args' \\
78+
'(-c --count)'{-c,--count}'[Number of ping packets to send]:count:(1 2 3 4 5 10 20 50 100)' \\
79+
'(-ch --chart)'{-ch,--chart}'[Display chart]' \\
80+
'(-d --display)'{-d,--display}'[Number of ping packets to display]:display:(1 2 3 4 5 8 10 15 20)' \\
81+
'(-i --interval)'{-i,--interval}'[Wait interval seconds between packets]:interval:(0.2 0.5 1 2 5)' \\
82+
'(-t --timeout)'{-t,--timeout}'[Timeout for response in seconds]:timeout:(1 2 5 10 30)' \\
83+
'(-s --size)'{-s,--size}'[Number of data bytes to send]:size:(32 56 64 128 256 512 1024)' \\
84+
'(-e --export)'{-e,--export}'[Export results to JSON file]' \\
85+
'(-h --help)'{-h,--help}'[Show help]' \\
86+
'(-v --version)'{-v,--version}'[Show version]'
87+
88+
case $state in
89+
args)
90+
case $words[1] in
91+
completion)
92+
_arguments ':shell:(bash zsh fish)'
93+
;;
94+
*)
95+
_alternative \\
96+
'hosts:host:(google.com 8.8.8.8 1.1.1.1 cloudflare.com localhost 127.0.0.1)' \\
97+
'files:file:_files'
98+
;;
99+
esac
100+
;;
101+
esac
102+
}
103+
104+
_pingu_commands() {
105+
local commands=(
106+
'completion:Generate shell completion script'
107+
'google.com:Ping Google DNS'
108+
'8.8.8.8:Ping Google DNS'
109+
'1.1.1.1:Ping Cloudflare DNS'
110+
'cloudflare.com:Ping Cloudflare'
111+
'localhost:Ping localhost'
112+
'127.0.0.1:Ping localhost IP'
113+
)
114+
115+
_describe 'commands' commands
116+
}
117+
118+
_pingu "$@"`;
119+
120+
export const fishCompletion = `# Fish completion for pingu
121+
122+
# Main command completions
123+
complete -c pingu -f -n '__fish_use_subcommand' -a 'completion' -d 'Generate shell completion script'
124+
125+
# Completion subcommand
126+
complete -c pingu -f -n '__fish_seen_subcommand_from completion' -a 'bash zsh fish' -d 'Shell type'
127+
128+
# Option completions
129+
complete -c pingu -s c -l count -d "Number of ping packets to send" -x -a "1 2 3 4 5 10 20 50 100"
130+
complete -c pingu -l chart -d "Display chart"
131+
complete -c pingu -s d -l display -d "Number of ping packets to display" -x -a "1 2 3 4 5 8 10 15 20"
132+
complete -c pingu -s i -l interval -d "Wait interval seconds between packets" -x -a "0.2 0.5 1 2 5"
133+
complete -c pingu -s t -l timeout -d "Timeout for response in seconds" -x -a "1 2 5 10 30"
134+
complete -c pingu -s s -l size -d "Number of data bytes to send" -x -a "32 56 64 128 256 512 1024"
135+
complete -c pingu -s e -l export -d "Export results to JSON file"
136+
complete -c pingu -s h -l help -d "Show help"
137+
complete -c pingu -s v -l version -d "Show version"
138+
139+
# Hostname/IP completions - only when not using completion subcommand
140+
complete -c pingu -f -n 'not __fish_seen_subcommand_from completion' -a "google.com" -d "Google DNS"
141+
complete -c pingu -f -n 'not __fish_seen_subcommand_from completion' -a "8.8.8.8" -d "Google DNS IP"
142+
complete -c pingu -f -n 'not __fish_seen_subcommand_from completion' -a "1.1.1.1" -d "Cloudflare DNS"
143+
complete -c pingu -f -n 'not __fish_seen_subcommand_from completion' -a "cloudflare.com" -d "Cloudflare"
144+
complete -c pingu -f -n 'not __fish_seen_subcommand_from completion' -a "localhost" -d "Local host"
145+
complete -c pingu -f -n 'not __fish_seen_subcommand_from completion' -a "127.0.0.1" -d "Localhost IP"`;
146+
147+
export function generateCompletion(shell: string): string {
148+
switch (shell.toLowerCase()) {
149+
case "bash":
150+
return bashCompletion;
151+
case "zsh":
152+
return zshCompletion;
153+
case "fish":
154+
return fishCompletion;
155+
default:
156+
throw new Error(`Unsupported shell: ${shell}. Supported shells: bash, zsh, fish`);
157+
}
158+
}
159+
160+
export function printCompletionHelp(): void {
161+
console.log(`
162+
🐚 Shell Completion Setup
163+
164+
Pingu supports tab completion for bash, zsh, and fish shells.
165+
166+
📋 Setup Instructions:
167+
168+
Bash:
169+
pingu completion bash > ~/.local/share/bash-completion/completions/pingu
170+
# Or system-wide:
171+
sudo pingu completion bash > /usr/local/etc/bash_completion.d/pingu
172+
173+
Then add to ~/.bashrc:
174+
source ~/.local/share/bash-completion/completions/pingu
175+
176+
Zsh:
177+
pingu completion zsh > ~/.local/share/zsh/site-functions/_pingu
178+
179+
Then add to ~/.zshrc:
180+
fpath=(~/.local/share/zsh/site-functions $fpath)
181+
autoload -U compinit && compinit
182+
183+
Fish:
184+
pingu completion fish > ~/.config/fish/completions/pingu.fish
185+
# Completions are automatically loaded
186+
187+
✨ Features:
188+
• Tab completion for all options (--count, --interval, etc.)
189+
• Smart value suggestions for numeric options
190+
• Common hostname/IP completions
191+
• Subcommand completion support
192+
193+
💡 Quick setup for current shell:
194+
eval "$(pingu completion bash)" # For bash
195+
eval "$(pingu completion zsh)" # For zsh
196+
pingu completion fish | source # For fish
197+
`);
198+
}

0 commit comments

Comments
 (0)