Skip to content

Commit 31883f9

Browse files
committed
feat: shell completion
1 parent 1bf5c67 commit 31883f9

4 files changed

Lines changed: 258 additions & 15 deletions

File tree

README.md

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -280,12 +280,13 @@ groups:
280280
devproc [options] [command]
281281
282282
Commands:
283-
up Start all services (default)
284-
down Stop all services
285-
restart Restart all services
286-
status Show service status
287-
init Create a new devproc.yaml config file
288-
validate Validate the config file without starting services
283+
up Start all services (default)
284+
down Stop all services
285+
restart Restart all services
286+
status Show service status
287+
init Create a new devproc.yaml config file
288+
validate Validate the config file without starting services
289+
completions <shell> Generate shell completions (bash, zsh, fish)
289290
290291
Options:
291292
-c, --config Path to config file (default: devproc.yaml)
@@ -323,6 +324,34 @@ When config is reloaded:
323324
- Removed services are stopped and removed
324325
- Modified services are restarted with the new configuration
325326

327+
### Shell Completions
328+
329+
Enable tab completion for commands and options:
330+
331+
```bash
332+
# Bash (add to ~/.bashrc)
333+
eval "$(devproc completions bash)"
334+
335+
# Zsh (add to ~/.zshrc)
336+
eval "$(devproc completions zsh)"
337+
338+
# Fish (add to ~/.config/fish/config.fish)
339+
devproc completions fish | source
340+
```
341+
342+
Or save to a file for faster shell startup:
343+
344+
```bash
345+
# Bash
346+
devproc completions bash > /usr/local/etc/bash_completion.d/devproc
347+
348+
# Zsh (ensure ~/.zsh/completions is in your fpath)
349+
devproc completions zsh > ~/.zsh/completions/_devproc
350+
351+
# Fish
352+
devproc completions fish > ~/.config/fish/completions/devproc.fish
353+
```
354+
326355
## Requirements
327356

