Eric Bower
·
2026-09-19
1const std = @import("std");
2
3pub const Shell = enum {
4 bash,
5 zsh,
6 fish,
7 nu,
8 yash,
9
10 pub fn fromString(s: []const u8) ?Shell {
11 if (std.mem.eql(u8, s, "bash")) return .bash;
12 if (std.mem.eql(u8, s, "zsh")) return .zsh;
13 if (std.mem.eql(u8, s, "fish")) return .fish;
14 if (std.mem.eql(u8, s, "nu")) return .nu;
15 if (std.mem.eql(u8, s, "yash")) return .yash;
16
17 return null;
18 }
19
20 pub fn getCompletionScript(self: Shell) []const u8 {
21 return switch (self) {
22 .bash => bash_completions,
23 .zsh => zsh_completions,
24 .fish => fish_completions,
25 .nu => nu_completions,
26 .yash => yash_completions,
27 };
28 }
29};
30
31const bash_completions =
32 \\_zmx_completions() {
33 \\ local cur prev words cword
34 \\ COMPREPLY=()
35 \\ cur="${COMP_WORDS[COMP_CWORD]}"
36 \\ prev="${COMP_WORDS[COMP_CWORD-1]}"
37 \\
38 \\ local commands="attach run send print write detach list kill history get set clear print-env wait tail completions version help"
39 \\
40 \\ if [[ $COMP_CWORD -eq 1 ]]; then
41 \\ COMPREPLY=($(compgen -W "$commands" -- "$cur"))
42 \\ return 0
43 \\ fi
44 \\
45 \\ case "$prev" in
46 \\ attach|run|send|print|write|kill|history|get|set|clear|print-env|wait|tail)
47 \\ local sessions=$(zmx list --short 2>/dev/null | tr '\n' ' ')
48 \\ COMPREPLY=($(compgen -W "$sessions" -- "$cur"))
49 \\ ;;
50 \\ completions)
51 \\ COMPREPLY=($(compgen -W "bash zsh fish nu yash" -- "$cur"))
52 \\ ;;
53 \\ list)
54 \\ COMPREPLY=($(compgen -W "--short" -- "$cur"))
55 \\ ;;
56 \\ *)
57 \\ ;;
58 \\ esac
59 \\}
60 \\
61 \\complete -o bashdefault -o default -F _zmx_completions zmx
62;
63
64const zsh_completions =
65 \\#compdef zmx
66 \\_zmx() {
67 \\ local context state state_descr line
68 \\ typeset -A opt_args
69 \\
70 \\ _arguments -C \
71 \\ '1: :->commands' \
72 \\ '2: :->args' \
73 \\ '*: :->trailing' \
74 \\ && return 0
75 \\
76 \\ case $state in
77 \\ commands)
78 \\ local -a commands
79 \\ commands=(
80 \\ 'attach:Attach to session, creating if needed'
81 \\ 'run:Send command without attaching'
82 \\ 'send:Send raw input to session PTY'
83 \\ 'print:Inject text into session display'
84 \\ 'write:Write stdin to file_path through the session'
85 \\ 'detach:Detach all clients from current session'
86 \\ 'list:List active sessions'
87 \\ 'kill:Kill a session'
88 \\ 'history:Output session scrollback'
89 \\ 'wait:Wait for session tasks to complete'
90 \\ 'tail:Follow session output'
91 \\ 'completions:Shell completion scripts'
92 \\ 'get:Get session labels'
93 \\ 'set:Set session labels'
94 \\ 'clear:Clear all session labels'
95 \\ 'print-env:Print tracked environment variables'
96 \\ 'version:Show version'
97 \\ 'help:Show help message'
98 \\ )
99 \\ _describe 'command' commands
100 \\ ;;
101 \\ args)
102 \\ case $words[2] in
103 \\ attach|a|kill|k|run|r|send|s|print|p|write|wr|history|get|g|set|clear|print-env|hi|wait|w|tail|t)
104 \\ _zmx_sessions
105 \\ ;;
106 \\ completions|c)
107 \\ _values 'shell' 'bash' 'zsh' 'fish' 'nu' 'yash'
108 \\ ;;
109 \\ list|l)
110 \\ _values 'options' '--short'
111 \\ ;;
112 \\ esac
113 \\ ;;
114 \\ trailing)
115 \\ # Additional args for commands like 'attach' or 'run'
116 \\ ;;
117 \\ esac
118 \\}
119 \\
120 \\_zmx_sessions() {
121 \\ local -a sessions
122 \\
123 \\ local local_sessions=$(zmx list --short 2>/dev/null)
124 \\ if [[ -n "$local_sessions" ]]; then
125 \\ sessions+=(${(f)local_sessions})
126 \\ fi
127 \\
128 \\ _describe 'local session' sessions
129 \\}
130 \\
131 \\compdef _zmx zmx
132;
133
134const fish_completions =
135 \\complete -c zmx -f
136 \\
137 \\# zmx flags
138 \\complete -c zmx -x -n '__fish_is_nth_token 1' -s v -l version -d 'Show version'
139 \\complete -c zmx -x -n '__fish_is_nth_token 1' -s h -d 'Show help message'
140 \\
141 \\# zmx subcommands
142 \\complete -c zmx -n "__fish_is_nth_token 1" -a attach -d 'Attach to session, creating if needed'
143 \\complete -c zmx -n "__fish_is_nth_token 1" -a run -d 'Send command without attaching'
144 \\complete -c zmx -n "__fish_is_nth_token 1" -a send -d 'Send raw input to session PTY'
145 \\complete -c zmx -n "__fish_is_nth_token 1" -a print -d 'Inject text into session display'
146 \\complete -c zmx -n "__fish_is_nth_token 1" -a write -d 'Write stdin to file_path through the session'
147 \\complete -c zmx -n "__fish_is_nth_token 1" -a detach -d 'Detach all clients (ctrl+\ for current client)'
148 \\complete -c zmx -n "__fish_is_nth_token 1" -a list -d 'List active sessions'
149 \\complete -c zmx -n "__fish_is_nth_token 1" -a kill -d 'Kill session and all attached clients'
150 \\complete -c zmx -n "__fish_is_nth_token 1" -a history -d 'Output session scrollback'
151 \\complete -c zmx -n "__fish_is_nth_token 1" -a wait -d 'Wait for session tasks to complete'
152 \\complete -c zmx -n "__fish_is_nth_token 1" -a tail -d 'Follow session output'
153 \\complete -c zmx -n "__fish_is_nth_token 1" -a completions -d 'Shell completions (bash, zsh, fish, nu, yash)'
154 \\complete -c zmx -n "__fish_is_nth_token 1" -a version -d 'Show version'
155 \\complete -c zmx -n "__fish_is_nth_token 1" -a get -d 'Get session labels'
156 \\complete -c zmx -n "__fish_is_nth_token 1" -a set -d 'Set session labels'
157 \\complete -c zmx -n "__fish_is_nth_token 1" -a clear -d 'Clear all session labels'
158 \\complete -c zmx -n "__fish_is_nth_token 1" -a print-env -d 'Print tracked environment variables'
159 \\complete -c zmx -n "__fish_is_nth_token 1" -a help -d 'Show help message'
160 \\
161 \\# Complete session names and shells
162 \\complete -c zmx -n "__fish_is_nth_token 2; and __fish_seen_subcommand_from a attach r run s send p print wr write hi history g get se set cl clear print-env" -a '(zmx list --short 2>/dev/null)' -d 'Session name'
163 \\complete -c zmx -n "not __fish_is_nth_token 1; and __fish_seen_subcommand_from k kill w wait t tail" -a '(zmx list --short 2>/dev/null)' -d 'Session name'
164 \\
165 \\complete -c zmx -n "__fish_is_nth_token 2; and __fish_seen_subcommand_from c completions" -a 'bash zsh fish nu yash' -d Shell
166 \\
167 \\# Subcommand flags
168 \\complete -c zmx -n "__fish_seen_subcommand_from a attach" -l labels -d 'Apply "key=value ..." labels as the session is created' -r
169 \\complete -c zmx -n "__fish_seen_subcommand_from r run" -s d -d 'Detach from the calling terminal; use `wait` to track its status'
170 \\complete -c zmx -n "__fish_seen_subcommand_from r run" -l fish -d 'Required when the session runs fish shell'
171 \\complete -c zmx -n "__fish_seen_subcommand_from l list" -l short -d 'Short output'
172 \\complete -c zmx -n "__fish_seen_subcommand_from k kill" -l force -d 'Force kill'
173 \\complete -c zmx -n "__fish_seen_subcommand_from hi history" -l vt -d 'History format for escape sequences'
174 \\complete -c zmx -n "__fish_seen_subcommand_from hi history" -l html -d 'History format for escape sequences'
175 \\complete -c zmx -n "__fish_seen_subcommand_from print-env" -s s -l shell -d 'Output POSIX export/unset commands for eval'
176;
177
178const nu_completions =
179 \\def "nu-complete zmx sessions" [] {
180 \\ zmx list --short | lines
181 \\}
182 \\
183 \\def "nu-complete zmx complete" [] {
184 \\ [bash fish nu yash zsh]
185 \\}
186 \\
187 \\export extern "zmx attach" [
188 \\ name: string@"nu-complete zmx sessions"
189 \\ --labels: string
190 \\ ...rest: string
191 \\]
192 \\
193 \\export extern "zmx run" [
194 \\ name: string@"nu-complete zmx sessions"
195 \\ -d
196 \\ --fish
197 \\ ...rest: string
198 \\]
199 \\
200 \\export extern "zmx send" [
201 \\ name: string@"nu-complete zmx sessions"
202 \\ text: string
203 \\]
204 \\
205 \\export extern "zmx print" [
206 \\ name: string@"nu-complete zmx sessions"
207 \\ text: string
208 \\]
209 \\
210 \\export extern "zmx write" [
211 \\ name: string@"nu-complete zmx sessions"
212 \\ path: path
213 \\]
214 \\
215 \\export extern "zmx kill" [
216 \\ --force
217 \\ name: string@"nu-complete zmx sessions"
218 \\]
219 \\
220 \\export extern "zmx detach" []
221 \\export extern "zmx list" [--short]
222 \\export extern "zmx history" [name: string@"nu-complete zmx sessions", --vt, --html]
223 \\export extern "zmx wait" [...sessions: string@"nu-complete zmx sessions"]
224 \\export extern "zmx tail" [...sessions: string@"nu-complete zmx sessions"]
225 \\export extern "zmx version" []
226 \\export extern "completions" [shell: string@"nu-complete zmx complete"]
227 \\export extern "zmx get" [
228 \\ name?: string@"nu-complete zmx sessions"
229 \\]
230 \\
231 \\export extern "zmx set" [
232 \\ name?: string@"nu-complete zmx sessions"
233 \\ ...pairs: string
234 \\]
235 \\
236 \\export extern "zmx clear" [
237 \\ name?: string@"nu-complete zmx sessions"
238 \\]
239 \\
240 \\export extern "zmx print-env" [
241 \\ name: string@"nu-complete zmx sessions"
242 \\ key?: string
243 \\ --shell(-s)
244 \\]
245 \\
246 \\export extern "zmx help" []
247;
248
249const yash_completions =
250 \\function completion/zmx {
251 \\ typeset OPTIONS ARGOPT PREFIX
252 \\ OPTIONS=( #>#
253 \\ "v --version; show version"
254 \\ "h; show help"
255 \\ ) #<#
256 \\
257 \\ command -f completion//parseoptions -e
258 \\ case $ARGOPT in
259 \\ (-)
260 \\ command -f completion//completeoptions
261 \\ ;;
262 \\ ("")
263 \\ if [ ${WORDS[#]} -le 1 ]; then
264 \\ command -f completion/zmx::completecmd
265 \\ else
266 \\ typeset zmxcmd="${WORDS[2]}"
267 \\ case $zmxcmd in
268 \\ (a|attach)
269 \\ command -f completion/zmx::attach:arg
270 \\ ;;
271 \\ (r|run)
272 \\ command -f completion/zmx::run:arg
273 \\ ;;
274 \\ (s|send)
275 \\ command -f completion/zmx::send:arg
276 \\ ;;
277 \\ (p|print)
278 \\ command -f completion/zmx::print:arg
279 \\ ;;
280 \\ (wr|write)
281 \\ command -f completion/zmx::write:arg
282 \\ ;;
283 \\ (d|detach)
284 \\ ;;
285 \\ (l|ls|list)
286 \\ command -f completion/zmx::list:arg
287 \\ ;;
288 \\ (g|get)
289 \\ command -f completion/zmx::get:arg
290 \\ ;;
291 \\ (set)
292 \\ command -f completion/zmx::set:arg
293 \\ ;;
294 \\ (cl|clear)
295 \\ command -f completion/zmx::clear:arg
296 \\ ;;
297 \\ (print-env)
298 \\ command -f completion/zmx::print-env:arg
299 \\ ;;
300 \\ (k|kill)
301 \\ command -f completion/zmx::kill:arg
302 \\ ;;
303 \\ (hi|history)
304 \\ command -f completion/zmx::history:arg
305 \\ ;;
306 \\ (w|wait)
307 \\ command -f completion/zmx::wait:arg
308 \\ ;;
309 \\ (t|tail)
310 \\ command -f completion/zmx::tail:arg
311 \\ ;;
312 \\ (c|completions)
313 \\ command -f completion/zmx::completions:arg
314 \\ ;;
315 \\ esac
316 \\ fi
317 \\ ;;
318 \\ esac
319 \\}
320 \\
321 \\function completion/zmx::completecmd {
322 \\ complete -P "$PREFIX" -D "Attach to session, creating if needed" attach a
323 \\ complete -P "$PREFIX" -D "Send command without attaching" run r
324 \\ complete -P "$PREFIX" -D "Send raw input to session PTY" send s
325 \\ complete -P "$PREFIX" -D "Inject text into session display" print p
326 \\ complete -P "$PREFIX" -D "Write stdin to file_path through the session" write wr
327 \\ complete -P "$PREFIX" -D "Detach all clients from current session" detach d
328 \\ complete -P "$PREFIX" -D "List active sessions" list ls l
329 \\ complete -P "$PREFIX" -D "Get session labels" get g
330 \\ complete -P "$PREFIX" -D "Set session labels" set
331 \\ complete -P "$PREFIX" -D "Clear all session labels" clear cl
332 \\ complete -P "$PREFIX" -D "Print tracked environment variables" print-env
333 \\ complete -P "$PREFIX" -D "Kill session and all attached clients" kill k
334 \\ complete -P "$PREFIX" -D "Output session scrollback" history hi
335 \\ complete -P "$PREFIX" -D "Wait for session tasks to complete" wait w
336 \\ complete -P "$PREFIX" -D "Follow session output" tail t
337 \\ complete -P "$PREFIX" -D "Shell completion scripts" completions c
338 \\ complete -P "$PREFIX" -D "Show version" version v
339 \\ complete -P "$PREFIX" -D "Show help message" help h
340 \\}
341 \\
342 \\function completion/zmx::sessions {
343 \\ typeset sessions
344 \\ typeset IFS='
345 \\'
346 \\ sessions=($(zmx list --short 2>/dev/null))
347 \\ if [ ${sessions[#]} -gt 0 ]; then
348 \\ complete -P "$PREFIX" -- "$sessions"
349 \\ fi
350 \\}
351 \\
352 \\function completion/zmx::attach:arg {
353 \\ OPTIONS=( #>#
354 \\ "--labels:; apply labels as session is created"
355 \\ ) #<#
356 \\ command -f completion//parseoptions -en
357 \\ case $ARGOPT in
358 \\ (-)
359 \\ command -f completion//completeoptions
360 \\ ;;
361 \\ (--labels)
362 \\ ;;
363 \\ (*)
364 \\ command -f completion//getoperands
365 \\ if [ ${WORDS[#]} -eq 1 ]; then
366 \\ command -f completion/zmx::sessions
367 \\ else
368 \\ complete -P "$PREFIX" -c
369 \\ fi
370 \\ ;;
371 \\ esac
372 \\}
373 \\
374 \\function completion/zmx::run:arg {
375 \\ OPTIONS=( #>#
376 \\ "d; detach from calling terminal"
377 \\ "--fish; session runs fish shell"
378 \\ ) #<#
379 \\ command -f completion//parseoptions -en
380 \\ case $ARGOPT in
381 \\ (-)
382 \\ command -f completion//completeoptions
383 \\ ;;
384 \\ (*)
385 \\ command -f completion//getoperands
386 \\ if [ ${WORDS[#]} -eq 1 ]; then
387 \\ command -f completion/zmx::sessions
388 \\ else
389 \\ complete -P "$PREFIX" -c
390 \\ fi
391 \\ ;;
392 \\ esac
393 \\}
394 \\
395 \\function completion/zmx::send:arg {
396 \\ command -f completion//getoperands
397 \\ if [ ${WORDS[#]} -eq 1 ]; then
398 \\ command -f completion/zmx::sessions
399 \\ fi
400 \\}
401 \\
402 \\function completion/zmx::print:arg {
403 \\ command -f completion//getoperands
404 \\ if [ ${WORDS[#]} -eq 1 ]; then
405 \\ command -f completion/zmx::sessions
406 \\ fi
407 \\}
408 \\
409 \\function completion/zmx::write:arg {
410 \\ command -f completion//getoperands
411 \\ if [ ${WORDS[#]} -eq 1 ]; then
412 \\ command -f completion/zmx::sessions
413 \\ elif [ ${WORDS[#]} -eq 2 ]; then
414 \\ complete -P "$PREFIX" -f
415 \\ fi
416 \\}
417 \\
418 \\function completion/zmx::list:arg {
419 \\ OPTIONS=( #>#
420 \\ "--short; short output"
421 \\ ) #<#
422 \\ command -f completion//parseoptions -en
423 \\ case $ARGOPT in
424 \\ (-)
425 \\ command -f completion//completeoptions
426 \\ ;;
427 \\ esac
428 \\}
429 \\
430 \\function completion/zmx::get:arg {
431 \\ command -f completion//getoperands
432 \\ if [ ${WORDS[#]} -eq 1 ]; then
433 \\ complete -P "$PREFIX" -D "Current session" .
434 \\ command -f completion/zmx::sessions
435 \\ fi
436 \\}
437 \\
438 \\function completion/zmx::set:arg {
439 \\ command -f completion//getoperands
440 \\ if [ ${WORDS[#]} -eq 1 ]; then
441 \\ complete -P "$PREFIX" -D "Current session" .
442 \\ command -f completion/zmx::sessions
443 \\ fi
444 \\}
445 \\
446 \\function completion/zmx::clear:arg {
447 \\ command -f completion//getoperands
448 \\ if [ ${WORDS[#]} -eq 1 ]; then
449 \\ complete -P "$PREFIX" -D "Current session" .
450 \\ command -f completion/zmx::sessions
451 \\ fi
452 \\}
453 \\
454 \\function completion/zmx::print-env:arg {
455 \\ OPTIONS=( #>#
456 \\ "s --shell; output POSIX export/unset commands for eval"
457 \\ ) #<#
458 \\ command -f completion//parseoptions -en
459 \\ case $ARGOPT in
460 \\ (-)
461 \\ command -f completion//completeoptions
462 \\ ;;
463 \\ (*)
464 \\ command -f completion//getoperands
465 \\ if [ ${WORDS[#]} -eq 1 ]; then
466 \\ complete -P "$PREFIX" -D "Current session" .
467 \\ command -f completion/zmx::sessions
468 \\ fi
469 \\ ;;
470 \\ esac
471 \\}
472 \\
473 \\function completion/zmx::kill:arg {
474 \\ OPTIONS=( #>#
475 \\ "--force; force kill"
476 \\ ) #<#
477 \\ command -f completion//parseoptions -en
478 \\ case $ARGOPT in
479 \\ (-)
480 \\ command -f completion//completeoptions
481 \\ ;;
482 \\ (*)
483 \\ command -f completion/zmx::sessions
484 \\ ;;
485 \\ esac
486 \\}
487 \\
488 \\function completion/zmx::history:arg {
489 \\ OPTIONS=( #>#
490 \\ "--vt; history format with escape sequences"
491 \\ "--html; history format in HTML"
492 \\ ) #<#
493 \\ command -f completion//parseoptions -en
494 \\ case $ARGOPT in
495 \\ (-)
496 \\ command -f completion//completeoptions
497 \\ ;;
498 \\ (*)
499 \\ command -f completion//getoperands
500 \\ if [ ${WORDS[#]} -eq 1 ]; then
501 \\ command -f completion/zmx::sessions
502 \\ fi
503 \\ ;;
504 \\ esac
505 \\}
506 \\
507 \\function completion/zmx::wait:arg {
508 \\ command -f completion//getoperands
509 \\ command -f completion/zmx::sessions
510 \\}
511 \\
512 \\function completion/zmx::tail:arg {
513 \\ command -f completion//getoperands
514 \\ command -f completion/zmx::sessions
515 \\}
516 \\
517 \\function completion/zmx::completions:arg {
518 \\ command -f completion//getoperands
519 \\ if [ ${WORDS[#]} -eq 1 ]; then
520 \\ complete -P "$PREFIX" -- bash zsh fish nu yash
521 \\ fi
522 \\}
523;