diff options
author | Tanaka Akira <akr@users.sourceforge.net> | 1999-04-15 18:16:27 +0000 |
---|---|---|
committer | Tanaka Akira <akr@users.sourceforge.net> | 1999-04-15 18:16:27 +0000 |
commit | b4a5b9db8b528f9c9b6a9cbb00db381c95659380 (patch) | |
tree | 17bf8f93d47de0af7495ec6d11361aef1ca62f9b /Functions | |
parent | ba4f5e80ec9d7e145718e79fed6e57a852c86c12 (diff) | |
download | zsh-b4a5b9db8b528f9c9b6a9cbb00db381c95659380.tar.gz zsh-b4a5b9db8b528f9c9b6a9cbb00db381c95659380.tar.xz zsh-b4a5b9db8b528f9c9b6a9cbb00db381c95659380.zip |
zsh-3.1.5-pws-9 zsh-3.1.5-pws-9
Diffstat (limited to 'Functions')
67 files changed, 1049 insertions, 139 deletions
diff --git a/Functions/Completion/_aliases b/Functions/Completion/_aliases new file mode 100644 index 000000000..1038a726e --- /dev/null +++ b/Functions/Completion/_aliases @@ -0,0 +1,3 @@ +#defcomp unalias + +complist -a diff --git a/Functions/Completion/_arrays b/Functions/Completion/_arrays new file mode 100644 index 000000000..cbeac7118 --- /dev/null +++ b/Functions/Completion/_arrays @@ -0,0 +1,3 @@ +#defcomp shift + +complist -A diff --git a/Functions/Completion/_autoload b/Functions/Completion/_autoload new file mode 100644 index 000000000..4f506baeb --- /dev/null +++ b/Functions/Completion/_autoload @@ -0,0 +1,3 @@ +#defcomp autoload + +complist -s '${^fpath}/*(N:t)' diff --git a/Functions/Completion/_bg_jobs b/Functions/Completion/_bg_jobs new file mode 100644 index 000000000..511bb8308 --- /dev/null +++ b/Functions/Completion/_bg_jobs @@ -0,0 +1,3 @@ +#defcomp bg + +complist -z -P '%' diff --git a/Functions/Completion/_bindkey b/Functions/Completion/_bindkey new file mode 100644 index 000000000..8eddeb2a8 --- /dev/null +++ b/Functions/Completion/_bindkey @@ -0,0 +1,7 @@ +#defcomp bindkey + +if [[ -mword 1 -*[DAN]* || -mcurrent -1 -*M ]]; then + complist -s '$(bindkey -l)' +else + complist -b +fi diff --git a/Functions/Completion/_builtin b/Functions/Completion/_builtin new file mode 100644 index 000000000..d2b11226b --- /dev/null +++ b/Functions/Completion/_builtin @@ -0,0 +1,7 @@ +#defcomp builtin + +if [[ -position 2 -1 ]]; then + compsub +else + complist -eB +fi diff --git a/Functions/Completion/_cd b/Functions/Completion/_cd new file mode 100644 index 000000000..f3ce67ec7 --- /dev/null +++ b/Functions/Completion/_cd @@ -0,0 +1,3 @@ +#defcomp cd + +_files -W cdpath -g '*(-/)' diff --git a/Functions/Completion/_command b/Functions/Completion/_command new file mode 100644 index 000000000..b2812de25 --- /dev/null +++ b/Functions/Completion/_command @@ -0,0 +1,7 @@ +#defcomp command + +if [[ -position 2 -1 ]]; then + _normal "$@" +else + complist -em +fi diff --git a/Functions/Completion/_command_names b/Functions/Completion/_command_names new file mode 100644 index 000000000..d3b8a109a --- /dev/null +++ b/Functions/Completion/_command_names @@ -0,0 +1,3 @@ +#defcomp -command- + +complist -c diff --git a/Functions/Completion/_compress b/Functions/Completion/_compress new file mode 100644 index 000000000..860aeb5b0 --- /dev/null +++ b/Functions/Completion/_compress @@ -0,0 +1,3 @@ +#defcomp compress + +_files -g '*~*.Z' diff --git a/Functions/Completion/_condition b/Functions/Completion/_condition new file mode 100644 index 000000000..3e45e1b8f --- /dev/null +++ b/Functions/Completion/_condition @@ -0,0 +1,10 @@ +#defcomp -condition- + +if [[ -current -1 -o ]]; then + complist -o -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' +elif [[ -current -1 -nt || -current -1 -ot || -current -1 -ef ]]; then + _files +else + _files + complist -v +fi diff --git a/Functions/Completion/_configure b/Functions/Completion/_configure new file mode 100644 index 000000000..de8d5fba5 --- /dev/null +++ b/Functions/Completion/_configure @@ -0,0 +1,12 @@ +#defcomp configure + +if [[ $PREFIX = *=* ]]; then + # Complete filenames after e.g. --prefix= + IPREFIX=${PREFIX%%=*}= + PREFIX=${PREFIX#*=} + complist -f +else + # Generate a list of options from configure --help + complist -s '$($COMMAND --help | + sed -n -e '\''s/^ *\(--[-a-z0-9]*\)[ =,].*$/\1/p'\'')' +fi diff --git a/Functions/Completion/_dd b/Functions/Completion/_dd new file mode 100644 index 000000000..2458541ea --- /dev/null +++ b/Functions/Completion/_dd @@ -0,0 +1,13 @@ +#defcomp dd + +if [[ -iprefix conv= ]]; then + # If there's a comma present, ignore up to the last one. The + # test alone will have that effect. + [[ -string , ]] + complist -S, -q \ + -k '(ascii ebcdic ibm block unblock lcase ucase swab noerror sync)' +elif [[ -iprefix 'if=' || -iprefix 'of=' ]]; then + _files +else + complist -S '=' -k '(if of ibs obs bs cbs skip files seek count conv)' +fi diff --git a/Functions/Completion/_default b/Functions/Completion/_default new file mode 100644 index 000000000..8bcf14f6a --- /dev/null +++ b/Functions/Completion/_default @@ -0,0 +1,13 @@ +#defcomp -default- + +# We first try the `compctl's. This is without first (-T) and default (-D) +# completion. If you want them add `-T' and/or `-D' to this command. +# If there is a `compctl' for the command we are working on, we return +# immediatly. If you want to use new style completion anyway, remove the +# `|| return'. Also, you may want to use new style completion if the +# `compctl' didn't produce any matches. In that case remove the `|| return' +# and at the line `[[ -nmatches 0 ]] || return' after `compcall'. + +compcall || return + +_files diff --git a/Functions/Completion/_dirs b/Functions/Completion/_dirs new file mode 100644 index 000000000..c79080d58 --- /dev/null +++ b/Functions/Completion/_dirs @@ -0,0 +1,3 @@ +#defcomp rmdir df du dircmp + +_files -/ '*(-/)' diff --git a/Functions/Completion/_disable b/Functions/Completion/_disable new file mode 100644 index 000000000..063b65a7d --- /dev/null +++ b/Functions/Completion/_disable @@ -0,0 +1,6 @@ +#defcomp disable + +[[ -mcurrent -1 -*a* ]] && complist -ea +[[ -mcurrent -1 -*f* ]] && complist -eF +[[ -mcurrent -1 -*r* ]] && complist -ew +[[ ! -mcurrent -1 -* ]] && complist -eB diff --git a/Functions/Completion/_dvi b/Functions/Completion/_dvi new file mode 100644 index 000000000..bb2fc293e --- /dev/null +++ b/Functions/Completion/_dvi @@ -0,0 +1,3 @@ +#defcomp xdvi dvips dvibook dviconcat dvicopy dvidvi dviselect dvitodvi dvitype + +_files -g '*.(dvi|DVI)' diff --git a/Functions/Completion/_echotc b/Functions/Completion/_echotc new file mode 100644 index 000000000..85ebb97ce --- /dev/null +++ b/Functions/Completion/_echotc @@ -0,0 +1,3 @@ +#defcomp echotc + +complist -k '(al dc dl do le up al bl cd ce cl cr dc dl do ho is le ma nd nl se so up)' diff --git a/Functions/Completion/_enable b/Functions/Completion/_enable new file mode 100644 index 000000000..22ff53ee7 --- /dev/null +++ b/Functions/Completion/_enable @@ -0,0 +1,6 @@ +#defcomp enable + +[[ -mcurrent -1 -*a* ]] && complist -da +[[ -mcurrent -1 -*f* ]] && complist -dF +[[ -mcurrent -1 -*r* ]] && complist -dw +[[ ! -mcurrent -1 -* ]] && complist -dB diff --git a/Functions/Completion/_fc b/Functions/Completion/_fc new file mode 100644 index 000000000..f0d2c03fd --- /dev/null +++ b/Functions/Completion/_fc @@ -0,0 +1,7 @@ +#defcomp fc + +if [[ -mcurrent -1 -*e ]]; then + complist -c +elif [[ -mcurrent -1 -[ARWI]## ]]; then + _files +fi diff --git a/Functions/Completion/_files b/Functions/Completion/_files new file mode 100644 index 000000000..ab3006e39 --- /dev/null +++ b/Functions/Completion/_files @@ -0,0 +1,10 @@ +#autoload + +# Utility function for completing files of a given type or any file. +# In many cases you will want to call this one instead of _path_files(). + +local nm=$NMATCHES + +_path_files "$@" + +[[ $# -ne 0 && -nmatches nm ]] && _path_files diff --git a/Functions/Completion/_find b/Functions/Completion/_find new file mode 100644 index 000000000..ca4f79908 --- /dev/null +++ b/Functions/Completion/_find @@ -0,0 +1,21 @@ +#defcomp find + +if [[ -mbetween -(ok|exec) \\\; ]]; then + _normal "$@" +elif [[ -iprefix - ]]; then + complist -s 'daystart {max,min,}depth follow noleaf version xdev \ + {a,c,}newer {a,c,m}{min,time} empty false {fs,x,}type gid inum links \ + {i,}{l,}name {no,}{user,group} path perm regex size true uid used \ + exec {f,}print{f,0,} ok prune ls' +elif [[ -position 1 ]]; then + complist -g '. ..' + _files -g '(-/)' +elif [[ -mcurrent -1 -((a|c|)newer|fprint(|0|f)) ]]; then + _files +elif [[ -current -1 -fstype ]]; then + complist -k '(ufs 4.2 4.3 nfs tmp mfs S51K S52K)' +elif [[ -current -1 -group ]]; then + complist -k groups +elif [[ -current -1 -user ]]; then + complist -u +fi diff --git a/Functions/Completion/_functions b/Functions/Completion/_functions new file mode 100644 index 000000000..8a352ea08 --- /dev/null +++ b/Functions/Completion/_functions @@ -0,0 +1,3 @@ +#defcomp unfunction + +complist -F diff --git a/Functions/Completion/_gunzip b/Functions/Completion/_gunzip new file mode 100644 index 000000000..35a27e774 --- /dev/null +++ b/Functions/Completion/_gunzip @@ -0,0 +1,3 @@ +#defcomp gunzip zcat + +_files -g '*.[gG][z]' diff --git a/Functions/Completion/_gzip b/Functions/Completion/_gzip new file mode 100644 index 000000000..3cda1e4ed --- /dev/null +++ b/Functions/Completion/_gzip @@ -0,0 +1,3 @@ +#defcomp gzip + +_files -g '*~*.[gG][zZ]' diff --git a/Functions/Completion/_hash b/Functions/Completion/_hash new file mode 100644 index 000000000..a6109563d --- /dev/null +++ b/Functions/Completion/_hash @@ -0,0 +1,13 @@ +#defcomp hash + +if [[ -mword 1 -*d* ]]; then + if [[ -string 1 '=' ]]; then + _path_files -g '*(-/)' + else + complist -n -q -S '=' + fi +elif [[ -string 1 '=' ]]; then + _files -g '*(*)' '*(-/)' +else + complist -m -q -S '=' +fi diff --git a/Functions/Completion/_hosts b/Functions/Completion/_hosts new file mode 100644 index 000000000..3acc327ac --- /dev/null +++ b/Functions/Completion/_hosts @@ -0,0 +1,3 @@ +#defcomp ftp ncftp ping rwho rup xping traceroute nslookup + +complist -k hosts diff --git a/Functions/Completion/_jobs b/Functions/Completion/_jobs new file mode 100644 index 000000000..018883c61 --- /dev/null +++ b/Functions/Completion/_jobs @@ -0,0 +1,3 @@ +#defcomp fg jobs + +complist -j -P '%' diff --git a/Functions/Completion/_kill b/Functions/Completion/_kill new file mode 100644 index 000000000..bf0e1d3f8 --- /dev/null +++ b/Functions/Completion/_kill @@ -0,0 +1,8 @@ +#defcomp kill + +if [[ -iprefix '-' ]]; then + complist -k "($signals[1,-3])" +else + complist -P '%' -j + complist -y _kill_helper -s '`ps 2>/dev/null | tail +2 | cut -c1-5`' +fi diff --git a/Functions/Completion/_kill_helper b/Functions/Completion/_kill_helper new file mode 100644 index 000000000..d3e9aaf4a --- /dev/null +++ b/Functions/Completion/_kill_helper @@ -0,0 +1,3 @@ +#autoload + +reply=( "$(ps 2>/dev/null)" ) diff --git a/Functions/Completion/_limits b/Functions/Completion/_limits new file mode 100644 index 000000000..35ccbe07e --- /dev/null +++ b/Functions/Completion/_limits @@ -0,0 +1,3 @@ +#defcomp limit unlimit + +complist -k "(${(j: :)${(f)$(limit)}%% *})" diff --git a/Functions/Completion/_main_complete b/Functions/Completion/_main_complete new file mode 100644 index 000000000..003a01785 --- /dev/null +++ b/Functions/Completion/_main_complete @@ -0,0 +1,48 @@ +#autoload + +# The main loop of the completion code. This is what is called when +# completion is attempted from the command line. +# The completion code gives us the special variables and the arguments +# from the command line are given as positional parameters. + +local comp name + +setopt localoptions nullglob rcexpandparam globdots +unsetopt markdirs globsubst shwordsplit nounset + +# An entry for `-first-' is the replacement for `compctl -T' +# Completion functions may set `COMPSKIP' to any value to make the +# main loops stop calling other completion functions. + +comp="$comps[-first-]" +if [[ ! -z "$comp" ]]; then + "$comp" "$@" + if (( $+COMPSKIP )); then + unset COMPSKIP + return + fi +fi + +# For arguments we use the `_normal function. + +if [[ $CONTEXT == argument || $CONTEXT == command ]]; then + _normal "$@" +else + # Let's see if we have a special completion definition for the other + # possible contexts. + + comp='' + + case $CONTEXT in + redirect) comp="$comps[-redirect-]";; + math) comp="$comps[-math-]";; + subscript) comp="$comps[-subscript-]";; + value) comp="$comps[-value-]";; + condition) comp="$comps[-condition-]";; + esac + + # If not, we use default completion, if any. + + [[ -z "$comp" ]] && comp="$comps[-default-]" + [[ -z "$comp" ]] || "$comp" "$@" +fi diff --git a/Functions/Completion/_make b/Functions/Completion/_make new file mode 100644 index 000000000..d576b0308 --- /dev/null +++ b/Functions/Completion/_make @@ -0,0 +1,3 @@ +#defcomp make gmake pmake + +complist -s "\$(awk '/^[a-zA-Z0-9][^/ ]+:/ {print \$1}' FS=: [mM]akefile)" diff --git a/Functions/Completion/_man b/Functions/Completion/_man new file mode 100644 index 000000000..8204fba0b --- /dev/null +++ b/Functions/Completion/_man @@ -0,0 +1,11 @@ +#defcomp man +setopt localoptions rcexpandparam + +local rep +if [[ $2 = (<->*|ln) ]]; then + rep=( $manpath/(man|cat)$2/$PREFIX*$SUFFIX.<->*(N:t:r) ) +else + rep=( $manpath/(man|cat)*/$PREFIX*$SUFFIX.<->*(N:t:r) ) +fi + +(( $#rep )) && compadd -m $rep diff --git a/Functions/Completion/_mh b/Functions/Completion/_mh new file mode 100644 index 000000000..67ce49fd2 --- /dev/null +++ b/Functions/Completion/_mh @@ -0,0 +1,70 @@ +#defcomp folder comp inc mark refile repl scan show next prev rmm pick whom mhn mhpath mhpatch + +# Completion for all possible MH commands. +# Alter the following two to your own mh directory and the directory +# where standard mh library files live. (It works anyway, but this +# will save a little time.) +local mymhdir=~/Mail +local mhlib=/usr/lib/mh + +# To be on the safe side, check this exists and if not, get it anyway. +[[ -d $mymhdir ]] || mymhdir=$(mhpath +) + +if [[ -iprefix - ]]; then + # get list of options, which MH commands can generate themselves + # awk is just too icky to use for this, sorry. send me one if + # you come up with it. + compadd -m $($COMMAND -help | perl -ne 'if (/^\s*-\(?(\S+)/) { + $n = $1; + $n =~ s/\)//g; + print $n =~ s/^\[([a-z]+)\]// ? "$n\n$1$n\n" : "$n\n"; + }') + return +elif [[ -iprefix '+' || -iprefix '@' || -current -1 -draftfolder ]]; then + # Complete folder names. + local mhpath + if [[ $IPREFIX != '@' ]]; then + [[ $IPREFIX = '+' ]] || IPREFIX=+ + mhpath=$mymhdir + else + mhpath=$(mhpath) + fi + + # painless, or what? + complist -W mhpath -/ +elif [[ -mcurrent -1 -(editor|(whatnow|rmm|show|more)proc) ]]; then + complist -c +elif [[ -current -1 -file ]]; then + complist -f +elif [[ -mcurrent -1 -(form|audit|filter) ]]; then + # Need some MH template file, which may be in our own MH directory + # or with the standard library. + local mhfpath + # This is the only place we need mhlib, so leave the test till here. + [[ -d $mhlib ]] || { mhlib=$(mhparam mhlproc); mhlib=$mhlib:h; } + mhfpath=($mymhdir $mhlib) + + complist -W mhfpath -g '*(.)' +elif [[ -mcurrent -1 -(no|)cc ]]; then + compadd -m all to cc me +elif [[ -mcurrent -1 -[rw]cache ]]; then + compadd -m public private never ask +else + # Generate sequences. + local foldnam folddir f + for f in $argv; do + [[ $f = [@+]* ]] && foldnam=$f + done + if [[ $foldnam = '+'* ]]; then + folddir=$mymhdir/${foldnam#+} + elif [[ $foldnam = '@'* ]]; then + folddir=$(mhpath)/${foldnam#@} + else + folddir=$(mhpath) + # leaving foldnam empty works here + fi + + complist -s '$(mark $foldnam | awk -F: '\''{ print $1 }'\'')' + compadd -m reply next cur prev first last all unseen + complist -W folddir -g '<->' +fi diff --git a/Functions/Completion/_most_recent_file b/Functions/Completion/_most_recent_file new file mode 100644 index 000000000..69900e6ff --- /dev/null +++ b/Functions/Completion/_most_recent_file @@ -0,0 +1,3 @@ +#defkeycomp expand-or-complete \C-xm + +complist -g '*(om[1])' diff --git a/Functions/Completion/_normal b/Functions/Completion/_normal new file mode 100644 index 000000000..22cc1decf --- /dev/null +++ b/Functions/Completion/_normal @@ -0,0 +1,56 @@ +#autoload + +local comp cmd1 cmd2 pat val name + +# Completing in command position? If not we set up `cmd1' and `cmd2' as +# two strings we have search in the completion definition arrays (e.g. +# a path and the last path name component). + +if [[ $CONTEXT == command ]]; then + comp="$comps[-command-]" + [[ -z "$comp" ]] || "$comp" "$@" + return +elif [[ "$COMMAND[1]" == '=' ]]; then + eval cmd1\=$COMMAND + cmd2="$COMMAND[2,-1]" +elif [[ "$COMMAND" == */* ]]; then + cmd1="$COMMAND" + cmd2="${COMMAND:t}" +else + cmd1="$COMMAND" + eval cmd2=$(whence -p $COMMAND) +fi + +# See if there are any matching pattern completions. + +if (( $#patcomps )); then + for i in "$patcomps[@]"; do + pat="${i% *}" + val="${i#* }" + if [[ "$cmd1" == $~pat || "$cmd2" == $~pat ]]; then + "$val" "$@" + if (( $+COMPSKIP )); then + unset COMPSKIP + return + fi + fi + done +fi + +# Now look up the two names in the normal completion array. + +name="$cmd1" +comp="$comps[$cmd1]" + +if [[ -z "$comp" ]]; then + name="$cmd2" + comp="$comps[$cmd2]" +fi + +# And generate the matches, probably using default completion. + +if [[ -z "$comp" ]]; then + name=-default- + comp="$comps[-default-]" +fi +[[ -z "$comp" ]] || "$comp" "$@" diff --git a/Functions/Completion/_path_files b/Functions/Completion/_path_files new file mode 100644 index 000000000..7db364b7d --- /dev/null +++ b/Functions/Completion/_path_files @@ -0,0 +1,272 @@ +#autoload + +# Utility function for in-path completion. +# First argument should be an complist-option (e.g. -f, -/, -g). The other +# arguments should be glob patterns, one per argument. +# +# E.g.: _path_files -g '*.tex' '*.texi' +# +# This is intended as a replacement for `complist -f', `complist -/', and +# `complist -g ...' (but don't use it with other options). +# +# You may also give the `-W <spec>' option as with `compctl' and `complist', +# but only as the first argument. +# +# This function also accepts an optional `-F <string>' option as its first +# argument or just after the `-W <spec>'. This can be used to define file +# name extension (a la `fignore'). Files with such an extension will not +# be considered possible completions. +# +# This function behaves as if you have a matcher definition like: +# compctl -M 'r:|[-.,_/]=* r:|=* m:{a-z}={A-Z} m:-=_ m:.=,' \ +# 'm:{a-z}={A-Z} l:|=* r:|=*' +# so you may want to modify this. + +local nm prepaths str linepath realpath donepath patstr prepath testpath rest +local tmp1 collect tmp2 suffixes i ignore + +setopt localoptions nullglob rcexpandparam globdots extendedglob +unsetopt markdirs globsubst shwordsplit nounset + +# Get the optional `-W' option and its argument. +if [[ "$1" = -W ]]; then + tmp1="$2" + if [[ "$tmp1[1]" = '(' ]]; then + prepaths=( $tmp1[2,-2]/ ) + else + prepaths=( ${(P)${tmp1}} ) + [[ $#prepaths -eq 0 ]] && prepaths=( $tmp1/ ) + fi + [[ $#prepaths -eq 0 ]] && prepaths=( '' ) + shift 2 +else + prepaths=( '' ) +fi + +# Get the optional `-F' option and its argument. +if [[ "$1" = -F ]]; then + ignore=(-F "$2") + shift 2 +else + ignore='' +fi + +# str holds the whole string from the command line with a `*' between +# the prefix and the suffix. + +str="${PREFIX:q}*${SUFFIX:q}" + +# We will first try normal completion called with `complist', but only if we +# weren't given a `-F' option. + +if [[ -z "$ignore" ]]; then + # First build an array containing the `-W' option, if there is any and we + # want to use it. We don't want to use it if the string from the command line + # is a absolute path or relative to the current directory. + + if [[ -z "$tmp1[1]" || "$str[1]" = [~/] || "$str" = (.|..)/* ]]; then + tmp1=() + else + tmp1=(-W "( $prepaths )") + fi + + # Now call complist. + + nm=$NMATCHES + if [[ $# -eq 0 ]]; then + complist "$tmp1[@]" -f + elif [[ "$1" = -g ]]; then + complist "$tmp1[@]" -g "$argv[2,-1]" + shift + else + complist "$tmp1[@]" $1 + shift + fi + + # If this generated any matches, we don't wnat to do in-path completion. + + [[ -nmatches nm ]] || return + + # No `-F' option, so we want to use `fignore'. + + ignore=(-F fignore) +fi + +# If we weren't given any file patterns as arguments, we trick ourselves +# into believing that we were given the pattern `*'. This is just to simplify +# the following code. + +[[ -z "$1" ]] && 1='*' + +# Now let's have a closer look at the string to complete. + +if [[ "$str[1]" = \~ ]]; then + # It begins with `~', so remember anything before the first slash to be able + # to report it to the completion code. Also get an expanded version of it + # (in `realpath'), so that we can generate the matches. Then remove that + # prefix from the string to complete, set `donepath' to build the correct + # paths and make sure that the loop below is run only once with an empty + # prefix path by setting `prepaths'. + + linepath="${str%%/*}/" + eval realpath\=path + str="${str#*/}" + donepath='' + prepaths=( '' ) +else + # If the string does not start with a `~' we don't remove a prefix from the + # string. + + liniepath='' + realpath='' + + if [[ "$str[1]" = / ]]; then + # If it is a absolut path name, we remove the first slash and put it in + # `donepath' meaning that we treat it as the path that was already handled. + # Also, we don't use the paths from `-W'. + + str="$str[2,-1]" + donepath='/' + prepaths=( '' ) + else + # The common case, we just use the string as it is, unless it begins with + # `./' or `../' in which case we don't use the paths from `-W'. + + [[ "$str" = (.|..)/* ]] && prepaths=( '' ) + donepath='' + fi +fi + +# First we skip over all pathname components in `str' which really exist in +# the file-system, so that `/usr/lib/l<TAB>' doesn't offer you `lib' and +# `lib5'. Pathname components skipped this way are taken from `str' and added +# to `donepath'. + +while [[ "$str" = */* ]] do + [[ -e "$realpath$donepath${str%%/*}" ]] || break + donepath="$donepath${str%%/*}/" + str="${str#*/}" +done + +# Now build the glob pattern. As noted above, this function behaves as if +# a global matcher with two matching specifications are given. + +if [[ -matcher 1 ]]; then + patstr="$str:gs/,/*,/:gs/_/*_/:gs./.*/.:gs/-/*[-_]/:gs/./*[.,]/:gs-*[.,]*[.,]*/-../-:gs.**.*." +else + patstr="${str%/*}/*${str##*/}*" + patstr="$patstr:gs./.*/.:gs.**.*." +fi + +# Finally, generate the matches. First we loop over all the paths from `-W'. +# Note that in this loop `str' is used as a modifyable version of `patstr' +# and `testpath' is a modifyable version of `donepath'. + +for prepath in "$prepaths[@]"; do + str="$patstr" + testpath="$donepath" + + # The second loop tests the components of the path in `str' to get the + # possible matches. + + while [[ "$str" = */* ]] do + # `rest' is the pathname after the first slash that is left. In `tmp1' + # we get the globbing matches for the pathname component currently + # handled. + + rest="${str#*/}" + tmp1="${prepath}${realpath}${testpath}(#l)${str%%/*}(-/)" + tmp1=( $~tmp1 ) + + if [[ $#tmp1 -eq 0 ]]; then + # If this didn't produce any matches, we don't need to test this path + # any further, so continue with the next `-W' path, if any. + + continue 2 + elif [[ $#tmp1 -gt 1 ]]; then + # If it produced more than one match, we want to remove those which + # don't have possible following pathname components matching the + # rest of the string we are completing. (The case with only one + # match is handled below.) + # In `collect' we will collect those of the produced pathnames that + # have a matching possible path-suffix. In `suffixes' we build an + # array containing strings build from the rest of the string to + # complete and the glob patterns we were given as arguments. + + collect=() + suffixes=( $rest$@ ) + suffixes=( "${(@)suffixes:gs.**.*.}" ) + + # In the loop the prefixes from the `tmp1' array produced above and + # the suffixes we just built are used to produce possible matches + # via globbing. + + for i in $tmp1; do + tmp2=( $~i/(#l)$~suffixes ) + [[ $#tmp2 -ne 0 ]] && collect=( $collect $i ) + done + + # If this test showed that none of the matches from the glob in `tmp1' + # has a possible sub-path matching what's on the line, we give up and + # continue with the next `-W' path. + + if [[ $#collect -eq 0 ]]; then + continue 2 + elif [[ $#collect -ne 1 ]]; then + # If we have more than one possible match, this means that the + # pathname component currently handled is ambiguous, so we give + # it to the completion code. + # First we build the full path prefix in `tmp1'. + + tmp1="$prepath$realpath$testpath" + + # Now produce all matching pathnames in `collect'. + + collect=( $~collect/(#l)$~suffixes ) + + # And then remove the common path prefix from all these matches. + + collect=( ${collect#$tmp1} ) + + # Finally, we add all these matches with the common (unexpanded) + # pathprefix (the `-p' option), the path-prefix (the `-W' option) + # to allow the completion code to test file type, and the path- + # suffix (the `-s' option). We also tell the completion code that + # these are file names and that `fignore' should be used as usual + # (the `-f' and `-F' options). + + for i in $collect; do + compadd -p "$linepath$testpath" -W "$tmp1" -s "/${i#*/}" -f "$ignore[@]" - "${i%%/*}" + done + + # We have just finished handling all the matches from above, so we + # can continue with the next `-W' path. + + continue 2 + fi + # We reach this point if only one of the path prefixes in `tmp1' + # has a existing path-suffix matching the string from the line. + # In this case we accept this match and continue with the next + # path-name component. + + tmp1=( "$collect[1]" ) + fi + # This is also reached if the first globbing produced only one match + # in this case we just continue with the next pathname component, too. + + tmp1="$tmp1[1]" + testpath="$testpath${tmp1##*/}/" + str="$rest" + done + + # We are here if all pathname components except the last one (which is still + # not tested) are unambiguous. So we add matches with the full path prefix, + # no path suffix, the `-W' we are currently handling, all the matches we + # can produce in this directory, if any. + + tmp1="$prepath$realpath$testpath" + suffixes=( $str$@ ) + suffixes=( "${(@)suffixes:gs.**.*.}" ) + tmp2=( $~tmp1(#l)$~suffixes ) + compadd -p "$linepath$testpath" -W "$prepath$realpath$testpath" -f "$ignore[@]" - ${tmp2#$tmp1} +done diff --git a/Functions/Completion/_pdf b/Functions/Completion/_pdf new file mode 100644 index 000000000..7d7756c3e --- /dev/null +++ b/Functions/Completion/_pdf @@ -0,0 +1,3 @@ +function acroread + +_files -g '*.(pdf|PDF)' diff --git a/Functions/Completion/_precommand b/Functions/Completion/_precommand new file mode 100644 index 000000000..2cf661147 --- /dev/null +++ b/Functions/Completion/_precommand @@ -0,0 +1,5 @@ +#defcomp - nohup nice eval time rusage noglob nocorrect exec + +[[ -position 1 -1 ]] + +_normal "$@" diff --git a/Functions/Completion/_ps b/Functions/Completion/_ps new file mode 100644 index 000000000..6bc0643b2 --- /dev/null +++ b/Functions/Completion/_ps @@ -0,0 +1,3 @@ +#defcomp gs ghostview gview psnup psselect pswrap pstops pstruct lpr + +_files -g '*([pP][sS]|eps)' diff --git a/Functions/Completion/_rcs b/Functions/Completion/_rcs new file mode 100644 index 000000000..537db6278 --- /dev/null +++ b/Functions/Completion/_rcs @@ -0,0 +1,9 @@ +#defcomp co ci rcs + +[[ $COMMAND = ci || $COMMAND = rcs ]] && _files + +if [[ $NMATCHES -eq 0 && -d RCS && $COMMAND != ci ]]; then + local rep + rep=(RCS/$PREFIX*$SUFFIX,v(:t:s/\,v//)) + (( $#rep )) && compadd -m $rep +fi diff --git a/Functions/Completion/_rlogin b/Functions/Completion/_rlogin new file mode 100644 index 000000000..e36554f23 --- /dev/null +++ b/Functions/Completion/_rlogin @@ -0,0 +1,9 @@ +#defcomp rlogin rsh ssh + +if [[ -position 1 ]]; then + complist -k hosts +elif [[ -position 2 ]]; then + complist -k '(-l)' +else + complist -u +fi diff --git a/Functions/Completion/_sched b/Functions/Completion/_sched new file mode 100644 index 000000000..ee785879b --- /dev/null +++ b/Functions/Completion/_sched @@ -0,0 +1,3 @@ +#defcomp sched + +[[ -position 2 -1 ]] && compsub diff --git a/Functions/Completion/_set b/Functions/Completion/_set new file mode 100644 index 000000000..e3069f134 --- /dev/null +++ b/Functions/Completion/_set @@ -0,0 +1,7 @@ +#defcomp set + +if [[ -mcurrent -1 [-+]o ]]; then + complist -o +elif [[ -current -1 -A ]]; then + complist -A +fi diff --git a/Functions/Completion/_setopt b/Functions/Completion/_setopt new file mode 100644 index 000000000..4abb3ccee --- /dev/null +++ b/Functions/Completion/_setopt @@ -0,0 +1,7 @@ +#defcomp setopt + +local nm=$NMATCHES + +complist -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' \ + -s '$({ unsetopt kshoptionprint; unsetopt } 2>/dev/null)' +[[ -nmatches nm ]] && complist -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' -o diff --git a/Functions/Completion/_source b/Functions/Completion/_source new file mode 100644 index 000000000..94e3fbeb1 --- /dev/null +++ b/Functions/Completion/_source @@ -0,0 +1,7 @@ +#defcomp source + +if [[ -position 2 -1 ]]; then + compsub +else + _files +fi diff --git a/Functions/Completion/_strip b/Functions/Completion/_strip new file mode 100644 index 000000000..6962ac455 --- /dev/null +++ b/Functions/Completion/_strip @@ -0,0 +1,2 @@ +#defcomp strip +_files -g '*(*)' diff --git a/Functions/Completion/_stty b/Functions/Completion/_stty new file mode 100644 index 000000000..6b54b5007 --- /dev/null +++ b/Functions/Completion/_stty @@ -0,0 +1,16 @@ +#defcomp stty + +if [[ -mcurrent -1 \ + (*erase|discard|status|dsusp|intr|kill|lnext|quit|reprint|start|s*p) ]] +then + compadd -m -Q '^-' '^h' '^?' '^c' '^u' +else + [[ -string '-' || -string '+' ]] + compadd -m rows columns intr quit erase kill eof eol \ + eol2 start stop susp dsusp reprint discard werase lnext \ + parenb parodd cs8 cstopb hupcl cread clocal parext \ + ignbrk brkint ignpar parmrk inpck istrip inlcr igncr icrnl iuclc \ + ixon ixany ixoff imaxbel isig icanon xcase echo echoe echok \ + echonl noflsh tostop echoctl echoprt echoke flusho pending iexten \ + opost olcuc onlcr ocrnl onocr onlret ofill ofdel +fi diff --git a/Functions/Completion/_subscript b/Functions/Completion/_subscript new file mode 100644 index 000000000..2b827a117 --- /dev/null +++ b/Functions/Completion/_subscript @@ -0,0 +1,4 @@ +#defcomp -subscript- + +_compalso -math- "$@" +[[ ${(Pt)${COMMAND}} = assoc* ]] && complist -k "( ${(kP)${COMMAND}} )" diff --git a/Functions/Completion/_tar b/Functions/Completion/_tar new file mode 100644 index 000000000..91767e44d --- /dev/null +++ b/Functions/Completion/_tar @@ -0,0 +1,11 @@ +#defcomp tar + +local nm=$NMATCHES tf="$2" + +if [[ ( -mword 1 *t*f* || -mword 1 *x*f* ) && -position 3 100000 ]]; then + complist -k "( $(tar tf $tf) )" +elif [[ -mword 1 *c*f* && -position 3 100000 ]]; then + _files +elif [[ -mcurrent -1 *f* && -position 2 ]]; then + _files -g '*.(tar|TAR)' +fi diff --git a/Functions/Completion/_tex b/Functions/Completion/_tex new file mode 100644 index 000000000..1f645e2a2 --- /dev/null +++ b/Functions/Completion/_tex @@ -0,0 +1,3 @@ +#defcomp tex latex slitex + +_files -g '*.(tex|TEX|texinfo|texi)' diff --git a/Functions/Completion/_trap b/Functions/Completion/_trap new file mode 100644 index 000000000..59e81c589 --- /dev/null +++ b/Functions/Completion/_trap @@ -0,0 +1,7 @@ +#defcomp trap + +if [[ -position 1 ]]; then + complist -c +else + complist -k signals +fi diff --git a/Functions/Completion/_uncompress b/Functions/Completion/_uncompress new file mode 100644 index 000000000..e25805d50 --- /dev/null +++ b/Functions/Completion/_uncompress @@ -0,0 +1,3 @@ +#defcomp uncompress zmore + +_files -g '*.Z' diff --git a/Functions/Completion/_unhash b/Functions/Completion/_unhash new file mode 100644 index 000000000..fe40c25a2 --- /dev/null +++ b/Functions/Completion/_unhash @@ -0,0 +1,6 @@ +#defcomp unhash + +[[ -mword 1 -*d* ]] && complist -n +[[ -mword 1 -*a* ]] && complist -a +[[ -mword 1 -*f* ]] && complist -F +[[ ! -mword 1 -* ]] && complist -m diff --git a/Functions/Completion/_unsetopt b/Functions/Completion/_unsetopt new file mode 100644 index 000000000..90d642b51 --- /dev/null +++ b/Functions/Completion/_unsetopt @@ -0,0 +1,7 @@ +#defcomp unsetopt + +local nm=$NMATCHES + +complist -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' \ + -s '$({ unsetopt kshoptionprint; setopt } 2>/dev/null)' +[[ -nmatches nm ]] && complist -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' -o diff --git a/Functions/Completion/_vars b/Functions/Completion/_vars new file mode 100644 index 000000000..7153b6f38 --- /dev/null +++ b/Functions/Completion/_vars @@ -0,0 +1,3 @@ +#defcomp -math- getopts read unset vared + +complist -v diff --git a/Functions/Completion/_vars_eq b/Functions/Completion/_vars_eq new file mode 100644 index 000000000..fcbb0148c --- /dev/null +++ b/Functions/Completion/_vars_eq @@ -0,0 +1,3 @@ +#defcomp declare export integer local readonly typeset + +complist -v -q -S '=' diff --git a/Functions/Completion/_wait b/Functions/Completion/_wait new file mode 100644 index 000000000..34bc53ee3 --- /dev/null +++ b/Functions/Completion/_wait @@ -0,0 +1,4 @@ +#defcomp wait + +complist -P '%' -j +complist -y _kill_helper -s '`ps 2>/dev/null | tail +2 | cut -c1-5`' diff --git a/Functions/Completion/_which b/Functions/Completion/_which new file mode 100644 index 000000000..324256e3d --- /dev/null +++ b/Functions/Completion/_which @@ -0,0 +1,3 @@ +#defcomp which whence where type + +complist -caF diff --git a/Functions/Completion/_x_options b/Functions/Completion/_x_options new file mode 100644 index 000000000..cc469286d --- /dev/null +++ b/Functions/Completion/_x_options @@ -0,0 +1,5 @@ +#defpatcomp */X11/* + +# A simple pattern completion, just as an example. + +complist -J options -k '(-display -name -xrm)' diff --git a/Functions/Completion/_xfig b/Functions/Completion/_xfig new file mode 100644 index 000000000..fcd2bba9f --- /dev/null +++ b/Functions/Completion/_xfig @@ -0,0 +1,3 @@ +#defcomp xfig + +_files -g '*.fig' diff --git a/Functions/Completion/_zftp b/Functions/Completion/_zftp new file mode 100644 index 000000000..4ff707cc6 --- /dev/null +++ b/Functions/Completion/_zftp @@ -0,0 +1,50 @@ +#defpatcomp zf* + +# Don't try any more completion after this. +COMPSKIP=1 + +# Completion for zftp builtin and zf* functions. The functions +# zfcd_match and zfget_match (used for old-style completion) +# need to be installed for remote file and directory completion to work. + +local subcom + +if [[ $COMMAND = zftp ]]; then + if [[ $CURRENT -eq 1 ]]; then + compadd -m open params user login type ascii binary mode put \ + putat get getat append appendat ls dir local remote mkdir rmdir + return + fi + subcom=$1 +else + subcom=$COMMAND +fi + +case $subcom in + *(cd|ls|dir)) + # complete remote directories; we could be smarter about hiding prefixes + zfcd_match $PREFIX $SUFFIX + (( $#reply )) && compadd -m -S/ -q $reply + ;; + + *(get(|at)|gcp|delete|remote)) + # complete remote files + zfget_match $PREFIX $SUFFIX + (( $#reply )) && compadd -F fignore -m $reply + ;; + + *(put(|at)|pcp)) + # complete local files + _files + ;; + + *(open|anon|params)) + # complete hosts: should do cleverer stuff with user names + complist -k hosts + ;; + + *) + # dunno... try ordinary completion after all. + unset COMPSKIP + ;; +esac diff --git a/Functions/Completion/_zle b/Functions/Completion/_zle new file mode 100644 index 000000000..bb1102e74 --- /dev/null +++ b/Functions/Completion/_zle @@ -0,0 +1,7 @@ +#defcomp zle + +if [[ -word 1 -N && -position 3 ]]; then + complist -F +else + complist -b +fi diff --git a/Functions/Completion/_zmodload b/Functions/Completion/_zmodload new file mode 100644 index 000000000..112acb57c --- /dev/null +++ b/Functions/Completion/_zmodload @@ -0,0 +1,9 @@ +#defcomp zmodload + +if [[ -mword 1 -*(a*u|u*a)* || -mword 1 -*a* && -position 3 -1 ]]; then + complist -B +elif [[ -mword 1 -*u* ]]; then + complist -s '$(zmodload)' +else + complist -s '${^module_path}/*(N:t:r)' +fi diff --git a/Functions/Completion/dump b/Functions/Completion/dump new file mode 100644 index 000000000..ad5547bea --- /dev/null +++ b/Functions/Completion/dump @@ -0,0 +1,89 @@ +# This is a file to be sourced to dump the definitions for new-style +# completion defined by 'init' in the same directory. For best results, +# it should be run immediately after init, before any of the completions +# have been autoloaded. The output should be directed into the "init.dump" +# in the same directory as init. If you rename init, just stick .dump onto +# the end of whatever you have called it and put it in the same directory. +# +# You will need to update the dump every time you add a new completion. +# To do this, simply remove the .dump file, start a new shell, and +# create the .dump file as before. +# +# It relies on KSH_ARRAYS not being set. + +# Print the number of files used for completion. This is used in init +# to see if auto-dump should re-dump the dump-file. + +_d_file=${COMPDUMP-${0:h}/init.dump} + +_d_files=( ${^~fpath}/_*~*~ ) + +print "#files: $#_d_files" > $_d_file + +unset _d_files + +# First dump the arrays comps and patcomps. The quoting hieroglyphyics +# ensure that a single quote inside a variable is itself correctly quoted. + +print "comps=(" >> $_d_file +for _d_f in ${(k)comps}; do + print -r - "'${_d_f//\'/'\\''}'" "'${comps[$_d_f]//\'/'\\''}'" +done >> $_d_file +print ")" >> $_d_file + +if (( $#patcomps )); then + print "\npatcomps=(" >> $_d_file + for _d_f in "$patcomps[@]"; do + print -r - "'${_d_f//\'/'\\''}'" + done >> $_d_file + print ")" >> $_d_file +fi + +print >> $_d_file + +# Now dump the key bindings. We dump all bindings for zle widgets +# whose names start with a underscore. +# We need both the zle -C's and the bindkey's to recreate. + +_d_bks=() +zle -lL | + while read -rA _d_line; do + if [[ ${_d_line[5]} = _* ]]; then + print -r - ${_d_line} + _d_bks=($_d_bks ${_d_line[3]}) + fi + done >> $_d_file +bindkey | + while read -rA _d_line; do + if [[ ${_d_line[2]} = (${(j.|.)~_d_bks}) ]]; then + print -r "bindkey '${_d_line[1][2,-2]}' ${_d_line[2]}" + fi + done >> $_d_file + +print >> $_d_file + + +# Autoloads: whence -w produces "_d_foo: function", so look for +# all functions beginning with `_'. + +_d_als=($(whence -wm '_*' | +while read -rA _d_line; do + [[ ${_d_line[2]} = function ]] && print -r - ${_d_line[1]%:} +done)) + +# print them out: about six to a line looks neat + +while (( $#_d_als )); do + print -n autoload + for (( _i = 0; _i < 6; _i++ )); do + if (( $#_d_als )); then + print -n " $_d_als[1]" + shift _d_als + fi + done + print +done >> $_d_file + +print >> $_d_file + +unset _d_line _d_zle _d_bks _d_als _d_f _f_file diff --git a/Functions/Completion/init b/Functions/Completion/init index a40c5f61b..35e7f6a3c 100644 --- a/Functions/Completion/init +++ b/Functions/Completion/init @@ -3,34 +3,22 @@ # directory that will automatically be made autoloaded (see the end of this # file). # The names of the files that will be considered for autoloading have to -# start with two underscores (like `__setopt). +# start with a underscores (like `_setopt). # The first line of these files will be read and has to say what should be # done with its contents: # -# `#function <names ...>' +# `#defcomp <names ...>' # if the first line looks like this, the file is # autoloaded as a function and that function will # be called to generate the matches when completing # for one of the commands whose <name> is given # -# `#array <names ...>' -# with a first line like this, the filename is taken as -# the name of an array; when trying to generate matches -# for the command <name>, the file will be sourced and -# should define this array, the builtin `complist' will -# then be called with the elements of this array as its -# arguments; this is intended for simple definitions -# for which you don't need a shell function -# -# `#pattern-function <pattern>' +# `#defpatcomp <pattern>' # this defines a function that should be called to generate # matches for commands whose name matches <pattern>; note # that only one pattern may be given # -# `#pattern-array <pattern>' -# like `#pattern-function' but defining an array -# -# `#key-function <style> [ <key-sequence> ... ] +# `#defkeycomp <style> [ <key-sequence> ... ] # this is used to bind special completions to all the given # <key-sequence>(s). The <style> is the name of one of the built-in # completion widgets (complete-word, delete-char-or-list, @@ -41,45 +29,47 @@ # rather than by the context. The widget has the same name as # the autoload file and can be bound using bindkey in the normal way. # -# `#key-array <style> [ <key-sequence> ... ] -# like `#key-function', but defining an array instead -# -# `#helper' +# `#autoload' # this is for helper functions that are not used to # generate matches, but should automatically be loaded # when they are called # # Note that no white space is allowed between the `#' and the rest of # the string. +# +# See the file `dump' for how to speed up initialiation. +# If we got the `-d'-flag, we will automatically dump the new state (at +# the end). -# An associative array for completions definitions. The keys of the entries -# are the names of the command, the values are names of functions or variables -# that are to be used to generate the matches. -# Pattern completions will be stored in an normal array named `patcomps'. -# Completion definitions bound directly to keys are stored in an assoc array -# named `keycomps'. +if [[ "$1" = -d ]]; then + _i_autodump=1 +else + _i_autodump=0 +fi + +# The associative array containing the definitions for the commands. +# Definitions for patterns will be stored in the normal array `patcomps'. typeset -A comps -typeset -A keycomps # This may be used to define completion handlers. The first argument is the -# name of the function or variable containing the definition, the other -# arguments are the command names for which this definition should be used. -# With only one argument the function/variable-name __$1 is used. +# name of the function containing the definition, the other arguments are the +# command names for which this definition should be used. +# With only one argument the function/variable-name _$1 is used. # If given the `-a' option, the function is defined as being autoloaded. defcomp() { - local name autol='' + local name if [[ "$1" = -a ]]; then shift autol=yes fi if [[ $# -eq 1 ]]; then - comps[$1]="__$1" - [[ -z "$autol" ]] || autoload "__$1" + comps[$1]="_$1" + [[ -z "$autol" ]] || autoload "_$1" else name="$1" shift @@ -90,10 +80,9 @@ defcomp() { fi } - # Almost like `defcomp', but this always gets two arguments: the name of a -# variable or function describing what should be completed and the pattern -# that will be compared to the command names for which completion is attempted. +# function describing what should be completed and the pattern that will be +# compared to the command names for which completion is attempted. defpatcomp() { if [[ "$1" = -a ]]; then @@ -101,13 +90,12 @@ defpatcomp() { autoload "$1" fi if (( $+patcomps )) then - patcomps=("$patcomps[@]" "$2 $1" ) + patcomps=("$patcomps[@]" "$2 $1") else - patcomps=( "$2 $1" ) + patcomps=("$2 $1") fi } - # This is used to define completion handlers directly bound to keys. The # first argument is as for `defcomp', giving the handler. The second # argument is the name of one of the built-in completion widgets. Any @@ -122,15 +110,10 @@ defkeycomp() { if [[ "$1" = -a ]]; then shift autoload "$1" - name="$1" - elif [[ "${1[1]}" = ' ' ]]; then - name="${1:t}" - else - name="$1" fi - keycomps[$name]="$1" + name="$1" shift - zle -C "$name" "$1" __main_key_complete + zle -C "$name" "$1" "$name" shift while (( $# )); do bindkey "$1" "$name" @@ -138,116 +121,101 @@ defkeycomp() { done } -# These can be used to easily save and restore the state of the special -# variables used by the completion code. - -alias compsave='local _oprefix _oiprefix _oargv _ocurrent; \ - _oprefix="$PREFIX"; \ - _oiprefix="$IPREFIX"; \ - _oargv=( "$@" ); \ - _ocurrent="$CURRENT"' -alias compreset='PREFIX="$_oprefix"; \ - IPREFIX="$_oiprefix"; \ - argv=( "$_oargv[@]" ); \ - CURRENT="$_ocur"' - - -# This is an easy way to get completion for sub-commands. - -alias compsub='__normal "$@" || return 1' - - # This searches $1 in the array for normal completions and calls the result. -compalso() { +_compalso() { local tmp tmp="$comps[$1]" - [[ -z "$tmp" ]] || callcomplete comps "$1" "$@" + [[ -z "$tmp" ]] || "$tmp" "$@" } +# These can be used to easily save and restore the state of the special +# variables used by the completion code. -# This generates matches. The first argument is the name of one of the -# arrays containing completion definitions. The second argument is the index -# into this array. The other arguments are the positional parameters to give -# to the completion function (containing the arguments from the command line). - -callcomplete() { - local file def +alias _compsave='local _oprefix$_level _oiprefix$_level _oargv$_level _ocurrent$_level _ocommand$_level _ocontext$_level; \ + eval "_oprefix${_level}=\"\$PREFIX\"; \ + _oiprefix${_level}=\"\$IPREFIX\"; \ + _oargv${_level}=( \"\$@\" ); \ + _ocurrent${_level}=\"\$CURRENT\"; \ + _ocommand${_level}=\"\$COMMAND\"; \ + _ocontext${_level}=\"\$CONTEXT\""' +alias _compreset='eval "PREFIX=\"\$_oprefix${_level}\"; \ + IPREFIX=\"\$_oiprefix${_level}\"; \ + argv=( \"\$_oargv${_level}[@]\" ); \ + CURRENT=\"\$_ocur${_level}\"; \ + COMMAND=\"\$_ocommand${_level}\"; \ + CONTEXT=\"\$_ocontext${_level}\""' - # Get the definition from the array. +# These can be used to build tests that modify the special parameters +# without having to reset them by hand. - eval "def=\$${1}[${2}]" +alias _if='(( $+_level )) || local _level=0; (( _level++ )); _compsave; if' +alias _elif='_compreset; elif' +alias _else='_compreset; else' +alias _fi='_compreset; fi; unset _oprefix$_level _oiprefix$_level _oargv$_level _ocurrent$_level _ocommand$_level _ocontext$_level; (( _level-- ))' - # If the definition starts with a space then this means that we should - # source a file to get the definition for an array. - if [[ "$def[1]" = ' ' ]]; then - # The definition starts with a space, so source the file and change - # the definition. +# Now we automatically make the definition files autoloaded. - file="$def[2,-1]" - builtin . "$file" - def="${file:t}" - eval "${1}[${2}]=$def" - fi +# First we get the name of a dump file if this will be used. - # Get rid of the array-name and -index. +: ${COMPDUMP:=$0.dump} - shift 2 - if [[ ${(P)+def} -eq 1 ]]; then - # It is a parameter name, call complist directly. +_i_files=( ${^~fpath}/_*~*~ ) +_i_initname=$0 +_i_done='' - complist "${(@P)def}" - else - # Otherwise it's a function name, call this function. +# If we have a dump file, load it. - "$def" "$@" +if [[ -f "$COMPDUMP" ]]; then + read -rA _i_line < "$COMPDUMP" + if [[ _i_autodump -eq 1 || $_i_line[2] -eq $#_i_files ]]; then + builtin . "$COMPDUMP" + _i_done=yes fi -} + unset _i_line +fi +if [[ -z "$_i_done" ]]; then + + for _i_dir in $fpath; do + [[ $_i_dir = . ]] && continue + for _i_file in $_i_dir/_*~*~(N); do + read -rA _i_line < $_i_file + _i_tag=$_i_line[1] + shift _i_line + if [[ $_i_tag = '#defcomp' ]]; then + defcomp -a ${_i_file:t} "${_i_line[@]}" + elif [[ $_i_tag = '#defpatcomp' ]]; then + defpatcomp -a "${_i_file:t}" "${_i_line[@]}" + elif [[ $_i_tag = '#defkeycomp' ]]; then + defkeycomp -a "${_i_file:t}" "${_i_line[@]}" + elif [[ $_i_tag = '#autoload' ]]; then + autoload ${_i_file:t} + fi + done + done + + bindkey | + while read -rA _i_line; do + if [[ "$_i_line[2]" = complete-word || + "$_i_line[2]" = delete-char-or-list || + "$_i_line[2]" = expand-or-complete || + "$_i_line[2]" = expand-or-complete-prefix || + "$_i_line[2]" = list-choices || + "$_i_line[2]" = menu-complete || + "$_i_line[2]" = menu-expand-or-complete || + "$_i_line[2]" = reverse-menu-complete ]]; then + zle -C _complete_$_i_line[2] $_i_line[2] _main_complete + bindkey "${_i_line[1][2,-2]}" _complete_$_i_line[2] + fi + done + unset _i_dir _i_line _i_file _i_tag -# Now we make the files automatically autoloaded. - -local dir file line func - -for dir in $fpath; do - [[ $dir = . ]] && continue - for file in $dir/__*~*~(N); do - read -rA line < $file - func=$line[1] - shift line - if [[ $func = '#function' ]]; then - defcomp -a ${file:t} "${line[@]}" - elif [[ $func = '#array' ]]; then - defcomp " $file" "${line[@]}" - elif [[ $func = '#pattern-function' ]]; then - defpatcomp -a ${file:t} "${line[@]}" - elif [[ $func = '#pattern-array' ]]; then - defcomp " $file" "${line[@]}" - elif [[ $func = '#key-function' ]]; then - defkeycomp -a "${file:t}" "${line[@]}" - elif [[ $func = '#key-array' ]]; then - defkeycomp " $file" "${line[@]}" - elif [[ $func = '#helper' ]]; then - autoload ${file:t} - fi - done -done - - -# Finally we make all this be called by changing the key bindings. - -bindkey | while read -A line; do - if [[ "$line[2]" = complete-word || - "$line[2]" = delete-char-or-list || - "$line[2]" = expand-or-complete || - "$line[2]" = expand-or-complete-prefix || - "$line[2]" = list-choices || - "$line[2]" = menu-complete || - "$line[2]" = menu-expand-or-complete || - "$line[2]" = reverse-menu-complete ]]; then - zle -C __complete_$line[2] $line[2] __main_complete - bindkey "${line[1][2,-2]}" __complete_$line[2] - fi - done + # if autodumping was requested, do it now. + + (( _i_autodump )) && builtin . ${_i_initname:h}/dump +fi + +unset _i_files _i_initname _i_done _i_autodump |