#!/usr/bin/env bash # Bash completion for pos — dynamically discovers pos-* subcommands # Install: source this file in ~/.bashrc or place in /etc/bash_completion.d/ # GEN:START posflags declare -A _pos_flags _pos_flags[communication-telegram]="--send --type --caption --parse-mode --no-preview --token --chat-id" _pos_flags[entertainment-send]="--print --markdown" _pos_flags[network-hotspot]="--foreground" _pos_flags[system-backup]="--service" _pos_flags[usb-server]="--ls --ls-shared --share --unshare --auto-share --callback --close-callback --auto-connect --disconnect --nickname --timeout --port --info --version" # GEN:END posflags _pos() { local cur prev words cword # Manual init if bash-completion package is not loaded if declare -F _init_completion &>/dev/null; then _init_completion || return else COMPREPLY=() cur="${COMP_WORDS[COMP_CWORD]}" prev="${COMP_WORDS[COMP_CWORD-1]}" words=("${COMP_WORDS[@]}") cword=$COMP_CWORD fi local pos_bin="${COMP_WORDS[0]}" local pos_dir pos_dir="$(dirname "$(command -v "$pos_bin" 2>/dev/null || echo "$pos_bin")")" # ── Collect all pos-* subcommands ────────────────────────── local all_cmds=() local f for f in "$pos_dir"/pos-*; do [ -x "$f" ] || continue all_cmds+=("${f##*/pos-}") done # ── Build category→subcommand map ────────────────────────── local -A cat_cmds for cmd in "${all_cmds[@]}"; do local cat="${cmd%%-*}" local sub="${cmd#*-}" if [ "$cat" != "$cmd" ]; then cat_cmds["$cat"]+="${sub} " fi done # ── Helpers ──────────────────────────────────────────────── _pos_complete_categories() { COMPREPLY=($(compgen -W "${!cat_cmds[*]}" -- "$cur")) } _pos_complete_subcats() { local cat="${words[1]}" COMPREPLY=($(compgen -W "${cat_cmds[$cat]:-} --help" -- "$cur")) } _pos_complete_compose_services() { local scale_dir="/usr/local/share/linux_post_install/scale-tail/services" if [ -d "$scale_dir" ]; then local svcs=() for d in "$scale_dir"/*/; do [ -d "$d" ] && svcs+=("$(basename "$d")") done COMPREPLY=($(compgen -W "${svcs[*]}" -- "$cur")) fi } _pos_complete_compose_cmds() { COMPREPLY=($(compgen -W "ls installed up down restart logs update config" -- "$cur")) } _pos_complete_docker_vbox_cmds() { COMPREPLY=($(compgen -W "create enter stop start rm ls" -- "$cur")) } _pos_complete_docker_vbox_names() { local names names=$(docker ps -a --filter label=linux_post_install.vbox=true --format '{{.Names}}' 2>/dev/null) COMPREPLY=($(compgen -W "$names" -- "$cur")) } _pos_complete_flags() { local tool="$1" COMPREPLY=($(compgen -W "${_pos_flags[$tool]:-} --help" -- "$cur")) } _pos_entertainment_plugins() { local d f name out=() for d in /usr/local/bin "$pos_dir/../entertainment"; do [ -d "$d" ] || continue for f in "$d"/*.sh; do [ -f "$f" ] || continue name="$(grep -m1 '^# POS_PLUGIN:' "$f" 2>/dev/null | sed 's/^# POS_PLUGIN:[[:space:]]*//;s/[[:space:]]*$//')" [ -n "$name" ] && out+=("$name") done done COMPREPLY=($(compgen -W "${out[*]}" -- "$cur")) } # ── Dispatch ─────────────────────────────────────────────── case "${#words[@]}" in 2) _pos_complete_categories ;; 3) _pos_complete_subcats ;; 4) case "${words[1]}-${words[2]}" in docker-compose) case "${words[3]}" in up|down|restart|logs) _pos_complete_compose_services ;; *) _pos_complete_compose_cmds ;; esac ;; docker-vbox) _pos_complete_docker_vbox_cmds ;; usb-server) _pos_complete_flags usb-server ;; communication-telegram) _pos_complete_flags communication-telegram ;; entertainment-send) _pos_complete_flags entertainment-send ;; entertainment-enable|entertainment-disable) _pos_entertainment_plugins ;; entertainment-config) COMPREPLY=($(compgen -W "set --help" -- "$cur")) ;; network-hotspot) _pos_complete_flags network-hotspot ;; system-backup) _pos_complete_flags system-backup ;; esac ;; 5) case "${words[1]}-${words[2]}" in docker-compose) case "${words[3]}" in up|down|restart|logs) _pos_complete_compose_services ;; esac ;; docker-vbox) case "${words[3]}" in create|enter|stop|start|rm) _pos_complete_docker_vbox_names ;; esac ;; communication-telegram) case "${words[3]}" in send|--send) _pos_complete_flags communication-telegram ;; esac ;; esac ;; 6) case "${words[1]}-${words[2]}" in communication-telegram) case "${words[3]}:${words[4]}" in send:--type|--send:--type) COMPREPLY=($(compgen -W "message file link sticker photo video audio voice animation" -- "$cur")) ;; send:--parse-mode|--send:--parse-mode) COMPREPLY=($(compgen -W "plain markdown html" -- "$cur")) ;; esac ;; esac ;; esac } complete -F _pos pos