diff options
Diffstat (limited to 'etc/bash_completion.d/vyatta-op')
-rw-r--r-- | etc/bash_completion.d/vyatta-op | 451 |
1 files changed, 451 insertions, 0 deletions
diff --git a/etc/bash_completion.d/vyatta-op b/etc/bash_completion.d/vyatta-op new file mode 100644 index 0000000..6336038 --- /dev/null +++ b/etc/bash_completion.d/vyatta-op @@ -0,0 +1,451 @@ + +# **** License **** +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# This code was originally developed by Vyatta, Inc. +# Portions created by Vyatta are Copyright (C) 2006, 2007 Vyatta, Inc. +# All Rights Reserved. +# +# Author: Tom Grennan +# Date: 2007 +# Description: setup bash completion for Vyatta operational commands +# +# **** End License **** + +test -z "$_vyatta_less_options" && \ + declare -r _vyatta_less_options="\ + --QUIT-AT-EOF\ + --quit-if-one-screen\ + --RAW-CONTROL-CHARS\ + --squeeze-blank-lines\ + --no-init" +test -z "$_vyatta_default_pager" && \ + declare -r _vyatta_default_pager="less \ + --buffers=64\ + --auto-buffers\ + --no-lessopen\ + $_vyatta_less_options" +declare -x VYATTA_PAGER=$_vyatta_default_pager + +_vyatta_op_do_key_bindings () +{ + if [ "$SHELL" != "/bin/vbash" ]; then + # only do bindings if vbash + return + fi + + bind '"?": possible-completions' + bind 'set show-all-if-ambiguous on' + + nullglob_save=$(shopt -p nullglob) + shopt -u nullglob + bind_cmds=$(grep '^bind .* # vyatta key binding$' $HOME/.bashrc) + eval $bind_cmds + eval $nullglob_save +} + +_vyatta_op_do_key_bindings + +test -f /etc/default/vyatta && \ + source /etc/default/vyatta + +test ! -d "$vyatta_op_templates" && \ + return 0 + +declare -r _vyatta_op_last_comp_init='>>>>>>LASTCOMP<<<<<<' +declare _vyatta_op_last_comp=${_vyatta_op_last_comp_init} +declare _vyatta_op_node_path +declare -a _vyatta_op_noncompletions _vyatta_op_completions +declare -x -a _vyatta_pipe_noncompletions _vyatta_pipe_completions + +# $1: label +# #2...: strings +_vyatta_op_debug () +{ + echo -ne \\n$1: + shift + for s ; do + echo -ne " \"$s\"" + done +} + +_vyatta_op_init () +{ + complete -F _vyatta_op_expand '' + + for xd in $vyatta_op_templates/* ; do + if [ -d $xd ] ; then + cmd=${xd##*/} + complete -F _vyatta_op_expand $cmd + eval alias $cmd=\'_vyatta_op_run $cmd\' + fi + done + + shopt -s histverify +} + +_vyatta_op_get_node_def_field () +{ + local file=$1 field=$2 + + sed -n '/^'"$field"':/,$ { +# strip field name and hold rest of line + s/[a-z]*: *// + h + :b +# at EOF, print hold buffer and quit + $ { x; p; q } +# input next line + n +# if start of another field def, print hold buf and quit + /^[a-z]*:/ { x; p; q } +# add to hold buf and branch to input next line + H + bb + }' $file +} + +# $1: label +# $2...: help +_vyatta_op_print_help () +{ + local label=$1 help=$2 + + if [ ${#help} -eq 0 ] ; then + echo -ne "\n $label" + elif [ ${#label} -lt 6 ] ; then + echo -ne "\n $label\t\t$help" + elif [ ${#label} -lt 14 ] ; then + echo -ne "\n $label\t$help" + else + echo -ne "\n $label\n\t\t$help" + fi +} + +# $1: $cur +# $2...: possible completions +_vyatta_op_help () +{ + local cur=$1; shift + local ndef node_tag_help node_run help last_help + + ndef=${_vyatta_op_node_path}/node.tag/node.def + [ -f $ndef ] && \ + node_tag_help=$( _vyatta_op_get_node_def_field $ndef help ) + + ndef=${_vyatta_op_node_path}/node.def + [ -f $ndef ] && \ + node_run=$( _vyatta_op_get_node_def_field $ndef run ) + + echo -en "\nPossible completions:" + if [ -z "$cur" -a -n "$node_run" ]; then + _vyatta_op_print_help '<Enter>' "Execute the current command" + fi + for comp ; do + if [ -z "$comp" ] ; then + if [ "X$node_tag_help" == "X$last_help" ] ; then + help="" + else + last_help=$node_tag_help + help=$node_tag_help + fi + _vyatta_op_print_help '*' "$help" + elif [[ -z "$cur" || $comp == ${cur}* ]] ; then + ndef=${_vyatta_op_node_path}/$comp/node.def + if [ -f $ndef ] ; then + help=$( _vyatta_op_get_node_def_field $ndef help ) + else + help=$node_tag_help + fi + if [ "X$help" == "X$last_help" ] ; then + help="" + else + last_help=$help + fi + _vyatta_op_print_help "$comp" "$help" + fi + done +} + +_vyatta_op_set_node_path () +{ + _vyatta_op_node_path=$vyatta_op_templates + for (( i=0 ; i<COMP_CWORD ; i++ )) ; do + if [ -f "${_vyatta_op_node_path}/${COMP_WORDS[i]}/node.def" ] ; then + _vyatta_op_node_path+=/${COMP_WORDS[i]} + elif [ -f ${_vyatta_op_node_path}/node.tag/node.def ] ; then + _vyatta_op_node_path+=/node.tag + else + return 1 + fi + done +} + +_vyatta_op_set_completions () +{ + local -a allowed completions + + for ndef in ${_vyatta_op_node_path}/*/node.def ; do + if [[ $ndef == */node.tag/node.def ]] ; then + local acmd=$( _vyatta_op_get_node_def_field $ndef allowed ) + local -a a=($( eval "$acmd" )) + if [ ${#a[@]} -ne 0 ] ; then + allowed+=( "${a[@]}" ) + else + allowed+=( "" ) + fi + else + local sdir=${ndef%/*} + allowed+=( ${sdir##*/} ) + fi + done + + # donot complete entries like <HOSTNAME> or <A.B.C.D> + _vyatta_op_noncompletions=( ) + completions=( ) + for (( i=0 ; i<${#allowed[@]} ; i++ )) ; do + if [[ "${allowed[i]}" == \<*\> ]] ; then + _vyatta_op_noncompletions+=( ${allowed[i]} ) + else + completions+=( ${allowed[i]} ) + fi + done + + _vyatta_op_completions=($( printf "%s\n" ${completions[@]} | sort -u )) +} + +_vyatta_op_comprely_needs_ambiguity () +{ + local -a uniq + + [ ${#COMPREPLY[@]} -eq 1 ] && return + + uniq=( `printf "%s\n" ${COMPREPLY[@]} | cut -c1 | sort -u` ) + + [ ${#uniq[@]} -eq 1 ] && return + false +} + +_vyatta_op_expand () +{ + local restore_shopts=$( shopt -p extglob nullglob | tr \\n \; ) + shopt -s extglob nullglob + local cur="" + + if (( ${#COMP_WORDS[@]} > 0 )); then + cur=${COMP_WORDS[COMP_CWORD]} + else + (( COMP_CWORD = ${#COMP_WORDS[@]} )) + fi + + if _vyatta_pipe_completion "${COMP_WORDS[@]}"; then + if [ "${COMP_WORDS[*]}" == "$_vyatta_op_last_comp" ] ; then + _vyatta_do_pipe_help + COMPREPLY=( "" " " ) + _vyatta_op_last_comp=${_vyatta_op_last_comp_init} + else + COMPREPLY=( "${_vyatta_pipe_completions[@]}" ) + _vyatta_op_last_comp="${COMP_WORDS[*]}" + fi + eval "$restore_shopts" + return + fi + + if [ "${COMP_WORDS[*]}" != "$_vyatta_op_last_comp" ] ; then + if ! _vyatta_op_set_node_path ; then + echo -e \\a + COMPREPLY=( "" " " ) + eval "$restore_shopts" + return 1 + fi + _vyatta_op_set_completions + fi + + COMPREPLY=($( compgen -W "${_vyatta_op_completions[*]}" -- $cur )) + + # if the last command line arg is empty and we have + # an empty completion option (meaning wild card), + # append a blank(s) to the completion array to force ambiguity + if [ -z "$cur" ] ; then + for comp ; do + if [ -z "$comp" ] ; then + if [ ${#COMPREPLY[@]} -eq 0 ] ; then + COMPREPLY+=( " " "" ) + elif _vyatta_op_comprely_needs_ambiguity ; then + COMPREPLY+=( " " ) + fi + fi + done + fi + + if [ "${COMP_WORDS[*]}" == "$_vyatta_op_last_comp" ] ; then + _vyatta_op_help "$cur" \ + ${_vyatta_op_noncompletions[@]} \ + ${_vyatta_op_completions[@]} \ + | ${VYATTA_PAGER:-cat} + COMPREPLY=( "" " " ) + _vyatta_op_last_comp=${_vyatta_op_last_comp_init} + else + _vyatta_op_last_comp="${COMP_WORDS[*]}" + fi + + eval "$restore_shopts" +} + +_vyatta_op_run () +{ + local -i estat + local tpath=$vyatta_op_templates + local restore_shopts=$( shopt -p extglob nullglob | tr \\n \; ) + shopt -s extglob nullglob + + _vyatta_op_last_comp=${_vyatta_op_last_comp_init} + false; estat=$? + + i=1 + for arg in "$@" + do + if [ -f "$tpath/$arg/node.def" ] ; then + tpath+=/$arg + elif [ -f $tpath/node.tag/node.def ] ; then + tpath+=/node.tag + else + echo "Invalid command" >&2 + eval $restore_shopts + return 1 + fi + let "i+=1" + done + + local run_cmd=$(_vyatta_op_get_node_def_field $tpath/node.def run) + local ret=0 + if [ -n "$run_cmd" ]; then + if [[ -t 1 && "$1" == "show" && \ + ! $run_cmd =~ ^\(LESSOPEN=\|less\|pager\|tail\|/opt/vyatta/bin/vyatta-tshark-interface-port.pl\).* ]] ; then + eval "($run_cmd) | ${VYATTA_PAGER:-cat}" + else + eval "$run_cmd" + fi + else + echo "Incomplete command" >&2 + ret=1 + fi + eval $restore_shopts + return $ret +} + +# "pipe" functions +count () +{ + wc -l +} + +match () +{ + grep -E -e "$1" +} + +no-match () +{ + grep -E -v -e "$1" +} + +no-more () +{ + cat +} + +# pipe command help +# $1: command +_vyatta_pipe_help () +{ + local help="No help text available" + case "$1" in + count) help="Count the number of lines in the output";; + match) help="Only output lines that match specified pattern";; + no-match) help="Only output lines that do not match specified pattern";; + more) help="Paginate the output";; + no-more) help="Do not paginate the output";; + '<pattern>') help="Pattern for matching";; + esac + echo -n "$help" +} + +_vyatta_do_pipe_help () +{ + local help='' + if (( ${#_vyatta_pipe_completions[@]} + ${#_vyatta_pipe_noncompletions[@]} + == 0 )); then + return + fi + echo -en "\nPossible completions:" + for comp in "${_vyatta_pipe_completions[@]}" \ + "${_vyatta_pipe_noncompletions[@]}"; do + _vyatta_op_print_help "$comp" "$(_vyatta_pipe_help "$comp")" + done +} + +# pipe completion +# $@: words +_vyatta_pipe_completion () +{ + local -a pipe_cmd=() + local -a all_cmds=( 'count' 'match' 'no-match' 'more' 'no-more' ) + local found=0 + _vyatta_pipe_completions=() + _vyatta_pipe_noncompletions=() + + for word in "$@"; do + if [ "$found" == "1" -o "$word" == "|" ]; then + pipe_cmd+=( "$word" ) + found=1 + fi + done + if (( found == 0 )); then + return 1 + fi + if (( ${#pipe_cmd[@]} == 1 )); then + # "|" only + _vyatta_pipe_completions=( "${all_cmds[@]}" ) + return 0 + fi + if (( ${#pipe_cmd[@]} == 2 )); then + # "|<space, chars, or space+chars>" + _vyatta_pipe_completions=($(compgen -W "${all_cmds[*]}" -- ${pipe_cmd[1]})) + return 0 + fi + if (( ${#pipe_cmd[@]} == 3 )); then + # "|<chars or space+chars><space or space+chars>" + case "${pipe_cmd[1]}" in + match|no-match) _vyatta_pipe_noncompletions=( '<pattern>' );; + esac + return 0 + fi + return 0 +} + +nullglob_save=$( shopt -p nullglob ) +shopt -s nullglob +for f in ${vyatta_datadir}/vyatta-op/functions/allowed/* ; do + source $f +done +eval $nullglob_save +unset nullglob_save + +# don't initialize if we are in configure mode +if [ "$_OFR_CONFIGURE" == "ok" ]; then + return 0 +fi + +_vyatta_op_init $@ + +### Local Variables: +### mode: shell-script +### End: |