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