main zmx / src / completions.zig
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;