328357
- [Bun](https://bun.sh) >= 1.0

docs/ROADMAP.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ Optional web UI for remote access.
242242
- [ ] Debug mode with verbose logging
243243
- [ ] Dry-run mode to preview what would happen
244244
- [ ] Service templates for common stacks
245-
- [ ] Shell completions (bash, zsh, fish)
245+
- [x] Shell completions (bash, zsh, fish)
246246

247247
---
248248

@@ -291,6 +291,7 @@ Want to help build these features? Here's how:
291291
- Added `devproc init` command to scaffold starter config
292292
- Added `devproc validate` command to check config for errors
293293
- Added clipboard support (`y` to copy last log, `Y` to copy all visible logs)
294+
- Added shell completions for bash, zsh, and fish (`devproc completions <shell>`)
294295

295296
### v0.4.0
296297

src/index.tsx

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
#!/usr/bin/env bun
22
import { render } from "@opentui/solid"
33
import { watch } from "fs"
4-
import { loadConfig, findConfigFile } from "./config/loader"
4+
import { loadConfig } from "./config/loader"
55
import { ProcessManager } from "./process/manager"
66
import { App } from "./app"
7+
import { getCompletion, SUPPORTED_SHELLS } from "./utils/completions"
78

89
const VERSION = "0.5.0"
910

@@ -15,12 +16,13 @@ Usage:
1516
devproc [options] [command]
1617
1718
Commands:
18-
up Start all services (default)
19-
down Stop all services
20-
restart Restart all services
21-
status Show service status (non-interactive)
22-
init Create a new devproc.yaml config file
23-
validate Validate the config file without starting services
19+
up Start all services (default)
20+
down Stop all services
21+
restart Restart all services
22+
status Show service status (non-interactive)
23+
init Create a new devproc.yaml config file
24+
validate Validate the config file without starting services
25+
completions <shell> Generate shell completions (bash, zsh, fish)
2426
2527
Options:
2628
-c, --config <file> Path to config file (default: devproc.yaml)
@@ -35,6 +37,16 @@ Examples:
3537
devproc validate Check config for errors
3638
devproc -c dev.yaml Use custom config file
3739
devproc -w Auto-reload on config changes
40+
41+
Shell Completions:
42+
# Bash (add to ~/.bashrc)
43+
eval "$(devproc completions bash)"
44+
45+
# Zsh (add to ~/.zshrc)
46+
eval "$(devproc completions zsh)"
47+
48+
# Fish (add to ~/.config/fish/config.fish)
49+
devproc completions fish | source
3850
`)
3951
}
4052

@@ -245,16 +257,45 @@ async function main() {
245257
}
246258

247259
// Commands
248-
if (["up", "down", "restart", "status", "init", "validate"].includes(arg!)) {
260+
if (["up", "down", "restart", "status", "init", "validate", "completions"].includes(arg!)) {
249261
command = arg!
250262
continue
251263
}
252264

265+
// Shell argument for completions command
266+
if (SUPPORTED_SHELLS.includes(arg!)) {
267+
// This will be handled after the loop
268+
continue
269+
}
270+
253271
console.error(`Unknown option: ${arg}`)
254272
printHelp()
255273
process.exit(1)
256274
}
257275

276+
// Handle completions command
277+
if (command === "completions") {
278+
// Find the shell argument
279+
const shellArg = args.find((arg) => SUPPORTED_SHELLS.includes(arg))
280+
if (!shellArg) {
281+
console.error("Error: Please specify a shell (bash, zsh, or fish)")
282+
console.log("")
283+
console.log("Usage: devproc completions <shell>")
284+
console.log("")
285+
console.log("Examples:")
286+
console.log(" devproc completions bash")
287+
console.log(" devproc completions zsh")
288+
console.log(" devproc completions fish")
289+
process.exit(1)
290+
}
291+
292+
const script = getCompletion(shellArg)
293+
if (script) {
294+
console.log(script)
295+
}
296+
process.exit(0)
297+
}
298+
258299
// Handle init command (doesn't need existing config)
259300
if (command === "init") {
260301
await initConfig()

src/utils/completions.ts

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
/**
2+
* Shell completion scripts for devproc
3+
*/
4+
5+
const COMMANDS = ["up", "down", "restart", "status", "init", "validate", "completions"]
6+
const OPTIONS = ["-c", "--config", "-w", "--watch", "-h", "--help", "-v", "--version"]
7+
const SHELLS = ["bash", "zsh", "fish"]
8+
9+
/**
10+
* Generate bash completion script
11+
*/
12+
export function bashCompletion(): string {
13+
return `# devproc bash completion
14+
# Add to ~/.bashrc or ~/.bash_profile:
15+
# eval "$(devproc completions bash)"
16+
# Or save to a file:
17+
# devproc completions bash > /usr/local/etc/bash_completion.d/devproc
18+
19+
_devproc() {
20+
local cur prev words cword
21+
_init_completion || return
22+
23+
local commands="${COMMANDS.join(" ")}"
24+
local options="${OPTIONS.join(" ")}"
25+
local shells="${SHELLS.join(" ")}"
26+
27+
case "\${prev}" in
28+
-c|--config)
29+
# Complete yaml files
30+
_filedir '@(yaml|yml)'
31+
return
32+
;;
33+
completions)
34+
COMPREPLY=( $(compgen -W "\${shells}" -- "\${cur}") )
35+
return
36+
;;
37+
esac
38+
39+
if [[ "\${cur}" == -* ]]; then
40+
COMPREPLY=( $(compgen -W "\${options}" -- "\${cur}") )
41+
elif [[ \${cword} -eq 1 ]]; then
42+
COMPREPLY=( $(compgen -W "\${commands}" -- "\${cur}") )
43+
fi
44+
}
45+
46+
complete -F _devproc devproc
47+
`
48+
}
49+
50+
/**
51+
* Generate zsh completion script
52+
*/
53+
export function zshCompletion(): string {
54+
return `#compdef devproc
55+
# devproc zsh completion
56+
# Add to ~/.zshrc:
57+
# eval "$(devproc completions zsh)"
58+
# Or save to a file in your fpath:
59+
# devproc completions zsh > ~/.zsh/completions/_devproc
60+
61+
_devproc() {
62+
local -a commands options shells
63+
64+
commands=(
65+
'up:Start all services (default)'
66+
'down:Stop all services'
67+
'restart:Restart all services'
68+
'status:Show service status'
69+
'init:Create a new devproc.yaml config file'
70+
'validate:Validate the config file'
71+
'completions:Generate shell completions'
72+
)
73+
74+
options=(
75+
'-c[Path to config file]:config file:_files -g "*.y(a|)ml"'
76+
'--config[Path to config file]:config file:_files -g "*.y(a|)ml"'
77+
'-w[Watch config file for changes]'
78+
'--watch[Watch config file for changes]'
79+
'-h[Show help]'
80+
'--help[Show help]'
81+
'-v[Show version]'
82+
'--version[Show version]'
83+
)
84+
85+
shells=(
86+
'bash:Generate bash completions'
87+
'zsh:Generate zsh completions'
88+
'fish:Generate fish completions'
89+
)
90+
91+
_arguments -s \\
92+
'1: :->command' \\
93+
'*: :->args' \\
94+
&& return 0
95+
96+
case "\$state" in
97+
command)
98+
_describe -t commands 'devproc command' commands
99+
_describe -t options 'options' options
100+
;;
101+
args)
102+
case "\$words[2]" in
103+
completions)
104+
_describe -t shells 'shell' shells
105+
;;
106+
*)
107+
_describe -t options 'options' options
108+
;;
109+
esac
110+
;;
111+
esac
112+
}
113+
114+
_devproc "\$@"
115+
`
116+
}
117+
118+
/**
119+
* Generate fish completion script
120+
*/
121+
export function fishCompletion(): string {
122+
return `# devproc fish completion
123+
# Add to ~/.config/fish/config.fish:
124+
# devproc completions fish | source
125+
# Or save to a file:
126+
# devproc completions fish > ~/.config/fish/completions/devproc.fish
127+
128+
# Disable file completion by default
129+
complete -c devproc -f
130+
131+
# Commands
132+
complete -c devproc -n "__fish_use_subcommand" -a "up" -d "Start all services (default)"
133+
complete -c devproc -n "__fish_use_subcommand" -a "down" -d "Stop all services"
134+
complete -c devproc -n "__fish_use_subcommand" -a "restart" -d "Restart all services"
135+
complete -c devproc -n "__fish_use_subcommand" -a "status" -d "Show service status"
136+
complete -c devproc -n "__fish_use_subcommand" -a "init" -d "Create a new devproc.yaml config file"
137+
complete -c devproc -n "__fish_use_subcommand" -a "validate" -d "Validate the config file"
138+
complete -c devproc -n "__fish_use_subcommand" -a "completions" -d "Generate shell completions"
139+
140+
# Options
141+
complete -c devproc -s c -l config -d "Path to config file" -r -F
142+
complete -c devproc -s w -l watch -d "Watch config file for changes"
143+
complete -c devproc -s h -l help -d "Show help"
144+
complete -c devproc -s v -l version -d "Show version"
145+
146+
# Completions subcommand
147+
complete -c devproc -n "__fish_seen_subcommand_from completions" -a "bash" -d "Generate bash completions"
148+
complete -c devproc -n "__fish_seen_subcommand_from completions" -a "zsh" -d "Generate zsh completions"
149+
complete -c devproc -n "__fish_seen_subcommand_from completions" -a "fish" -d "Generate fish completions"
150+
`
151+
}
152+
153+
/**
154+
* Get completion script for a specific shell
155+
*/
156+
export function getCompletion(shell: string): string | null {
157+
switch (shell.toLowerCase()) {
158+
case "bash":
159+
return bashCompletion()
160+
case "zsh":
161+
return zshCompletion()
162+
case "fish":
163+
return fishCompletion()
164+
default:
165+
return null
166+
}
167+
}
168+
169+
/**
170+
* List of supported shells
171+
*/
172+
export const SUPPORTED_SHELLS = SHELLS

0 commit comments

Comments
 (0)