# SPDX-License-Identifier: GPL-3.0-or-later """Shell completion script generation.""" from __future__ import annotations COMMANDS = ( "run", "check", "baseline", "list-detectors", "rules", "web", "tui", "triage", "fim-baseline", "fim-update", "fim-check", "pkgdb-check", "pkgdb-verify", "rootcheck", "status", "incident", "posture", "respond", "watchdog", "completion", ) RULE_ACTIONS = ("list", "show", "test", "docs") BASELINE_ACTIONS = ("build", "accept", "revoke", "list") INCIDENT_ACTIONS = ("list", "show", "export") POSTURE_ACTIONS = ("check",) RESPOND_ACTIONS = ("plan", "apply") COMPLETION_SHELLS = ("bash", "zsh") def bash_completion(prog: str = "enodia-sentinel") -> str: commands = " ".join(COMMANDS) rule_actions = " ".join(RULE_ACTIONS) baseline_actions = " ".join(BASELINE_ACTIONS) incident_actions = " ".join(INCIDENT_ACTIONS) posture_actions = " ".join(POSTURE_ACTIONS) respond_actions = " ".join(RESPOND_ACTIONS) shells = " ".join(COMPLETION_SHELLS) return f"""# bash completion for {prog} _{prog.replace('-', '_')}_complete() {{ local cur prev cmd COMPREPLY=() cur="${{COMP_WORDS[COMP_CWORD]}}" prev="${{COMP_WORDS[COMP_CWORD-1]}}" cmd="" for word in "${{COMP_WORDS[@]:1}}"; do case "$word" in -* ) ;; * ) cmd="$word"; break ;; esac done if [[ $COMP_CWORD -le 1 || -z "$cmd" ]]; then COMPREPLY=( $(compgen -W "--version --config -c {commands}" -- "$cur") ) return 0 fi case "$cmd" in rules) COMPREPLY=( $(compgen -W "{rule_actions} --json" -- "$cur") ) ;; baseline) COMPREPLY=( $(compgen -W "{baseline_actions} --reason --expires --force --stale --json" -- "$cur") ) ;; incident) COMPREPLY=( $(compgen -W "{incident_actions} --json" -- "$cur") ) ;; posture) COMPREPLY=( $(compgen -W "{posture_actions} --json" -- "$cur") ) ;; respond) COMPREPLY=( $(compgen -W "{respond_actions} --json --dry-run" -- "$cur") ) ;; completion) COMPREPLY=( $(compgen -W "{shells}" -- "$cur") ) ;; check|fim-check|status) COMPREPLY=( $(compgen -W "--json --packages" -- "$cur") ) ;; pkgdb-verify) COMPREPLY=( $(compgen -W "--sample" -- "$cur") ) ;; watchdog) COMPREPLY=( $(compgen -W "--url --token --max-age --insecure-tls" -- "$cur") ) ;; esac }} complete -F _{prog.replace('-', '_')}_complete {prog} """ def zsh_completion(prog: str = "enodia-sentinel") -> str: command_specs = " ".join(f"{c}:{c}" for c in COMMANDS) return f"""#compdef {prog} # zsh completion for {prog} local -a commands commands=({command_specs}) _arguments -C \\ '(-h --help)'{{-h,--help}}'[show help]' \\ '--version[show version]' \\ '(-c --config)'{{-c,--config}}'[path to TOML config]:config file:_files' \\ '1:command:->command' \\ '*::arg:->args' case $state in command) _describe 'command' commands ;; args) case $words[2] in rules) _arguments '1:action:((list show test docs))' '--json[emit JSON]' ;; baseline) _arguments '1:action:((build accept revoke list))' '2:kind:((fim pkgfile listener suid))' '--reason[reason]' '--expires[TTL]' '--force[force]' '--stale[stale]' '--json[emit JSON]' ;; incident) _arguments '1:action:((list show export))' '--json[emit JSON]' ;; posture) _arguments '1:action:((check))' '--json[emit JSON]' ;; respond) _arguments '1:action:((plan apply))' '--json[emit JSON]' '--dry-run[rehearse apply without executing]' ;; completion) _arguments '1:shell:((bash zsh))' ;; check|status) _arguments '--json[emit JSON]' ;; fim-check) _arguments '--packages[verify package-owned files]' ;; pkgdb-verify) _arguments '--sample[package sample size]' ;; watchdog) _arguments '--url[dashboard URL]' '--token[bearer token]' '--max-age[seconds]' '--insecure-tls[allow self-signed TLS]' ;; esac ;; esac """ def script(shell: str, prog: str = "enodia-sentinel") -> str: if shell == "bash": return bash_completion(prog) if shell == "zsh": return zsh_completion(prog) raise ValueError(f"unsupported shell: {shell}")