From c4b0e2f297a695c32d7ddc1b0b18f656591bd2e0 Mon Sep 17 00:00:00 2001 From: Tanaka Akira Date: Mon, 6 Sep 1999 09:16:29 +0000 Subject: Initial revision --- Completion/Base/_values | 367 ++++++++++++++++++++++++++++++++++++++++++++++ Completion/User/_nslookup | 159 ++++++++++++++++++++ Functions/Misc/nslookup | 34 +++++ 3 files changed, 560 insertions(+) create mode 100644 Completion/Base/_values create mode 100644 Completion/User/_nslookup create mode 100644 Functions/Misc/nslookup diff --git a/Completion/Base/_values b/Completion/Base/_values new file mode 100644 index 000000000..4be3e8203 --- /dev/null +++ b/Completion/Base/_values @@ -0,0 +1,367 @@ +#autoload + +setopt localoptions extendedglob + +local name arg def descr xor str tmp ret=1 expl nm="$compstate[nmatches]" +local snames odescr gdescr sep +typeset -A names onames xors _values + +# Probably fill our cache. + +if [[ "$*" != "$_vals_cache_args" ]]; then + _vals_cache_args="$*" + + unset _vals_cache_{sep,descr,names,onames,snames,xors,odescr} + + typeset -gA _vals_cache_{names,onames,xors} + _vals_cache_snames=() + _vals_cache_odescr=() + + # Get the separator, if any. + + if [[ "$1" = -s ]]; then + _vals_cache_sep="$2" + shift 2 + fi + + # This is the description string for the values. + + _vals_cache_descr="$1" + shift + + # Now parse the descriptions. + + while (( $# )); do + + # Get the `name', anything before an unquoted colon. + + if [[ "$1" = *[^\\]:* ]]; then + name="${${${(M)1#*[^\\]:}[1,-2]}//\\\\:/:}" + else + name="$1" + fi + + descr='' + xor='' + + # Get a description, if any. + + if [[ "$name" = *\[*\] ]]; then + descr="${${name#*\[}[1,-2]}" + name="${name%%\[*}" + fi + + # Get the names of other values that are mutually exclusive with + # this one. + + if [[ "$name" = \(*\)* ]]; then + xor="${${name[2,-1]}%%\)*}" + name="${name#*\)}" + fi + + # Finally see if this value may appear more than once. + + if [[ "$name" = \** ]]; then + name="$name[2,-1]" + else + xor="$xor $name" + fi + + # Store the information in the cache. + + _vals_cache_odescr=( "$_vals_cache_odescr[@]" "${name}:$descr" ) + [[ -n "$xor" ]] && _vals_cache_xors[$name]="${${xor##[ ]#}%%[ ]#}" + + # Get the description and store that. + + if [[ "$1" = *[^\\]:* ]]; then + descr=":${1#*[^\\]:}" + else + descr='' + fi + + if [[ "$descr" = ::* ]]; then + + # Optional argument. + + _vals_cache_onames[$name]="$descr[3,-1]" + elif [[ "$descr" = :* ]]; then + + # Mandatory argument. + + _vals_cache_names[$name]="$descr[2,-1]" + else + + # No argument. + + _vals_cache_snames=( "$_vals_cache_snames[@]" "$name" ) + fi + shift + done +fi + +snames=( "$_vals_cache_snames[@]" ) +names=( "${(@kv)_vals_cache_names}" ) +onames=( "${(@kv)_vals_cache_onames}" ) +xors=( "${(@kv)_vals_cache_xors}" ) +odescr=( "$_vals_cache_odescr[@]" ) +gdescr="$_vals_cache_descr" +sep="$_vals_cache_sep" + +if [[ -n "$sep" ]]; then + + # We have a separator character. We parse the PREFIX and SUFFIX to + # see if any of the values that must not appear more than once are + # already on the line. + + while [[ "$PREFIX" = *${sep}* ]]; do + + # Get one part, remove it from PREFIX and put it into IPREFIX. + + tmp="${PREFIX%%${sep}*}" + PREFIX="${PREFIX#*${sep}}" + IPREFIX="${IPREFIX}${tmp}${sep}" + + # Get the value `name'. + + name="${tmp%%\=*}" + + if [[ "$tmp" = *\=* ]]; then + _values[$name]="${tmp#*\=}" + else + _values[$name]='' + fi + + # And remove the descriptions for the values this one makes + # superfluous. + + if [[ -n "$xors[$name]" ]]; then + snames=( "${(@)snames:#(${(j:|:)~${=xors[$name]}})}" ) + odescr=( "${(@)odescr:#(${(j:|:)~${=xors[$name]}}):*}" ) + unset {names,onames,xors}\[${^=tmp}\] + fi + done + if [[ "$SUFFIX" = *${sep}* ]]; then + + # The same for the suffix. + + str="${SUFFIX%%${sep}*}" + SUFFIX="${SUFFIX#*${sep}}" + while [[ -n "$SUFFIX" ]]; do + tmp="${PREFIX%%${sep}*}" + if [[ "$SUFFIX" = *${sep}* ]]; then + SUFFIX="${SUFFIX#*${sep}}" + else + SUFFIX='' + fi + PREFIX="${PREFIX#*${sep}}" + IPREFIX="${IPREFIX}${tmp}${sep}" + + name="${tmp%%\=*}" + + if [[ "$tmp" = *\=* ]]; then + _values[$name]="${tmp#*\=}" + else + _values[$name]='' + fi + + if [[ -n "$xors[$name]" ]]; then + snames=( "${(@)snames:#(${(j:|:)~${=xors[$name]}})}" ) + odescr=( "${(@)odescr:#(${(j:|:)~${=xors[$name]}}):*}" ) + unset {names,onames,xors}\[${^=tmp}\] + fi + done + SUFFIX="$str" + fi +fi + +descr='' +str="$PREFIX$SUFFIX" + +if [[ "$str" = *\=* ]]; then + + # The string from the line contains a `=', so we get the stuff before + # it and after it and see what we can do here... + + name="${str%%\=*}" + arg="${str#*\=}" + + if (( $snames[(I)${name}] )); then + + # According to our information, the value doesn't get an argument, + # so give up. + + _message "\`${name}' gets no value" + return 1 + elif (( $+names[$name] )); then + + # It has to get an argument, we skip over the name and complete + # the argument (below). + + def="$names[$name]" + if ! compset -P '*\='; then + IPREFIX="${IPREFIX}${name}=" + PREFIX="$arg" + SUFFIX='' + fi + elif (( $+onames[$name] )); then + + # Gets an optional argument, same as previous case. + + def="$onames[$name]" + if ! compset -P '*\='; then + IPREFIX="${IPREFIX}${name}=" + PREFIX="$arg" + SUFFIX='' + fi + else + local pre="$PREFIX" suf="$SUFFIX" + + # The part before the `=' isn't a known value name, so we see if + # it matches only one of the known names. + + if [[ "$PREFIX" = *\=* ]]; then + PREFIX="${PREFIX%%\=*}" + pre="${pre#*\=}" + SUFFIX='' + else + SUFFIX="${SUFFIX%%\=*}" + pre="${suf#*\=}" + suf='' + fi + + tmp=( "${(@k)names}" "${(@k)onames}" ) + compadd -M 'r:|[-_]=* r:|=*' -D tmp - "$tmp[@]" + + if [[ $#tmp -eq 1 ]]; then + + # It does, so we use that name and immediatly start completing + # the argument for it. + + IPREFIX="${IPREFIX}${tmp[1]}=" + PREFIX="$pre" + SUFFIX="$suf" + + def="$names[$tmp[1]]" + [[ -z "$def" ]] && def="$onames[$tmp[1]]" + elif (( $#tmp )); then + _message "ambiguous option \`${PREFIX}${SUFFIX}'" + return 1 + else + _message "unknown option \`${PREFIX}${SUFFIX}'" + return 1 + fi + fi +else + + # No `=', just complete value names. + + _description expl "$gdescr" + + [[ -n "$sep" && ${#snames}+${#names}+${#onames} -ne 1 ]] && + expl=( "-qS$sep" "$expl[@]" ) + + tmp='' + if [[ -n "$compconfig[describe_values]" && + "$compconfig[describe_values]" != *\!${words[1]}* ]]; then + if _display tmp odescr -M 'r:|[_-]=* r:|=*'; then + if (( $#snames )); then + compadd "$expl[@]" -y tmp -M 'r:|[_-]=* r:|=*' - \ + "$snames[@]" && ret=0 + compadd -n -S= -J "_$gdescr" -M 'r:|[_-]=* r:|=*' - \ + "${(@k)names}" && ret=0 + compadd -n -qS= -J "_$gdescr" -M 'r:|[_-]=* r:|=*' - \ + "${(@k)onames}" && ret=0 + elif (( $#names )); then + compadd -n -S= "$expl[@]" -y tmp -M 'r:|[_-]=* r:|=*' - \ + "${(@k)names}" && ret=0 + compadd -n -qS= -J "_$gdescr" -M 'r:|[_-]=* r:|=*' - \ + "${(@k)onames}" && ret=0 + else + compadd -n -qS= "$expl[@]" -y tmp -M 'r:|[_-]=* r:|=*' - \ + "${(@k)onames}" && ret=0 + fi + fi + fi + if [[ -z "$tmp" ]]; then + compadd "$expl[@]" -M 'r:|[_-]=* r:|=*' - "$snames[@]" && ret=0 + compadd -S= "$expl[@]" -M 'r:|[_-]=* r:|=*' - "${(@k)names}" && ret=0 + compadd -qS= "$expl[@]" -M 'r:|[_-]=* r:|=*' - "${(@k)onames}" && ret=0 + fi + return ret +fi + +if [[ -z "$def" ]]; then + _message 'no value' + return 1 +else + local action + + descr="${${${(M)def#*[^\\]:}[1,-2]}//\\\\:/:}" + action="${${def#*[^\\]:}//\\\\:/:}" + + _description expl "$descr" + + # We add the separator character as a autoremovable suffix unless + # we have only one possible value left. + + [[ -n "$sep" && ${#snames}+${#names}+${#onames} -ne 1 ]] && + expl=( "-qS$sep" "$expl[@]" ) + + if [[ "$action" = -\>* ]]; then + values=( "${(@kv)_values}" ) + state="${${action[3,-1]##[ ]#}%%[ ]#}" + compstate[restore]='' + return 1 + else + typeset -A values + + values=( "${(@kv)_values}" ) + + if [[ "$action" = \ # ]]; then + + # An empty action means that we should just display a message. + + _message "$descr" + return 1 + + elif [[ "$action" = \(\(*\)\) ]]; then + local ws + + # ((...)) contains literal strings with descriptions. + + eval ws\=\( "${action[3,-3]}" \) + + if _display tmp ws; then + compadd "$expl[@]" -y tmp - "${(@)ws%%:*}" + else + _message "$descr" + return 1 + fi + elif [[ "$action" = \(*\) ]]; then + + # Anything inside `(...)' is added directly. + + compadd "$expl[@]" - ${=action[2,-2]} + elif [[ "$action" = \{*\} ]]; then + + # A string in braces is evaluated. + + eval "$action[2,-2]" + + elif [[ "$action" = \ * ]]; then + + # If the action starts with a space, we just call it. + + ${(e)=~action} + else + + # Otherwise we call it with the description-arguments built above. + + action=( $=action ) + ${(e)action[1]} "$expl[@]" ${(e)~action[2,-1]} + fi + fi +fi + +[[ nm -ne "$compstate[nmatches]" ]] diff --git a/Completion/User/_nslookup b/Completion/User/_nslookup new file mode 100644 index 000000000..7d2a12142 --- /dev/null +++ b/Completion/User/_nslookup @@ -0,0 +1,159 @@ +#compdef nslookup + +# This may also be called from the `nslookup' wrapper function during +# `vared'iting a line. +# In this case this function tries to call other user-defined functions +# for certain contexts before adding completion. If these functions are +# defined, they are called and the default completions from this function +# are not added. The functions called are named `_nslookup_', with +# `' being any of: +# +# command +# When completing the first word on the line. +# redirect +# When completing after a redirection operator. +# +# Also, when completing after the first word, if the first word contains +# only lower case letters, we try to call the function `_nslookup_', +# where `' is the first word from the line. If the first word contains +# other characters than lower case letters, we try to call the function +# `_nslookup_host'. + +setopt localoptions extendedglob + +local state expl ret=1 setopts + +setopts=( + 'all[print current values]' \ + '(nodebug)debug[simple debugging information]' \ + '(debug)nodebug[no simple debugging information]' \ + '(nod2)d2[extra debugging information]' \ + '(d2)nod2[no extra debugging information]' \ + '(nodefname)defname[append default domain name]' \ + '(defname)nodefname[don'"'"'t append default domain name]' \ + '(nosearch)search[append search list]' \ + '(search)nosearch[don'"'"'t append search list]' \ + '(norecurse)recurse[name server may query other servers]' \ + '(recurse)norecurse[name server may not query other servers]' \ + '(novc)vc[use virtual circuit]' \ + '(vc)novc[don'"'"'t use virtual circuit]' \ + '(noignoretc)ignoretc[ignore packet truncation errors]' \ + '(ignoretc)noignoretc[don'"'"'t ignore packet truncation errors]' \ + 'class[change query class]:query class:((in\:Internet\ class chaos\:CHAOS\ class hesiod\:MIT\ Athena\ Hesiod\ class any\:wildcard\ \(any\ of\ the\ above\)))' + 'domain[change default domain]:default domain:_hosts' + 'srchlist[change default domain and search list]: :->srchlist' + 'port[change name server port]:name server port:' + {query,}type'[change type of information query]:query information type:((a\:internet\ address cname\:canonical\ name\ for\ alias hinfo\:CPU\ and\ operating\ system\ type minfo\:mailbox\ or\ mail\ list\ information mx\:mail\ exchanger ns\:name\ server\ for\ zone ptr\:host\ name\ or\ other\ information soa\:domain\'"'"'s\ \`start-of-authority\'"'"'\ information txt\:text\ information uinfo\:user\ information wks\:supported\ well-known\ services))' + 'retry[change number of retries]:number of retries:' + 'root[change name of root server]:root server:_hosts' + 'timeout[change initial timeout interval]:timeout (seconds):' +) + +if [[ -n "$compcontext" ]]; then + if [[ CURRENT -eq 1 ]]; then + + funcall ret _nslookup_command && return ret + + _description expl 'command' + compadd "$expl[@]" - server lserver root finger ls view help set && ret=0 + _hosts && ret=0 + return ret + elif [[ "$compstate[context]" = redirect ]]; then + + funcall ret _nslookup_redirect && return ret + + if [[ "$words[1]" != (finger|ls) ]]; then + _message "redirection not allowed for command \`$words[1]'" + return 1 + elif [[ "$compstate[redirect]" = '>' ]]; then + _description expl 'write to file' + elif [[ "$compstate[redirect]" = '>>' ]]; then + _description expl 'append to file' + else + _message "unknown redirection operator \`$compstate[redirect]'" + return 1 + fi + + _files "$expl[@]" + return + fi + + if [[ "$words[1]" = [a-z]## ]]; then + funcall ret _nslookup_$words[1] && return ret + else + funcall ret _nslookup_host && return ret + fi + + case "$words[1]" in + (|l)server) + _description expl 'new default server' + _hosts "$expl[@]" + return + ;; + root|exit|help|\?) + return 1 + ;; + finger) + _message 'finger name' + return 1 + ;; + ls) + _arguments -s \ + '-t[records of given type]:query information type:((a\:internet\ address cname\:canonical\ name\ for\ alias hinfo\:CPU\ and\ operating\ system\ type minfo\:mailbox\ or\ mail\ list\ information mx\:mail\ exchanger ns\:name\ server\ for\ zone ptr\:host\ name\ or\ other\ information soa\:domain\'"'"'s\ \`start-of-authority\'"'"'\ information txt\:text\ information uinfo\:user\ information wks\:supported\ well-known\ services))' \ + '-a[aliases of hosts in domain]' \ + '-d[all records]' \ + '-h[CPU and operating system information]' \ + '-s[well-known services]' \ + ':domain:_hosts' + return + ;; + view) + _description expl 'view file' + _files "$expl[@]" + return + ;; + set) + typeset -A values + + _values 'state information' "$setopts[@]" && ret=0 + + [[ -z "$state" ]] && return ret + ;; + *) + _description expl 'server' + _hosts "$expl[@]" + return + esac +fi + +# Now comes the command line option completion part. + +if [[ -z "$state" ]]; then + local line + typeset -A options + + _arguments \ + "-${(@)^${(@M)setopts:#*\]:*}/\[/=[}" \ + "-${(@)^setopts:#(\(|*\]:)*}" \ + "${(@)^${(@)${(@M)setopts:#\(*}/\)/)-}/\(/(-}" \ + ':host to find:_hosts' \ + ':server:_hosts' && ret=0 +fi + +# This is completion after `srchlist' for both types. + +if [[ -n "$state" ]]; then + if compset -P '*/'; then + _description expl 'search list entry' + else + _description expl 'default domain name and first search list entry' + fi + if [[ -n "$_vals_cache_multi" ]]; then + _hosts "$expl[@]" -qS/ -r "/\\- \\t\\n$_vals_cache_multi" + else + _hosts "$expl[@]" -qS/ + fi + return +fi + +return ret diff --git a/Functions/Misc/nslookup b/Functions/Misc/nslookup new file mode 100644 index 000000000..15afb2ff1 --- /dev/null +++ b/Functions/Misc/nslookup @@ -0,0 +1,34 @@ +# Simple wrapper function for `nslookup'. With completion if you are using +# the function based completion system. + +setopt localoptions completealiases + +local char line compcontext=nslookup pid + +trap 'print -p exit;return' INT + +coproc command nslookup +pid=$! + +while read -pk1 char; do + line="$line$char" + [[ "$line" = *' +> ' ]] && break +done +print -nr - "$line" + +line='' +while vared -p '> ' line; do + print -p "$line" + line='' + while read -pk1 char; do + line="$line$char" + [[ "$line" = *' +> ' ]] && break + done + print -nr - "$line" + line='' +done + +print -p exit +wait $pid -- cgit 1.4.1