From f008d8f929114ce1fac67929f4784d336ae18b98 Mon Sep 17 00:00:00 2001 From: Clayton Coleman Date: Sat, 30 Mar 2013 18:46:28 -0400 Subject: [PATCH] Add autocompletion instructions and a revised script to RHC. Expose 'rake autocomplete' to generate a new version of the script. --- autocomplete/rhc | 115 -- autocomplete/rhc_bash | 1183 +++++++++++++++++ client.spec | 2 +- lib/rhc/autocomplete.rb | 91 +- .../{rhc.erb => bash.erb} | 10 +- lib/rhc/commands.rb | 27 +- lib/rhc/commands/base.rb | 7 +- lib/rhc/commands/setup.rb | 20 + lib/rhc/core_ext.rb | 8 + spec/rhc/commands/setup_spec.rb | 9 + tasks/package.rake | 6 + 11 files changed, 1292 insertions(+), 186 deletions(-) delete mode 100644 autocomplete/rhc create mode 100644 autocomplete/rhc_bash rename lib/rhc/autocomplete_templates/{rhc.erb => bash.erb} (66%) diff --git a/autocomplete/rhc b/autocomplete/rhc deleted file mode 100644 index 5134b915b..000000000 --- a/autocomplete/rhc +++ /dev/null @@ -1,115 +0,0 @@ -# -# This is the bash auto completion script for the rhc command -# -_rhc() -{ - local cur opts - COMPREPLY=() - cur="${COMP_WORDS[COMP_CWORD]}" - - if [ $COMP_CWORD -eq 1 ]; then - opts="domain app sshkey port-forward server setup help" - COMPREPLY=($(compgen -W "${opts}" -- ${cur})) - elif [ $COMP_CWORD -eq 2 ]; then - case "${COMP_WORDS[1]}" in - domain) - opts="create show alter status destroy" - ;; - app) - opts="create show start stop force-stop restart reload status destroy tidy add-alias remove-alias snapshot tail cartridge" - ;; - sshkey) - opts="add update remove list" - ;; - port-forward) - opts="--debug --help --rhlogin --password --namespace --config --timeout --app" - ;; - *) - opts="" - ;; - esac - - elif [ $COMP_CWORD -eq 3 ]; then - case "${COMP_WORDS[1]}" in - domain) - case "${COMP_WORDS[2]}" in - create | alter | destroy) - opts="--debug --help --rhlogin --password --namespace --config --timeout" - ;; - show | status) - opts="--debug --help --rhlogin --password --config --timeout" - ;; - *) - ;; - esac - ;; - app) - case "${COMP_WORDS[2]}" in - create) - opts="--debug --help --rhlogin --password --no-dns --nogit --app --repo --type --enable-jenkins --config --timeout" - ;; - show | start | stop | force-stop | restart | reload | status | destroy | tidy | add-alias | remove-alias | destroy ) - opts="--debug --help --rhlogin --password --app --alias --bypass --config --timeout" - ;; - tail) - opts="--debug --help --rhlogin --password --app --opts --filepath --config --timeout" - ;; - snapshot) - opts="save restore" - ;; - cartridge) - opts="add remove stop start restart status reload list" - ;; - *) - ;; - esac - ;; - sshkey) - case "${COMP_WORDS[2]}" in - add | update) - opts="--debug --help --rhlogin --password --identifier --ssh --config --timeout" - ;; - remove) - opts="--debug --help --rhlogin --password --identifier --config --timeout" - ;; - list) - opts="--debug --help --rhlogin --password --config --timeout" - ;; - *) - ;; - esac - ;; - esac - - elif [ $COMP_CWORD -eq 4 ]; then - case "${COMP_WORDS[1]}" in - app) - case "${COMP_WORDS[2]}" in - snapshot) - case "${COMP_WORDS[3]}" in - save | restore) - opts="--debug --help --rhlogin --password --app --filepath --config --timeout" - ;; - *) - ;; - esac - ;; - cartridge) - case "${COMP_WORDS[3]}" in - add | remove | stop | start | restart | status | reload | list) - opts="--debug --help --rhlogin --password --app --cartridge --config --timeout" - ;; - *) - ;; - esac - ;; - esac - ;; - esac - - fi - - if [ ${#opts[@]} -gt 0 ]; then COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ); fi - return 0 -} -complete -o default -F _rhc rhc diff --git a/autocomplete/rhc_bash b/autocomplete/rhc_bash new file mode 100644 index 000000000..e197c8c1c --- /dev/null +++ b/autocomplete/rhc_bash @@ -0,0 +1,1183 @@ +# +# This is the bash auto completion script for the rhc command +# +_rhc() +{ + local cur opts prev + COMPREPLY=() + cur="${COMP_WORDS[COMP_CWORD]}" + if [ $COMP_CWORD -eq 1 ]; then + if [[ "$cur" == -* ]]; then + opts="--clean --config --debug --insecure --mock --noprompt --password --rhlogin --server --ssl-ca-file --ssl-client-cert-file --ssl-version --timeout --token" + elif [ -z $cur ]; then + opts="account account-logout alias alias-add alias-delete-cert alias-list alias-remove alias-update-cert app app-create app-delete app-force-stop app-reload app-restart app-show app-ssh app-start app-stop app-tidy apps authorization authorization-add authorization-delete authorization-delete-all cartridge cartridge-add cartridge-list cartridge-reload cartridge-remove cartridge-restart cartridge-scale cartridge-show cartridge-start cartridge-status cartridge-stop cartridge-storage domain domain-create domain-delete domain-show domain-update git-clone port-forward server setup snapshot snapshot-restore snapshot-save sshkey sshkey-add sshkey-list sshkey-remove sshkey-show tail threaddump" + else + opts="account account-logout add-alias add-authorization add-cartridge add-sshkey alias alias-add alias-delete-cert alias-list alias-remove alias-update-cert app app-create app-delete app-force-stop app-reload app-restart app-show app-ssh app-start app-stop app-tidy apps authorization authorization-add authorization-delete authorization-delete-all cartridge cartridge-add cartridge-list cartridge-reload cartridge-remove cartridge-restart cartridge-scale cartridge-show cartridge-start cartridge-status cartridge-stop cartridge-storage create-app create-domain delete-all-authorization delete-app delete-authorization delete-cert-alias delete-domain domain domain-alter domain-create domain-delete domain-destroy domain-show domain-update force-stop-app git-clone list-alias list-cartridge list-sshkey logout logout-account port-forward reload-app reload-cartridge remove-alias remove-cartridge remove-sshkey restart-app restart-cartridge restore-snapshot save-snapshot scale-cartridge server setup show-app show-cartridge show-domain show-sshkey snapshot snapshot-restore snapshot-save ssh ssh-app sshkey sshkey-add sshkey-delete sshkey-list sshkey-remove sshkey-show start-app start-cartridge status-cartridge stop-app stop-cartridge storage-cartridge tail threaddump tidy-app update-cert-alias update-domain" + fi + else + prev="${COMP_WORDS[@]:0:COMP_CWORD}" + SAVE_IFS=$IFS + IFS=" " + case "${prev[*]}" in + + "rhc account") + if [[ "$cur" == -* ]]; then + opts="" + else + opts="logout" + fi + ;; + + "rhc account logout") + if [[ "$cur" == -* ]]; then + opts="--all" + else + opts="" + fi + ;; + + "rhc account-logout") + if [[ "$cur" == -* ]]; then + opts="--all" + else + opts="" + fi + ;; + + "rhc add-alias") + if [[ "$cur" == -* ]]; then + opts="--app --namespace" + else + opts="" + fi + ;; + + "rhc add-authorization") + if [[ "$cur" == -* ]]; then + opts="--expires-in --note --scopes" + else + opts="" + fi + ;; + + "rhc add-cartridge") + if [[ "$cur" == -* ]]; then + opts="--app --cartridge --namespace" + else + opts="" + fi + ;; + + "rhc add-sshkey") + if [[ "$cur" == -* ]]; then + opts="--confirm" + else + opts="" + fi + ;; + + "rhc alias") + if [[ "$cur" == -* ]]; then + opts="" + else + opts="add remove update-cert delete-cert list" + fi + ;; + + "rhc alias add") + if [[ "$cur" == -* ]]; then + opts="--app --namespace" + else + opts="" + fi + ;; + + "rhc alias delete-cert") + if [[ "$cur" == -* ]]; then + opts="--app --confirm --namespace" + else + opts="" + fi + ;; + + "rhc alias list") + if [[ "$cur" == -* ]]; then + opts="--app --namespace" + else + opts="" + fi + ;; + + "rhc alias remove") + if [[ "$cur" == -* ]]; then + opts="--app --namespace" + else + opts="" + fi + ;; + + "rhc alias update-cert") + if [[ "$cur" == -* ]]; then + opts="--app --certificate --namespace --passphrase --private-key" + else + opts="" + fi + ;; + + "rhc alias-add") + if [[ "$cur" == -* ]]; then + opts="--app --namespace" + else + opts="" + fi + ;; + + "rhc alias-delete-cert") + if [[ "$cur" == -* ]]; then + opts="--app --confirm --namespace" + else + opts="" + fi + ;; + + "rhc alias-list") + if [[ "$cur" == -* ]]; then + opts="--app --namespace" + else + opts="" + fi + ;; + + "rhc alias-remove") + if [[ "$cur" == -* ]]; then + opts="--app --namespace" + else + opts="" + fi + ;; + + "rhc alias-update-cert") + if [[ "$cur" == -* ]]; then + opts="--app --certificate --namespace --passphrase --private-key" + else + opts="" + fi + ;; + + "rhc app") + if [[ "$cur" == -* ]]; then + opts="" + else + opts="create delete start stop force-stop restart reload tidy show ssh" + fi + ;; + + "rhc app create") + if [[ "$cur" == -* ]]; then + opts="--[no-]dns --[no-]git --app --enable-jenkins --from-code --gear-size --namespace --nogit --repo --scaling --type" + else + opts="" + fi + ;; + + "rhc app delete") + if [[ "$cur" == -* ]]; then + opts="--app --bypass --confirm --namespace" + else + opts="" + fi + ;; + + "rhc app force-stop") + if [[ "$cur" == -* ]]; then + opts="--app --namespace" + else + opts="" + fi + ;; + + "rhc app reload") + if [[ "$cur" == -* ]]; then + opts="--app --namespace" + else + opts="" + fi + ;; + + "rhc app restart") + if [[ "$cur" == -* ]]; then + opts="--app --namespace" + else + opts="" + fi + ;; + + "rhc app show") + if [[ "$cur" == -* ]]; then + opts="--app --gears --namespace --state" + else + opts="" + fi + ;; + + "rhc app snapshot") + if [[ "$cur" == -* ]]; then + opts="" + else + opts="" + fi + ;; + + "rhc app ssh") + if [[ "$cur" == -* ]]; then + opts="--app --namespace --ssh" + else + opts="" + fi + ;; + + "rhc app start") + if [[ "$cur" == -* ]]; then + opts="--app --namespace" + else + opts="" + fi + ;; + + "rhc app stop") + if [[ "$cur" == -* ]]; then + opts="--app --namespace" + else + opts="" + fi + ;; + + "rhc app tidy") + if [[ "$cur" == -* ]]; then + opts="--app --namespace" + else + opts="" + fi + ;; + + "rhc app-create") + if [[ "$cur" == -* ]]; then + opts="--[no-]dns --[no-]git --app --enable-jenkins --from-code --gear-size --namespace --nogit --repo --scaling --type" + else + opts="" + fi + ;; + + "rhc app-delete") + if [[ "$cur" == -* ]]; then + opts="--app --bypass --confirm --namespace" + else + opts="" + fi + ;; + + "rhc app-force-stop") + if [[ "$cur" == -* ]]; then + opts="--app --namespace" + else + opts="" + fi + ;; + + "rhc app-reload") + if [[ "$cur" == -* ]]; then + opts="--app --namespace" + else + opts="" + fi + ;; + + "rhc app-restart") + if [[ "$cur" == -* ]]; then + opts="--app --namespace" + else + opts="" + fi + ;; + + "rhc app-show") + if [[ "$cur" == -* ]]; then + opts="--app --gears --namespace --state" + else + opts="" + fi + ;; + + "rhc app-ssh") + if [[ "$cur" == -* ]]; then + opts="--app --namespace --ssh" + else + opts="" + fi + ;; + + "rhc app-start") + if [[ "$cur" == -* ]]; then + opts="--app --namespace" + else + opts="" + fi + ;; + + "rhc app-stop") + if [[ "$cur" == -* ]]; then + opts="--app --namespace" + else + opts="" + fi + ;; + + "rhc app-tidy") + if [[ "$cur" == -* ]]; then + opts="--app --namespace" + else + opts="" + fi + ;; + + "rhc apps") + if [[ "$cur" == -* ]]; then + opts="" + else + opts="" + fi + ;; + + "rhc authorization") + if [[ "$cur" == -* ]]; then + opts="" + else + opts="add delete delete-all" + fi + ;; + + "rhc authorization add") + if [[ "$cur" == -* ]]; then + opts="--expires-in --note --scopes" + else + opts="" + fi + ;; + + "rhc authorization delete") + if [[ "$cur" == -* ]]; then + opts="--auth-token" + else + opts="" + fi + ;; + + "rhc authorization delete-all") + if [[ "$cur" == -* ]]; then + opts="" + else + opts="" + fi + ;; + + "rhc authorization-add") + if [[ "$cur" == -* ]]; then + opts="--expires-in --note --scopes" + else + opts="" + fi + ;; + + "rhc authorization-delete") + if [[ "$cur" == -* ]]; then + opts="--auth-token" + else + opts="" + fi + ;; + + "rhc authorization-delete-all") + if [[ "$cur" == -* ]]; then + opts="" + else + opts="" + fi + ;; + + "rhc cartridge") + if [[ "$cur" == -* ]]; then + opts="" + else + opts="list add show remove start stop restart status reload scale storage" + fi + ;; + + "rhc cartridge add") + if [[ "$cur" == -* ]]; then + opts="--app --cartridge --namespace" + else + opts="" + fi + ;; + + "rhc cartridge list") + if [[ "$cur" == -* ]]; then + opts="--verbose" + else + opts="" + fi + ;; + + "rhc cartridge reload") + if [[ "$cur" == -* ]]; then + opts="--app --cartridge --namespace" + else + opts="" + fi + ;; + + "rhc cartridge remove") + if [[ "$cur" == -* ]]; then + opts="--app --cartridge --confirm --namespace" + else + opts="" + fi + ;; + + "rhc cartridge restart") + if [[ "$cur" == -* ]]; then + opts="--app --cartridge --namespace" + else + opts="" + fi + ;; + + "rhc cartridge scale") + if [[ "$cur" == -* ]]; then + opts="--app --cartridge --max --min --namespace" + else + opts="" + fi + ;; + + "rhc cartridge show") + if [[ "$cur" == -* ]]; then + opts="--app --cartridge --namespace" + else + opts="" + fi + ;; + + "rhc cartridge start") + if [[ "$cur" == -* ]]; then + opts="--app --cartridge --namespace" + else + opts="" + fi + ;; + + "rhc cartridge status") + if [[ "$cur" == -* ]]; then + opts="--app --cartridge --namespace" + else + opts="" + fi + ;; + + "rhc cartridge stop") + if [[ "$cur" == -* ]]; then + opts="--app --cartridge --namespace" + else + opts="" + fi + ;; + + "rhc cartridge storage") + if [[ "$cur" == -* ]]; then + opts="--add --app --cartridge --force --namespace --remove --set --show" + else + opts="" + fi + ;; + + "rhc cartridge-add") + if [[ "$cur" == -* ]]; then + opts="--app --cartridge --namespace" + else + opts="" + fi + ;; + + "rhc cartridge-list") + if [[ "$cur" == -* ]]; then + opts="--verbose" + else + opts="" + fi + ;; + + "rhc cartridge-reload") + if [[ "$cur" == -* ]]; then + opts="--app --cartridge --namespace" + else + opts="" + fi + ;; + + "rhc cartridge-remove") + if [[ "$cur" == -* ]]; then + opts="--app --cartridge --confirm --namespace" + else + opts="" + fi + ;; + + "rhc cartridge-restart") + if [[ "$cur" == -* ]]; then + opts="--app --cartridge --namespace" + else + opts="" + fi + ;; + + "rhc cartridge-scale") + if [[ "$cur" == -* ]]; then + opts="--app --cartridge --max --min --namespace" + else + opts="" + fi + ;; + + "rhc cartridge-show") + if [[ "$cur" == -* ]]; then + opts="--app --cartridge --namespace" + else + opts="" + fi + ;; + + "rhc cartridge-start") + if [[ "$cur" == -* ]]; then + opts="--app --cartridge --namespace" + else + opts="" + fi + ;; + + "rhc cartridge-status") + if [[ "$cur" == -* ]]; then + opts="--app --cartridge --namespace" + else + opts="" + fi + ;; + + "rhc cartridge-stop") + if [[ "$cur" == -* ]]; then + opts="--app --cartridge --namespace" + else + opts="" + fi + ;; + + "rhc cartridge-storage") + if [[ "$cur" == -* ]]; then + opts="--add --app --cartridge --force --namespace --remove --set --show" + else + opts="" + fi + ;; + + "rhc create-app") + if [[ "$cur" == -* ]]; then + opts="--[no-]dns --[no-]git --app --enable-jenkins --from-code --gear-size --namespace --nogit --repo --scaling --type" + else + opts="" + fi + ;; + + "rhc create-domain") + if [[ "$cur" == -* ]]; then + opts="--namespace" + else + opts="" + fi + ;; + + "rhc delete-all-authorization") + if [[ "$cur" == -* ]]; then + opts="" + else + opts="" + fi + ;; + + "rhc delete-app") + if [[ "$cur" == -* ]]; then + opts="--app --bypass --confirm --namespace" + else + opts="" + fi + ;; + + "rhc delete-authorization") + if [[ "$cur" == -* ]]; then + opts="--auth-token" + else + opts="" + fi + ;; + + "rhc delete-cert-alias") + if [[ "$cur" == -* ]]; then + opts="--app --confirm --namespace" + else + opts="" + fi + ;; + + "rhc delete-domain") + if [[ "$cur" == -* ]]; then + opts="--namespace" + else + opts="" + fi + ;; + + "rhc domain") + if [[ "$cur" == -* ]]; then + opts="" + else + opts="create alter update show destroy delete" + fi + ;; + + "rhc domain alter") + if [[ "$cur" == -* ]]; then + opts="--namespace" + else + opts="" + fi + ;; + + "rhc domain create") + if [[ "$cur" == -* ]]; then + opts="--namespace" + else + opts="" + fi + ;; + + "rhc domain delete") + if [[ "$cur" == -* ]]; then + opts="--namespace" + else + opts="" + fi + ;; + + "rhc domain destroy") + if [[ "$cur" == -* ]]; then + opts="--namespace" + else + opts="" + fi + ;; + + "rhc domain show") + if [[ "$cur" == -* ]]; then + opts="" + else + opts="" + fi + ;; + + "rhc domain update") + if [[ "$cur" == -* ]]; then + opts="--namespace" + else + opts="" + fi + ;; + + "rhc domain-alter") + if [[ "$cur" == -* ]]; then + opts="--namespace" + else + opts="" + fi + ;; + + "rhc domain-create") + if [[ "$cur" == -* ]]; then + opts="--namespace" + else + opts="" + fi + ;; + + "rhc domain-delete") + if [[ "$cur" == -* ]]; then + opts="--namespace" + else + opts="" + fi + ;; + + "rhc domain-destroy") + if [[ "$cur" == -* ]]; then + opts="--namespace" + else + opts="" + fi + ;; + + "rhc domain-show") + if [[ "$cur" == -* ]]; then + opts="" + else + opts="" + fi + ;; + + "rhc domain-update") + if [[ "$cur" == -* ]]; then + opts="--namespace" + else + opts="" + fi + ;; + + "rhc force-stop-app") + if [[ "$cur" == -* ]]; then + opts="--app --namespace" + else + opts="" + fi + ;; + + "rhc git-clone") + if [[ "$cur" == -* ]]; then + opts="--app --namespace --repo" + else + opts="" + fi + ;; + + "rhc list-alias") + if [[ "$cur" == -* ]]; then + opts="--app --namespace" + else + opts="" + fi + ;; + + "rhc list-cartridge") + if [[ "$cur" == -* ]]; then + opts="--verbose" + else + opts="" + fi + ;; + + "rhc list-sshkey") + if [[ "$cur" == -* ]]; then + opts="" + else + opts="" + fi + ;; + + "rhc logout") + if [[ "$cur" == -* ]]; then + opts="--all" + else + opts="" + fi + ;; + + "rhc logout-account") + if [[ "$cur" == -* ]]; then + opts="--all" + else + opts="" + fi + ;; + + "rhc port-forward") + if [[ "$cur" == -* ]]; then + opts="--app --namespace" + else + opts="" + fi + ;; + + "rhc reload-app") + if [[ "$cur" == -* ]]; then + opts="--app --namespace" + else + opts="" + fi + ;; + + "rhc reload-cartridge") + if [[ "$cur" == -* ]]; then + opts="--app --cartridge --namespace" + else + opts="" + fi + ;; + + "rhc remove-alias") + if [[ "$cur" == -* ]]; then + opts="--app --namespace" + else + opts="" + fi + ;; + + "rhc remove-cartridge") + if [[ "$cur" == -* ]]; then + opts="--app --cartridge --confirm --namespace" + else + opts="" + fi + ;; + + "rhc remove-sshkey") + if [[ "$cur" == -* ]]; then + opts="" + else + opts="" + fi + ;; + + "rhc restart-app") + if [[ "$cur" == -* ]]; then + opts="--app --namespace" + else + opts="" + fi + ;; + + "rhc restart-cartridge") + if [[ "$cur" == -* ]]; then + opts="--app --cartridge --namespace" + else + opts="" + fi + ;; + + "rhc restore-snapshot") + if [[ "$cur" == -* ]]; then + opts="--app --filepath --namespace" + else + opts="" + fi + ;; + + "rhc save-snapshot") + if [[ "$cur" == -* ]]; then + opts="--app --filepath --namespace" + else + opts="" + fi + ;; + + "rhc scale-cartridge") + if [[ "$cur" == -* ]]; then + opts="--app --cartridge --max --min --namespace" + else + opts="" + fi + ;; + + "rhc server") + if [[ "$cur" == -* ]]; then + opts="" + else + opts="" + fi + ;; + + "rhc setup") + if [[ "$cur" == -* ]]; then + opts="--[no-]create-token --clean --server" + else + opts="" + fi + ;; + + "rhc show-app") + if [[ "$cur" == -* ]]; then + opts="--app --gears --namespace --state" + else + opts="" + fi + ;; + + "rhc show-cartridge") + if [[ "$cur" == -* ]]; then + opts="--app --cartridge --namespace" + else + opts="" + fi + ;; + + "rhc show-domain") + if [[ "$cur" == -* ]]; then + opts="" + else + opts="" + fi + ;; + + "rhc show-sshkey") + if [[ "$cur" == -* ]]; then + opts="" + else + opts="" + fi + ;; + + "rhc snapshot") + if [[ "$cur" == -* ]]; then + opts="" + else + opts="save restore" + fi + ;; + + "rhc snapshot restore") + if [[ "$cur" == -* ]]; then + opts="--app --filepath --namespace" + else + opts="" + fi + ;; + + "rhc snapshot save") + if [[ "$cur" == -* ]]; then + opts="--app --filepath --namespace" + else + opts="" + fi + ;; + + "rhc snapshot-restore") + if [[ "$cur" == -* ]]; then + opts="--app --filepath --namespace" + else + opts="" + fi + ;; + + "rhc snapshot-save") + if [[ "$cur" == -* ]]; then + opts="--app --filepath --namespace" + else + opts="" + fi + ;; + + "rhc ssh") + if [[ "$cur" == -* ]]; then + opts="--app --namespace --ssh" + else + opts="" + fi + ;; + + "rhc ssh-app") + if [[ "$cur" == -* ]]; then + opts="--app --namespace --ssh" + else + opts="" + fi + ;; + + "rhc sshkey") + if [[ "$cur" == -* ]]; then + opts="" + else + opts="list show add delete remove" + fi + ;; + + "rhc sshkey add") + if [[ "$cur" == -* ]]; then + opts="--confirm" + else + opts="" + fi + ;; + + "rhc sshkey delete") + if [[ "$cur" == -* ]]; then + opts="" + else + opts="" + fi + ;; + + "rhc sshkey list") + if [[ "$cur" == -* ]]; then + opts="" + else + opts="" + fi + ;; + + "rhc sshkey remove") + if [[ "$cur" == -* ]]; then + opts="" + else + opts="" + fi + ;; + + "rhc sshkey show") + if [[ "$cur" == -* ]]; then + opts="" + else + opts="" + fi + ;; + + "rhc sshkey-add") + if [[ "$cur" == -* ]]; then + opts="--confirm" + else + opts="" + fi + ;; + + "rhc sshkey-delete") + if [[ "$cur" == -* ]]; then + opts="" + else + opts="" + fi + ;; + + "rhc sshkey-list") + if [[ "$cur" == -* ]]; then + opts="" + else + opts="" + fi + ;; + + "rhc sshkey-remove") + if [[ "$cur" == -* ]]; then + opts="" + else + opts="" + fi + ;; + + "rhc sshkey-show") + if [[ "$cur" == -* ]]; then + opts="" + else + opts="" + fi + ;; + + "rhc start-app") + if [[ "$cur" == -* ]]; then + opts="--app --namespace" + else + opts="" + fi + ;; + + "rhc start-cartridge") + if [[ "$cur" == -* ]]; then + opts="--app --cartridge --namespace" + else + opts="" + fi + ;; + + "rhc status-cartridge") + if [[ "$cur" == -* ]]; then + opts="--app --cartridge --namespace" + else + opts="" + fi + ;; + + "rhc stop-app") + if [[ "$cur" == -* ]]; then + opts="--app --namespace" + else + opts="" + fi + ;; + + "rhc stop-cartridge") + if [[ "$cur" == -* ]]; then + opts="--app --cartridge --namespace" + else + opts="" + fi + ;; + + "rhc storage-cartridge") + if [[ "$cur" == -* ]]; then + opts="--add --app --cartridge --force --namespace --remove --set --show" + else + opts="" + fi + ;; + + "rhc tail") + if [[ "$cur" == -* ]]; then + opts="--app --files --namespace --opts" + else + opts="" + fi + ;; + + "rhc threaddump") + if [[ "$cur" == -* ]]; then + opts="--app --namespace" + else + opts="" + fi + ;; + + "rhc tidy-app") + if [[ "$cur" == -* ]]; then + opts="--app --namespace" + else + opts="" + fi + ;; + + "rhc update-cert-alias") + if [[ "$cur" == -* ]]; then + opts="--app --certificate --namespace --passphrase --private-key" + else + opts="" + fi + ;; + + "rhc update-domain") + if [[ "$cur" == -* ]]; then + opts="--namespace" + else + opts="" + fi + ;; + + esac + IFS=$SAVE_IFS + fi + + COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) + return 0 +} + +complete -o default -F _rhc rhc diff --git a/client.spec b/client.spec index bbf054203..def344d8a 100644 --- a/client.spec +++ b/client.spec @@ -76,7 +76,7 @@ gem install --install-dir $RPM_BUILD_ROOT/%{gemdir} --bindir $RPM_BUILD_ROOT/%{_ # Copy the bash autocompletion script mkdir -p "$RPM_BUILD_ROOT/etc/bash_completion.d/" -cp autocomplete/rhc $RPM_BUILD_ROOT/etc/bash_completion.d/rhc +cp autocomplete/rhc_bash $RPM_BUILD_ROOT/etc/bash_completion.d/rhc cp LICENSE $RPM_BUILD_ROOT/%{gemdir}/gems/rhc-%{version}/LICENSE cp COPYRIGHT $RPM_BUILD_ROOT/%{gemdir}/gems/rhc-%{version}/COPYRIGHT diff --git a/lib/rhc/autocomplete.rb b/lib/rhc/autocomplete.rb index c33cc22ef..dfe0f6f7c 100644 --- a/lib/rhc/autocomplete.rb +++ b/lib/rhc/autocomplete.rb @@ -1,66 +1,57 @@ -require 'commander' -require 'commander/runner' -require 'commander/delegates' - module RHC - class AutoCompleteBindings - attr_reader :top_level_opts, :commands - def initialize(top_level_opts, commands) - @top_level_opts = top_level_opts - @commands = commands - end - end - class AutoComplete - def initialize(script="rhc") - @script_erb = ERB.new(File.read(File.join(File.dirname(__FILE__), 'autocomplete_templates', "#{script}.erb")), nil, '-') - cli_init - # :name => {:actions => [], :switches => []} - @command_data = {} - @top_level_commands = [] - @global_switches = [] - Commander::Runner.instance.options.each { |o| @global_switches << o[:switches][-1] } + attr_reader :runner + + def initialize(runner=::Commander::Runner.instance, shell='bash') + @runner, @shell = runner, shell end - def gen() - process_data - gen_script + def to_s + @s ||= template.result AutoCompleteBindings.new(self).get_binding end private - def cli_init - runner = RHC::CommandRunner.new([]) - Commander::Runner.instance_variable_set :@singleton, runner - RHC::Commands.load.to_commander + + def template + @template ||= ERB.new(File.read(File.join(File.dirname(__FILE__), 'autocomplete_templates', "#{@shell}.erb")), nil, '-') end + end - def process_data - Commander::Runner.instance.commands.each_pair do |name, cmd| - next if cmd.summary.nil? + class AutoCompleteBindings + attr_reader :commands, :top_level_commands, :global_options - if name.rindex(' ').nil? + def initialize(data) + @commands = {} + @top_level_commands = [] + + data.runner.commands.each_pair do |name, cmd| + next if cmd.summary.nil? + next if cmd.deprecated(name) + + if cmd.root? + if cmd.name == name @top_level_commands << name - elsif false - commands = name.split ' ' - action = commands.pop - id = commands.join(' ') - data = @command_data[:"#{id}"] || {:actions => [], - :switches => []} - data[:actions] << action - @command_data[:"#{id}"] = data end - - switches = [] - cmd.options { |o| switches << o[:switches][-1] if o[:switches] } - data = @command_data[:"#{name}"] || {:actions => [], - :switches => []} - data[:switches] = switches.concat(@global_switches) - @command_data[:"#{name}"] = data + else + @top_level_commands << name if name == cmd.name + commands = name.split ' ' + action = commands.pop + id = commands.join(' ') + v = @commands[id] || {:actions => [], :switches => []} + v[:actions] << action unless id == '' && name != cmd.name + @commands[id] = v end - end - def gen_script - @script_erb.result AutoCompleteBindings.new(@top_level_commands.join(' '), @command_data).get_binding + v = @commands[name.to_s] || {:actions => [], :switches => []} + v[:switches].concat(cmd.options.map{ |o| o[:switches][-1].split(' ')[0] if o[:switches] }.compact.sort) + @commands[name.to_s] = v end - end + @commands.delete('') + @commands = @commands.to_a.sort{ |a,b| a[0] <=> b[0] } + + @top_level_commands.sort! + + @global_options = data.runner.options.map{ |o| o[:switches][-1].split(' ')[0] }.sort + end + end end diff --git a/lib/rhc/autocomplete_templates/rhc.erb b/lib/rhc/autocomplete_templates/bash.erb similarity index 66% rename from lib/rhc/autocomplete_templates/rhc.erb rename to lib/rhc/autocomplete_templates/bash.erb index 2352b75fd..2db970b41 100644 --- a/lib/rhc/autocomplete_templates/rhc.erb +++ b/lib/rhc/autocomplete_templates/bash.erb @@ -7,13 +7,19 @@ _rhc() COMPREPLY=() cur="${COMP_WORDS[COMP_CWORD]}" if [ $COMP_CWORD -eq 1 ]; then - opts=<%= "\"%s\"" % @top_level_opts %> + if [[ "$cur" == -* ]]; then + opts=<%= "\"%s\"" % global_options.join(' ') %> + elif [ -z $cur ]; then + opts=<%= "\"%s\"" % top_level_commands.join(' ') %> + else + opts=<%= "\"%s\"" % commands.map{ |c| c.first }.delete_if{ |s| s.include? ' ' }.sort.join(' ') %> + fi else prev="${COMP_WORDS[@]:0:COMP_CWORD}" SAVE_IFS=$IFS IFS=" " case "${prev[*]}" in - <%- for name, data in @commands %> + <%- for name, data in commands %> <%= "\"rhc %s\")" % name %> if [[ "$cur" == -* ]]; then opts=<%= "\"%s\"" % data[:switches].join(" ") %> diff --git a/lib/rhc/commands.rb b/lib/rhc/commands.rb index fa65e2f25..3e85cde23 100644 --- a/lib/rhc/commands.rb +++ b/lib/rhc/commands.rb @@ -5,7 +5,7 @@ # to avoid conflicts and side effects of similar short switches module Commander class Command - attr_accessor :default_action, :root + attr_accessor :default_action, :root, :info def default_action? default_action.present? end @@ -13,6 +13,12 @@ def root? root.present? end + def deprecated(as_alias=nil) + return false unless info + return info[:deprecated] if info[:deprecated] + info[:aliases].select{ |a| ['-',' '].map{ |s| Array(a[:action]).join(s) }.include?(as_alias) }.map{ |a| a[:deprecated] }.first if as_alias + end + def parse_options_and_call_procs *args runner = Commander::Runner.instance opts = OptionParser.new @@ -137,14 +143,12 @@ def self.global_option(*args, &block) global_options << [args.freeze, block] end - def self.deprecated? - command_name = Commander::Runner.instance.command_name_from_args - command = Commander::Runner.instance.active_command + def self.deprecated! + instance = Commander::Runner.instance + command_name = instance.command_name_from_args + command = instance.active_command - info = commands[commands.keys.find{ |k| k.join('-') == command.name }] - new_cmd = info[:deprecated] || info[:aliases].select{ |a| ['-',' '].map{ |s| Array(a[:action]).join(s) }.include?(command_name) }.map{ |a| a[:deprecated] }.first - - if new_cmd + if new_cmd = command.deprecated(command_name) new_cmd = "rhc #{command.name}" if new_cmd == true RHC::Helpers.deprecated_command new_cmd end @@ -181,14 +185,14 @@ def self.to_commander(instance=Commander::Runner.instance) c.syntax = opts[:syntax] c.default_action = opts[:default] + c.info = opts + (options_metadata = Array(opts[:options])).each do |o| option_data = [o[:switches], o[:description]].flatten(1) c.option *option_data o[:arg] = Commander::Runner.switch_to_sym(Array(o[:switches]).last) end - #deprecated[name] = opts[:deprecated] unless opts[:deprecated].nil? - (args_metadata = Array(opts[:args])).each do |meta| switches = meta[:switches] unless switches.nil? or switches.empty? @@ -201,7 +205,6 @@ def self.to_commander(instance=Commander::Runner.instance) action = Array(a[:action]) [' ', '-'].each do |s| cmd = action.join(s) - #deprecated[cmd] = true if a[:deprecated] instance.alias_command cmd, name end end @@ -213,7 +216,7 @@ def self.to_commander(instance=Commander::Runner.instance) end c.when_called do |args, options| - deprecated? + deprecated! config = c.instance_variable_get(:@config) diff --git a/lib/rhc/commands/base.rb b/lib/rhc/commands/base.rb index e77edf802..f5d12362d 100644 --- a/lib/rhc/commands/base.rb +++ b/lib/rhc/commands/base.rb @@ -87,12 +87,7 @@ def self.object_name(value=nil) def self.description(*args) o = args.join(' ') - indent = o.scan(/^[ \t]*(?=\S)/).min.size || 0 - options[:description] = - o.gsub(/^[ \t]{#{indent}}/, ''). - gsub(/(\b|')\s*\n(?!\s*\n)(\S)/m, '\1 \2'). - gsub(/\n+\Z/, ''). - gsub(/\n{3,}/, "\n\n") + options[:description] = o.strip_heredoc end def self.summary(value) options[:summary] = value diff --git a/lib/rhc/commands/setup.rb b/lib/rhc/commands/setup.rb index 8976450fc..2327bb64b 100644 --- a/lib/rhc/commands/setup.rb +++ b/lib/rhc/commands/setup.rb @@ -23,11 +23,31 @@ class Setup < Base If the server supports authorization tokens, you may pass the --create-token option to instruct the wizard to generate a key for you. + + If you would like to enable tab-completion in Bash shells, pass + --autocomplete for more information. DESC option ["--server NAME"], "Hostname of an OpenShift server", :context => :server_context, :required => true option ['--clean'], "Ignore any saved configuration options" option ['--[no-]create-token'], "Create an authorization token for this server" + option ['--autocomplete'], "Instructions for enabling tab-completion" def run + if options.autocomplete + path = File.join(File.join(Gem.loaded_specs['rhc'].full_gem_path, "autocomplete"), "rhc_bash") + say <<-LINE.strip_heredoc + To enable tab-completion for RHC under Bash shells, add the following command to + your .bashrc or .bash_profile file: + + . #{path} + + Save your shell and then restart. Type "rhc" and then hit the TAB key twice to + trigger completion of your command. + + Tab-completion is not available in the Windows terminal. + LINE + return 0 + end + raise OptionParser::InvalidOption, "Setup can not be run with the --noprompt option" if options.noprompt RHC::RerunWizard.new(config, options).run ? 0 : 1 end diff --git a/lib/rhc/core_ext.rb b/lib/rhc/core_ext.rb index d9b174eb5..94342eecf 100644 --- a/lib/rhc/core_ext.rb +++ b/lib/rhc/core_ext.rb @@ -37,6 +37,14 @@ class String def wrap(wrap_length=80, char="\n") scan(/.{#{wrap_length}}|.+/).join(char) end + + def strip_heredoc + indent = scan(/^[ \t]*(?=\S)/).min.size || 0 + gsub(/^[ \t]{#{indent}}/, ''). + gsub(/(\b|\S)[^\S\n]*\n(\S)/m, '\1 \2'). + gsub(/\n+\Z/, ''). + gsub(/\n{3,}/, "\n\n") + end end unless HTTP::Message.method_defined? :ok? diff --git a/spec/rhc/commands/setup_spec.rb b/spec/rhc/commands/setup_spec.rb index b78e1b221..849f60f14 100644 --- a/spec/rhc/commands/setup_spec.rb +++ b/spec/rhc/commands/setup_spec.rb @@ -101,4 +101,13 @@ it('should output usage') { run_output.should match("Connects to an OpenShift server to get you started. Will") } end end + + describe '--autocomplete' do + let(:arguments) { ['setup', '--autocomplete'] } + + context 'is passed' do + it('should output information') { run_output.should match("To enable tab-completion") } + it('should output the gem path') { run_output.should match File.join(Gem.loaded_specs['rhc'].full_gem_path, 'autocomplete') } + end + end end diff --git a/tasks/package.rake b/tasks/package.rake index aff7fb562..3e307dd36 100644 --- a/tasks/package.rake +++ b/tasks/package.rake @@ -32,3 +32,9 @@ end # Add the 'pkg' directory to the clean task CLEAN.include("pkg") + +task :autocomplete do + require 'rhc' + RHC::Commands.load.to_commander + IO.write('autocomplete/rhc_bash', RHC::AutoComplete.new.to_s) +end \ No newline at end of file