diff --git a/Makefile b/Makefile index aaee5e61..a1a66e79 100644 --- a/Makefile +++ b/Makefile @@ -23,6 +23,8 @@ install: all mkdir -p $(DESTDIR)/$(mandir)/man1 install -m 644 docs/man/lorax.1 $(DESTDIR)/$(mandir)/man1 install -m 644 docs/man/livemedia-creator.1 $(DESTDIR)/$(mandir)/man1 + mkdir -p $(DESTDIR)/etc/bash_completion.d + install -m 644 etc/bash_completion.d/composer-cli $(DESTDIR)/etc/bash_completion.d check: @echo "*** Running pylint ***" diff --git a/etc/bash_completion.d/composer-cli b/etc/bash_completion.d/composer-cli new file mode 100644 index 00000000..b48f6de3 --- /dev/null +++ b/etc/bash_completion.d/composer-cli @@ -0,0 +1,143 @@ +# bash completion for composer-cli + +__composer_cli_flags="-h --help -j --json -s --socket --log -a --api --test -V" + +declare -A __composer_cli_cmds=( + [compose]="list start types status log cancel delete details metadata logs results image" + [blueprints]="list show changes diff save delete depsolve push freeze tag undo workspace" + [modules]="list" + [projects]="list info" + [sources]="list info add change delete" + [help]="" +) + +__composer_socket_ok() { + [ -w "${COMPOSER_SOCKET:-/run/weldr/api.socket}" ] +} + +__composer_blueprints() { + __composer_socket_ok && composer-cli blueprints list +} + +__composer_sources() { + __composer_socket_ok && composer-cli sources list +} + +__composer_compose_types() { + __composer_socket_ok && composer-cli compose types +} + +__composer_composes() { + __composer_socket_ok && composer-cli compose list $@ | while read id rest; do echo $id; done +} + +__word_in_list() { + local w word=$1; shift + for w in "$@"; do + [ "$w" == "$word" ] && return 0 + done + return 1 +} + +_composer_cli() { + local cur="${COMP_WORDS[COMP_CWORD]}" prev="${COMP_WORDS[COMP_CWORD-1]}" + local w="" wi=0 cmd="__NONE__" subcmd="__NONE__" cmd_cword=0 + + # find the command and its subcommand + for (( wi=0; wi < ${#COMP_WORDS[*]}; wi++ )); do + if __word_in_list "${COMP_WORDS[wi]}" "${!__composer_cli_cmds[@]}"; then + cmd="${COMP_WORDS[wi]}" + subcmd="${COMP_WORDS[wi+1]}" + cmd_cword=$((COMP_CWORD-wi)) + break + fi + done + + COMPREPLY=() + + if [ "$cmd_cword" -le 0 ]; then + # No command yet, complete flags or commands + case "$prev" in + -s|--socket|--log) + # If it's a flag that takes a filename, suggest filenames + compopt -o filenames + COMPREPLY=($(compgen -f -- "${cur}")) + ;; + -a|--api|--test) + # If it's a flag that takes an arg we can't guess, don't suggest anything + COMPREPLY=() + ;; + *) + if [ "${cur:0:1}" == "-" ]; then + # Suggest flags if cur starts with '-' + COMPREPLY=($(compgen -W "${__composer_cli_flags}" -- "${cur}")) + else + # Suggest commands if there isn't one already + COMPREPLY=($(compgen -W "${!__composer_cli_cmds[*]}" -- "${cur}")) + fi + ;; + esac + elif [ $cmd_cword == 1 ]; then + # Complete the word after the command + COMPREPLY=($(compgen -W "${__composer_cli_cmds[$cmd]} help" -- "${cur}")) + elif [ $cmd_cword == 2 ]; then + # Complete word(s) after subcommand + case "$cmd:$subcmd" in + compose:list) + COMPREPLY=($(compgen -W "waiting running finish failed" -- "${cur}")) + ;; + *:list|*:help|compose:types) + COMPREPLY=() + ;; + sources:info|sources:delete) + COMPREPLY=($(compgen -W "$(__composer_sources)" -- "${cur}")) + ;; + sources:add|sources:change|blueprints:workspace|blueprints:push) + compopt -o filenames + COMPREPLY=($(compgen -f -- "${cur}")) + ;; + blueprints:freeze) + COMPREPLY=($(compgen -W "$(__composer_blueprints) show save" -- "${cur}")) + ;; + compose:start|blueprints:*) + COMPREPLY=($(compgen -W "$(__composer_blueprints)" -- "${cur}")) + ;; + compose:cancel) + COMPREPLY=($(compgen -W "$(__composer_composes running waiting)" -- "${cur}")) + ;; + compose:delete|compose:results|compose:metadata) + COMPREPLY=($(compgen -W "$(__composer_composes finished failed)" -- "${cur}")) + ;; + compose:log*) + COMPREPLY=($(compgen -W "$(__composer_composes running finished failed)" -- "${cur}")) + ;; + compose:image) + COMPREPLY=($(compgen -W "$(__composer_composes finished)" -- "${cur}")) + ;; + compose:*) + COMPREPLY=($(compgen -W "$(__composer_composes)" -- "${cur}")) + ;; + esac + else + # Complete words past the subcommand's argument (if appropriate) + case "$cmd:$subcmd" in + compose:delete) + COMPREPLY=($(compgen -W "$(__composer_composes finished failed)" -- "${cur}")) + ;; + compose:start) + if [ "$cmd_cword" == 3 ]; then + COMPREPLY=($(compgen -W "$(__composer_compose_types)" -- "${cur}")) + fi + ;; + # TODO: blueprints:diff and blueprints:undo want commits + blueprints:freeze|blueprints:save|blueprints:depsolve|blueprints:changes|blueprints:show) + COMPREPLY=($(compgen -W "$(__composer_blueprints)" -- "${cur}")) + ;; + sources:info) + COMPREPLY=($(compgen -W "$(__composer_sources)" -- "${cur}")) + ;; + esac + fi +} + +complete -F _composer_cli composer-cli diff --git a/lorax.spec b/lorax.spec index 5647e4fc..0693eeb4 100644 --- a/lorax.spec +++ b/lorax.spec @@ -225,6 +225,7 @@ getent passwd weldr >/dev/null 2>&1 || useradd -r -g weldr -d / -s /sbin/nologin %files -n composer-cli %{_bindir}/composer-cli %{python3_sitelib}/composer/* +%{_sysconfdir}/bash-completion/composer-cli %changelog * Fri Jul 20 2018 Brian C. Lane 28.16-1