summaryrefslogtreecommitdiff
path: root/etc/bash_completion.d
diff options
context:
space:
mode:
authorAn-Cheng Huang <ancheng@vyatta.com>2007-09-25 15:55:26 -0700
committerAn-Cheng Huang <ancheng@vyatta.com>2007-09-25 15:55:26 -0700
commite9a79a249cec69fc178098d2f75db9389068510a (patch)
tree0e366094b7fecd3988c243fbbb574015e0c900c8 /etc/bash_completion.d
downloadvyatta-cfg-e9a79a249cec69fc178098d2f75db9389068510a.tar.gz
vyatta-cfg-e9a79a249cec69fc178098d2f75db9389068510a.zip
initial import (from eureka /cli) plus new build system.upstream
Diffstat (limited to 'etc/bash_completion.d')
-rw-r--r--etc/bash_completion.d/vyatta-cfg789
1 files changed, 789 insertions, 0 deletions
diff --git a/etc/bash_completion.d/vyatta-cfg b/etc/bash_completion.d/vyatta-cfg
new file mode 100644
index 0000000..b16ffbf
--- /dev/null
+++ b/etc/bash_completion.d/vyatta-cfg
@@ -0,0 +1,789 @@
+# **** License ****
+# Version: VPL 1.0
+#
+# The contents of this file are subject to the Vyatta Public License
+# Version 1.0 ("License"); you may not use this file except in
+# compliance with the License. You may obtain a copy of the License at
+# http://www.vyatta.com/vpl
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# This code was originally developed by Vyatta, Inc.
+# Portions created by Vyatta are Copyright (C) 2006, 2007 Vyatta, Inc.
+# All Rights Reserved.
+#
+# Author: An-Cheng Huang
+# Date: 2007
+# Description: bash completion for Vyatta configuration commands
+#
+# **** End License ****
+
+# only do this if we are going into configure mode
+if [ "$_OFR_CONFIGURE" != "ok" ]; then
+ return 0
+fi
+
+if [ -r /etc/default/vyatta ]; then
+ source /etc/default/vyatta
+fi
+
+declare is_set=0
+declare last_idx=0
+declare -a comp_words=()
+
+# commands to unalias
+declare -a unalias_cmds=( clear configure date debug edit exit load \
+ no show save terminal undebug )
+for cmd in "${unalias_cmds[@]}"; do
+ unalias $cmd >& /dev/null
+done
+
+show ()
+{
+ eval "${vyatta_sbindir}/vyatta-output-config.pl \
+ \${VYATTA_EDIT_LEVEL//\// } $@"
+}
+
+save ()
+{
+ eval "${vyatta_sbindir}/vyatta-save-config.pl $@"
+}
+
+load ()
+{
+ eval "${vyatta_sbindir}/vyatta-load-config.pl $@"
+}
+
+declare vyatta_cfg_prompt_level=''
+set_config_ps1 ()
+{
+ local level=$1
+ if [ -z "$level" ]; then
+ export PS1="[edit]\n\u@\h# "
+ vyatta_cfg_prompt_level=''
+ else
+ export PS1="[edit $level]\n\u@\h# "
+ vyatta_cfg_prompt_level="$level"
+ fi
+}
+
+edit ()
+{
+ local num_comp=${#@}
+ local _mpath=${VYATTA_TEMP_CONFIG_DIR}/${VYATTA_EDIT_LEVEL}
+ local _tpath=${VYATTA_CONFIG_TEMPLATE}/${VYATTA_TEMPLATE_LEVEL}
+ local idx
+ for (( idx=1; idx <= num_comp; idx++ )); do
+ local comp
+ eval "comp=\$$idx"
+ vyatta_escape comp comp
+ push_path _mpath $comp
+ push_path _tpath $comp
+ if [ ! -d $_mpath ]; then
+ # "edit" only allows existing node
+ break
+ fi
+
+ # check if it's not tag value
+ if [ -d $_tpath ]; then
+ continue
+ fi
+
+ # check if it's tag value
+ pop_path _tpath
+ push_path _tpath $VYATTA_TAG_NAME
+ if [ -d $_tpath ]; then
+ continue
+ fi
+ pop_path _tpath
+ pop_path _mpath
+ break
+ done
+ # "edit" only valid for
+ # * "node.tag" level
+ # * "node.def" level without "type:"
+ if (( idx != ( num_comp + 1) )); then
+ echo "Invalid node \"$*\" for the 'edit' command"
+ return 1
+ fi
+ if [ "${_tpath:((-9))}" != "/node.tag" ]; then
+ # we are not at "node.tag" level. look for "type:".
+ if [ ! -r "$_tpath/node.def" ]; then
+ vyatta_cfg_type=""
+ else
+ vyatta_parse_tmpl "$_tpath/node.def"
+ fi
+ if [ -n "$vyatta_cfg_type" ]; then
+ # "type:" present
+ echo "The 'edit' command cannot be issued at the \"$*\" level"
+ return 1
+ fi
+ fi
+ export VYATTA_EDIT_LEVEL="${_mpath#$VYATTA_TEMP_CONFIG_DIR}/"
+ export VYATTA_TEMPLATE_LEVEL="${_tpath#$VYATTA_CONFIG_TEMPLATE}/"
+
+ declare -a path_arr
+ path_str2arr VYATTA_EDIT_LEVEL path_arr
+ local path_str="${path_arr[*]}"
+ set_config_ps1 $path_str
+}
+
+really_exit()
+{
+ umount $VYATTA_TEMP_CONFIG_DIR
+ rm -rf $VYATTA_TEMP_CONFIG_DIR $VYATTA_CHANGES_ONLY_DIR $VYATTA_CONFIG_TMP
+ unset _OFR_CONFIGURE
+ builtin exit 0
+}
+
+exit ()
+{
+ local discard
+ if [ $# == 0 ]; then
+ discard=0
+ elif [ $# == 1 ] && [ "$1" == "discard" ]; then
+ discard=1
+ else
+ echo "Invalid argument \"$*\" for 'exit'"
+ return 1
+ fi
+
+ if [ "$VYATTA_EDIT_LEVEL" == "/" ]; then
+ # we are at the root level. check if we can really exit.
+ if [ -f "$VYATTA_TEMP_CONFIG_DIR/$VYATTA_MOD_NAME" ]; then
+ if (( ! discard )); then
+ echo "Cannot exit: configuration modified."
+ echo "Use 'exit discard' to discard the changes and exit."
+ return 1
+ fi
+ fi
+ really_exit
+ fi
+
+ # "exit" to the root level.
+ export VYATTA_EDIT_LEVEL="/"
+ export VYATTA_TEMPLATE_LEVEL="/"
+ set_config_ps1 ''
+}
+
+declare v_cfg_completion_debug=0
+decho ()
+{
+ if (( v_cfg_completion_debug )); then
+ echo -n "$*"
+ fi
+}
+
+push_path_arr ()
+{
+ # $1: \@path_arr
+ # $2: component
+ eval "$1=( \${$1[@]} '$2' )"
+}
+
+pop_path_arr ()
+{
+ # $1: \@path_arr
+ eval "$1=( \${$1[@]:0:((\${#$1[@]}-1))} )"
+}
+
+path_arr2str ()
+{
+ # $1: \@path_arr
+ # $2: \$path_str
+ eval "$2=\"\${$1[*]}\""
+ eval "$2=/\${$2// //}"
+}
+
+path_str2arr ()
+{
+ # $1: \$path_str
+ # $2: \@path_arr
+ local tmp
+ eval "tmp=\${$1:1}"
+ eval "$2=( \${tmp//\// } )"
+}
+
+push_path ()
+{
+ # $1: \$path_str
+ # $2: component
+ declare -a path_arr
+ eval "path_str2arr $1 path_arr"
+ eval "push_path_arr path_arr '$2'"
+ eval "path_arr2str path_arr $1"
+}
+
+pop_path ()
+{
+ # $1: \$path_str
+ declare -a path_arr
+ eval "path_str2arr $1 path_arr"
+ pop_path_arr path_arr
+ eval "path_arr2str path_arr $1"
+}
+
+get_filtered_dir_listing ()
+{
+ # $1: path
+ # $2: \@listing
+ if [ ! -d $1 ]; then
+ eval "$2=()"
+ return
+ fi
+ local pattern='^node\.def$|^node\.tag$|^node\.val$|^\.modified$'
+ patterh=$pattern'|^\.commit\.lck$|^\.wh\.'
+ local cmd="ls $1 |egrep -v '$pattern'"
+ declare -a listing=( $(eval $cmd) )
+ for enode in "${listing[@]}"; do
+ local unode
+ vyatta_unescape enode unode
+ eval "$2[\${#$2[@]}]=$unode"
+ done
+}
+
+filter_existing_nodes ()
+{
+ # $1: mpath
+ # $2: \@orig
+ # $3: \@filtered
+ declare -a orig
+ eval "orig=( \${$2[@]} )"
+ for node in "${orig[@]}"; do
+ if [ -d "$1/$node" ]; then
+ eval "$3[\${#$3[@]}]=$node"
+ fi
+ done
+}
+
+get_prefix_filtered_list ()
+{
+ # $1: prefix
+ # $2: \@list
+ # $3: \@filtered
+ declare -a olist
+ eval "olist=( \"\${$2[@]}\" )"
+ local idx=0
+ for elem in "${olist[@]}"; do
+ local sub=${elem#$1}
+ if [ "$elem" == "$sub" ]; then
+ continue
+ fi
+ eval "$3[$idx]=$elem"
+ (( idx++ ))
+ done
+}
+
+declare vyatta_cfg_help=""
+declare vyatta_cfg_type=""
+declare vyatta_cfg_tag=0
+declare vyatta_cfg_multi=0
+declare -a vyatta_cfg_allowed=()
+vyatta_parse_tmpl ()
+{
+ # $1: tmpl
+ vyatta_cfg_help=""
+ vyatta_cfg_type=""
+ vyatta_cfg_tag=0
+ vyatta_cfg_multi=0
+ vyatta_cfg_allowed=()
+ if [ ! -r $1 ]; then
+ return
+ fi
+ eval `sed -n '
+ /^help:[ ]\+/,/^[a-z]\+:/ {
+ s/^help:[ ]\+/vyatta_cfg_help=/p
+ /^ /p
+ }
+ /^syntax:[ ]\+\$(@)[ ]\+in[ ]\+/ {
+ s/^syntax:[ ]\+\$(@)[ ]\+in[ ]\+/vyatta_cfg_allowed=( /
+ s/^\([^;]\+\);.*$/\1 )/
+ s/[ ]*,[ ]*/ /gp
+ }
+ s/^tag:/vyatta_cfg_tag=1/p
+ s/^multi:/vyatta_cfg_multi=1/p
+ s/^type:[ ]\+\([^ ]\+\)$/vyatta_cfg_type=\1/p
+ ' $1`
+ if [ -z "$vyatta_cfg_help" ]; then
+ vyatta_cfg_help='<No help text available>'
+ fi
+}
+
+# this fills in $vyatta_help_text
+generate_help_text ()
+{
+ # $1: \@items
+ # $2: \@help_strs
+ declare -a items
+ declare -a helps
+ eval "items=( \"\${$1[@]}\" )"
+ eval "helps=( \"\${$2[@]}\" )"
+ vyatta_help_text="\\nPossible completions:"
+ for (( idx = 0; idx < ${#items[@]}; idx++ )); do
+ vyatta_help_text="${vyatta_help_text}\\n\\x20\\x20"
+ if [ ${#items[$idx]} -lt 6 ]; then
+ vyatta_help_text="${vyatta_help_text}${items[$idx]}\\t\\t"
+ elif [ ${#items[$idx]} -lt 14 ]; then
+ vyatta_help_text="${vyatta_help_text}${items[$idx]}\\t"
+ else
+ vyatta_help_text="${vyatta_help_text}${items[$idx]}\\n\\x20\\x20\\t\\t"
+ fi
+ vyatta_help_text="${vyatta_help_text}${helps[$idx]}"
+ done
+}
+
+# this fills in $vyatta_help_text
+get_tmpl_subdir_help ()
+{
+ # $1: path
+ # $2: \@subdirs
+ declare -a subdirs
+ eval "subdirs=( \${$2[@]} )"
+ if [ ${#subdirs[@]} == 0 ]; then
+ vyatta_help_text=""
+ return
+ fi
+ declare -a hitems=()
+ declare -a hstrs=()
+ for subdir in "${subdirs[@]}"; do
+ if [ ! -r $1/$subdir/node.def ]; then
+ vyatta_cfg_help="<No help text available>"
+ else
+ vyatta_parse_tmpl "$1/$subdir/node.def"
+ fi
+ hitems[${#hitems[@]}]=$subdir
+ hstrs[${#hstrs[@]}]=$vyatta_cfg_help
+ done
+ generate_help_text hitems hstrs
+}
+
+# return 0 if yes. 1 if no.
+item_in_list ()
+{
+ # $1: item
+ # $2: \@list
+ declare -a olist
+ local item
+ eval "olist=( \${$2[@]} )"
+ for item in "${olist[@]}"; do
+ if [ "$1" == "$item" ]; then
+ return 0
+ fi
+ done
+ return 1
+}
+
+append_allowed_values ()
+{
+ # $1: tmpl_path
+ # $2: \@values
+ if [ ! -r "$1/node.def" ]; then
+ return
+ fi
+ vyatta_parse_tmpl "$1/node.def"
+ local item
+ for item in "${vyatta_cfg_allowed[@]}"; do
+ if ! item_in_list $item $2; then
+ eval "$2=( \${$2[@]} \"$item\" )"
+ fi
+ done
+}
+
+# return 0 if yes. 1 if no.
+is_setting_new_leaf ()
+{
+ # $1: tmpl_path
+ if [ $is_set == 0 ]; then
+ return 1
+ fi
+ vyatta_parse_tmpl "$1/node.def"
+ if [ -z "$vyatta_cfg_type" ]; then
+ return 1
+ fi
+ return 0
+}
+
+# this fills in $vyatta_help_text
+get_node_value_help ()
+{
+ # $1: path
+ # $2: \@values
+ declare -a vals
+ eval "vals=( \"\${$2[@]}\" )"
+ if [ $is_set == 0 -a ${#vals[@]} == 0 ]; then
+ vyatta_help_text=""
+ return
+ fi
+ if [ ! -r "$1/node.def" ]; then
+ vyatta_cfg_help="<No help text available>"
+ vyatta_cfg_type=""
+ else
+ vyatta_parse_tmpl "$1/node.def"
+ fi
+ if [ $is_set == 1 -a ! -z "$vyatta_cfg_type" ]; then
+ # add a <type> value
+ local val="<$vyatta_cfg_type>"
+ vals=( $val "${vals[@]}" )
+ fi
+ if [ ${#vals[@]} == 0 ]; then
+ vyatta_help_text=""
+ return
+ fi
+ declare -a hitems=()
+ declare -a hstrs=()
+ for val in "${vals[@]}"; do
+ hitems[${#hitems[@]}]=$val
+ hstrs[${#hstrs[@]}]=$vyatta_cfg_help
+ done
+ generate_help_text hitems hstrs
+}
+
+get_value_list ()
+{
+ # $1: path
+ # $2: \@listing
+ local vfile=$1/node.val
+ if [ ! -r $vfile ]; then
+ eval "$2=()"
+ return
+ fi
+ declare -a listing=()
+ eval `sed 's/^\(.*\)$/listing[\\${#listing[@]}]='\''\1'\''/' $vfile`
+ eval "$2=( \"\${listing[@]}\" )"
+}
+
+vyatta_escape ()
+{
+ # $1: \$original
+ # $2: \$escaped
+ eval "$2=\${$1//\%/%25}"
+ eval "$2=\${$2//\//%2F}"
+}
+
+vyatta_unescape ()
+{
+ # $1: \$escaped
+ # $2: \$original
+ eval "$2=\${$1//\%2F/\/}"
+ eval "$2=\${$2//\%25/%}"
+}
+
+declare -a vyatta_completions
+declare vyatta_help_text="\\nNo help text available"
+declare vyatta_do_help=0
+vyatta_do_complete ()
+{
+ # when this function is called, it is expected that:
+ # * "vyatta_help_text" is filled with the help text.
+ # * "vyatta_completions" is an array of "filtered" possible completions
+ # (i.e., only those starting with the current last component).
+ local do_help=$vyatta_do_help
+
+ # we may not want to do the following
+<<'ENDCOMMENT'
+ if [ ${#vyatta_completions[@]} == 1 ]; then
+ # no ambiguous completions. do completion instead of help.
+ do_help=0
+ fi
+
+ # now check if we can auto-complete at least 1 more character.
+ if (( do_help )); then
+ local schar=""
+ for comp in "${vyatta_completions[@]}"; do
+ local sub=$comp
+ if [ ! -z "${COMP_WORDS[COMP_CWORD]}" ]; then
+ sub=${comp#${comp_words[$last_idx]}}
+ if [ "$comp" == "$sub" ]; then
+ # should not happen since vyatta_completions should be filtered.
+ continue
+ fi
+ fi
+ if [ -z "$schar" ]; then
+ schar=${sub:0:1}
+ else
+ if [ "$schar" != "${sub:0:1}" ]; then
+ schar=""
+ break
+ fi
+ fi
+ done
+ if [ ! -z "$schar" ]; then
+ do_help=0
+ fi
+ fi
+ENDCOMMENT
+
+ if (( do_help )); then
+ echo -en $vyatta_help_text
+ COMPREPLY=( $(compgen -W "== --") )
+ else
+ COMPREPLY=( $(compgen -W "${vyatta_completions[*]}" \
+ -- ${COMP_WORDS[COMP_CWORD]}) )
+ fi
+ vyatta_help_text="\\nNo help text available"
+}
+
+vyatta_config_complete ()
+{
+ if [ "$COMP_LINE" == "$VYATTA_COMP_LINE" ]; then
+ VYATTA_COMP_LINE=''
+ vyatta_do_help=1
+ else
+ VYATTA_COMP_LINE=$COMP_LINE
+ vyatta_do_help=0
+ fi
+
+ local command=${COMP_WORDS[0]}
+ # completion for "set" is different from other commands
+ is_set=0
+ if [ "$command" == "set" ]; then
+ is_set=1
+ fi
+ local end_space=0
+ local num_comp=$COMP_CWORD
+ if [ -z "${COMP_WORDS[$COMP_CWORD]}" ]; then
+ end_space=1
+ (( num_comp -= 1 ))
+ fi
+ (( last_idx = num_comp - 1 ))
+ comp_words=( ${COMP_WORDS[@]:1:$num_comp} )
+
+ # handle "exit"
+ if [ "$command" == "exit" ]; then
+ if (( num_comp > 1 || ( end_space && num_comp > 0 ) )); then
+ COMPREPLY=()
+ return
+ fi
+ declare -a hitems=( "discard" )
+ declare -a hstrs=( "Discard any changes" )
+ generate_help_text hitems hstrs
+ vyatta_completions=( "discard" )
+ vyatta_do_complete
+ return
+ fi
+
+ local _mpath=${VYATTA_TEMP_CONFIG_DIR}/${VYATTA_EDIT_LEVEL}
+ local _tpath=${VYATTA_CONFIG_TEMPLATE}/${VYATTA_TEMPLATE_LEVEL}
+ local last_tag=0
+ local idx=0
+ for (( idx=0; idx < num_comp; idx++ )); do
+ last_tag=0
+ local comp=${comp_words[$idx]}
+ vyatta_escape comp comp
+ push_path _mpath $comp
+ push_path _tpath $comp
+ if [ -d $_tpath ]; then
+ if (( ! is_set )); then
+ # we are not in "set" => only allow existing node
+ if [ ! -d $_mpath ]; then
+ break
+ fi
+ fi
+ continue
+ fi
+ pop_path _tpath
+ push_path _tpath $VYATTA_TAG_NAME
+ if [ -d $_tpath ]; then
+ if (( ! is_set && end_space )); then
+ # we are not in "set" && last component is complete.
+ # => only allow existing tag value.
+ if [ ! -d $_mpath ]; then
+ break
+ fi
+ fi
+ if (( idx != last_idx )); then
+ # TODO validate value
+ # break if not valid
+ # XXX is this validation necessary? (set will validate anyway)
+ true
+ fi
+ last_tag=1
+ continue
+ fi
+ pop_path _tpath
+ pop_path _mpath
+ break
+ done
+ # at the end of the loop, 3 possibilities:
+ # 1. (idx < last_idx): some component before the last is invalid
+ # => invalid command
+ # 2. (idx == last_idx): last component matches neither template nor node.tag
+ # => if end_space, then invalid command
+ # otherwise, may be an incomplete (non-tag) component, or incomplete
+ # "leaf value"
+ # => try matching dirs in _tpath or value(s) in _mpath/node.val
+ # 3. (idx == num_comp): the whole command matches templates/tags
+ if (( idx < last_idx || ( idx == last_idx && end_space ) )); then
+ # TODO error message?
+ COMPREPLY=()
+ return
+ fi
+
+ declare -a matches
+ if (( idx == last_idx )); then
+ # generate possibile matches (dirs in _tpath, and "help" from
+ # node.def in each dir, or values in _mpath/node.val)
+ declare -a fmatches
+ if [ -f $_mpath/node.val ]; then
+ decho [1a]
+ get_value_list $_mpath matches
+ get_prefix_filtered_list ${comp_words[$last_idx]} matches fmatches
+ append_allowed_values $_tpath fmatches
+ get_node_value_help $_tpath fmatches
+ else
+ decho [1b]
+ # see if the last component is a new leaf node
+ fmatches=()
+ if is_setting_new_leaf $_tpath; then
+ append_allowed_values $_tpath fmatches
+ get_node_value_help $_tpath fmatches
+ else
+ # last component is a non-value node. look for child nodes.
+ if (( ! is_set )); then
+ # not "set". only complete existing nodes.
+ declare -a amatches=()
+ get_filtered_dir_listing $_tpath amatches
+ filter_existing_nodes $_mpath amatches matches
+ else
+ get_filtered_dir_listing $_tpath matches
+ fi
+ get_prefix_filtered_list ${comp_words[$last_idx]} matches fmatches
+ get_tmpl_subdir_help $_tpath fmatches
+ fi
+ fi
+ vyatta_completions=( ${fmatches[@]} )
+ vyatta_do_complete
+ return
+ fi
+
+ if (( last_tag && end_space )); then
+ # if not "set", check _mpath (last component is the tag) is valid
+ # generate possible matches (dirs in _tpath, and "help" from node.def
+ # in each dir)
+ decho [2]
+ if [ $is_set == 1 -o -d $_mpath ]; then
+ if (( ! is_set )); then
+ # not "set". only complete existing nodes.
+ declare -a fmatches=()
+ get_filtered_dir_listing $_tpath fmatches
+ filter_existing_nodes $_mpath fmatches matches
+ else
+ get_filtered_dir_listing $_tpath matches
+ fi
+ get_tmpl_subdir_help $_tpath matches
+ vyatta_completions=( ${matches[@]} )
+ vyatta_do_complete
+ return
+ fi
+ return
+ fi
+
+ if (( last_tag && !end_space )); then
+ # generate possible matches (dirs in _mpath, and "help" from node.def
+ # in dirs in _tpath)
+ decho [3]
+ pop_path _mpath
+ pop_path _tpath
+ get_filtered_dir_listing $_mpath matches
+ declare -a fmatches
+ get_prefix_filtered_list ${comp_words[$last_idx]} matches fmatches
+ append_allowed_values $_tpath fmatches
+ get_node_value_help $_tpath fmatches
+ vyatta_completions=( ${fmatches[@]} )
+ vyatta_do_complete
+ return
+ fi
+
+ if (( !last_tag && end_space )); then
+ # generate possible matches
+ # 1. dirs in _tpath, and "help" from node.def in each dir
+ # 2. value(s) in _mpath/node.val (only if _tpath/node.def is "multi:")
+ # 3. dirs in _mpath (only if _tpath/node.def is "tag:")
+ if [ -d $_tpath/node.tag ]; then
+ # last component is a "tag name". look for tag values.
+ decho [4a]
+ get_filtered_dir_listing $_mpath matches
+ append_allowed_values $_tpath matches
+ get_node_value_help $_tpath matches
+ elif [ -f $_mpath/node.val ]; then
+ # last component is a leaf node. look for values.
+ decho [4b]
+ get_value_list $_mpath matches
+ append_allowed_values $_tpath matches
+ get_node_value_help $_tpath matches
+ else
+ decho [4c]
+ # see if the last component is a new leaf node
+ matches=()
+ if is_setting_new_leaf $_tpath; then
+ append_allowed_values $_tpath matches
+ get_node_value_help $_tpath matches
+ else
+ # last component is a non-value node. look for child nodes.
+ if (( ! is_set )); then
+ # not "set". only complete existing nodes.
+ declare -a fmatches=()
+ get_filtered_dir_listing $_tpath fmatches
+ filter_existing_nodes $_mpath fmatches matches
+ else
+ get_filtered_dir_listing $_tpath matches
+ fi
+ get_tmpl_subdir_help $_tpath matches
+ fi
+ fi
+ vyatta_completions=( ${matches[@]} )
+ vyatta_do_complete
+ return
+ fi
+
+ if (( !last_tag && !end_space )); then
+ # generate possible matches (dirs in _tpath, and "help" from node.def
+ # in each dir)
+ decho [5]
+ pop_path _tpath
+ get_filtered_dir_listing $_tpath matches
+ declare -a fmatches
+ get_prefix_filtered_list ${comp_words[$last_idx]} matches fmatches
+ get_tmpl_subdir_help $_tpath fmatches
+ vyatta_completions=( ${fmatches[@]} )
+ vyatta_do_complete
+ return
+ fi
+}
+
+mkdir -p $VYATTA_ACTIVE_CONFIGURATION_DIR
+mkdir -p $VYATTA_CHANGES_ONLY_DIR
+mkdir -p $VYATTA_CONFIG_TMP
+if [ ! -d $VYATTA_TEMP_CONFIG_DIR ]; then
+ mkdir -p $VYATTA_TEMP_CONFIG_DIR
+ sudo mount -t unionfs -o dirs=${VYATTA_CHANGES_ONLY_DIR}=rw:/opt/vyatta/config/active=ro unionfs ${VYATTA_TEMP_CONFIG_DIR}
+fi
+
+# disallow 'Ctrl-D' exit, since we need special actions on 'exit'
+set -o ignoreeof 1
+
+set_config_ps1 ''
+alias commit=my_commit
+alias set=my_set
+alias delete=my_delete
+
+export VYATTA_COMP_LINE=""
+
+# readline bindings
+bind 'set show-all-if-ambiguous on'
+if ! bind -p |grep -q '\\C-x\\C-t'; then
+ bind '"\C-x\C-t": kill-region'
+fi
+if ! bind -p |grep -q '\\C-x\\C-o'; then
+ bind '"\C-x\C-o": copy-region-as-kill'
+fi
+
+complete -F vyatta_config_complete set
+complete -F vyatta_config_complete delete
+complete -F vyatta_config_complete show
+complete -F vyatta_config_complete edit
+complete -F vyatta_config_complete exit
+