1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-09-01 09:41:44 +02:00

Updated from list as far as 10376

This commit is contained in:
Peter Stephenson 2000-04-01 20:43:43 +00:00
parent 20c5fbe688
commit e025336f2f
97 changed files with 17816 additions and 3876 deletions

7000
ChangeLog

File diff suppressed because it is too large Load diff

View file

@ -3,386 +3,345 @@
# Complete the arguments of the current command according to the
# descriptions given as arguments to this function.
local long args rest ws cur nth def nm expl descr action opt arg tmp
local long cmd="$words[1]" descr mesg subopts opt usecc autod
local oldcontext="$curcontext" hasopts
# Associative arrays used to collect information about the options.
long=$argv[(I)--]
if (( long )); then
local name tmp tmpargv
typeset -A opts mopts dopts dmopts odopts odmopts
if [[ long -eq 1 ]]; then
tmpargv=()
else
tmpargv=( "${(@)argv[1,long-1]}" )
fi
# See if we support long options, too.
name=${~words[1]}
[[ "$name" != /* ]] && tmp="$PWD/$name"
nth=$argv[(I)--]
if (( nth )); then
long=( "${(@)argv[nth+1,-1]}" )
argv=("${(@)argv[1,nth-1]}")
else
long=()
name="_args_cache_${name}"
name="${name//[^a-zA-Z0-9_]/_}"
if (( ! ${(P)+name} )); then
local iopts sopts pattern tmpo cur cache
typeset -U lopts
cache=()
# We have to build a new long-option cache, get the `-i' and
# `-s' options.
set -- "${(@)argv[long+1,-1]}"
iopts=()
sopts=()
while [[ "$1" = -[is]* ]]; do
if [[ "$1" = -??* ]]; then
tmp="${1[3,-1]}"
cur=1
else
tmp="$2"
cur=2
fi
if [[ "$tmp[1]" = '(' ]]; then
tmp=( ${=tmp[2,-2]} )
else
tmp=( "${(@P)tmp}" )
fi
if [[ "$1" = -i* ]]; then
iopts=( "$iopts[@]" "$tmp[@]" )
else
sopts=( "$sopts[@]" "$tmp[@]" )
fi
shift cur
done
# Now get the long option names by calling the command with `--help'.
# The parameter expansion trickery first gets the lines as separate
# array elements. Then we select all lines whose first non-blank
# character is a hyphen. Since some commands document more than one
# option per line, separated by commas, we convert commas int
# newlines and then split the result again at newlines after joining
# the old array elements with newlines between them. Then we select
# those elements that start with two hyphens, remove anything up to
# those hyphens and anything from the space or comma after the
# option up to the end.
lopts=("--${(@)^${(@)${(@)${(@M)${(@ps:\n:j:\n:)${(@)${(@M)${(@f)$(_call options ${~words[1]} --help 2>&1)//\[--/
--}:#[ ]#-*}//,/
}}:#[ ]#--*}#*--}%%[], ]*}:#}")
lopts=( "${(@)lopts:#--}" )
# Now remove all ignored options ...
while (( $#iopts )); do
lopts=( ${lopts:#$~iopts[1]} )
shift iopts
done
# ... and add "same" options
while (( $#sopts )); do
lopts=( $lopts ${lopts/$sopts[1]/$sopts[2]} )
shift 2 sopts
done
# Then we walk through the descriptions plus a few builtin ones.
set -- "$@" '*=FILE*:file:_files' \
'*=(DIR|PATH)*:directory:_files -/' '*: :'
while (( $# )); do
# First, we get the pattern and the action to use and take them
# from the positional parameters.
pattern="${${${(M)1#*[^\\]:}[1,-2]}//\\\\:/:}"
descr="${1#${pattern}}"
shift
# We get all options matching the pattern and take them from the
# list we have built. If no option matches the pattern, we
# continue with the next.
tmp=("${(@M)lopts:##$~pattern}")
lopts=("${(@)lopts:##$~pattern}")
(( $#tmp )) || continue
opt=''
# If there are option strings with a `[=', we take these get an
# optional argument.
tmpo=("${(@M)tmp:#*\[\=*}")
if (( $#tmpo )); then
tmp=("${(@)tmp:#*\[\=*}")
tmpo=("${(@)${(@)tmpo%%\=*}//[^a-z0-9-]}")
if [[ "$descr" = ::* ]]; then
cache=( "$cache[@]" "${(@)^tmpo}=${descr}" )
else
cache=( "$cache[@]" "${(@)^tmpo}=:${descr}" )
fi
fi
# Descriptions with `=': mandatory argument.
tmpo=("${(@M)tmp:#*\=*}")
if (( $#tmpo )); then
tmp=("${(@)tmp:#*\=*}")
tmpo=("${(@)${(@)tmpo%%\=*}//[^a-z0-9-]}")
cache=( "$cache[@]" "${(@)^tmpo}=${descr}" )
fi
# Everything else is just added as a option without arguments.
if (( $#tmp )); then
tmp=("${(@)tmp//[^a-zA-Z0-9-]}")
cache=( "$cache[@]" "$tmp[@]" )
fi
done
eval "${name}=( \"\${(@)cache:# #}\" )"
fi
set -- "$tmpargv[@]" "${(@P)name}"
fi
# Now parse the arguments...
args=()
nth=1
while (( $# )); do
# This describes a one-shot option.
if [[ "$1" = [-+]* ]]; then
if [[ "$1" = *:* ]]; then
# If the option name ends in a `-', the first argument comes
# directly after the option, if it ends in a `+', the first
# argument *may* come directly after the option, otherwise it
# is in the next word.
if [[ "$1" = [^:]##-:* ]]; then
dopts[${${1%%:*}[1,-2]}]="${1#*:}"
elif [[ "$1" = [^:]##+:* ]]; then
odopts[${${1%%:*}[1,-2]}]="${1#*:}"
else
opts[${1%%:*}]="${1#*:}"
fi
else
opts[$1]=''
fi
elif [[ "$1" = \*[-+]* ]]; then
# The same for options that may appear more than once.
if [[ "$1" = *:* ]]; then
if [[ "$1" = [^:]##-:* ]]; then
dmopts[${${1[2,-1]%%:*}[1,-2]}]="${1#*:}"
elif [[ "$1" = [^:]##+:* ]]; then
odmopts[${${1[2,-1]%%:*}[1,-2]}]="${1#*:}"
else
mopts[${1[2,-1]%%:*}]="${1#*:}"
fi
else
mopts[${1[2,-1]}]=''
fi
elif [[ "$1" = \*:* ]]; then
# This is `*:...', describing `all other arguments'.
rest="${1[3,-1]}"
elif [[ "$1" = :* ]]; then
# This is `:...', describing `the next argument'.
args[nth++]="${1#*:}"
else
# And this is `n:...', describing the `n'th argument.
args[${1%%:*}]="${1#*:}"
nth=$(( ${1%%:*} + 1 ))
fi
shift
subopts=()
while [[ "$1" = -(O*|C) ]]; do
case "$1" in
-C) usecc=yes; shift ;;
-O) subopts=( "${(@P)2}" ); shift 2 ;;
*) subopts=( "${(@P)1[3,-1]}" ); shift ;;
esac
done
if [[ $#long -ne 0 && "$PREFIX" = --* ]]; then
zstyle -s ":completion:${curcontext}:options" auto-description autod
# If the current words starts with `--' and we should use long
# options, just call...
if (( $# )) && comparguments -i "$autod" "$@"; then
local nm="$compstate[nmatches]" action noargs aret expl local
local next direct odirect equal single match matched ws tmp1 tmp2 tmp3
local opts subc prefix suffix
local origpre="$PREFIX" origipre="$IPREFIX"
_long_options "$long[@]"
else
if comparguments -D descr action; then
comparguments -C subc
curcontext="${oldcontext%:*}:$subc"
# Otherwise parse the command line...
ws=( "${(@)words[2,-1]}" )
cur=$(( CURRENT-2 ))
nth=1
# ...until the current word is reached.
while [[ cur -gt 0 ]]; do
# `def' holds the description for the option we are currently after.
# Check if the next argument for the option is optional.
if [[ "$def" = :* ]]; then
opt=yes
if comparguments -O next direct odirect equal; then
opts=yes
_tags arguments options
else
opt=''
_tags arguments
fi
arg=''
# Remove one description/action pair from `def' if that isn't empty.
if [[ -n "$def" ]]; then
if [[ "$def" = ?*:*:* ]]; then
def="${def#?*:*:}"
else
def=''
fi
else
if comparguments -a; then
noargs='no more arguments'
else
# If it is empty, and the word starts with `--' and we should
# complete long options, just ignore this word, otherwise make sure
# we test for options below and handle normal arguments.
if [[ $#long -eq 0 || "$ws[1]" != --* ]]; then
opt=yes
arg=yes
else
def=''
fi
noargs='no arguments'
fi
comparguments -O next direct odirect equal || return 1
if [[ -n "$opt" ]]; then
opts=yes
_tags options
fi
# `opt' was set above if we have to test if the word is an option.
# We first test for the simple options -- those without arguments or
# those whose arguments have to be given as separate words.
while true; do
while _tags; do
if [[ -n "$matched" ]] || _requested arguments; then
_description arguments expl "$descr"
if (( $+opts[$ws[1]] )); then
# Options that may only be given once are removed from the
# associative array so that we are not offered them again.
def="$opts[$ws[1]]"
unset "opts[$ws[1]]"
elif (( $+mopts[$ws[1]] )); then
def="$mopts[$ws[1]]"
else
# If the word is none of the simple options, test for those
# whose first argument has to or may come directly after the
# option. This is done in four loops looking very much alike.
if (( $#dopts )); then
# First we get the option names.
tmp=( "${(@k)dopts}" )
# Then we loop over them and see if the current word begins
# with one of the option names.
while (( $#tmp )); do
[[ "$ws[1]" = ${tmp[1]}* ]] && break
shift 1 tmp
done
if (( $#tmp )); then
# It does. So use the description for it, but only from
# the second argument on, because we are searching the
# description for the next command line argument.
opt=''
def="$dopts[$tmp[1]]"
unset "dopts[$tmp[1]]"
if [[ "$def" = ?*:*:* ]]; then
def="${def#?*:*:}"
else
def=''
fi
if [[ "$action" = -\>* ]]; then
comparguments -W line opt_args
state="${${action[3,-1]##[ ]#}%%[ ]#}"
if [[ -n "$usecc" ]]; then
curcontext="${oldcontext%:*}:$subc"
else
context="$subc"
fi
compstate[restore]=''
aret=yes
else
if [[ -z "$local" ]]; then
local line
typeset -A opt_args
local=yes
fi
fi
if [[ -n "$opt" && $#dmopts -ne 0 ]]; then
tmp=( "${(@k)dmopts}" )
while (( $#tmp )); do
[[ "$ws[1]" = ${tmp[1]}* ]] && break
shift 1 tmp
done
if (( $#tmp )); then
opt=''
def="$dmopts[$tmp[1]]"
if [[ "$def" = ?*:*:* ]]; then
def="${def#?*:*:}"
else
def=''
fi
comparguments -W line opt_args
if [[ "$action" = \ # ]]; then
# An empty action means that we should just display a message.
[[ -n "$matched" ]] && compadd -n -Q -S '' -s "$SUFFIX" - "$PREFIX"
mesg="$descr"
elif [[ "$action" = \(\(*\)\) ]]; then
# ((...)) contains literal strings with descriptions.
eval ws\=\( "${action[3,-3]}" \)
_describe "$descr" ws -M "$match" "$subopts[@]"
elif [[ "$action" = \(*\) ]]; then
# Anything inside `(...)' is added directly.
_all_labels arguments expl "$descr" \
compadd "$subopts[@]" - ${=action[2,-2]}
elif [[ "$action" = \{*\} ]]; then
# A string in braces is evaluated.
while _next_label arguments expl "$descr"; do
eval "$action[2,-2]"
done
elif [[ "$action" = \ * ]]; then
# If the action starts with a space, we just call it.
eval "action=( $action )"
while _next_label arguments expl "$descr"; do
"$action[@]"
done
else
# Otherwise we call it with the description-arguments.
eval "action=( $action )"
_all_labels arguments expl "$descr" \
"$action[1]" "$subopts[@]" "${(@)action[2,-1]}"
fi
fi
if [[ -n "$opt" && $#odopts -ne 0 ]]; then
tmp=( "${(@k)odopts}" )
while (( $#tmp )); do
[[ "$ws[1]" = ${tmp[1]}* ]] && break
shift 1 tmp
done
if (( $#tmp )); then
opt=''
def="$odopts[$tmp[1]]"
unset "odopts[$tmp[1]]"
# For options whose first argument *may* come after the
# option, we skip over the first description only if there
# is something after the option name on the line.
if [[ "$ws[1]" != "$tmp[1]" ]]; then
if [[ "$def" = ?*:*:* ]]; then
def="${def#?*:*:}"
else
def=''
fi
fi
fi
fi
if [[ -n "$opt" && $#odmopts -ne 0 ]]; then
tmp=( "${(@k)odmopts}" )
while (( $#tmp )); do
[[ "$ws[1]" = ${tmp[1]}* ]] && break
shift 1 tmp
done
if (( $#tmp )); then
opt=''
def="$odmopts[$tmp[1]]"
if [[ "$ws[1]" != "$tmp[1]" ]]; then
if [[ "$def" = ?*:*:* ]]; then
def="${def#?*:*:}"
else
def=''
fi
fi
fi
fi
# If we didn't find a matching option description and we were
# told to use normal argument descriptions, just increase
# our counter `nth'.
if [[ -n "$opt" && -n "$arg" ]]; then
def=''
(( nth++ ))
fi
fi
fi
shift 1 ws
(( cur-- ))
if [[ -z "$matched$hasopts" ]] && _requested options &&
{ ! zstyle -T ":completion:${curcontext}:options" prefix-needed ||
[[ "$origpre" = [-+]* ||
( -z "$aret$mesg" && nm -eq compstate[nmatches] ) ]] } ; then
local prevpre="$PREFIX" previpre="$IPREFIX"
hasopts=yes
PREFIX="$origpre"
IPREFIX="$origipre"
comparguments -M match
if comparguments -s single; then
_description options expl option
if [[ "$single" = direct ]]; then
compadd "$expl[@]" -QS '' - "${PREFIX}${SUFFIX}"
elif [[ "$single" = next ]]; then
compadd "$expl[@]" -Q - "${PREFIX}${SUFFIX}"
elif [[ "$single" = equal ]]; then
compadd "$expl[@]" -QqS= - "${PREFIX}${SUFFIX}"
else
tmp1=( "$next[@]" "$direct[@]" "$odirect[@]" "$equal[@]" )
tmp3=( "${(M@)tmp1:#[-+]?[^:]*}" )
tmp1=( "${(M@)tmp1:#[-+]?(|:*)}" )
tmp2=( "${PREFIX}${(@M)^${(@)${(@)tmp1%%:*}#[-+]}:#?}" )
_describe -o option \
tmp1 tmp2 -Q -S '' -- \
tmp3 -Q
fi
single=yes
else
next=( "$next[@]" "$odirect[@]" )
_describe -o option \
next -Q -M "$match" -- \
direct -QS '' -M "$match" -- \
equal -QqS= -M "$match"
fi
PREFIX="$prevpre"
IPREFIX="$previpre"
fi
done
if [[ -n "$opts" && -z "$aret$matched$mesg" &&
nm -eq compstate[nmatches] ]]; then
PREFIX="$origpre"
IPREFIX="$origipre"
prefix="${PREFIX#*\=}"
suffix="$SUFFIX"
PREFIX="${PREFIX%%\=*}"
SUFFIX=''
compadd -M "$match" -D equal - "${(@)equal%%:*}"
if [[ $#equal -eq 1 ]]; then
PREFIX="$prefix"
SUFFIX="$suffix"
IPREFIX="${IPREFIX}${equal[1]%%:*}="
matched=yes
comparguments -L "${equal[1]%%:*}" descr action subc
curcontext="${oldcontext%:*}:$subc"
_tags arguments
continue
fi
fi
break
done
# Now generate the matches.
[[ -z "$aret" || -z "$usecc" ]] && curcontext="$oldcontext"
nm="$compstate[nmatches]"
[[ -n "$aret" ]] && return 300
if [[ -z "$def" || "$def" = :* ]]; then
# We either don't have a description for an argument of an option
# or we have a description for a optional argument.
if [[ -z "$def" ]]; then
# If we have none at all, use the one for this argument position.
def="$args[nth]"
[[ -z "$def" ]] && def="$rest"
fi
# In any case, we have to complete option names here, but we may
# be in a string that starts with an option names and continues with
# the first argument, test that (again, four loops).
opt=yes
if (( $#dopts )); then
# Get the option names.
tmp=( "${(@k)dopts}" )
while (( $#tmp )); do
if compset -P "$tmp[1]"; then
# The current string starts with the option name, so ignore
# that and complete the rest of the string.
def="$dopts[$tmp[1]]"
opt=''
break
fi
shift 1 tmp
done
fi
if [[ -n "$opt" && $#dmopts -ne 0 ]]; then
tmp=( "${(@k)dmopts}" )
while (( $#tmp )); do
if compset -P "$tmp[1]"; then
def="$dmopts[$tmp[1]]"
opt=''
break
fi
shift 1 tmp
done
fi
if [[ -n "$opt" && $#odopts -ne 0 ]]; then
tmp=( "${(@k)odopts}" )
while (( $#tmp )); do
if compset -P "$tmp[1]"; then
def="$odopts[$tmp[1]]"
opt=''
break
fi
shift 1 tmp
done
fi
if [[ -n "$opt" && $#odmopts -ne 0 ]]; then
tmp=( "${(@k)odmopts}" )
while (( $#tmp )); do
if compset -P "$tmp[1]"; then
def="$odmopts[$tmp[1]]"
opt=''
break
fi
shift 1 tmp
done
fi
if [[ -n "$opt" ]]; then
# We aren't in an argument directly after a option name, so
# all option names are possible matches.
_description expl option
compadd "$expl[@]" - "${(@k)opts}" "${(@k)mopts}" \
"${(@k)dopts}" "${(@k)dmopts}" \
"${(@k)odopts}" "${(@k)odmopts}"
fi
fi
# Now add the matches from the description, if any.
if [[ -n "$def" ]]; then
# Ignore the leading colon describing optional arguments.
[[ "$def" = :* ]] && def="$def[2,-1]"
# Get the description and the action.
descr="${def%%:*}"
action="${${def#*:}%%:*}"
_description expl "$descr"
if [[ -z "$action" ]]; then
# An empty action means that we should just display a message.
_message "$descr"
return 1
elif [[ "$action[1]" = \( ]]; then
# Anything inside `(...)' is added directly.
compadd "$expl[@]" - ${=action[2,-2]}
elif [[ "$action" = \ * ]]; then
# If the action starts with a space, we just call it.
$=action
else
# Otherwise we call it with the description-arguments built above.
action=( $=action )
"$action[1]" "$expl[@]" "${(@)action[2,-1]}"
fi
fi
[[ -n "$mesg" ]] && _message "$mesg"
[[ -n "$noargs" ]] && _message "$noargs"
# Set the return value.
[[ nm -ne "$compstate[nmatches]" ]]
[[ nm -ne "$compstate[nmatches]" ]]
else
return 1
fi

View file

@ -1,13 +1,23 @@
#defcomp -default-
#compdef -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'.
local ctl
compcall || return
if { zstyle -s ":completion:${curcontext}:" use-compctl ctl ||
zmodload -e zsh/compctl } && [[ "$ctl" != (no|false|0|off) ]]; then
local opt
_files
opt=()
[[ "$ctl" = *first* ]] && opt=(-T)
[[ "$ctl" = *default* ]] && opt=("$opt[@]" -D)
compcall "$opt[@]" || return 0
fi
_wanted files || return 1
_files && return 0
# magicequalsubst allows arguments like <any-old-stuff>=~/foo to do
# file name expansion after the =. In that case, it's natural to
# allow completion to handle file names after any equals sign.
[[ -o magicequalsubst ]] && compset -P 1 '*=' && _files

View file

@ -2,154 +2,52 @@
# This can be used to add options or values with descriptions as matches.
setopt localoptions extendedglob
local _opt _expl _tmps _tmpd _tmpmd _tmpms _ret=1 _showd _nm _hide _args
local _type=values _descr
local gdescr isopt cmd opt nsets tmp descr match descrs matches adescr i
local disps disp expl tmps tmpd tmpmd tmpms name ret=1 showd _nm
# Get the option.
cmd="$words[1]"
# Get the options.
while getopts 'oc:' opt; do
if [[ "$opt" = o ]]; then
isopt=yes
else
cmd="$OPTARG"
fi
done
shift OPTIND-1
if [[ "$1" = -o ]]; then
_type=options
shift
fi
# Do the tests. `showd' is set if the descriptions should be shown.
if [[ -n "$isopt" ]]; then
_wanted "$_type" || return 1
# We take the value to test the number of patches from a non-local
# parameter `nm' if that exists and contains only digits. It's a hack.
zstyle -T ":completion:${curcontext}:$_type" verbose && _showd=yes
if [[ "$nm" = [0-9]## ]]; then
_nm="$nm"
else
_nm=0
fi
[[ -n "$compconfig[option_prefix]" &&
"$compconfig[option_prefix]" != *\!${cmd}* &&
"$PREFIX" != [-+]* &&
( "$compconfig[option_prefix]" = *nodefault* ||
_nm -ne compstate[nmatches] ) ]] && return 1
[[ -n "$compconfig[describe_options]" &&
"$compconfig[describe_options]" != *\!${cmd}* ]] && showd=yes
else
[[ -n "$compconfig[describe_values]" &&
"$compconfig[describe_values]" != *\!${cmd}* ]] && showd=yes
fi
gdescr="$1"
_descr="$1"
shift
# Now interpret the arguments.
[[ "$_type" = options ]] &&
zstyle -t ":completion:${curcontext}:options" prefix-hidden && _hide=yes
nsets=0
adescr=()
descrs=()
matches=()
while (( $# )); do
(( nsets++ ))
descr="$1"
[[ -n "$showd" ]] && adescr=( "$adescr[@]" "${(@PM)^descr:#*:?*},$nsets" )
if [[ "$2" = -* ]]; then
match=''
shift
while _next_label "$_type" _expl "$_descr"; do
if [[ -n "$_showd" ]]; then
compdescribe -I ' -- ' "$@"
else
match="$2"
shift 2
fi
tmp=$argv[(i)--]
if [[ tmp -eq 1 ]]; then
opt=()
else
opt=( "${(@)argv[1,tmp-1]}" )
fi
if [[ tmp -gt $# ]]; then
argv=()
else
shift tmp
compdescribe -i "$@"
fi
# `descr' and `matches' collect the names of the arrays containing the
# possible matches with descriptions and the matches to add.
# The options to give to `compadd' are stored in local arrays.
while compdescribe -g _args _tmpd _tmpmd _tmps _tmpms; do
descrs[nsets]="$descr"
matches[nsets]="$match"
typeset -a _descr_opts_$nsets
eval "_descr_opts_${nsets}=( \"\$opt[@]\" )"
done
# See if we should remove the option prefix characters.
(( nsets )) || return 1
# Build the display strings if needed.
[[ -n "$showd" ]] && _display disps "$adescr[@]"
_description expl "$gdescr"
# Loop through the array/option sets we have.
i=0
while [[ ++i -le nsets ]]; do
name=_descr_opts_$i
[[ -n "$showd" ]] && disp=( "${(@)${(@M)disps:#*,${i}}%,*}" )
descr=( "${(@P)descrs[i]}" )
# We collect the strings to display in `tmpd' (one string per line)
# and `tmps' (in columns) and the matches to add in `tmpmd' and `tmpms'.
tmpd=()
tmps=()
tmpmd=()
tmpms=()
if [[ -n "$matches[i]" ]]; then
match=( "${(@P)matches[i]}" )
while (( $#match )); do
if [[ -n "$showd" && "$descr[1]" = *:?* ]]; then
tmpd=( "$tmpd[@]" "$disp[1]" )
tmpmd=( "$tmpmd[@]" "$match[1]" )
shift 1 disp
else
tmps=( "$tmps[@]" "${descr[1]%%:*}" )
tmpms=( "$tmpms[@]" "$match[1]" )
if [[ -n "$_hide" ]]; then
if [[ "$PREFIX" = --* ]]; then
_tmpd=( "${(@)_tmpd#--}" )
_tmps=( "${(@)_tmps#--}" )
elif [[ "$PREFIX" = [-+]* ]]; then
_tmpd=( "${(@)_tmpd#[-+]}" )
_tmps=( "${(@)_tmps#[-+]}" )
fi
shift 1 match
shift 1 descr
done
else
while (( $#descr )); do
if [[ -n "$showd" && "$descr[1]" = *:?* ]]; then
tmpd=( "$tmpd[@]" "$disp[1]" )
tmpmd=( "$tmpmd[@]" "${descr[1]%%:*}" )
shift 1 disp
else
tmps=( "$tmps[@]" "${descr[1]%%:*}" )
tmpms=( "$tmpms[@]" "${descr[1]%%:*}" )
fi
shift 1 descr
done
fi
# See if we should remove the option prefix characters.
if [[ -n "$isopt" && "$compconfig[option_prefix]" = hide* ]]; then
if [[ "$PREFIX" = --* ]]; then
tmpd=( "${(@)tmpd#--}" )
tmps=( "${(@)tmps#--}" )
elif [[ "$PREFIX" = [-+]* ]]; then
tmpd=( "${(@)tmpd#[-+]}" )
tmps=( "${(@)tmps#[-+]}" )
fi
fi
compadd "${(@P)name}" "$expl[@]" -ld tmpd - "$tmpmd[@]" && ret=0
compadd "${(@P)name}" "$expl[@]" -d tmps - "$tmpms[@]" && ret=0
done
return ret
compadd "$_args[@]" "$_expl[@]" -ld _tmpd - "$_tmpmd[@]" && _ret=0
compadd "$_args[@]" "$_expl[@]" -d _tmps - "$_tmpms[@]" && _ret=0
done
done
return _ret

View file

@ -1,27 +1,85 @@
#autoload
local expl disp jobs job jids
local expl disp jobs job jids pfx='%' desc how expls
_wanted jobs || return 1
if [[ "$1" = -t ]]; then
zstyle -T ":completion:${curcontext}:jobs" prefix-needed &&
[[ "$PREFIX" != %* && compstate[nmatches] -ne 0 ]] && return 1
shift
fi
zstyle -t ":completion:${curcontext}:jobs" prefix-hidden && pfx=''
zstyle -T ":completion:${curcontext}:jobs" verbose && desc=yes
if [[ "$1" = -r ]]; then
jids=( "${(@k)jobstates[(R)running*]}" )
shift
_description expl 'running job'
expls='running job'
elif [[ "$1" = -s ]]; then
jids=( "${(@k)jobstates[(R)running*]}" )
shift
_description expl 'suspended job'
expls='suspended job'
else
[[ "$1" = - ]] && shift
jids=( "${(@k)jobtexts}" )
_description expl job
expls=job
fi
disp=()
jobs=()
for job in "$jids[@]"; do
disp=( "$disp[@]" "${(l:3:: ::%:)job} -- ${jobtexts[$job]}" )
jobs=( "$jobs[@]" "$job" )
done
if [[ -n "$desc" ]]; then
disp=()
for job in "$jids[@]"; do
[[ -n "$desc" ]] &&
disp=( "$disp[@]" "${pfx}${(r:2:: :)job} -- ${(r:COLUMNS-8:: :)jobtexts[$job]}" )
done
fi
compadd "$@" "$expl[@]" -ld disp - "%$^jobs[@]"
zstyle -s ":completion:${curcontext}:jobs" numbers how
if [[ "$how" = (yes|true|on|1) ]]; then
jobs=( "$jids[@]" )
else
local texts i text str tmp num max=0
# Find shortest unambiguous strings.
texts=( "$jobtexts[@]" )
jobs=()
for i in "$jids[@]"; do
text="$jobtexts[$i]"
str="${text%% *}"
if [[ "$text" = *\ * ]]; then
text="${text#* }"
else
text=""
fi
tmp=( "${(@M)texts:#${str}*}" )
num=1
while [[ -n "$text" && $#tmp -ge 2 ]]; do
str="${str} ${text%% *}"
if [[ "$text" = *\ * ]]; then
text="${text#* }"
else
text=""
fi
tmp=( "${(@M)texts:#${str}*}" )
(( num++ ))
done
[[ num -gt max ]] && max="$num"
jobs=( "$jobs[@]" "$str" )
done
if [[ "$how" = [0-9]## && max -gt how ]]; then
jobs=( "$jids[@]" )
else
[[ -z "$pfx" && -n "$desc" ]] && disp=( "${(@)disp#%}" )
fi
fi
if [[ -n "$desc" ]]; then
_all_labels jobs expl "$expls" compadd "$@" -ld disp - "%$^jobs[@]"
else
_all_labels jobs expl "$expls" compadd "$@" - "%$^jobs[@]"
fi

View file

@ -1,4 +1,56 @@
#defcomp -subscript-
#compdef -subscript-
_compalso -math- "$@"
[[ ${(Pt)${COMMAND}} = assoc* ]] && complist -k "( ${(kP)${COMMAND}} )"
local expl
if [[ "$PREFIX" = :* ]]; then
_wanted characters expl 'character class' \
compadd -p: -S ':]' alnum alpha blank cntrl digit graph \
lower print punct space upper xdigit
elif [[ ${(Pt)${compstate[parameter]}} = assoc* ]]; then
local suf
[[ "$RBUFFER" != \]* ]] && suf=']'
_wanted association-keys expl 'association key' \
compadd -S "$suf" - "${(@kP)${compstate[parameter]}}"
elif [[ ${(Pt)${compstate[parameter]}} = array* ]]; then
local list i j ret=1 disp
_tags indexes parameters
while _tags; do
if _requested indexes; then
ind=( {1..${#${(P)${compstate[parameter]}}}} )
if zstyle -T ":completion:${curcontext}:indexes" verbose; then
list=()
for i in "$ind[@]"; do
if [[ "$i" = ${PREFIX}*${SUFFIX} ]]; then
list=( "$list[@]"
"${i}:$(print -D ${(P)${compstate[parameter]}[$i]})" )
else
list=( "$list[@]" '' )
fi
done
zformat -a list ' -- ' "$list[@]"
disp=( -d list)
else
disp=()
fi
if [[ "$RBUFFER" = \]* ]]; then
_all_labels -V indexes expl 'array index' \
compadd -S '' "$disp[@]" - "$ind[@]" && ret=0
else
_all_labels -V indexes expl 'array index' \
compadd -S ']' "$disp[@]" - "$ind[@]" && ret=0
fi
fi
_requested parameters && _parameters && ret=0
(( ret )) || return 0
done
return 1
else
_compalso -math-
fi

View file

@ -1,10 +1,53 @@
#defcomp -tilde-
#compdef -tilde-
# We use all named directories and user names here. If this is too slow
# for you or if there are too many of them, you may want to use
# `compgen -k friends -qS/' or something like that. To get all user names
# if there are no matches in the `friends' array, add
# `(( compstate[nmatches] )) || compgen -nu -qS/'
# below that.
# `compadd -qS/ - "$friends[@]"' or something like that.
compgen -nu -qS/
local expl suf dirs list lines revlines i ret disp nm="$compstate[nmatches]"
if [[ "$SUFFIX" = */* ]]; then
ISUFFIX="/${SUFFIX#*/}$ISUFFIX"
SUFFIX="${SUFFIX%%/*}"
suf=(-S '')
else
suf=(-qS/)
fi
_tags users named-directories directory-stack
while _tags; do
_requested users && _users "$suf[@]" "$@" && ret=0
_requested named-directories expl 'named directory' \
compadd "$suf[@]" "$@" - "${(@k)nameddirs}"
if _requested directory-stack &&
{ ! zstyle -T ":completion:${curcontext}:directory-stack" prefix-needed ||
[[ "$PREFIX" = [-+]* || nm -eq compstate[nmatches] ]] }; then
if zstyle -T ":completion:${curcontext}:directory-stack" verbose; then
integer i
lines=("${PWD}" "${dirstack[@]}")
if [[ ( -prefix - && ! -o pushdminus ) ||
( -prefix + && -o pushdminus ) ]]; then
revlines=( $lines )
for (( i = 1; i <= $#lines; i++ )); do
lines[$i]="$((i-1)) -- ${revlines[-$i]}"
done
else
for (( i = 1; i <= $#lines; i++ )); do
lines[$i]="$((i-1)) -- ${lines[$i]}"
done
fi
list=( ${PREFIX[1]}${^lines%% *} )
disp=( -ld lines )
else
list=( ${PREFIX[1]}{0..${#dirstack}} )
disp=()
fi
_all_labels -V directory-stack expl 'directory stack' \
compadd "$suf[@]" "$disp[@]" -Q - "$list[@]" && ret=0
fi
(( ret )) || return 0
done

View file

@ -1,322 +1,103 @@
#autoload
setopt localoptions extendedglob
local subopts opt usecc
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
subopts=()
while [[ "$1" = -(O*|C) ]]; do
case "$1" in
-C) usecc=yes; shift ;;
-O) subopts=( "${(@P)2}" ); shift 2 ;;
*) subopts=( "${(@P)1[3,-1]}" ); shift ;;
esac
done
# Probably fill our cache.
if compvalues -i "$@"; then
if [[ "$*" != "$_vals_cache_args" ]]; then
_vals_cache_args="$*"
local noargs args opts descr action expl sep subc
local oldcontext="$curcontext"
unset _vals_cache_{sep,descr,names,onames,snames,xors,odescr}
if ! compvalues -D descr action; then
typeset -gA _vals_cache_{names,onames,xors}
_vals_cache_snames=()
_vals_cache_odescr=()
_wanted values || return 1
# Get the separator, if any.
curcontext="${oldcontext%:*}:values"
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.
compvalues -V noargs args opts
if [[ "$PREFIX" = *\=* ]]; then
PREFIX="${PREFIX%%\=*}"
pre="${pre#*\=}"
SUFFIX=''
else
SUFFIX="${SUFFIX%%\=*}"
pre="${suf#*\=}"
suf=''
fi
local name
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
name="${PREFIX%%\=*}"
if compvalues -L "$name" descr action; then
IPREFIX="${IPREFIX}${name}="
PREFIX="${PREFIX#*\=}"
else
compadd -n -qS= "$expl[@]" -y tmp -M 'r:|[_-]=* r:|=*' - \
"${(@k)onames}" && ret=0
local prefix suffix
prefix="${PREFIX#*\=}"
suffix="$SUFFIX"
PREFIX="$name"
SUFFIX=''
args=( "$args[@]" "$opts[@]" )
compadd -M 'r:|[_-]=* r:|=*' -D args - "${(@)args[@]%%:*}"
[[ $#args -ne 1 ]] && return 1
PREFIX="$prefix"
SUFFIX="$suffix"
IPREFIX="${IPREFIX}${args[1]%%:*}="
compvalues -L "${args[1]%%:*}" descr action subc
curcontext="${oldcontext%:*}:$subc"
fi
else
compvalues -d descr
if [[ ${#noargs}+${#args}+${#opts} -ne 1 ]] && compvalues -s sep; then
sep=( "-qQS" "$sep" )
else
sep=()
fi
_describe "$descr" \
noargs "$sep[@]" -M 'r:|[_-]=* r:|=*' -- \
args -S= -M 'r:|[_-]=* r:|=*' -- \
opts -qS= -M 'r:|[_-]=* r:|=*'
curcontext="$oldcontext"
return
fi
else
compvalues -C subc
curcontext="${oldcontext%:*}:$subc"
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
if ! _tags arguments; then
curcontext="$oldcontext"
return 1
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"
_description arguments 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 ]] &&
[[ ${#snames}+${#names}+${#onames} -ne 1 ]] && compvalues -s sep &&
expl=( "-qS$sep" "$expl[@]" )
if [[ "$action" = -\>* ]]; then
values=( "${(@kv)_values}" )
compvalues -v val_args
state="${${action[3,-1]##[ ]#}%%[ ]#}"
if [[ -n "$usecc" ]]; then
curcontext="${oldcontext%:*}:$subc"
else
context="$subc"
fi
compstate[restore]=''
return 1
else
typeset -A values
typeset -A val_args
values=( "${(@kv)_values}" )
compvalues -v val_args
if [[ "$action" = \ # ]]; then
@ -332,36 +113,44 @@ else
eval ws\=\( "${action[3,-3]}" \)
if _display tmp ws; then
compadd "$expl[@]" -y tmp - "${(@)ws%%:*}"
else
_message "$descr"
return 1
fi
_describe "$descr" ws -M 'r:|[_-]=* r:|=*' "$subopts[@]"
elif [[ "$action" = \(*\) ]]; then
# Anything inside `(...)' is added directly.
compadd "$expl[@]" - ${=action[2,-2]}
_all_labels arguments expl "$descr" \
compadd "$subopts[@]" - ${=action[2,-2]}
elif [[ "$action" = \{*\} ]]; then
# A string in braces is evaluated.
eval "$action[2,-2]"
while _next_label arguments expl "$descr"; do
eval "$action[2,-2]"
done
elif [[ "$action" = \ * ]]; then
# If the action starts with a space, we just call it.
${(e)=~action}
eval "action=( $action )"
while _next_label arguments expl "$descr"; do
"$action[@]"
done
else
# Otherwise we call it with the description-arguments built above.
action=( $=action )
${(e)action[1]} "$expl[@]" ${(e)~action[2,-1]}
eval "action=( $action )"
_all_labels arguments expl "$descr" \
"$action[1]" "$subopts[@]" "${(@)action[2,-1]}"
fi
fi
fi
[[ nm -ne "$compstate[nmatches]" ]]
curcontext="$oldcontext"
[[ nm -ne "$compstate[nmatches]" ]]
else
curcontext="$oldcontext"
return 1;
fi

View file

@ -1,3 +1,10 @@
#defcomp autoload
#compdef autoload
complist -s '${^fpath}/*(N:t)'
local expl
if (( $words[(I)[-+]*w*] )); then
_description files expl 'zwc file'
_files "$expl[@]" -g '*.zwc'
else
_wanted functions expl 'shell function' compadd - ${^fpath}/*(N:t)
fi

View file

@ -1,3 +1,47 @@
#defcomp cd
#compdef cd chdir pushd
_files -W cdpath -g '*(-/)'
# Handling of cd.
# - Normally just completes directories. Uses cdpath if that's set
# and the string doesn't begin with ~, /, ./ or ../.
# - In the second argument to cd for the form `cd old new', completes
# possible `new' strings by examining `old' and $PWD.
# - After - or +, completes numbers, but the listing
# gives you the list of directories to complete. This turns on
# menu-completion and lists the possibilities automatically, otherwise
# it's not a lot of use. If you don't type the + or - it will
# complete directories as normal.
setopt localoptions nonomatch
local expl
if [[ CURRENT -eq 3 ]]; then
# cd old new: look for old in $PWD and see what can replace it
local rep
# Get possible completions using word in position 2
rep=(${~PWD/$words[2]/*}~$PWD(-/N))
# Now remove all the common parts of $PWD and the completions from this
rep=(${${rep#${PWD%%$words[2]*}}%${PWD#*$words[2]}})
(( $#rep )) && _wanted -C replacement strings expl replacement compadd $rep
elif _popd || [[ $PREFIX != (\~|/|./|../)* && $#cdpath -ne 0 ]]; then
local tdir tdir2
# With cdablevars, we can convert foo/bar/... to ~foo/bar/... if
# there is no directory foo. In that case we could also complete
# variable names, but it hardly seems worth it.
# Note we need a tilde because cdablevars also allows user home
# directories, hence we also need nonomatch to suppress error messages.
if [[ -o cdablevars && -n "$PREFIX" && ! -d ${tdir::=${PREFIX%%/*}} &&
-d ${~tdir2::="~$tdir"} ]]; then
PREFIX="~$PREFIX"
_wanted directories expl directory _path_files -/
else
local tmpcdpath
tmpcdpath=(${${(@)cdpath:#.}:#$PWD})
_alternative \
'local-directories:local directories:_path_files -/' \
"path-directories:directories in cdpath:_path_files -W tmpcdpath -/"
fi
else
_wanted directories expl directory _path_files -/
fi

View file

@ -1,22 +1,40 @@
#compdef compdef
local func base=2
local state line expl list disp
while [[ $words[base] = -* ]]; do
case $words[base] in
-d) delete=yes ;;
-p) type=pattern ;;
-k) type=key ;;
esac
(( base++ ))
done
_arguments -C -s \
'(-d)-a[make function autoloadable]' \
'(-d -p -P)-n[leave existing definitions intact]' \
'(-a -n -p -P -k -K)-d[delete]:*:completed command:->ccom' \
'(-n -d -P -k -K)-p[completion for command matching pattern]:completion function:->cfun:pattern' \
'(-n -d -p -k -K)-P[as -p for commands without own completion]:completion function:->cfun:pattern' \
'(-d -p -P -K)-k[define widget and key binding]:completion function:->cfun:widget name::style:->style:*:key' \
'(-d -p -P -k)-K[define multiple widgets based on function]:completion function:->cfun:widget name::style:->style:*:key' \
'1:completion function:->cfun' \
'2:commands:_command_names'
if [ "$delete" ]; then
compadd ${(k)_comps}
else
if [[ CURRENT -eq base ]]; then
for func in ${^~fpath:/.}/_(|*[^~])(N:t); compadd -P_ - ${func#_}
else
compgen -c
fi
fi
case $state in
ccom)
_wanted commands expl 'completed command' compadd - ${(k)_comps}
;;
cfun)
if _wanted functions; then
list=( ${^fpath:/.}/_(|*[^~])(N:t) )
if zstyle -T ":completion:${curcontext}:functions" prefix-hidden; then
disp=( ${list[@]#_} )
_all_labels functions expl 'completion function' \
compadd -d disp - "$list[@]"
else
_all_labels functions expl 'completion function' compadd - "$list[@]"
fi
fi
;;
style)
_wanted widgetstyle expl 'widget style' \
compadd -M 'r:|-=* r:|=*' \
complete-word delete-char-or-list expand-or-complete \
expand-or-complete-prefix list-choices menu-complete \
menu-expand-or-complete reverse-menu-complete
;;
esac

View file

@ -1,6 +1,8 @@
#defcomp disable
#compdef disable
[[ -mcurrent -1 -*a* ]] && complist -ea
[[ -mcurrent -1 -*f* ]] && complist -eF
[[ -mcurrent -1 -*r* ]] && complist -ew
[[ ! -mcurrent -1 -* ]] && complist -eB
_arguments -C -s \
"(-f -r)-a[act on aliases]:*:aliases:(${(k)aliases} ${(k)galiases})" \
"(-a -r)-f[act on functions]:*:functions:(${(k)functions})" \
"(-a -f)-r[act on reserved words]:*:reserved-words:(${(k)reswords})" \
'-m[treat arguments as patterns]' \
"*:builtin command:(${(k)builtins})"

View file

@ -0,0 +1,6 @@
#compdef emulate
_arguments -C -s \
'-L[set local_options and local_traps as well]' \
'-R[reset all options instead of only those needed for script portability]' \
'1::shell to emulate:(zsh sh ksh csh)'

View file

@ -1,6 +1,8 @@
#defcomp enable
#compdef enable
[[ -mcurrent -1 -*a* ]] && complist -da
[[ -mcurrent -1 -*f* ]] && complist -dF
[[ -mcurrent -1 -*r* ]] && complist -dw
[[ ! -mcurrent -1 -* ]] && complist -dB
_arguments -C -s \
"(-f -r)-a[act on aliases]:*:aliases:(${(k)dis_aliases})" \
"(-a -r)-f[act on functions]:*:functions:(${(k)dis_functions})" \
"(-a -f)-r[act on reserved words]:*:reserved-words:(${(k)dis_reswords})" \
'-m[treat arguments as patterns]' \
"*:builtin command:(${(@k)dis_builtins})"

View file

@ -1,7 +1,27 @@
#defcomp fc
#compdef fc history
if [[ -mcurrent -1 -*e ]]; then
complist -c
elif [[ -mcurrent -1 -[ARWI]## ]]; then
_files
local fc_common
fc_common=( \
'(-A -R -W -I)-m[treat first argument as a pattern]' \
'(-A -R -W -I)-r[reverse order of the commands]' \
'(-A -R -W -I -e)-n[suppress line numbers]' \
'(-A -R -W -I -e -f -E -i)-d[print time-stamps]' \
'(-A -R -W -I -e -d -E -i)-f[mm/dd/yyyy format time-stamps]' \
'(-A -R -W -I -e -d -f -i)-E[dd.mm.yyyy format time-stamps]' \
'(-A -R -W -I -e -d -f -E)-i[yyyy-mm-dd format time-stamps]' \
'(-A -R -W -I -e)-D[print elapsed times]' \
'(-A -R -W -I)*::commands:_command_names -e' )
if [[ $words[1] = *history ]]; then
_arguments -C -s "$fc_common[@]"
else
_arguments -C -s \
'(-A -R -W -I -e)-l[list resulting commands on stdout]' \
'(-A -R -W -I -l -n -d -f -E -i -D)-e[specify editor to invoke]:editor to invoke:_command_names -e' \
'(-l -m -e -r -n -d -f -E -i -D -A -W *)-R[read history from file]:history file:_files' \
'(-l -m -e -r -n -d -f -E -i -D -R -W *)-A[append history to file]:history file:_files' \
'(-l -m -e -r -n -d -f -E -i -D -R -A *)-W[write history to file]:history file:_files' \
'(-l -m -e -r -n -d -f -E -i -D -A -W *)-I[read/write new events only]:history file:_files' \
"$fc_common[@]"
fi

View file

@ -1,3 +1,3 @@
#compdef true false
#compdef true false log times whoami
_message 'no argument or option'

View file

@ -3,16 +3,32 @@
# If given the `-m <pattern>' option, this tries to complete only pids
# of processes whose command line match the `<pattern>'.
local list expl match
local out list expl match desc listargs args
_wanted processes || return 1
if [[ "$1" = -m ]]; then
match="${2}*"
shift 2
fi
_description expl 'process ID'
zstyle -s ":completion:${curcontext}:pids" command args
list=("${(@Mr:COLUMNS-1:)${(f@)$(ps ${=compconfig[ps_listargs]:-$=compconfig[ps_args]} 2>/dev/null)}[2,-1]:#[ ]#${PREFIX}[0-9]#${SUFFIX}[ ]*${~match}}")
out="$(_call pids ps 2>/dev/null)"
compadd "$expl[@]" "$@" -ld list - \
${${${(M)${(f)"$(ps $=compconfig[ps_args] 2>/dev/null)"}[2,-1]:#*${~match}}## #}%% *}
if zstyle -T ":completion:${curcontext}:processes" verbose; then
zstyle -s ":completion:${curcontext}:pids-list" command listargs
(( $#listargs )) || listargs=( "$args[@]" )
if [[ "$listargs" = "$args" ]]; then
list=("${(@Mr:COLUMNS-1:)${(f@)out}[2,-1]:#[ ]#${PREFIX}[0-9]#${SUFFIX}[ ]*${~match}}")
else
list=("${(@Mr:COLUMNS-1:)${(f@)$(_call pids-list ps 2>/dev/null)}[2,-1]:#[ ]#${PREFIX}[0-9]#${SUFFIX}[ ]*${~match}}")
fi
desc=(-ld list)
else
desc=()
fi
_all_labels processes expl 'process ID' \
compadd "$@" "$desc[@]" - \
${${${(M)${(f)"${out}"}[2,-1]:#[ ]#${PREFIX}[0-9]#${SUFFIX}[ ]#*${~match}}## #}%% *}

View file

@ -5,36 +5,39 @@
# way round if pushdminus is set). Note that this function is also called
# from _cd for cd and pushd.
emulate -L zsh
setopt extendedglob nonomatch
[[ $PREFIX = [-+]* ]] || return 1
local expl list lines revlines disp
local expl list lines revlines ret=1 i
! zstyle -T ":completion:${curcontext}:directory-stack" prefix-needed ||
[[ $PREFIX = [-+]* ]] || return 1
IPREFIX=$PREFIX[1]
PREFIX=$PREFIX[2,-1]
_wanted directory-stack || return 1
# get the list of directories with their canonical number
# and turn the lines into an array, removing the current directory
lines=( ${${(f)"$(dirs -v)"}##0*} )
if [[ ( $IPREFIX = - && ! -o pushdminus ) ||
( $IPREFIX = + && -o pushdminus ) ]]; then
integer i
revlines=( $lines )
for (( i = 1; i <= $#lines; i++ )); do
lines[$i]="$((i-1)) -- ${revlines[-$i]##[0-9]#[ ]#}"
done
if zstyle -T ":completion:${curcontext}:directory-stack" verbose; then
# get the list of directories with their canonical number
# and turn the lines into an array, removing the current directory
lines=("${dirstack[@]}")
if [[ ( $PREFIX[1] = - && ! -o pushdminus ) ||
( $PREFIX[1] = + && -o pushdminus ) ]]; then
integer i
revlines=( $lines )
for (( i = 1; i <= $#lines; i++ )); do
lines[$i]="$((i-1)) -- ${revlines[-$i]##[0-9]#[ ]#}"
done
else
for (( i = 1; i <= $#lines; i++ )); do
lines[$i]="$i -- ${lines[$i]##[0-9]#[ ]#}"
done
fi
# get the array of numbers only
list=( ${PREFIX[1]}${^lines%% *} )
disp=( -ld lines )
else
for (( i = 1; i <= $#lines; i++ )); do
lines[$i]="$i -- ${lines[$i]##[0-9]#[ ]#}"
done
list=( ${PREFIX[1]}{0..${#dirstack}} )
disp=()
fi
# get the array of numbers only
list=(${lines%% *})
_description expl 'directory stack index'
compadd "$expl[@]" -ld lines -V dirs -Q - "$list[@]" && ret=0
[[ -z $compstate[list] ]] && compstate[list]=list && ret=0
[[ -n $compstate[insert] ]] && compstate[insert]=menu && ret=0
return ret
_all_labels -V directory-stack expl 'directory stack' \
compadd "$@" "$disp[@]" -Q - "$list[@]"

View file

@ -1,3 +1,23 @@
#defcomp sched
#compdef sched
[[ -position 2 -1 ]] && _normal "$@"
local expl lines disp
if [[ CURRENT -eq 2 ]]; then
if compset -P -; then
_wanted -C - jobs || return 1
lines=(${(f)"$(sched)"})
if zstyle -T ":completion:${curcontext}:jobs" verbose; then
disp=( -ld lines )
else
disp=()
fi
[[ -z $lines ]] || _all_labels jobs expl 'scheduled jobs' \
compadd "$disp[@]" - {1..$#lines}
return
else
_message 'time specification'
return 1
fi
fi
compset -n 3 && _normal

View file

@ -20,17 +20,19 @@ done
[[ "$1" = -(|-) ]] && shift
if _wanted signals expl signal &&
{ [[ -z "$minus" ]] || ! _style signals prefix-needed ||
if _wanted signals &&
{ [[ -z "$minus" ]] ||
! zstyle -T ":completion:${curcontext}:signals" prefix-needed ||
[[ "$PREFIX" = -* ]] } ; then
local disp tmp
if _style signals prefix-hidden; then
if zstyle -t ":completion:${curcontext}:signals" prefix-hidden; then
tmp=( "${(@)signals[1,last]}" )
disp=(-d tmp)
else
disp=()
fi
compadd "$@" "$expl[@]" "$disp[@]" -M 'm:{a-z}=${A-Z}' - \
"${minus}${(@)^signals[1,last]}"
_all_labels signals expl signal \
compadd "$@" "$disp[@]" -M 'm:{a-z}={A-Z}' - \
"${minus}${(@)^signals[1,last]}"
fi

View file

@ -1,10 +1,20 @@
#compdef stat
local expl ret=1
if [[ "$words[CURRENT-1]" = -[AH] ]]; then
compgen -A
_arrays
else
[[ "$PREFIX[1]" = + ]] &&
compadd - +device +inode +mode +nlink +uid +gid +rdev +size \
+atime +mtime +ctime +blksize +block +link
_files
_tags files options || return 1
while _tags; do
_requested files && _files && ret=0
_requested options &&
{ ! zstyle -T ":completion:${curcontext}:options" prefix-needed ||
[[ "$PREFIX[1]" = + || ret -eq 1 ]] } &&
_all_labels options expl 'inode element' \
compadd - +device +inode +mode +nlink +uid +gid +rdev \
+size +atime +mtime +ctime +blksize +block +link
(( ret )) || return 0
done
fi

View file

@ -0,0 +1,22 @@
#compdef zcompile
local context state line expl
typeset -A opt_args
_arguments -s \
'(-c -m -a)-U[don'\''t expand aliases]' \
'(-M)-R[mark as read]' \
'(-R)-M[mark as mapped]' \
'(-c -z -m -a)-k[ksh-style autoloading]' \
'(-c -k -m -a)-z[zsh-style autoloading]' \
'(-U -z -k)-c[currently defined functions]' \
'(-U -z -k)-m[use names as patterns]' \
'(-U -z -k)-a[write autoload functions]' \
':zwc file:_files' \
'*:function:->function' && return 0
if (( $+opt_args[-c] )); then
_wanted functions expl 'function to write' compadd - ${(k)functions}
else
_wanted file expl 'zsh source file' _files
fi

View file

@ -1,50 +1,92 @@
#defpatcomp zf*
# Don't try any more completion after this.
_compskip=1
#compdef -p zf*
# Completion for zftp builtin and zf* functions. The functions
# zfcd_match and zfget_match (used for old-style completion)
# zfcd_match and zfget_match (also used for old-style completion)
# need to be installed for remote file and directory completion to work.
local subcom
# emulate -L zsh
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
# Don't try any more completion after this.
_compskip=all
local subcom expl curcontext="${curcontext}"
if [[ $words[1] = zftp ]]; then
if [[ $CURRENT -eq 2 ]]; then
_wanted commands expl sub-command \
compadd open params user login type ascii binary mode put \
putat get getat append appendat ls dir local remote mkdir rmdir \
session rmsession
return
fi
subcom=$1
subcom=$words[2]
curcontext="${curcontext/:zftp:/:zftp-${words[2]}:}"
else
subcom=$COMMAND
subcom=$words[1]
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
;;
# complete remote directories
_wanted directories && zfcd_match $PREFIX $SUFFIX
;;
*(get(|at)|gcp|delete|remote))
# complete remote files
zfget_match $PREFIX $SUFFIX
(( $#reply )) && compadd -F fignore -m $reply
;;
# complete remote files
_wanted files && zfget_match $PREFIX $SUFFIX
;;
*(put(|at)|pcp))
# complete local files
_files
;;
# complete local files
_wanted files && _files
;;
*(open|anon|params))
# complete hosts: should do cleverer stuff with user names
complist -k hosts
;;
# complete hosts: should do cleverer stuff with user names
_wanted hosts && _hosts
;;
*(goto|mark))
# complete bookmarks. First decide if ncftp mode is go.
_wanted bookmarks || return 1
if [[ $words[2] = -*n* ]]; then
if [[ -f ~/.ncftp/bookmarks ]]; then
_all_labels bookmarks expl bookmark \
compadd - $(awk -F, 'NR > 2 { print $1 }' ~/.ncftp/bookmarks)
fi
else
if [[ -f ${ZFTP_BMFILE:=${ZDOTDIR:-$HOME}/.zfbkmarks} ]]; then
_all_labels bookmarks expl bookmark \
compadd - $(awk '{print $1}' $ZFTP_BMFILE)
fi
fi
;;
*session)
# complete sessions, excluding the current one.
_wanted sessions expl 'another FTP session' \
compadd - ${$(zftp session):#$ZFTP_SESSION}
;;
*transfer)
# complete arguments like sess1:file1 sess2:file2
if [[ $PREFIX = *:* ]]; then
# complete file in the given session
_wanted files || return 1
local sess=${PREFIX%%:*} oldsess=$ZFTP_SESSION
compset -p $(( $#sess + 1 ))
[[ -n $sess ]] && zftp session $sess
zfget_match $PREFIX $SUFFIX
[[ -n $sess && -n $oldsess ]] && zftp session $oldsess
else
# note here we can complete the current session
_wanted sessions expl 'FTP session' compadd -S : - $(zftp session)
fi
;;
*)
# dunno... try ordinary completion after all.
unset _compskip
;;
# dunno... try ordinary completion after all.
_compskip=''
return 1
;;
esac

View file

@ -7,17 +7,17 @@ _arguments -C -s \
'(-d -w -r -L)-b[io to pseudo-terminal blocking]' \
'(-e -b -w -r -L)-d[delete command]:*:name:->name' \
'(-e -b -d -r -L)-w[send string to command]:name:->name:*:strings to write' \
'(-e -b -d -w -L)-r[read string from command]:name:->name:param:_parameters:*:nothing:_nothing' \
'(-e -b -d -w -L *)-r[read string from command]:name:->name:param:_parameters' \
'(-e -b -d -w -r)-L[list defined commands as calls]' \
'*::args:_normal'
'(-r)*::args:_normal'
if [[ $state = name ]] && _wanted zptynames expl 'zpty command names'; then
if [[ $state = name ]] && _wanted names; then
list=( ${${(f)"$(zpty)"}#*\) } )
names=( ${list%%:*} )
if zstyle -T ":completion:${curcontext}" verbose; then
zformat -a list ' --' ${${(f)"$(zpty)"}#*\) }
compadd "$expl[@]" -d list - "$names[@]"
_all_labels names expl 'zpty command names' compadd -d list - "$names[@]"
else
compadd "$expl[@]" - "$names[@]"
_all_labels names expl 'zpty command names' compadd - "$names[@]"
fi
fi

View file

@ -1,7 +1,8 @@
#compdef zstyle
local curcontext="$curcontext" state ostate line expl ctop
local nm=$compstat[nmatches]
local curcontext="$curcontext" state context ostate line expl ctop
local nm=$compstate[nmatches] mesg
typeset -A opt_args
typeset -A styles
# Assoc array of styles; the values give the possible top-level
@ -9,15 +10,18 @@ typeset -A styles
# followed by a colon, followed by a state to enter, empty if none.
styles=(
accept-exact c:bool
add-space c:bool
arguments c:
auto-description c:
cache-path 'c:_path_files -/'
break c:
completer c:completer
completions c:
condition c:
cursor c:bool
cursor c:cursor
disable-stat c:bool
domains c:
expand c:
file-patterns c:filepat
format c:
glob c:
group-name c:
@ -26,8 +30,9 @@ styles=(
hidden c:bool
hosts c:_hosts
hosts-ports c:host-port
hosts-ports-users c:host-port-user
ignored-suffixes c:
users-hosts-ports c:user-host-port
ignore-parents c:ignorepar
ignored-patterns c:
insert-unambiguous c:bool
last-prompt c:bool
list c:listwhen
@ -36,21 +41,26 @@ styles=(
list-packed c:bool
list-rows-first c:bool
local c:
matcher-list c:
max-errors c:
menu c:boolauto
numbers c:bool
original c:bool
path 'c:_path_files -/'
packageset c:packageset
path 'c:_wanted directories expl directory _path_files -/'
ports c:_ports
prefix-hidden c:bool
prefix-needed c:bool
prompt c:
remove-all-dups c:bool
single-ignored c:single-ignored
sort c:bool
tag-order c:tag
special-dirs c:sdirs
squeeze-slashes c:bool
stop c:stop
subst-glob-only c:
substitute c:
tag-order c:tag
users c:_users
users-hosts c:user-host
verbose c:bool
@ -83,9 +93,20 @@ while [[ -n $state ]]; do
case "$ostate" in
contexts)
if [[ $PREFIX != :*: ]]; then
_wanted contexts expl context &&
compadd -P : -S : "$expl[@]" completion zftp
if _wanted contexts; then
if [[ $PREFIX != :*: ]]; then
_all_labels contexts expl context compadd -P : -S : completion zftp
elif [[ $PREFIX = :completion:* ]]; then
mesg=''
case "$PREFIX" in
:completion:[^:]#) mesg=function ;;
:completion:[^:]#:[^:]#) mesg=completer ;;
:completion:[^:]#:[^:]#:[^:]#) mesg='command or context' ;;
:completion:[^:]#:[^:]#:[^:]#:[^:]#) mesg=argument ;;
:completion:[^:]#:[^:]#:[^:]#:[^:]#:[^:]#) mesg=tag ;;
esac
[[ -n "$mesg" ]] && _message "$mesg"
fi
fi
;;
@ -96,8 +117,8 @@ while [[ -n $state ]]; do
else
ctop=cz
fi
_wanted styles expl style &&
compadd "$expl[@]" - ${(k)styles[(R)[^:]#[$ctop][^:]#:*]}
_wanted styles expl style \
compadd -M 'r:|-=* r:|=*' - ${(k)styles[(R)[^:]#[$ctop][^:]#:*]}
;;
style-arg)
@ -105,66 +126,116 @@ while [[ -n $state ]]; do
;;
bool)
_wanted values expl boolean &&
compadd "$expl[@]" true false
_wanted values expl boolean compadd true false
;;
boolauto)
_wanted values expl boolean &&
compadd "$expl[@]" true false auto select
_wanted values expl boolean compadd true false auto select
;;
cursor)
if [[ "$words[2]" = *:completion:inc* ]]; then
_wanted values expl 'cursor positioning' compadd complete key default
elif [[ "$words[2]" = *:completion::* ]]; then
_wanted values expl 'cursor positioning' compadd true false
else
_wanted values expl 'cursor positioning' \
compadd complete key default true false
fi
;;
completer)
_wanted values expl completer &&
compadd "$expl[@]" _complete _approximate _correct _match \
_expand _list _menu _oldlist
_wanted values expl completer \
compadd _complete _approximate _correct _match \
_expand _list _menu _oldlist _next_tags
;;
host-port*)
if [[ $PREFIX != *:* ]]; then
_hosts -S :
elif [[ $ostate != *user || $PREFIX != *:*:* ]]; then
compset -P 1 '*:'
user-host-port)
if [[ $PREFIX != *[@:]* ]]; then
_users -S @
elif [[ $PREFIX = *[@:]*[[@:]* ]]; then
compset -P 2 '*[:@]'
_ports
else
compset -P 2 '*:'
_users
compset -P 1 '*[:@]'
_hosts -S :
fi
;;
host-port)
if [[ $PREFIX != *:* ]]; then
_hosts -S :
else
compset -P 1 '*:'
_ports
fi
;;
listwhen)
_wanted values expl 'when to list completions' &&
compadd "$expl[@]" always never sometimes
_wanted values expl 'when to list completions' \
compadd always never sometimes
;;
packageset)
_wanted values expl 'default package set' \
compadd available installed uninstalled
;;
progress)
_wanted values expl 'progress meter style' &&
compadd "$expl[@]" none bar percent
_wanted values expl 'progress meter style' \
compadd none bar percent
;;
sdirs)
_wanted values expl 'whether to complete . or ..' &&
compadd "$expl[@]" true false ..
_wanted values expl 'whether to complete . or ..' \
compadd true false ..
;;
stop)
_wanted values expl 'when to insert matches' &&
compadd "$expl[@]" true false verbose
_wanted values expl 'when to insert matches' \
compadd true false verbose
;;
tag)
_wanted tags expl tag && compadd "$expl[@]" - $taglist
compset -q
if compset -P '*:*:'; then
_message description
elif compset -P '*:'; then
_message 'tag alias'
else
_wanted tags expl tag compadd - $taglist
fi
;;
filepat)
if compset -P '*:*:'; then
_message description
elif compset -P '*:'; then
_message tag
else
_message 'glob patterns'
fi
;;
user-host)
if [[ $PREFIX = *:* ]]; then
compset -P '*:'
if [[ $PREFIX = *[@:]* ]]; then
compset -P '*[@:]'
_hosts
else
_users
_users -S @
fi
;;
ignorepar)
_wanted values expl 'which parents to ignore' \
compadd parent pwd .. directory
;;
single-ignored)
_wanted values expl 'how to handle a single ignored match' \
compadd - show menu
;;
_*)
${=ostate}
;;

View file

@ -1,35 +1,80 @@
#compdef -k complete-word \C-xh
_complete_help() {
local _sort_tags=_help_sort_tags text i
typeset -A help_tags
typeset -U help_contexts
help_contexts=()
local _sort_tags=_help_sort_tags text i j k
typeset -A help_funcs help_tags help_sfuncs help_styles
compadd() { return 1 }
zstyle() {
local _f="${${(@)${(@)funcstack[2,(i)_(main_complete|complete|approximate|normal)]}:#_(wanted|requested|loop|try)}% *}"
[[ -z "$_f" ]] && _f="${${(@)funcstack[2,(i)_(main_complete|complete|approximate|normal)]}:#_(wanted|requested|loop|try)}"
if [[ "$help_sfuncs[$2]" != *${_f}* ||
"$help_styles[${2}${_f}]" != *${3}* ]]; then
[[ "$help_sfuncs[$2]" != *${_f}* ]] &&
help_sfuncs[$2]="${help_sfuncs[$2]}:${_f}"
local _t
case "$1" in
-s) _t='[string] ';;
-a) _t='[array] ';;
-h) _t='[assoc] ';;
*) _t='[boolean]';;
esac
help_styles[${2}${_f}]="${help_styles[${2}${_f}]},${_t} ${3}:${_f}"
fi
builtin zstyle "$@"
}
_main_complete
unfunction compadd
unfunction compadd zstyle
for i in "$help_contexts[@]"; do
for i in "${(@ok)help_funcs}"; do
text="${text}
tags in context \`${i}': ${help_tags[$i]}"
tags in context :completion:${i}:"
tmp=()
for j in "${(@s.:.)help_funcs[$i][2,-1]}"; do
tmp=( "$tmp[@]" "${(@s.,.)help_tags[${i}${j}][2,-1]}" )
done
zformat -a tmp ' (' "$tmp[@]"
tmp=( '
'${^tmp}')' )
text="${text}${tmp}"
done
compstate[list]=list
compstate[force_list]=yes
text="$text
"
for i in "${(@ok)help_sfuncs}"; do
text="${text}
styles in context ${i}"
tmp=()
for j in "${(@s.:.)help_sfuncs[$i][2,-1]}"; do
tmp=( "$tmp[@]" "${(@s.,.)help_styles[${i}${j}][2,-1]}" )
done
zformat -a tmp ' (' "$tmp[@]"
tmp=( '
'${^tmp}')' )
text="${text}${tmp}"
done
compstate[list]='list force'
compstate[insert]=''
compadd -UX "$text[2,-1]" -n ''
}
_help_sort_tags() {
help_contexts=( "$help_contexts[@]" "$curcontext" )
help_tags[$curcontext]="${help_tags[$curcontext]}
${argv}"
comptry "$@"
local f="${${(@)${(@)funcstack[3,(i)_(main_complete|complete|approximate|normal)]}:#_(wanted|requested|loop|try)}% *}"
if [[ "$help_funcs[$curcontext]" != *${f}* ||
"$help_tags[${curcontext}${f}]" != *(${(j:|:)~argv})* ]]; then
[[ "$help_funcs[$curcontext]" != *${f}* ]] &&
help_funcs[$curcontext]="${help_funcs[$curcontext]}:${f}"
help_tags[${curcontext}${f}]="${help_tags[${curcontext}${f}]},${argv}:${f}"
comptry "$@"
fi
}
_complete_help "$@"

View file

@ -1,2 +1,105 @@
#compdef -k complete-word \e/
compgen -Q -H 0 ''
#compdef -K _history-complete-older complete-word \e/ _history-complete-newer complete-word \e,
#
# Complete words from the history
#
# by Adam Spiers, with help gratefully received from
# Sven Wischnowsky and Bart Schaefer
#
# Available styles:
#
# :history-words:list -- display lists of available matches
# :history-words:stop -- prevent looping at beginning and end of matches
# during menu-completion
# :history-words:sort -- sort matches lexically (default is to sort by age)
# :history-words:remove-all-dups --
# remove /all/ duplicate matches rather than just
# consecutives
#
_history_complete_word () {
local expl direction stop
if [[ $WIDGET = *newer ]]; then
direction=newer
else
direction=older
fi
zstyle -s ":completion:${curcontext}:history-words" stop stop
zstyle -t ":completion:${curcontext}:history-words" list || compstate[list]=''
if [[ -n "$compstate[old_list]" &&
( -n "$stop" || "$compstate[insert]" = menu ) ]] ; then
# array of matches is newest -> oldest (reverse of history order)
if [[ "$direction" == 'older' ]]; then
if [[ compstate[old_insert] -eq $_hist_menu_length ||
"$_hist_stop" == 'oldest' ]]; then
_hist_stop='oldest'
[[ "$stop" = verbose ]] &&
_message 'beginning of history reached'
elif [[ "$_hist_stop" == 'newest' ]]; then
zle -Rc
_history_complete_word_gen_matches
else
compstate[old_list]=keep
(( compstate[insert] = compstate[old_insert] + 1 ))
fi
elif [[ "$direction" == 'newer' ]]; then
if [[ compstate[old_insert] -eq 1 || "$_hist_stop" == 'newest' ]]; then
_hist_stop='newest'
[[ "$stop" = verbose ]] && _message 'end of history reached'
elif [[ "$_hist_stop" == 'oldest' ]]; then
zle -Rc
_history_complete_word_gen_matches
else
compstate[old_list]=keep
(( compstate[insert] = compstate[old_insert] - 1 ))
fi
fi
else
_hist_stop=''
_hist_old_prefix="$PREFIX"
_history_complete_word_gen_matches
fi
[[ -n "$compstate[nmatches]" ]]
}
_history_complete_word_gen_matches () {
local opt
[[ -n "$_hist_stop" ]] && PREFIX="$_hist_old_prefix"
if zstyle -t ":completion:${curcontext}:history-words" remove-all-dups; then
opt=-
else
opt=-1
fi
if zstyle -t ":completion:${curcontext}:history-words" sort; then
opt="${opt}J"
else
opt="${opt}V"
fi
_wanted "$opt" history-words expl 'history word' \
compadd -Q - "$historywords[@]"
zstyle -t ":completion:${curcontext}:history-words" list ||
compstate[list]=
_hist_menu_length="$compstate[nmatches]"
case "$direction" in
newer) compstate[insert]=$_hist_menu_length
[[ -n "$_hist_stop" ]] && (( compstate[insert]-- ))
;;
older) compstate[insert]=1
[[ -n "$_hist_stop" ]] && (( compstate[insert]++ ))
;;
esac
[[ -n "$_hist_stop" ]] && _hist_stop=''
}
_history_complete_word "$@"

View file

@ -1,70 +1,92 @@
#compdef -k complete-word \C-xn
# Main widget/completer.
# Main widget.
_next_tags() {
local comp
if [[ $#funcstack -gt 1 ]]; then
# Called as completer, probably `remove' our helper function. A better
# test would be nice, but I think one should still be able to edit the
# current word between attempts to complete it.
[[ $_next_tags_pre != ${LBUFFER%${PREFIX}} ]] && unset _sort_tags
return 1
if [[ -z $compstate[old_list] ]]; then
comp=()
else
local comp
comp=(_complete)
fi
if [[ -z $compstate[old_list] ]]; then
comp=()
else
comp=(_next_tags _complete)
fi
(( $+_sort_tags )) || _next_tags_not=
(( $+_sort_tags )) || _next_tags_not=
_sort_tags=_next_tags_sort
_next_tags_pre="${LBUFFER%${PREFIX}}"
_next_tags_not="$_next_tags_not $_lastcomp[tags]"
_sort_tags=_next_tags_sort
_next_tags_pre="${LBUFFER%${PREFIX}}"
_next_tags_not="$_next_tags_not $_lastcomp[tags]"
_main_complete "$comp[@]"
_main_complete "$comp[@]"
[[ $compstate[insert] = automenu ]] &&
compstate[insert]=automenu-unambiguous
[[ $compstate[insert] = automenu ]] &&
compstate[insert]=automenu-unambiguous
compstate[insert]=''
compstate[list]='list force'
compstate[insert]=''
compstate[list]='list force'
compprefuncs=( "$compprefuncs[@]" _next_tags_pre )
}
# Pre-completion function.
_next_tags_pre() {
# Probably `remove' our sort function. A better test would be nice, but
# I think one should still be able to edit the current word between
# attempts to complete it.
if [[ $_next_tags_pre != ${LBUFFER%${PREFIX}} ]]; then
unset _sort_tags
else
compprefuncs=( "$compprefuncs[@]" _next_tags_pre )
fi
}
# Helper function for sorting tags. Most of this is copied from _tags.
_next_tags_sort() {
local order tags tag nodef
local order tags tag nodef tmp
zstyle -a ":completion:${curcontext}:" tag-order order ||
order=( 'arguments values' options globbed-files directories all-files )
order=('arguments values' options)
# But we also remove the tags we've already tried...
tags=( "${(@)order:#(${(j:|:)~${=_next_tags_not}})}" )
tags=( "${(@)order:#(${(j:|:)~${=_next_tags_not}})(|:*)}" )
# ... unless that would remove all offered tags.
[[ $#tags -ne $#order && "$tags" != *(${(j:|:)~argv})* ]] &&
tags=( $order ) _next_tags_not=
if [[ $funcstack[4] = _files ]]; then
if zstyle -a ":completion:${curcontext}:" file-patterns tmp; then
[[ "$tags" = *${${tmp[-1]##[^\\]:}%:*}* ]] &&
tags=( $order ) _next_tags_not=
else
[[ "$tags" = *all-files* ]] && tags=( $order ) _next_tags_not=
fi
else
[[ $#tags -ne $#order && "$tags" != *(${(j:|:)~argv})* ]] &&
tags=( $order ) _next_tags_not=
fi
for tag in $tags; do
case $tag in
-) nodef=yes;;
*\(\)) "${${tag%%[ ]#\(\)}##[ ]#}" "$@";;
\!*) comptry "${(@)argv:#(${(j:|:)~${=tag[2,-1]}})}";;
?*) comptry ${=tag};;
\!*) comptry "${(@)argv:#(${(j:|:)~${=~tag[2,-1]}})}";;
?*) comptry -m "$tag";;
esac
done
[[ -z "$nodef" ]] && comptry "$@"
if [[ -z "$nodef" ]]; then
if [[ $funcstack[4] = _files ]]; then
if zstyle -a ":completion:${curcontext}:" file-patterns tmp; then
[[ "$argv" = *${${tmp[-1]##[^\\]:}%:*}* ]] && _next_tags_not=
else
[[ "$argv" = *all-files* ]] && _next_tags_not=
fi
fi
comptry "${(@)argv:#(${(j:|:)~${=_next_tags_not}})(|:*)}"
fi
}
[[ -o kshautoload ]] || _next_tags "$@"

View file

@ -0,0 +1,44 @@
#autoload
local gopt=-J len tmp pre suf tloop ret=1 descr
if [[ "$1" = -t ]]; then
tloop=yes
shift
fi
if [[ "$1" = -([12]|)[VJ] ]]; then
gopt="$1"
shift
fi
tmp=${argv[(ib:4:)-]}
len=$#
if [[ tmp -lt len ]]; then
pre=$(( tmp-1 ))
suf=$tmp
elif [[ tmp -eq $# ]]; then
pre=-2
suf=$(( len+1 ))
else
pre=4
suf=5
fi
while [[ -z "$tloop" ]] || comptags -N; do
while comptags -A "$1" curtag; do
if [[ "$curtag" = *:* ]]; then
zformat -f descr "${curtag#*:}" "d:$3"
_description "$gopt" "${curtag%:*}" "$2" "$descr"
curtag="${curtag%:*}"
"$4" "${(P@)2}" "${(@)argv[5,-1]}"
else
_description "$gopt" "$curtag" "$2" "$3"
"${(@)argv[4,pre]}" "${(P@)2}" "${(@)argv[suf,-1]}" && ret=0
fi
done
[[ -z "$tloop" || ret -eq 0 ]] && break
done
return ret

View file

@ -1,19 +1,23 @@
#autoload
local tags def expl descr action mesgs nm="$compstack[nmatches]"
local context
local tags def expl descr action mesgs nm="$compstate[nmatches]" subopts
local opt curcontext="$curcontext"
if [[ "$1" = -C?* ]]; then
context="${1[3,-1]}"
shift
elif [[ "$1" = -C ]]; then
context="$2"
shift 2
fi
subopts=()
while getopts 'O:C:' opt; do
case "$opt" in
O) subopts=( "${(@P)OPTARG}" ) ;;
C) curcontext="${curcontext%:*}:$OPTARG" ;;
esac
done
shift OPTIND-1
[[ "$1" = -(|-) ]] && shift
mesgs=()
_tags -C "$context" "${(@)argv%%:*}"
_tags "${(@)argv%%:*}"
while _tags; do
for def; do
@ -21,7 +25,7 @@ while _tags; do
descr="${${def#*:}%%:*}"
action="${def#*:*:}"
_description expl "$descr"
_description "${def%%:*}" expl "$descr"
if [[ "$action" = \ # ]]; then
@ -35,28 +39,35 @@ while _tags; do
eval ws\=\( "${action[3,-3]}" \)
_describe "$descr" ws -M 'r:|[_-]=* r:|=*'
_describe "$descr" ws -M 'r:|[_-]=* r:|=*' "$subopts[@]"
elif [[ "$action" = \(*\) ]]; then
# Anything inside `(...)' is added directly.
compadd "$expl[@]" - ${=action[2,-2]}
_all_labels "${def%%:*}" expl "$descr" \
compadd "$subopts[@]" - ${=action[2,-2]}
elif [[ "$action" = \{*\} ]]; then
# A string in braces is evaluated.
eval "$action[2,-2]"
while _next_label "${def%%:*}" expl "$descr"; do
eval "$action[2,-2]"
done
elif [[ "$action" = \ * ]]; then
# If the action starts with a space, we just call it.
${(e)=~action}
eval "action=( $action )"
while _next_label "${def%%:*}" expl "$descr"; do
"$action[@]"
done
else
# Otherwise we call it with the description-arguments built above.
action=( $=action )
${(e)action[1]} "$expl[@]" ${(e)~action[2,-1]}
eval "action=( $action )"
_all_labels "${def%%:*}" expl "$descr" \
"$action[1]" "$subopts[@]" "${(@)action[2,-1]}"
fi
fi
done

View file

@ -1,102 +1,30 @@
#autoload
# This code will try to correct the string on the line based on the
# strings generated for the context if `compconfig[correct]' is set.
# These corrected strings will be shown in a list and one can
# cycle through them as in a menucompletion or get the corrected prefix.
#
# Supported configuration keys:
#
# approximate_accept
# This should be set to a number, specifying the maximum number
# of errors that should be accepted. If the string also contains
# a `n' or `N', the code will use the numeric argument as the
# maximum number of errors if a numeric argument was given. If no
# numeric argument was given, the number from the value of this
# key will be used. E.g. with `compconf approximate_accept=2n' two
# errors will be accepted, but if the user gives another number
# with the numeric argument, this will be prefered. Also, with
# `compconf approximate_accept=0n', normally no correction will be
# tried, but if a numeric argument is given, automatic correction
# will be used. On the other hand, if the string contains an `!'
# and a `n' or `N', correction is not attempted if a numeric
# argument is given. Once the number of errors to accept is
# determined, the code will repeatedly try to generate matches by
# allowing one error, two errors, and so on. Independent of the
# number of errors the user wants to accept, the code will allow
# only fewer errors than there are characters in the string from
# the line.
#
# approximate_original
# This value is used to determine if the original string should
# be included in the list (and thus be presented to the user when
# cycling through the corrections). If it is set to any non-empty
# value, the original string will be offered. If it contains the
# sub-string `last', the original string will appear as the last
# string when cycling through the corrections, otherwise it will
# appear as the first one (so that the command line does not
# change immediately). Also, if the value contains the sub-string
# `always', the original string will always be included, whereas
# normally it is included only if more than one possible
# correction was generated.
#
# approximate_prompt
# This can be set to a string that should be printed before the
# list of corrected strings when cycling through them. This string
# may contain the control sequences `%n', `%B', etc. known from
# the `-X' option of `compctl'. Also, the sequence `%e' will be
# replaced by the number of errors accepted to generate the
# corrected strings.
#
# approximate_insert
# If this is set to a string starting with `unambig', the code
# will try to insert a usable unambiguous string in the command
# line instead of always cycling through the corrected strings.
# If such a unambiguous string could be found, the original
# string is not used, independent of the setting of
# `approximate_original'. If no sensible string could be found,
# one can cycle through the corrected strings as usual.
#
# If any of these keys is not set, but the the same key with the
# prefix `correct' instead of `approximate' is set, that value will
# be used.
# strings generated for the context. These corrected strings will be
# shown in a list and one can cycle through them as in a menucompletion
# or get the corrected prefix.
local _comp_correct _correct_prompt comax
local cfgacc cfgorig cfgps cfgins
# We don't try correction if the string is too short or we have tried it
# already.
# Only if all global matchers hav been tried.
[[ _matcher_num -gt 1 || "${#:-$PREFIX$SUFFIX}" -le 1 ]] && return 1
[[ compstate[matcher] -ne compstate[total_matchers] ]] && return 1
local _comp_correct _correct_expl comax cfgacc
local oldcontext="${curcontext}" opm="$compstate[pattern_match]"
# We don't try correction if the string is too short.
[[ "${#:-$PREFIX$SUFFIX}" -le 1 ]] && return 1
# Get the configuration values, using either the prefix `correct' or
# `approximate'.
if [[ "$compstate[pattern_match]" = (|\**) ]]; then
cfgacc="${compconfig[approximate_accept]:-$compconfig[correct_accept]}"
cfgorig="${compconfig[approximate_original]:-$compconfig[correct_original]}"
cfgps="${compconfig[approximate_prompt]:-$compconfig[correct_prompt]}"
cfgins="${compconfig[approximate_insert]:-$compconfig[correct_insert]}"
else
cfgacc="$compconfig[correct_accept]"
cfgorig="$compconfig[correct_original]"
cfgps="$compconfig[correct_prompt]"
cfgins="$compconfig[correct_insert]"
fi
zstyle -s ":completion:${curcontext}:" max-errors cfgacc || cfgacc='2 numeric'
# Get the number of errors to accept.
if [[ "$cfgacc" = *[nN]* && NUMERIC -ne 1 ]]; then
# Stop if we also have a `!'.
if [[ "$cfgacc" = *numeric* && ${NUMERIC:-1} -ne 1 ]]; then
# A numeric argument may mean that we should not try correction.
[[ "$cfgacc" = *\!* ]] && return 1
[[ "$cfgacc" = *not-numeric* ]] && return 1
# Prefer the numeric argument if that has a sensible value.
comax="$NUMERIC"
comax="${NUMERIC:-1}"
else
comax="${cfgacc//[^0-9]}"
fi
@ -105,13 +33,15 @@ fi
[[ "$comax" -lt 1 ]] && return 1
# Otherwise temporarily define functions to use instead of
# the builtins that add matches. This is used to be able
# to stick the `(#a...)' into the right place (after an
_tags corrections original
# Otherwise temporarily define a function to use instead of
# the builtin that adds matches. This is used to be able
# to stick the `(#a...)' in the right place (after an
# ignored prefix).
compadd() {
[[ "$*" != *-([a-zA-Z/]#|)U* &&
[[ ${argv[(I)-[a-zA-Z]#U[a-zA-Z]#]} -eq 0 &&
"${#:-$PREFIX$SUFFIX}" -le _comp_correct ]] && return
if [[ "$PREFIX" = \~*/* ]]; then
@ -119,79 +49,49 @@ compadd() {
else
PREFIX="(#a${_comp_correct})$PREFIX"
fi
if [[ -n "$_correct_prompt" ]]; then
builtin compadd -X "$_correct_prompt" -J _correct "$@"
else
builtin compadd -J _correct "$@"
fi
builtin compadd "$_correct_expl[@]" "$@"
}
compgen() {
[[ "$*" != *-([a-zA-Z/]#|)U* &&
"${#:-$PREFIX$SUFFIX}" -le _comp_correct ]] && return
if [[ "$PREFIX" = \~*/* ]]; then
PREFIX="${PREFIX%%/*}/(#a${_comp_correct})${PREFIX#*/}"
else
PREFIX="(#a${_comp_correct})$PREFIX"
fi
if [[ -n "$_correct_prompt" ]]; then
builtin compgen "$@" -X "$_correct_prompt" -J _correct
else
builtin compgen "$@" -J _correct
fi
}
# Now initialise our counter. We also set `compstate[matcher]'
# to `-1'. This allows completion functions to use the simple
# `[[ compstate[matcher] -gt 1 ]] && return' to avoid being
# called for multiple global match specs and still be called
# again when correction is done. Also, this makes it easy to
# test if correction is attempted since `compstate[matcher]'
# will never be set to a negative value by the completion code.
_comp_correct=1
compstate[matcher]=-1
_correct_prompt="${cfgps//\%e/1}"
# We also need to set `extendedglob' and make the completion
# code behave as if globcomplete were set.
setopt extendedglob
[[ -z "$compstate[pattern_match]" ]] && compstate[pattern_match]='*'
while [[ _comp_correct -le comax ]]; do
curcontext="${oldcontext/(#b)([^:]#:[^:]#:)/${match[1][1,-2]}-${_comp_correct}:}"
_description corrections _correct_expl corrections \
"e:$_comp_correct" "o:$PREFIX$SUFFIX"
if _complete; then
if [[ "$cfgins" = unambig* &&
"${#compstate[unambiguous]}" -ge "${#:-$PREFIX$SUFFIX}" ]]; then
if zstyle -t ":completion:${curcontext}:" insert-unambiguous &&
[[ "${#compstate[unambiguous]}" -ge "${#:-$PREFIX$SUFFIX}" ]]; then
compstate[pattern_insert]=unambiguous
elif [[ compstate[nmatches] -gt 1 || "$cfgorig" = *always* ]]; then
if [[ "$cfgorig" = *last* ]]; then
builtin compadd -U -V _correct_original -nQ - "$PREFIX$SUFFIX"
elif [[ -n "$cfgorig" ]]; then
builtin compadd -U -nQ - "$PREFIX$SUFFIX"
fi
elif _requested original &&
{ [[ compstate[nmatches] -gt 1 ]] ||
zstyle -t ":completion:${curcontext}:" original }; then
local expl
_description -V original expl original
builtin compadd "$expl[@]" -U -Q - "$PREFIX$SUFFIX"
# If you always want to see the list of possible corrections,
# set `compstate[list]=list' here.
# set `compstate[list]=list force' here.
compstate[force_list]=list
[[ "$compstate[list]" != list* ]] &&
compstate[list]="$compstate[list] force"
fi
compstate[matcher]="$compstate[total_matchers]"
unfunction compadd compgen
unfunction compadd
compstate[pattern_match]="$opm"
return 0
fi
[[ "${#:-$PREFIX$SUFFIX}" -le _comp_correct+1 ]] && break
(( _comp_correct++ ))
_correct_prompt="${cfgps//\%e/$_comp_correct}"
done
compstate[matcher]="$compstate[total_matchers]"
unfunction compadd compgen
unfunction compadd
compstate[pattern_match]="$opm"
return 1

View file

@ -1,4 +1,4 @@
#autoload
#autoload +X
local tmp

View file

@ -2,51 +2,65 @@
# Generate all possible completions. Note that this is not intended as
# a normal completion function, but as one possible value for the
# compconfig[completer] parameter.
# completer style.
local comp name
local comp name oldcontext
typeset -T curcontext="$curcontext" ccarray
oldcontext="$curcontext"
# If we have a user-supplied context name, use only that.
if [[ -n "$compcontext" ]]; then
ccarray[3]="$compcontext"
comp="$_comps[$compcontext]"
[[ -z "$comp" ]] || "$comp"
return
fi
# 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
ccarray[3]=-first-
"$comp"
if (( $+_compskip )); then
unset _compskip
if [[ "$_compskip" = all ]]; then
_compskip=''
(( compstate[nmatches] ))
return
fi
fi
# For arguments and command names we use the `_normal' function.
if [[ "$compstate[context]" = command ]]; then
_normal
curcontext="$oldcontext"
_normal -s
else
# Let's see if we have a special completion definition for the other
# possible contexts.
comp=''
local cname="-${compstate[context]:s/_/-/}-"
case $compstate[context] in
equal) comp="$_comps[-equal-]";;
tilde) comp="$_comps[-tilde-]";;
redirect) comp="$_comps[-redirect-]";;
math) comp="$_comps[-math-]";;
subscript) comp="$_comps[-subscript-]";;
value) comp="$_comps[-value-]";;
array_value) comp="$_comps[-array-value-]";;
condition) comp="$_comps[-condition-]";;
parameter) comp="$_comps[-parameter-]";;
brace_parameter) comp="$_comps[-brace-parameter-]";;
esac
ccarray[3]="$cname"
comp="$_comps[$cname]"
# If not, we use default completion, if any.
[[ -z "$comp" ]] && comp="$_comps[-default-]"
if [[ -z "$comp" ]]; then
if [[ "$_compskip" = *default* ]]; then
_compskip=''
return 1
fi
comp="$_comps[-default-]"
fi
[[ -z "$comp" ]] || "$comp"
fi
_compskip=''
(( compstate[nmatches] ))

View file

@ -1,8 +1,8 @@
#autoload
# This is mainly a wrapper around the more general `_approximate.
# This is mainly a wrapper around the more general `_approximate'.
# By setting `compstate[pattern_match]' to something unequal to `*' and
# then calling `_approximate, we get only corrections, not all strings
# then calling `_approximate', we get only corrections, not all strings
# with the corrected prefix and something after it.
#
# Supported configuration keys are the same as for `_approximate', only

View file

@ -1,22 +1,56 @@
#autoload
local gropt=-J
local name gropt=-J format gname hidden hide match opts
if [[ "$1" = -V ]]; then
gropt=-V
opts=()
if [[ "$1" = -([12]|)[VJ] ]]; then
gropt="$1"
shift
fi
if [[ -n "$compconfig[group_matches]" ]]; then
if [[ -n "$compconfig[description_format]" ]]; then
eval "$1=($gropt ${(q)2} -X ${(q)compconfig[description_format]//\\%d/$2})"
_lastdescr=( "$_lastdescr[@]" "$3" )
_setup "$1"
name="$2"
zstyle -s ":completion:${curcontext}:$1" format format ||
zstyle -s ":completion:${curcontext}:descriptions" format format
zstyle -s ":completion:${curcontext}:$1" hidden hidden
if [[ "$hidden" = (all|yes|true|1|on) ]]; then
[[ "$hidden" = all ]] && format=''
opts=(-n)
fi
zstyle -s ":completion:${curcontext}:$1" group-name gname &&
[[ -z "$gname" ]] && gname="$1"
zstyle -s ":completion:${curcontext}:$1" matcher match &&
opts=($opts -M "${(q)match}")
[[ -n "$_matcher" ]] && opts=($opts -M "${(q)_matcher}")
if [[ -z "$_comp_no_ignore" ]] &&
zstyle -a ":completion:${curcontext}:$1" ignored-patterns _comp_ignore; then
opts=( $opts -F _comp_ignore )
else
_comp_ignore=()
fi
shift 2
[[ -n "$format" ]] && zformat -f format "$format" "d:$1" "${(@)argv[2,-1]}"
if [[ -n "$gname" ]]; then
if [[ -n "$format" ]]; then
eval "${name}=($opts $gropt ${(q)gname} -X \"${format}\")"
else
eval "$1=($gropt ${(q)2})"
eval "${name}=($opts $gropt ${(q)gname})"
fi
else
if [[ -n "$compconfig[description_format]" ]]; then
eval "$1=(-X ${(q)compconfig[description_format]//\\%d/$2})"
if [[ -n "$format" ]]; then
eval "${name}=($opts $gropt -default- -X \"${format}\")"
else
eval "$1=()"
eval "${name}=($opts $gropt -default-)"
fi
fi
return 0

View file

@ -6,61 +6,20 @@
# This function will allow other completer functions to be called if
# the expansions done produce no result or do not change the original
# word from the line.
#
# Configuration keys:
#
# expand_substitute
# If this is unset or set to the empty string, the code will first
# try to expand all substitutions in the string (such as $(...) and
# ${...}). If this is set to an non-empty string it should be
# an expression usable inside a $[...] arithmetical expression.
# In this case, expansion of substitutions will be done if the
# expression evaluates to `1'. For example, with
#
# compconf expand_substitute='NUMERIC != 1'
#
# substitution will be performed only if given an explicit numeric
# argument other than `1', as by typing ESC 2 TAB.
#
# expand_glob
# If this is unset or set to an empty string, globbing will be
# attempted on the word resulting from substitution or the
# original string. The values accepted for this key are the same
# as for expand_substitute.
#
# expand_menu
# If this is unset or set to the empty string, the words resulting
# from expansion (if any) will simply be inserted in the ommand line,
# replacing the original string. However, if this key is set to an
# non-empty string, the user can cycle through the expansion as in
# a menucompletion. Unless the value contains the sub-string `only',
# the user will still be offered all expansions at once as one of
# the strings to insert in the command line. Also, if the value
# contains the sub-string `last', the string with all expansion will
# be offered first, whereas normally it is offered as the last string
# to insert. Finally, if the value contains the sub-string `sort',
# the expansions will be sorted alphabetically, normally they are
# kept in the order the expansion produced them in.
#
# expand_original
# If this is set to an non-empty string, the original string from the
# line will be included in the list of strings the user can cycle
# through as in a menucompletion. If the value contains the sub-string
# `last', the original string will appear as the last string, with
# other values it is inserted as the first one (so that the command
# line does not change immediatly).
#
# expand_prompt
# This may be set to a string that should be displayed before the
# possible expansions. This is given to the -X option and thus may
# contain the control sequences `%n', `%B', etc. Also, the sequence
# `%o' in this string will be replaced by the original string.
local exp word="$PREFIX$SUFFIX" group=-V
setopt localoptions nullglob
# Do this only for the first global matcher.
[[ _matcher_num -gt 1 ]] && return 1
[[ "$compstate[matcher]" -le 1 ]] || return 1
local exp word="$PREFIX$SUFFIX" sort expr expl subd suf=" "
# First, see if we should insert all *completions*.
if zstyle -s ":completion:${curcontext}:" completions expr &&
[[ "${(e):-\$[$expr]}" -eq 1 ]]; then
compstate[insert]=all
return 1
fi
# In exp we will collect the expansion.
@ -69,79 +28,68 @@ exp=("$word")
# First try substitution. That weird thing spanning multiple lines
# changes quoted spaces, tabs, and newlines into spaces.
[[ -z "$compconfig[expand_substitute]" ||
"${(e):-\$[$compconfig[expand_substitute]]}" -eq 1 ]] &&
zstyle -s ":completion:${curcontext}:" substitute expr &&
[[ "${(e):-\$[$expr]}" -eq 1 ]] &&
exp=( "${(e)exp//\\[
]/ }" )
# If the array is empty, store the original string again.
[[ -z "$exp" ]] && exp=("$word")
(( $#exp )) || exp=("$word")
subd=("$exp[@]")
# Now try globbing.
[[ -z "$compconfig[expand_glob]" ||
"${(e):-\$[$compconfig[expand_glob]]}" -eq 1 ]] &&
exp=( ${~exp}(N) )
zstyle -s ":completion:${curcontext}:" glob expr &&
[[ "${(e):-\$[$expr]}" -eq 1 ]] &&
exp=( ${~exp} )
# If we don't have any expansions or only one and that is the same
# as the original string, we let other completers run.
[[ $#exp -eq 0 ||
( $#exp -eq 1 && "$exp[1]" = "$word" ) ]] && return 1
(( $#exp )) || exp=("$subd[@]")
# We have expansions, should we menucomplete them?
[[ $#exp -eq 1 && "$exp[1]" = "$word"(|\(N\)) ]] && return 1
if [[ -z "$compconfig[expand_menu]" ]]; then
# With subst-globs-only we bail out if there were no glob expansions,
# regardless of any substitutions
# No, so if the user only wants a list, we add the strings
# separately. Otherwise we add the whole array as one string,
# probably also adding the original string.
zstyle -s ":completion:${curcontext}:" subst-globs-only expr &&
[[ "${(e):-\$[$expr]}" -eq 1 && "$subd" = "$exp"(|\(N\)) ]] && return 1
if [[ -z "$compstate[insert]" ]]; then
compadd -U -V _expand -Q - "$exp[@]"
else
[[ -n "$compconfig[expand_original]" &&
"$compconfig[expand_original]" != *last* ]] &&
compadd -UnQ -V _expand_original - "$word"
# Now add as matches whatever the user requested.
compadd -UQ -V _expand - "$exp"
zstyle -s ":completion:${curcontext}:" sort sort
[[ -n "$compconfig[expand_original]" &&
"$compconfig[expand_original]" = *last* ]] &&
compadd -UnQ -V _expand_original - "$word"
[[ "$sort" = (yes|true|1|on) ]] && exp=( "${(@o)exp}" )
compstate[insert]=menu
fi
# If there is only one expansion, add a suitable suffix
(($#exp == 1)) && suf='' && [[ -d $exp && "$exp[1]" != */ ]] && suf='/'
if [[ -z "$compstate[insert]" ]] ;then
_description all-expansions expl 'all expansions' "o:$word"
compadd "$expl[@]" -UQ -qS "$suf" - "$exp"
else
# Sorting? We just use a different group type then.
_tags all-expansions expansions original
[[ "$compconfig[expand_menu]" = *sort* ]] && group=-J
# Now add the expansion string, probably also adding the original
# and/or the string containing all expanded string.
[[ -n "$compconfig[expand_original]" &&
"$compconfig[expand_original]" != *last* ]] &&
compadd -UnQ -V _expand_original - "$word"
[[ "$compconfig[expand_menu]" = *last* &&
"$compconfig[expand_menu]" != *only* ]] &&
compadd -UnQ -V _expand_all - "$exp"
if [[ -z "$compconfig[expand_prompt]" ]]; then
compadd -UQ $group _expand - "$exp[@]"
else
compadd -UQ -X "${compconfig[expand_prompt]//\%o/$word}" \
$group _expand - "$exp[@]"
if _requested all-expansions; then
_description all-expansions expl 'all expansions'
compadd "$expl[@]" -UQ -qS "$suf" - "$exp"
fi
[[ "$compconfig[expand_menu]" != *last* &&
"$compconfig[expand_menu]" != *only* ]] &&
compadd -UnQ -V _expand_all - "$exp"
[[ -n "$compconfig[expand_original]" &&
"$compconfig[expand_original]" = *last* ]] &&
compadd -UnQ -V _expand_original - "$word"
if [[ $#exp -gt 1 ]] && _requested expansions; then
if [[ "$sort" = menu ]]; then
_description expansions expl expansions "o:$word"
else
_description -V expansions expl expansions "o:$word"
fi
compadd "$expl[@]" -UQ - "$exp[@]"
fi
_requested original expl original && compadd "$expl[@]" -UQ - "$word"
compstate[insert]=menu
fi

View file

@ -1,26 +1,49 @@
#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 opts tmp glob pats expl tag i pat descr minus
local nm=$NMATCHES
zparseopts -a opts \
'/=tmp' 'f=tmp' 'g+:-=tmp' q n 1 2 P: S: r: R: W: X+: M+: F: J+: V+:
_path_files "$@"
type="${(@j::M)${(@)tmp#-}#?}"
(( $tmp[(I)-g*] )) && glob="${(j: :)${(M)tmp:#-g*}#-g}"
if [[ $# -ne 0 && -nmatches nm ]]; then
local opt opts
# We didn't get any matches for those types of files described by
# the `-g' or `-/' option. Now we try it again accepting all files.
# First we get those options that we have to use even if then. If
# we find out that the `-f' option was given, we already accepted
# all files and give up immediatly.
opts=()
while getopts "P:S:W:F:J:V:X:f/g:" opt; do
[[ "$opt" = f ]] && return
[[ "$opt" = [PSWFJVX] ]] && opts=("$opts[@]" "-$opt" "$OPTARG")
done
_path_files "$opts[@]"
if zstyle -a ":completion:${curcontext}:" file-patterns pats; then
[[ "$type" = */* ]] && glob="$glob *(-/)"
pats=( \ ${(M)^${pats//\\%p/ ${glob:-\*} }:#*[^\\]:*} )
else
if [[ "$type" = *g* ]]; then
if [[ "$type" = */* ]]; then
pats=( " ${glob//:/\\:} *(-/):globbed-files" '*:all-files' )
else
pats=( " ${glob//:/\\:}:globbed-files"
'*(-/):directories' '*:all-files' )
fi
elif [[ "$type" = */* ]]; then
pats=( '*(-/):directories' '*:all-files' )
else
pats=( '*:all-files' )
fi
fi
for tag in "${(@)${(@)pats#*[^\\]:}%%:*}"; do
i="$pats[(I)*[^\\\\]:${tag}(|:*)]"
pat="${${pats[i]%%:${tag}*}//\\\\:/:}"
if [[ i -gt 0 && "$pat" != \ # ]]; then
if [[ "$pats[i]" = *:${tag}:* ]]; then
descr="${pats[i]#*:${tag}:}"
minus=()
else
descr=file
minus=(-)
fi
fi
_wanted "$tag" expl "$descr" \
_path_files -g "$pat" "$opts[@]" "$minus[@]" && return 0
done
return 1

View file

@ -4,11 +4,10 @@
(( $compstate[ignored] )) || return 1
local curcontext="${curcontext/:[^:]#:/:ignored-${(M)#_completers[1,_completer_num]:#_ignored}:}"
local comp i _comp_no_ignore=yes tmp expl
zstyle -a ":completion:${curcontext}:" completer comp ||
comp=( "${(@)_completers[1,_completer_num-1][(R)_ignored,-1]}" )
comp=( "${(@)_completers[1,_completer_num-1][(R)_ignored(|:*),-1]}" )
for i in "$comp[@]"; do
if [[ "$i" != _ignored ]] && "$i"; then

View file

@ -1,38 +1,16 @@
#autoload
# This completer function makes the other completer functions used
# insert possible completions only after once the list has been
# shown.
#
# Configuration keys:
#
# list_condition
# If this key is unset or set to the empty string, this completer
# will delay the insertion of matches unconditionally. However,
# if this value is set, it should be set to an expression usable
# inside a $[...] arithmetical expression. In this case, delaying
# will be done if the expression evaluates to `1'.
# For example, with
#
# compconf list_condition='NUMERIC != 1'
#
# delaying will be done only if given an explicit numeric argument
# other than `1'.
#
# list_word
# To find out if only listing should be done, the code normally
# compares the contents of the line with the contents the line
# had at the time of the last invocation. If this key is set to
# an non-empty string comparison is done using only the current
# word. So if it is set, attempting completion on a word equal
# to the one completion was called on the last time will not
# delay the generation of matches.
# insert possible completions only after the list has been shown at
# least once.
local pre suf
[[ _matcher_num -gt 1 ]] && return 1
local pre suf expr
# Get the strings to compare.
if [[ -z "$compconfig[list_word]" ]]; then
if zstyle -t ":completion:${curcontext}:" word; then
pre="$HISTNO$LBUFFER"
suf="$RBUFFER"
else
@ -42,16 +20,15 @@ fi
# Should we only show a list now?
if [[ ( -z "$compconfig[list_condition]" ||
"${(e):-\$[$compconfig[expand_glob]]}" -eq 1 ) &&
zstyle -s ":completion:${curcontext}:" condition expr
if [[ ( -z "$expr" || "${(e):-\$[$expr]}" -eq 1 ) &&
( "$pre" != "$_list_prefix" || "$suf" != "$_list_suffix" ) ]]; then
# Yes. Tell the completion code about it and save the new values
# to compare the next time.
compstate[insert]=''
compstate[list]=list
compstate[force_list]=yes
compstate[list]='list force'
_list_prefix="$pre"
_list_suffix="$suf"
fi

View file

@ -2,47 +2,206 @@
# 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
# If you want to complete only set or unset options for the unsetopt
# and setopt builtin, un-comment these lines:
#
# local _set_options _unset_options
#
# _set_options=(${(k)options[(R)on]})
# _unset_options=(${(k)options[(R)off]})
#
# This is needed because completion functions may set options locally
# which makes the output of setopt and unsetopt reflect a different
# state than the global one for which you are completing.
# 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.
setopt localoptions nullglob rcexpandparam extendedglob
unsetopt markdirs globsubst shwordsplit nounset ksharrays
comp="$_comps[-first-]"
if [[ ! -z "$comp" ]]; then
"$comp" "$@"
if (( $+_compskip )); then
unset _compskip
return
local func funcs ret=1 tmp _compskip format _comp_ignore \
_completers _completer _completer_num curtag \
_matchers _matcher _matcher_num _comp_tags \
context state line opt_args val_args curcontext="$curcontext" \
_last_nmatches=-1 _last_menu_style _def_menu_style _menu_style sel \
_saved_exact="${compstate[exact]}" \
_saved_lastprompt="${compstate[last_prompt]}" \
_saved_list="${compstate[list]}" \
_saved_insert="${compstate[insert]}"
typeset -U _lastdescr
[[ -z "$curcontext" ]] && curcontext=:::
# Special completion contexts after `~' and `='.
if compset -P 1 '='; then
compstate[context]=equal
elif [[ "$PREFIX" != */* && "$PREFIX[1]" = '~' ]]; then
compset -p 1
compstate[context]=tilde
fi
# Initial setup.
_setup default
_def_menu_style=( "$_last_menu_style[@]"
# We can't really do that because the current value of $SELECTMIN
# may be the one set by this function.
# There is a similar problem with $ZLS_COLORS in _setup.
# ${SELECTMIN+select${SELECTMIN:+\=$SELECTMIN}}
)
_last_menu_style=()
# Get the names of the completers to use in the positional parameters.
if (( $# )); then
_completers=( "$@" )
else
zstyle -a ":completion:${curcontext}:" completer _completers ||
_completers=( _complete )
fi
# And now just call the completer functions defined.
_completer_num=1
# Call the pre-functions.
funcs=( "$compprefuncs[@]" )
compprefuncs=()
for func in "$funcs[@]"; do
"$func"
done
for tmp in "$_completers[@]"; do
if [[ "$tmp" = *:-* ]]; then
_completer="${${tmp%:*}[2,-1]//_/-}${tmp#*:}"
tmp="${tmp%:*}"
elif [[ $tmp = *:* ]]; then
_completer="${tmp#*:}"
tmp="${tmp%:*}"
else
_completer="${tmp[2,-1]//_/-}"
fi
curcontext="${curcontext/:[^:]#:/:${_completer}:}"
zstyle -a ":completion:${curcontext}:" matcher-list _matchers ||
_matchers=( '' )
_matcher_num=1
for _matcher in "$_matchers[@]"; do
if "$tmp"; then
ret=0
break 2
fi
(( _matcher_num++ ))
done
(( _completer_num++ ))
done
curcontext="${curcontext/:[^:]#:/::}"
if [[ $compstate[old_list] = keep || $compstate[nmatches] -gt 1 ]]; then
[[ _last_nmatches -ge 0 && _last_nmatches -ne $compstate[nmatches] ]] &&
_menu_style=( "$_last_menu_style[@]" "$_menu_style[@]" )
if [[ "$compstate[insert]" = "$_saved_insert" ]]; then
if [[ -n "$_menu_style[(r)(yes|true|1|on)]" ||
( -n "$_menu_style[(r)auto*]" &&
"$compstate[insert]" = automenu ) ]]; then
compstate[insert]=menu
elif [[ -n "$_menu_style[(r)auto*]" &&
"$compstate[insert]" != automenu ]]; then
compstate[insert]=automenu-unambiguous
elif [[ -n "$_menu_style[(r)(no|false|0|off)]" ]]; then
compstate[insert]=unambiguous
elif [[ -n "$_def_menu_style[(r)(yes|true|1|on)]" ||
( -n "$_def_menu_style[(r)auto*]" &&
"$compstate[insert]" = automenu ) ]]; then
compstate[insert]=menu
elif [[ -n "$_def_menu_style[(r)auto*]" &&
"$compstate[insert]" != automenu ]]; then
compstate[insert]=automenu-unambiguous
elif [[ -n "$_def_menu_style[(r)(no|false|0|off)]" ]]; then
compstate[insert]=unambiguous
fi
fi
_menu_style=( "$_menu_style[@]" "$_def_menu_style[@]" )
if [[ "$compstate[insert]" = *menu* ]]; then
if [[ -n "$_menu_style[(r)no-select*]" ]]; then
unset SELECTMIN
else
sel=( "${(@M)_menu_style:#select*}" )
if (( $# )); then
local min=9999999 i num
for i in "$sel[@]"; do
if [[ "$i" = *\=* ]]; then
num="${i#*\=}"
[[ num -lt 0 ]] && num=0
else
num=0
fi
[[ num -lt min ]] && min="$num"
(( min )) || break
done
zmodload -i zsh/complist
SELECTMIN="$min"
fi
fi
fi
elif [[ $compstate[nmatches] -eq 0 &&
$#_lastdescr -ne 0 && $compstate[old_list] != keep ]] &&
zstyle -s ":completion:${curcontext}:warnings" format format; then
compstate[list]='list force'
compstate[insert]=''
if [[ "$format" = *%d* ]]; then
local str mesg
_lastdescr=( "\`${(@)^_lastdescr:#}'" )
case $#_lastdescr in
1) str="$_lastdescr[1]";;
2) str="$_lastdescr[1] or $_lastdescr[2]";;
*) str="${(j:, :)_lastdescr[1,-2]}, or $_lastdescr[-1]";;
esac
zformat -f mesg "$format" "d:$str"
compadd -UX "$mesg" -n - ''
else
_setup warnings
compadd -UQX "$format" -V warnings - "${(@)_lastdescr:#}"
fi
fi
# For arguments we use the `_normal function.
# Now call the post-functions.
if [[ $CONTEXT == argument || $CONTEXT == command ]]; then
_normal "$@"
else
# Let's see if we have a special completion definition for the other
# possible contexts.
funcs=( "$comppostfuncs[@]" )
comppostfuncs=()
for func in "$funcs[@]"; do
"$func"
done
comp=''
_lastcomp=( "${(@kv)compstate}" )
_lastcomp[completer]="$_completer"
_lastcomp[prefix]="$PREFIX"
_lastcomp[suffix]="$SUFFIX"
_lastcomp[iprefix]="$IPREFIX"
_lastcomp[isuffix]="$ISUFFIX"
_lastcomp[qiprefix]="$QIPREFIX"
_lastcomp[qisuffix]="$QISUFFIX"
_lastcomp[tags]="$_comp_tags"
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
return ret

View file

@ -1,53 +1,51 @@
#autoload
# This is intended to be used as a completer function after the normal
# completer as in: `compconf completer=_complete:_match'.
# completer as in: `zstyle ":completion:::::" completer _complete _match'.
# It temporarily switches on pattern matching, allowing you to try
# completion on patterns without having to setopt glob_complete.
#
# Note, however, that this is only really useful if you don't use the
# expand-or-complete function because otherwise the pattern will
# be expanded using globbing.
#
# Configuration key used:
#
# match_original
# If this is set to a `only', pattern matching will only be tried
# with the string from the line. If it is set to any other non-empty
# string, the original pattern will be tried first and if that yields
# no completions, matching will be tried again with a `*' inserted
# at the cursor position. If this key is not set or set to an empty
# string, matching will only be attempted with the `*' inserted.
local tmp opm="$compstate[pattern_match]" ret=0
[[ _matcher_num -gt 1 ]] && return 1
# Do nothing if we don't have a pattern or there are still global
# match specifications to try.
local tmp opm="$compstate[pattern_match]" ret=0 orig ins
# Do nothing if we don't have a pattern.
tmp="${${:-$PREFIX$SUFFIX}#[~=]}"
[[ "$tmp:q" = "$tmp" ||
compstate[matcher] -ne compstate[total_matchers] ]] && return 1
[[ "$tmp:q" = "$tmp" ]] && return 1
zstyle -s ":completion:${curcontext}:" match-original orig
zstyle -b ":completion:${curcontext}:" insert-unambiguous ins
# Try completion without inserting a `*'?
if [[ -n "$compconfig[match_original]" ]]; then
compstate[matcher]=-1
if [[ -n "$orig" ]]; then
compstate[pattern_match]='-'
_complete && ret=1
compstate[pattern_match]="$opm"
compstate[matcher]="$compstate[total_matchers]"
(( ret )) && return 0
if (( ret )); then
[[ "$ins" = yes &&
$#compstate[unambiguous] -ge ${#:-${PREFIX}${SUFFIX}} ]] &&
compstate[pattern_insert]=unambiguous
return 0
fi
fi
# No completion with inserting `*'?
[[ "$compconfig[match_original]" = only ]] && return 1
[[ "$orig" = only ]] && return 1
compstate[matcher]=-1
compstate[pattern_match]='*'
_complete && ret=1
compstate[pattern_match]="$opm"
compstate[matcher]="$compstate[total_matchers]"
[[ ret -eq 1 && "$ins" = yes &&
$#compstate[unambiguous] -ge ${#:-${PREFIX}${SUFFIX}} ]] &&
compstate[pattern_insert]=unambiguous
return 1-ret

View file

@ -1,10 +1,12 @@
#autoload
[[ _matcher_num -gt 1 ]] && return 1
# This completer is an example showing how menucompletion can be
# implemented with the new completion system.
# Use this one before the normal _complete completer, as in:
#
# compconf completer=_menu:_complete
# zstyle ":completion:::::" completer _menu _complete
if [[ -n "$compstate[old_list]" ]]; then

View file

@ -0,0 +1,24 @@
#autoload
local gopt=-J descr
if [[ "$1" = -([12]|)[VJ] ]]; then
gopt="$1"
shift
fi
if comptags -A "$1" curtag; then
if [[ "$curtag" = *:* ]]; then
zformat -f descr "${curtag#*:}" "d:$3"
_description "$gopt" "${curtag%:*}" "$2" "$descr"
curtag="${curtag%:*}"
eval "${2}=( \${(P)2} \$argv[4,-1] )"
else
_description "$gopt" "$curtag" "$2" "$3"
eval "${2}=( \$argv[4,-1] \${(P)2} )"
fi
return 0
fi
return 1

53
Completion/Core/_oldlist Normal file
View file

@ -0,0 +1,53 @@
#autoload
[[ _matcher_num -gt 1 ]] && return 1
local list
zstyle -s ":completion:${curcontext}:" old-list list
# If this is a listing widget and there is already an old list,
# and either the style :oldlist:old-list is `always', or it is not `never'
# and the list is not already shown, then use the existing list for listing
# (even if it was generated by another widget).
# Do this also if there is an old list and it was generated by the
# completer named by the oldlist_list key.
if [[ -n $compstate[old_list] && $list != never ]]; then
if [[ $WIDGET = *list* && ( $list = always || $list != shown ) ]]; then
compstate[old_list]=keep
return 0
elif [[ $list = *${_lastcomp[completer]}* ]]; then
[[ "$_lastcomp[insert]" = unambig* ]] && compstate[to_end]=single
compstate[old_list]=keep
if [[ -o automenu ]]; then
compstate[insert]=menu
else
compadd -Qs "$SUFFIX" - "$PREFIX"
fi
return 0
fi
fi
# If this is a completion widget, and we have a completion inserted already,
# and the style :oldlist:old-menu is `true', then we cycle through the
# existing list (even if it was generated by another widget).
if [[ -z $compstate[old_insert] && -n $compstate[old_list] ]]; then
compstate[old_list]=keep
elif [[ $WIDGET = *complete(|-prefix|-word) ]] &&
zstyle -t ":completion:${curcontext}:" old-menu; then
if [[ -n $compstate[old_insert] ]]; then
compstate[old_list]=keep
if [[ $WIDGET = *reverse* ]]; then
compstate[insert]=$(( compstate[old_insert] - 1 ))
else
compstate[insert]=$(( compstate[old_insert] + 1 ))
fi
else
return 1
fi
return 0
fi
return 1

View file

@ -1,85 +1,64 @@
#autoload
# Utility function for in-path completion.
# Supported arguments are: `-f', `-/', `-g <patterns>', `-J <group>',
# `-V <group>', `-W paths', `-X explanation', and `-F <ignore>'. All but
# the last have the same syntax and meaning as for `complist'. The
# `-F <ignore>' option may be used to give a list of suffixes either by
# giving the name of an array or literally by giving them in a string
# surrounded by parentheses. Files with one of the suffixes thus given
# are treated like files with one of the suffixes in the `fignore' array
# in normal completion.
#
# This function uses the helper functions `_match_test' and `_match_pattern'.
# Utility function for in-path completion. This allows `/u/l/b<TAB>'
# to complete to `/usr/local/bin'.
# First see if we should generate matches for the global matcher in use.
local linepath realpath donepath prepath testpath exppath skips skipped
local tmp1 tmp2 tmp3 tmp4 i orig eorig pre suf tpre tsuf opre osuf cpre
local pats haspats=no ignore pfxsfx rem remt sopt gopt opt
local nm=$compstate[nmatches] menu matcher mopts atmp sort match
_match_test _path_files || return
typeset -U prepaths exppaths
# Yes, so...
local nm prepaths str linepath realpath donepath patstr prepath testpath rest
local tmp1 collect tmp2 suffixes i ignore matchflags opt group sopt pats gopt
local addpfx addsfx expl
setopt localoptions nullglob rcexpandparam globdots extendedglob
setopt localoptions nullglob rcexpandparam
unsetopt markdirs globsubst shwordsplit nounset
prepaths=('')
ignore=()
group=()
sopt='-'
gopt=''
pats=()
addpfx=()
addsfx=()
expl=()
exppaths=()
# Get the options.
while getopts "P:S:W:F:J:V:X:f/g:" opt; do
case "$opt" in
P) addpfx=(-P "$OPTARG")
;;
S) addsfx=(-S "$OPTARG")
;;
W) tmp1="$OPTARG"
if [[ "$tmp1[1]" = '(' ]]; then
prepaths=( ${^=tmp1[2,-2]}/ )
else
prepaths=( ${(P)=${tmp1}} )
(( ! $#prepaths )) && prepaths=( ${tmp1}/ )
fi
(( ! $#prepaths )) && prepaths=( '' )
;;
F) tmp1="$OPTARG"
if [[ "$tmp1[1]" = '(' ]]; then
ignore=( ${^=tmp1[2,-2]}/ )
else
ignore=( ${(P)${tmp1}} )
fi
(( $#ignore )) && ignore=(-F "( $ignore )")
;;
[JV]) group=("-$opt" "$OPTARG")
;;
X) expl=(-X "$OPTARG")
;;
f) sopt="${sopt}f"
pats=("$pats[@]" '*')
;;
/) sopt="${sopt}/"
pats=("$pats[@]" '*(-/)')
;;
g) gopt='-g'
pats=("$pats[@]" ${=OPTARG})
;;
esac
done
zparseopts -a mopts \
'P:=pfxsfx' 'S:=pfxsfx' 'q=pfxsfx' 'r:=pfxsfx' 'R:=pfxsfx' \
'W:=prepaths' 'F:=ignore' 'M+:=matcher' \
J+: V+: X+: 1: 2: n: 'f=tmp1' '/=tmp1' 'g+:-=tmp1'
sopt="-${(@j::M)${(@)tmp1#-}#?}"
(( $tmp1[(I)-[/g]*] )) && haspats=yes
(( $tmp1[(I)-g*] )) && gopt=yes
if (( $tmp1[(I)-/] )); then
pats=( '*(-/)' ${=${(M)tmp1:#-g*}#-g} )
else
pats=( "${(@)=${(@M)tmp1:#-g*}#-g}" )
fi
pats=( "${(@)pats:# #}" )
if (( $#prepaths )); then
tmp1="${prepaths[2]}"
if [[ "$tmp1[1]" = '(' ]]; then
prepaths=( ${^=tmp1[2,-2]%/}/ )
elif [[ "$tmp1[1]" = '/' ]]; then
prepaths=( "${tmp1%/}/" )
else
prepaths=( ${(P)^tmp1%/}/ )
(( ! $#prepaths )) && prepaths=( ${tmp1%/}/ )
fi
(( ! $#prepaths )) && prepaths=( '' )
else
prepaths=( '' )
fi
if (( $#ignore )); then
if [[ "${ignore[2]}" = \(* ]]; then
ignore=( ${=ignore[2][2,-2]} )
else
ignore=( ${(P)ignore[2]} )
fi
fi
# If we were given no file selection option, we behave as if we were given
# a `-f'.
if [[ "$sopt" = - ]]; then
if [[ "$sopt" = -(f|) ]]; then
if [[ -z "$gopt" ]]; then
sopt='-f'
pats=('*')
@ -88,224 +67,472 @@ if [[ "$sopt" = - ]]; then
fi
fi
# str holds the whole string from the command line with a `*' between
# the prefix and the suffix.
if (( ! $mopts[(I)-[JVX]] )); then
local expl
str="${PREFIX:q}*${SUFFIX:q}"
# If the string began with a `~', the quoting turned this into `\~',
# remove the slash.
[[ "$str" = \\\~* ]] && str="$str[2,-1]"
# We will first try normal completion called with `complist', but only if we
# weren't given a `-F' option.
if (( ! $#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=()
if [[ -z "$gopt" && "$sopt" = -/ ]]; then
_description directories expl directory
else
tmp1=(-W "( $prepaths )")
_description files expl file
fi
# Now call complist.
nm=$NMATCHES
if [[ -z "$gopt" ]]; then
complist "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" "$tmp1[@]" $sopt
else
complist "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" "$tmp1[@]" $sopt -g "$pats"
tmp1=$expl[(I)-M*]
if (( tmp1 )); then
if (( $#matcher )); then
matcher[2]="$matcher[2] $expl[1+tmp1]"
else
matcher=(-M "$expl[1+tmp1]")
fi
fi
# If this generated any matches, we don't want to do in-path completion.
[[ -nmatches nm ]] || return
# No `-F' option, so we want to use `fignore'.
ignore=(-F fignore)
mopts=( "$mopts[@]" "$expl[@]" )
fi
if zstyle -s ":completion:${curcontext}:files" sort tmp1; then
case "$tmp1" in
*size*) sort=oL;;
*links*) sort=ol;;
*(time|date|modi)*) sort=om;;
*access*) sort=oa;;
*(inode|change)*) sort=oc;;
*) sort=on;;
esac
[[ "$tmp1" = *rev* ]] && sort[1]=O
if [[ "$sort" = on ]]; then
sort=''
else
mopts=( "${(@)mopts/#-J/-V}" )
tmp2=()
for tmp1 in "$pats[@]"; do
if [[ "$tmp1" = (#b)(?*)(\(\([^\|~]##\)\)) ]]; then
tmp2=( "$tmp2[@]" "${match[1]}((${sort}${match[2][3,-1]}" )
elif [[ "$tmp1" = (#b)(?*)(\([^\|~]##\)) ]]; then
tmp2=( "$tmp2[@]" "${match[1]}(${sort}${match[2][2,-1]}" )
else
tmp2=( "$tmp2[@]" "${tmp1}(${sort})" )
fi
done
pats=( "$tmp2[@]" )
fi
fi
# Check if we have to skip over sequences of slashes. The value of $skips
# is used below to match the pathname components we always have to accept
# immediatly.
if zstyle -t ":completion:${curcontext}:paths" squeeze-slashes; then
skips='((.|..|)/)##'
else
skips='((.|..)/)##'
fi
# We get the prefix and the suffix from the line and save the whole
# original string. Then we see if we will do menucompletion.
pre="$PREFIX"
suf="$SUFFIX"
opre="$PREFIX"
osuf="$SUFFIX"
orig="${PREFIX}${SUFFIX}"
eorig="$orig"
[[ $compstate[insert] = (*menu|[0-9]*) || -n "$_comp_correct" ||
( -n "$compstate[pattern_match]" &&
"${orig#\~}" != "${${orig#\~}:q}" ) ]] && menu=yes
# If given no `-F' option, we may want to use $fignore, turned into patterns.
[[ -z "$_comp_no_ignore" && $#ignore -eq 0 &&
( -z $gopt || "$pats" = \ #\*\ # ) && -n $FIGNORE ]] &&
ignore=( "?*${^fignore[@]}" )
if (( $#ignore )); then
_comp_ignore=( "$_comp_ignore[@]" "$ignore[@]" )
(( $mopts[(I)-F] )) || mopts=( "$mopts[@]" -F _comp_ignore )
fi
(( $#matcher )) && mopts=( "$mopts[@]" "$matcher[@]" )
# Now let's have a closer look at the string to complete.
if [[ "$str[1]" = \~ ]]; then
if [[ "$pre[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\=$linepath
str="${str#*/}"
linepath="${pre[2,-1]%%/*}"
if [[ -z "$linepath" ]]; then
realpath="${HOME%/}/"
elif (( $+userdirs[$linepath] )); then
realpath="${userdirs[$linepath]%/}/"
elif (( $+nameddirs[$linepath] )); then
realpath="${nameddirs[$linepath]%/}/"
else
_message "unknown user \`$linepath'"
return 1
fi
linepath="~${linepath}/"
[[ "$realpath" = "$linepath" ]] && return 1
pre="${pre#*/}"
orig="${orig#*/}"
donepath=''
prepaths=( '' )
elif [[ "$pre" = *\$*/* ]]; then
# If there is a parameter expansion in the word from the line, we try
# to complete the beast by expanding the prefix and completing anything
# after the first slash after the parameter expansion.
# This fails for things like `f/$foo/b/<TAB>' where the first `f' is
# meant as a partial path.
linepath="${(M)pre##*\$[^/]##/}"
realpath=${(e)~linepath}
[[ "$realpath" = "$linepath" ]] && return 1
pre="${pre#${linepath}}"
i="${#linepath//[^\\/]}"
orig="${orig[1,(in:i:)/][1,-2]}"
donepath=''
prepaths=( '' )
else
# If the string does not start with a `~' we don't remove a prefix from the
# string.
liniepath=''
linepath=''
realpath=''
if [[ "$str[1]" = / ]]; then
if [[ "$pre[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]"
pre="$pre[2,-1]"
orig="$orig[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=( '' )
[[ "$pre" = (.|..)/* ]] && 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 by calling `_match_pattern'.
patstr="$str"
matchflags=""
_match_pattern _path_files patstr matchflags
# We almost expect the pattern to have changed `..' into `*.*.', `/.' into
# `/*.', and probably to contain two or more consecutive `*'s. Since these
# have special meaning for globbing, we remove them. But before that, we
# add the pattern for matching any characters before a slash.
patstr="$patstr:gs-/-*/-:gs/*.*.//:gs-/*.-/.-:gs/**/*/"
# 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'.
# Now we generate the matches. First we loop over all prefix paths given
# with the `-W' option.
for prepath in "$prepaths[@]"; do
str="$patstr"
# Get local copies of the prefix, suffix, and the prefix path to use
# in the following loop, which walks through the pathname components
# in the string from the line.
tpre="$pre"
tsuf="$suf"
testpath="$donepath"
# The second loop tests the components of the path in `str' to get the
# possible matches.
tmp2="${(M)tpre##${~skips}}"
tpre="${tpre#$tmp2}"
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.
tmp1=( "$prepath$realpath$donepath$tmp2" )
rest="${str#*/}"
tmp1="${prepath}${realpath}${testpath}${~matchflags}${str%%/*}(-/)"
tmp1=( $~tmp1 )
while true; do
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.
# Get the prefix and suffix for matching.
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$^pats )
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}/${~matchflags}${~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}/${~matchflags}${~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 "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" -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]" )
if [[ "$tpre" = */* ]]; then
PREFIX="${tpre%%/*}"
SUFFIX=""
else
PREFIX="${tpre}"
SUFFIX="${tsuf%%/*}"
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"
# Get the matching files by globbing.
tmp2=( "$tmp1[@]" )
if [[ "$tpre$tsuf" = */* ]]; then
if [[ ! -o globdots && "$PREFIX" = .* ]]; then
tmp1=( ${^tmp1}${skipped}*(-/) ${^tmp1}${skipped}.*(-/) )
else
tmp1=( ${^tmp1}${skipped}*(-/) )
fi
if [[ -o globdots || "$PREFIX" = .* ]] &&
zstyle -s ":completion:${curcontext}:paths" special-dirs atmp; then
if [[ "$atmp" = (yes|true|1|on) ]]; then
tmp1=( "$tmp1[@]" . .. )
elif [[ "$atmp" = .. ]]; then
tmp1=( "$tmp1[@]" .. )
fi
fi
else
if [[ ! -o globdots && "$PREFIX" = .* ]]; then
tmp1=( ${^tmp1}${skipped}${^~pats} ${^tmp1}${skipped}.${^~pats:#.*} )
else
tmp1=( ${^tmp1}${skipped}${^~pats} )
fi
if [[ "$sopt" = *[/f]* && ( -o globdots || "$PREFIX" = .* ) ]] &&
zstyle -s ":completion:${curcontext}:paths" special-dirs atmp; then
if [[ "$atmp" = (yes|true|1|on) ]]; then
tmp1=( "$tmp1[@]" . .. )
elif [[ "$atmp" = .. ]]; then
tmp1=( "$tmp1[@]" .. )
fi
fi
fi
if [[ -n "$PREFIX$SUFFIX" ]]; then
# See which of them match what's on the line.
if [[ -n "$_comp_correct" ]]; then
tmp2=( "$tmp1[@]" )
builtin compadd -D tmp1 -F _comp_ignore "$matcher[@]" - "${(@)tmp1:t}"
if [[ $#tmp1 -eq 0 ]]; then
tmp1=( "$tmp2[@]" )
compadd -D tmp1 -F _comp_ignore "$matcher[@]" - "${(@)tmp2:t}"
fi
else
[[ "$tmp1[1]" = */* ]] && tmp2=( "$tmp1[@]" )
builtin compadd -D tmp1 -F _comp_ignore "$matcher[@]" - "${(@)tmp1:t}"
fi
# If no file matches, save the expanded path and continue with
# the outer loop.
if (( ! $#tmp1 )); then
if [[ "$tmp2[1]" = */* ]]; then
tmp2=( "${(@)tmp2#${prepath}${realpath}}" )
if [[ "$tmp2[1]" = */* ]]; then
tmp2=( "${(@)tmp2:h}" )
compquote tmp2
if [[ "$tmp2" = */ ]]; then
exppaths=( "$exppaths[@]" ${^tmp2}${tpre}${tsuf} )
else
exppaths=( "$exppaths[@]" ${^tmp2}/${tpre}${tsuf} )
fi
else
exppaths=( "$exppaths[@]" ${tpre}${tsuf} )
fi
fi
continue 2
fi
elif (( ! $#tmp1 )); then
# A little extra hack: if we were completing `foo/<TAB>' and `foo'
# contains no files, this will normally produce no matches and other
# completers might think that's it's their time now. But if the next
# completer is _correct or something like that, this will result in
# an attempt to correct a valid directory name. So we just add the
# original string in such a case so that the command line doesn't
# change but other completers still think there are matches.
# We do this only if we weren't given a `-g' or `-/' option because
# otherwise this would keep `_files' from completing all filenames
# if none of the patterns match.
if [[ -z "$tpre$tsuf" && -n "$pre$suf" ]]; then
pfxsfx=(-S '' "$pfxsfx[@]")
### Don't remember what the break was good for. We explicitly
### execute this only when there are no matches in the directory,
### so why continue?
###
### tmp1=( "$tmp2[@]" )
### break
elif [[ "$haspats" = no && -z "$tpre$tsuf" &&
"$pre" = */ && -z "$suf" ]]; then
PREFIX="${opre}"
SUFFIX="${osuf}"
compadd -nQS '' - "$linepath$donepath$orig"
tmp4=-
fi
continue 2
fi
if [[ -z "$_comp_no_ignore" && "$tpre$tsuf" != */* && $#tmp1 -ne 0 ]] &&
zstyle -s ":completion:${curcontext}:files" ignore-parents rem &&
[[ ( "$rem" != *dir* || "$pats" = '*(-/)' ) &&
( "$rem" != *..* || "$tmp1" = *../* ) ]]; then
if [[ "$rem" = *parent* ]]; then
for i in ${(M)^tmp1:#*/*}(-/); do
remt="${${i#$prepath$realpath$donepath}%/*}"
while [[ "$remt" = */* &&
! "$prepath$realpath$donepath$remt" -ef "$i" ]]; do
remt="${remt%/*}"
done
[[ "$remt" = */* || "$remt" -ef "$i" ]] &&
_comp_ignore=( "$_comp_ignore[@]" "${(q)i}" )
done
fi
if [[ "$rem" = *pwd* ]]; then
for i in ${^tmp1}(-/); do
[[ "$i" -ef "$PWD" ]] && _comp_ignore=( "$_comp_ignore[@]" "${(q)i}" )
done
fi
(( $#_comp_ignore && $mopts[(I)-F] )) || mopts=( "$mopts[@]" -F _comp_ignore )
fi
# Step over to the next component, if any.
if [[ "$tpre" = */* ]]; then
tpre="${tpre#*/}"
elif [[ "$tsuf" = */* ]]; then
tpre="${tsuf#*/}"
tsuf=""
else
break
fi
# There are more components, so skip over the next components and make a
# slash be added.
tmp2="${(M)tpre##((.|..|)/)##}"
if [[ -n "$tmp2" ]]; then
skipped="/$tmp2"
tpre="${tpre#$tmp2}"
else
skipped=/
fi
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.
# The next loop searches the first ambiguous component.
tmp1="$prepath$realpath$testpath"
suffixes=( $str$^pats )
suffixes=( "${(@)suffixes:gs.**.*.}" )
tmp2=( ${~tmp1}${~matchflags}${~suffixes} )
if [[ $#tmp2 -eq 0 && "$sopt" = */* ]]; then
[[ "$testpath[-1]" = / ]] && testpath="$testpath[1,-2]"
compadd "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" -f - "$linepath$testpath"
else
compadd "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" -p "$linepath$testpath" -W "$prepath$realpath$testpath" -f "$ignore[@]" - ${(@)tmp2#$tmp1}
tmp3="$pre$suf"
tpre="$pre"
tsuf="$suf"
tmp1=( "${(@)tmp1#${prepath}${realpath}${testpath}}" )
while true; do
# First we check if some of the files match the original string
# for this component. If there are some we remove all other
# names. This avoids having `foo' complete to `foo' and `foobar'.
if [[ "$tmp3" = */* ]]; then
tmp4=( "${(@M)tmp1:#${tmp3%%/*}/*}" )
(( $#tmp4 )) && tmp1=( "$tmp4[@]" )
fi
# Next we see if this component is ambiguous.
if [[ "$tmp3" = */* ]]; then
tmp4=$tmp1[(I)^${(q)tmp1[1]%%/*}/*]
else
tmp4=$tmp1[(I)^${(q)tmp1[1]}]
fi
if [[ "$tpre" = */* ]]; then
tmp2="${cpre}${tpre%%/*}"
PREFIX="${donepath}${linepath}${tmp2}"
SUFFIX="/${tpre#*/}${tsuf#*/}"
else
tmp2="${cpre}${tpre}"
PREFIX="${donepath}${linepath}${tmp2}"
SUFFIX="${tsuf}"
fi
if (( tmp4 )) ||
[[ -n "$compstate[pattern_match]" && "$tmp2" != "${(q)tmp2}" ]]; then
# It is. For menucompletion we now add the possible completions
# for this component with the unambigous prefix we have built
# and the rest of the string from the line as the suffix.
# For normal completion we add the rests of the filenames
# collected as the suffixes to make the completion code expand
# it as far as possible.
tmp2="$testpath"
compquote tmp1 tmp2
if [[ -n $menu || -z "$compstate[insert]" ]] ||
! zstyle -t ":completion:${curcontext}:paths" expand suffix; then
(( tmp4 )) && zstyle -t ":completion:${curcontext}:paths" cursor &&
compstate[to_end]=''
if [[ "$tmp3" = */* ]]; then
compadd -Qf "$mopts[@]" -p "$linepath$tmp2" -s "/${tmp3#*/}" \
-W "$prepath$realpath$testpath" \
"$pfxsfx[@]" -M "r:|/=* r:|=*" \
- "${(@)tmp1%%/*}"
else
compadd -Qf "$mopts[@]" -p "$linepath$tmp2" \
-W "$prepath$realpath$testpath" \
"$pfxsfx[@]" -M "r:|/=* r:|=*" \
- "$tmp1[@]"
fi
else
if [[ "$tmp3" = */* ]]; then
atmp=( -Qf "$mopts[@]" -p "$linepath$tmp2"
-W "$prepath$realpath$testpath"
"$pfxsfx[@]" -M "r:|/=* r:|=*" )
for i in "$tmp1[@]"; do
compadd "$atmp[@]" -s "/${i#*/}" - "${i%%/*}"
done
else
compadd -Qf "$mopts[@]" -p "$linepath$tmp2" \
-W "$prepath$realpath$testpath" \
"$pfxsfx[@]" -M "r:|/=* r:|=*" \
- "$tmp1[@]"
fi
fi
tmp4=-
break
fi
# If we have checked all components, we stop now and add the
# strings collected after the loop.
if [[ "$tmp3" != */* ]]; then
tmp4=""
break
fi
# Otherwise we add the unambiguous component to `testpath' and
# take it from the filenames.
testpath="${testpath}${tmp1[1]%%/*}/"
tmp1=( "${(@)tmp1#*/}" )
tmp3="${tmp3#*/}"
if [[ "$tpre" = */* ]]; then
cpre="${cpre}${tpre%%/*}/"
tpre="${tpre#*/}"
elif [[ "$tsuf" = */* ]]; then
cpre="${cpre}${tpre}/"
tpre="${tsuf#*/}"
tsuf=""
else
tpre=""
tsuf=""
fi
done
if [[ -z "$tmp4" ]]; then
if [[ "$osuf" = */* ]]; then
PREFIX="${opre}${osuf}"
SUFFIX=""
else
PREFIX="${opre}"
SUFFIX="${osuf}"
fi
tmp4="$testpath"
compquote tmp4 tmp1
compadd -Qf "$mopts[@]" -p "$linepath$tmp4" -W "$prepath$realpath$testpath" \
"$pfxsfx[@]" -M "r:|/=* r:|=*" - "$tmp1[@]"
fi
done
# If we are configured to expand paths as far as possible and we collected
# expanded paths that are different from the string on the line, we add
# them as possible matches.
if zstyle -t ":completion:${curcontext}:paths" expand prefix &&
[[ nm -eq compstate[nmatches] && $#exppaths -ne 0 &&
"$exppaths" != "$eorig" ]]; then
PREFIX="${opre}"
SUFFIX="${osuf}"
compadd -Q "$mopts[@]" -S '' -M "r:|/=* r:|=*" -p "$linepath" - "$exppaths[@]"
fi
[[ nm -ne compstate[nmatches] ]]

View file

@ -4,10 +4,10 @@
[[ -n "$SUFFIX" ]] || return 1
local curcontext="${curcontext/:[^:]#:/:prefix:}" comp i
local comp i
zstyle -a ":completion:${curcontext}:" completer comp ||
comp=( "${(@)_completers[1,-${#_completers_left}-1][(R)_prefix,-1]}" )
comp=( "${(@)_completers[1,_completer_num-1][(R)_prefix(|:*),-1]}" )
if zstyle -t ":completion:${curcontext}:" add-space; then
ISUFFIX=" $SUFFIX"

View file

@ -1,9 +1,20 @@
#autoload
local tag tname="$funcstack[2,-1]"
local gopt=-J
for tag; do
[[ "${_cur_tags[${tname}]}" = *:${tag}(:|\[*\]:)* ]] && return 0
done
if [[ "$1" = -([12]|)[VJ] ]]; then
gopt="$1"
shift
fi
return 1
if comptags -R "$1"; then
_comp_tags="$_comp_tags $1"
if [[ $# -gt 3 ]]; then
_all_labels "$gopt" "$@"
elif [[ $# -gt 1 ]]; then
_description "$gopt" "$@"
fi
return 0
else
return 1
fi

View file

@ -1,13 +1,61 @@
#autoload
local colors i
local val nm="$compstate[nmatches]"
for i; do
if _style -a "$i" list-colors colors; then
if [[ "$1" = default ]]; then
ZLS_COLORS="${(j.:.)${(@)colors:gs/:/\\\:}}"
else
eval "ZLS_COLORS=\"(${i})\${(j.:(${i}).)\${(@)colors:gs/:/\\\:}}:\${ZLS_COLORS}\""
fi
if zstyle -a ":completion:${curcontext}:$1" list-colors val; then
zmodload -i zsh/complist
if [[ "$1" = default ]]; then
ZLS_COLORS="${(j.:.)${(@)val:gs/:/\\\:}}"
else
eval "ZLS_COLORS=\"(${1})\${(j.:(${1}).)\${(@)val:gs/:/\\\:}}:\${ZLS_COLORS}\""
fi
done
# Here is the problem mentioned in _main_complete.
# elif [[ "$1" = default && -n "$ZLS_COLORS$ZLS_COLOURS" ]]; then
# zmodload -i zsh/complist
# ZLS_COLORS="$ZLS_COLORS$ZLS_COLOURS"
fi
if zstyle -t ":completion:${curcontext}:$1" list-packed; then
compstate[list]="${compstate[list]} packed"
elif [[ $? -eq 1 ]]; then
compstate[list]="${compstate[list]:gs/packed//}"
else
compstate[list]="$_saved_list"
fi
if zstyle -t ":completion:${curcontext}:$1" list-rows-first; then
compstate[list]="${compstate[list]} rows"
elif [[ $? -eq 1 ]]; then
compstate[list]="${compstate[list]:gs/rows//}"
else
compstate[list]="$_saved_list"
fi
if zstyle -t ":completion:${curcontext}:$1" last-prompt; then
compstate[last_prompt]=yes
elif [[ $? -eq 1 ]]; then
compstate[last_prompt]=''
else
compstate[last_prompt]="$_saved_lastprompt"
fi
if zstyle -t ":completion:${curcontext}:$1" accept-exact; then
compstate[exact]=accept
elif [[ $? -eq 1 ]]; then
compstate[exact]=''
else
compstate[exact]="$_saved_exact"
fi
[[ _last_nmatches -ge 0 && _last_nmatches -ne nm ]] &&
_menu_style=( "$_last_menu_style[@]" "$_menu_style[@]" )
if zstyle -a ":completion:${curcontext}:$1" menu val; then
_last_nmatches=$nm
_last_menu_style=( "$val[@]" )
else
_last_nmatches=-1
fi

View file

@ -1,81 +1,83 @@
#autoload
if (( $# )); then
local cmd="$words[1]" func="$funcstack[2]" defs i tags tag pat style prio
local prev
while getopts 'c:f:' i; do
if [[ "$i" = c ]]; then
cmd="$OPTARG"
else
func="$OPTARG"
fi
done
# A `--' as the first argument says that we should tell comptags to use
# the preceding function nesting level. This is only documented here because
# if everythings goes well, users won't have to worry about it and should
# not mess with it.
shift OPTIND-1
defs=( "${(@M)argv:#${(kj:|:)~override_tags[(R)(|+*)]}}" )
(( $#defs )) && set -- "$defs[@]"
_offered_tags=( "$_offered_tags[@]" "$@" )
_last_tags=()
defs=()
for i; do
if [[ -n ${override_tags[$i]} && ${override_tags[$i]} != (\[|+\[)* ]]; then
if [[ ${override_tags[$i]} = *\[* ]]; then
prio=( "${i}:*=${override_tags[$i]#+}" )
else
prio=( "${i}:${(@v)^comptags[(I)(|*:)${i}(|:*)]}" )
(( $#prio )) || prio=( "${i}:${comptags[any]}" )
prio="${${${prio[(r)(|*:)\*=[^:]#\[*\](|:*)]}##(|*:)\*}%%:*}"
prio=( "${i}:*=${override_tags[$i]#+}${(M)prio%%\[*\]}" )
fi
else
prio=( "${i}:${(@v)^comptags[(I)(|*:)${i}(|:*)]}" )
(( $#prio )) || prio=( "${i}:${comptags[any]}" )
fi
defs=( "$defs[@]" "$prio[@]" )
done
tags=()
for i in "$defs[@]"; do
tag="${i%%:*}"
for pat in "${(s.:.)i#*:}"; do
if [[ ( "$pat" = _* && "$func" = ${~pat%%\=*} ) ||
"$cmd" = ${~pat%%\=*} ]]; then
prio="${pat#*\=}"
[[ "$prio" = -* ]] && continue 2
if [[ "$prio" = *\[*\] ]]; then
style="${(M)prio%%\[*}"
prio="${prio%%\[*}"
else
style=''
fi
[[ ${override_tags[$tag]} = (|+)\[* ]] &&
style="${override_tags[$tag]#+}"
(( prio++ ))
tags[$prio]="${tags[$prio]}:${tag}${style}"
break
fi
done
done
prios=( "${(@)tags:#}" )
return 0
if [[ "$1" = -- ]]; then
prev=-
shift
fi
_failed_tags=( "$_failed_tags[@]" "$_last_tags[@]" )
if (( $# )); then
(( $#prios )) || return 1
# We have arguments: the tags supported in this context.
tags="${prios[1]}:"
shift 1 prios
local curcontext="$curcontext" order tag nodef tmp
_last_tags=( "${(@s.:.)${${tags#:}%:}}" )
_tried_tags=( "$_tried_tags[@]" "$_last_tags[@]" )
if [[ "$1" = -C?* ]]; then
curcontext="${curcontext%:*}:${1[3,-1]}"
shift
elif [[ "$1" = -C ]]; then
curcontext="${curcontext%:*}:${2}"
shift 2
else
targs=()
fi
return 0
[[ "$1" = -(|-) ]] && shift
if zstyle -a ":completion:${curcontext}:" group-order order; then
local name
for name in "$order[@]"; do
compadd -J "$name"
compadd -V "$name"
compadd -J "$name" -1
compadd -V "$name" -1
compadd -J "$name" -2
compadd -V "$name" -2
done
fi
# Set and remember offered tags.
comptags "-i$prev" "$curcontext" "$@"
# Sort the tags.
if [[ -n "$_sort_tags" ]]; then
"$_sort_tags" "$@"
else
zstyle -a ":completion:${curcontext}:" tag-order order ||
order=('arguments values' options)
for tag in $order; do
case $tag in
-) nodef=yes;;
*\(\)) if ! "${${tag%%[ ]#\(\)}##[ ]#}" "$@"; then
nodef=yes
break
fi
;;
\!*) comptry "${(@)argv:#(${(j:|:)~${=~tag[2,-1]}})}";;
?*) comptry -m "$tag";;
esac
done
[[ -z "$nodef" ]] && comptry "$@"
fi
# Return non-zero if at least one set of tags should be used.
comptags "-T$prev"
return
fi
# The other mode: switch to the next set of tags.
comptags "-N$prev"

View file

@ -1,6 +1,6 @@
#autoload
local targs
local targs gopt=-J
if [[ "$1" = -C?* ]]; then
targs=( -C "${1[3,-1]}" )
@ -12,10 +12,22 @@ else
targs=()
fi
[[ "$1" = -(|-) ]] && shift
if [[ $# -gt 1 ]]; then
_tags "$targs[@]" "$1" && _description "${(@)argv[2,-1]}"
else
_tags "$targs[@]" "$1"
if [[ "$1" = -([12]|)[VJ] ]]; then
gopt="$1"
shift
fi
if [[ $# -gt 3 ]]; then
if _tags "$targs[@]" "$1"; then
_comp_tags="$_comp_tags $1"
_all_labels -t "$gopt" "$@"
else
return 1
fi
elif [[ $# -gt 1 ]]; then
_tags -- "$targs[@]" "$1" && _comp_tags="$_comp_tags $1" &&
_description "$gopt" "$@"
else
_tags -- "$targs[@]" "$1" && _comp_tags="$_comp_tags $1"
fi

View file

@ -1,4 +1,4 @@
# This is a file to be sourced to dump the definitions for new-style
# This is a function to dump the definitions for new-style
# completion defined by 'compinit' in the same directory. The output
# should be directed into the "compinit.dump" in the same directory as
# compinit. If you rename init, just stick .dump onto the end of whatever
@ -9,33 +9,46 @@
# To do this, simply remove the .dump file, start a new shell, and
# create the .dump file as before. Again, compinit -d handles this
# automatically.
#
# It relies on KSH_ARRAYS not being set.
# Print the number of files used for completion. This is used in compinit
# to see if auto-dump should re-dump the dump-file.
_d_file=${COMPDUMP-${0:h}/compinit.dump}
emulate -L zsh
setopt extendedglob
typeset _d_file _d_f _d_bks _d_line _d_als
_d_file=${_comp_dumpfile-${0:h}/compinit.dump}.$HOST.$$
typeset -U _d_files
_d_files=( ${^~fpath}/_*~*~(N:t) )
_d_files=( ${^~fpath:/.}/^([^_]*|*~|*.zwc)(N:t) )
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 ${(ok)_comps}; do
print -r - "'${_d_f//\'/'\\''}'" "'${_comps[$_d_f]//\'/'\\''}'"
print -r - "${(q)_d_f}" "${(q)_comps[$_d_f]}"
done >> $_d_file
print ")" >> $_d_file
print "\n_patcomps=(" >> $_d_file
for _d_f in "$_patcomps[@]"; do
print -r - "'${_d_f//\'/'\\''}'"
for _d_f in "${(ok@)_patcomps}"; do
print -r - "${(q)_d_f}" "${(q)_patcomps[$_d_f]}"
done >> $_d_file
print ")" >> $_d_file
print "\n_postpatcomps=(" >> $_d_file
for _d_f in "${(ok@)_postpatcomps}"; do
print -r - "${(q)_d_f}" "${(q)_postpatcomps[$_d_f]}"
done >> $_d_file
print ")" >> $_d_file
print "\n_compautos=(" >> $_d_file
for _d_f in "${(ok@)_compautos}"; do
print -r - "${(q)_d_f}" "${(q)_compautos[$_d_f]}"
done >> $_d_file
print ")" >> $_d_file
@ -44,11 +57,13 @@ 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.
# We can ignore any zle -C which rebinds a standard widget (second
# argument to zle does not begin with a `_').
_d_bks=()
zle -lL |
while read -rA _d_line; do
if [[ ${_d_line[5]} = _* ]]; then
if [[ ${_d_line[3]} = _* && ${_d_line[5]} = _* ]]; then
print -r - ${_d_line}
_d_bks=($_d_bks ${_d_line[3]})
fi
@ -73,17 +88,26 @@ done))
# print them out: about five to a line looks neat
_i=5
print -n autoload -U >> $_d_file
while (( $#_d_als )); do
print -n autoload
for (( _i = 0; _i < 5; _i++ )); do
if (( $#_d_als )); then
print -n " $_d_als[1]"
shift _d_als
if (( ! $+_compautos[$_d_als[1]] )); then
print -n " $_d_als[1]"
if (( _i-- && $#_d_als > 1 )); then
_i=5
print -n '\nautoload -U'
fi
done
print
fi
shift _d_als
done >> $_d_file
print >> $_d_file
unset _d_line _d_zle _d_bks _d_als _d_f _f_file
for _i in "${(ok@)_compautos}"; do
print "autoload -U $_compautos[$_i] $_i" >> $_d_file
done
mv $_d_file ${_d_file%.$HOST.$$}
unfunction compdump
autoload -U compdump

View file

@ -1,25 +1,23 @@
# Initialisation for new style completion. This mainly contains some helper
# function and aliases. Everything else is split into different files in this
# directory that will automatically be made autoloaded (see the end of this
# file).
# functions and aliases. Everything else is split into different files 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 a underscores (like `_setopt).
# start with an underscores (like `_setopt').
# The first line of these files will be read and has to say what should be
# done with its contents:
#
# `#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
# `#compdef <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 <names> are given.
#
# `#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
# `#compdef -p <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.
#
# `#defkeycomp <style> [ <key-sequence> ... ]
# this is used to bind special completions to all the given
# `#compdef -k <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,
# expand-or-complete, expand-or-complete-prefix, list-choices,
@ -29,35 +27,89 @@
# 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.
#
# `#autoload'
# this is for helper functions that are not used to
# `#compdef -K <widget-name> <style> <key-sequence> [ ... ]'
# This is similar to -k, except it takes any number of sets of
# three arguments. In each set, the widget <widget-name> will
# be defined, which will behave as <style>, as with -k, and will
# be bound to <key-sequence>, exactly one of which must be defined.
# <widget-name> must be different for each: this must begin with an
# underscore, else one will be added, and should not clash with other
# completion widgets (names based on the name of the function are the
# clearest), but is otherwise arbitrary. It can be tested in the
# function by the parameter $WIDGET.
#
# `#autoload [ <options> ]'
# This is for helper functions that are not used to
# generate matches, but should automatically be loaded
# when they are called
# when they are called. The <options> will be given to the
# autoload builtin when making the function autoloaded. Note
# that this need not include `-U'.
#
# Note that no white space is allowed between the `#' and the rest of
# the string.
#
# See the file `compdump' for how to speed up initialiation.
# Functions that are used to generate matches should return zero if they
# were able to add matches and non-zero otherwise.
#
# If you are using global matching specifications with `compctl -M ...'
# have a look at the files `_match_test' and `_match_pattern'. To make
# all the example functions use matching as specified with `-M' these
# need some editing.
#
# If we got the `-d'-flag, we will automatically dump the new state (at
# the end).
# See the file `compdump' for how to speed up initialisation.
if [[ "$1" = -d ]]; then
_i_autodump=1
else
_i_autodump=0
fi
# If we got the `-d'-flag, we will automatically dump the new state (at
# the end). This takes the dumpfile as an argument. -d (with the
# default dumpfile) is now the default; to turn off dumping use -D.
emulate -L zsh
setopt extendedglob
typeset _i_dumpfile _i_files _i_line _i_done _i_dir _i_autodump=1
typeset _i_tag _i_file _i_addfiles
while [[ $# -gt 0 && $1 = -[dDf] ]]; do
if [[ "$1" = -d ]]; then
_i_autodump=1
shift
if [[ $# -gt 0 && "$1" != -[df] ]]; then
_i_dumpfile="$1"
shift
fi
elif [[ "$1" = -D ]]; then
_i_autodump=0
shift
elif [[ "$1" = -f ]]; then
# Not used any more; use _compdir
shift
shift
fi
done
# The associative array containing the definitions for the commands.
# Definitions for patterns will be stored in the normal array `_patcomps'.
# Definitions for patterns will be stored in the associations `_patcomps'
# and `_postpatcomps'. `_compautos' contains the names and options
# for autoloaded functions that get options.
typeset -A _comps
_patcomps=()
typeset -gA _comps _patcomps _postpatcomps _compautos
# The associative array use to report information about the last
# cmpletion to the outside.
typeset -gA _lastcomp
# Remember dumpfile.
if [[ -n $_i_dumpfile ]]; then
# Explicitly supplied dumpfile.
_comp_dumpfile="$_i_dumpfile"
else
_comp_dumpfile="${ZDOTDIR:-$HOME}/.zcompdump"
fi
# These can hold names of functions that are to be called before/after all
# matches have been generated.
compprefuncs=()
comppostfuncs=()
# Loading it now ensures that the `funcstack' parameter is always correct.
: $funcstack
# This function is used to register or delete completion functions. For
# registering completion functions, it is invoked with the name of the
@ -70,6 +122,9 @@ _patcomps=()
# function will be invoked when completing for a command whose name
# matches the pattern given as argument after the function name (in this
# case only one argument is accepted).
# The option `-P' is like `-p', but the function will be called after
# trying to find a function defined for the command on the line if no
# such function could be found.
# With the `-k' option a function for a special completion keys is
# defined and immediatly bound to those keys. Here, the extra arguments
# are the name of one of the builtin completion widgets and any number
@ -78,7 +133,8 @@ _patcomps=()
# whose name is given as the first argument be autoloaded. When defining
# a function for command names the `-n' option may be given and keeps
# the definitions from overriding any previous definitions for the
# commands.
# commands; with `-k', the `-n' option prevents compdef from rebinding
# a key sequence which is already bound.
# For deleting definitions, the `-d' option must be given. Without the
# `-p' option, this deletes definitions for functions for the commands
# whose names are given as arguments. If combined with the `-p' option
@ -110,11 +166,16 @@ compdef() {
# Get the options.
while getopts "anpkd" opt; do
if [[ $#* -eq 0 ]]; then
echo "compdef needs parameters"
return 1
fi
while getopts "anpPkKd" opt; do
case "$opt" in
a) autol=yes;;
n) new=yes;;
[pk]) if [[ -n "$type" ]]; then
[pPkK]) if [[ -n "$type" ]]; then
# Error if both `-p' and `-k' are given (or one of them
# twice).
echo "$0: type already set to $type"
@ -122,6 +183,10 @@ compdef() {
fi
if [[ "$opt" = p ]]; then
type=pattern
elif [[ "$opt" = P ]]; then
type=postpattern
elif [[ "$opt" = K ]]; then
type=widgetkey
else
type=key
fi
@ -131,12 +196,17 @@ compdef() {
done
shift OPTIND-1
if [[ $#* -eq 0 ]]; then
echo "compdef needs parameters"
return 1
fi
if [[ -z "$delete" ]]; then
# Adding definitions, first get the name of the function name
# and probably do autoloading.
func="$1"
[[ -n "$autol" ]] && autoload "$func"
[[ -n "$autol" ]] && autoload -U "$func"
shift
case "$type" in
@ -145,11 +215,33 @@ compdef() {
echo "$0: only one pattern allowed"
return 1
fi
# Patterns are stored in strings like `c* foo', with a space
# between the pattern and the function name.
_patcomps=("$_patcomps[@]" "$1 $func")
_patcomps[$1]="$func"
;;
postpattern)
if [[ $# -gt 1 ]]; then
echo "$0: only one pattern allowed"
return 1
fi
_postpatcomps[$1]="$func"
;;
widgetkey)
while [[ -n $1 ]]; do
if [[ $# -lt 3 ]]; then
echo "$0: compdef -K requires <widget> <comp-widget> <key>"
return 1
fi
[[ $1 = _* ]] || 1="_$1"
[[ $2 = .* ]] || 2=".$2"
zle -C "$1" "$2" "$func"
if [[ -n $new ]]; then
bindkey "$3" | read -A opt
[[ $opt[-1] = undefined-key ]] && bindkey "$3" "$1"
else
bindkey "$3" "$1"
fi
shift 3
done
;;
key)
if [[ $# -lt 2 ]]; then
echo "$0: missing keys"
@ -157,30 +249,44 @@ compdef() {
fi
# Define the widget.
zle -C "$func" "$1" "$func"
if [[ $1 = .* ]]; then
zle -C "$func" "$1" "$func"
else
zle -C "$func" ".$1" "$func"
fi
shift
# And bind the keys...
for i; do
if [[ -n $new ]]; then
bindkey "$i" | read -A opt
[[ $opt[-1] = undefined-key ]] || continue
fi
bindkey "$i" "$func"
done
;;
*)
# For commands store the function name in the `_comps'
# associative array, command names as keys.
for i; do
[[ -z "$new" || "${+_comps[$i]}" -eq 0 ]] && _comps[$i]="$func"
done
if [[ -z "$new" ]]; then
for i; do
_comps[$i]="$func"
done
else
for i; do
[[ "${+_comps[$i]}" -eq 0 ]] && _comps[$i]="$func"
done
fi
;;
esac
else
# Handle the `-d' option, deleting.
case "$type" in
pattern)
# Note the space.
for i; do
_patcomps=("${(@)patcomps:#$i *}")
done
unset "_patcomps[$^@]"
;;
postpattern)
unset "_postpatcomps[$^@]"
;;
key)
# Oops, cannot do that yet.
@ -189,81 +295,210 @@ compdef() {
return 1
;;
*)
# Deleting definitons for command is even simpler.
for i; do
unset "_comps[$i]"
done
unset "_comps[$^@]"
esac
fi
}
# Do *not* use this...
compconf() {
local style name val i tmp cmt
if [[ -z "$_compconf_warn" ]]; then
_compconf_warn=yep
print "
Hello
\`compconf' will be removed in the near future, we now use a more
general (and powerful) mechanism using the \`zstyle' builtin. An
approximation to your old setup using \`zstyle' should be available
in the file:
\`${HOME}/.zsh-styles'
Note that the values for the styles may be partly incorrect. Please
read the manual to find out how to configure the completion system
with styles.
Have fun
Sven
" 1>&2
command rm -f ${HOME}/.zsh-styles
fi
for i; do
name="${i%%\=*}"
val="${i#*\=}"
tmp=''
cmt=''
case "$name" in
urls_path)
tmp="'*:urls' path ${(qq)val}"
;;
urls_localhttp)
tmp="'*:urls' local ${${(qqs.:.)val}}"
;;
describe_options)
tmp="'*:options' verbose 'yes'"
;;
describe_values)
tmp="'*:values' verbose 'yes'"
;;
autodescribe_options)
tmp="'*:options' auto-description ${(qq)val}"
;;
description_format)
tmp="'*:descriptions' format ${(qq)val}"
;;
message_format)
tmp="'*:messages' format ${(qq)val}"
;;
warning_format)
tmp="'*:warnings' format ${(qq)val}"
;;
option_prefix)
tmp="'*:options' prefix-needed yes"
[[ "$val" = hide* ]] &&
tmp="$tmp
zstyle ':completion:*:options' prefix-hidden yes"
;;
group_matches)
tmp="'*' group-name ''"
;;
colors_path)
tmp="'*:colors' path ${(qq)val}"
;;
path_expand)
tmp="'*:paths' expand ${(qq)val}"
;;
path_cursor)
tmp="'*:paths' cursor ${(qq)val}"
;;
(approximate|incremental|predict|list|oldlist|match)_*)
tmp="'*${name%%_*}:*' ${${name#*_}//_/-} ${(qq)val}"
;;
correct_*)
cmt="# This one is a bit ugly. You may want to use only \`*:correct'
# if you also have the \`correctword_*' or \`approximate_*' keys.
"
tmp="'*(correct(|-word)|approximate):*' ${name#*_} ${(qq)val}"
;;
correctword_*)
tmp="'*:correct-word' ${name#correctword_} ${(qq)val}"
;;
expand_*)
cmt="# This one is a bit ugly. You may want to use only \`*:expand'
# if you also have the \`expandword_*' keys.
"
tmp="'*expand(|expand-word):*' ${name#*_} ${(qq)val}"
;;
expandword_*)
tmp="'expand-word:*' ${name#expandword_} ${(qq)val}"
;;
history_*)
tmp="'history-words:*' ${name#history_} ${(qq)val}"
;;
completer)
tmp="'*' completer ${${(qqs.:.)val}}"
;;
last_prompt)
tmp="'*' last-prompt 'yes'"
;;
esac
[[ -n "$tmp" ]] && style="${style}${cmt}zstyle :completion:${tmp}
"
done
eval "${style}"
print "$style" >>! ${HOME}/.zsh-styles
}
# Now we automatically make the definition files autoloaded.
# First we get the name of a dump file if this will be used.
: ${COMPDUMP:=$0.dump}
if [[ ! -o extendedglob ]]; then
_i_noextglob=yes
setopt extendedglob
typeset -U _i_files
_i_files=( ${^~fpath:/.}/^([^_]*|*~|*.zwc)(N:t) )
if [[ $#_i_files -lt 20 || $_compdir = */Core || -d $_compdir/Core ]]; then
# Too few files: we need some more directories,
# or we need to check that all directories (not just Core) are present.
if [[ -n $_compdir ]]; then
_i_addfiles=()
if [[ $_compdir = */Core ]]; then
# Add all the Completion subdirectories
_i_addfiles=(${_compdir:h}/*(/))
elif [[ -d $_compdir/Core ]]; then
# Likewise
_i_addfiles=(${_compdir}/*(/))
fi
for _i_line in {1..$#i_addfiles}; do
_i_file=${_i_addfiles[$_i_line]}
[[ -d $_i_file && -z ${fpath[(r)$_i_file]} ]] ||
_i_addfiles[$_i_line]=
done
fpath=($fpath $_i_addfiles)
_i_files=( ${^~fpath:/.}/^([^_]*|*~|*.zwc)(N:t) )
fi
fi
typeset -U _i_files
_i_files=( ${^~fpath}/_*~*~(N:t) )
_i_initname=$0
# Rebind the standard widgets
for _i_line in complete-word delete-char-or-list expand-or-complete \
expand-or-complete-prefix list-choices menu-complete \
menu-expand-or-complete reverse-menu-complete; do
zle -C $_i_line .$_i_line _main_complete
done
zle -la menu-select && zle -C menu-select .menu-select _main_complete
_i_done=''
# Make sure compdump is available, even if we aren't going to use it.
autoload -U compdump compinstall
# If we have a dump file, load it.
if [[ -f "$COMPDUMP" ]]; then
read -rA _i_line < "$COMPDUMP"
if [[ -f "$_comp_dumpfile" ]]; then
read -rA _i_line < "$_comp_dumpfile"
if [[ _i_autodump -eq 1 && $_i_line[2] -eq $#_i_files ]]; then
builtin . "$COMPDUMP"
builtin . "$_comp_dumpfile"
_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
for _i_file in $_i_dir/^([^_]*|*~|*.zwc)(N); do
read -rA _i_line < $_i_file
_i_tag=$_i_line[1]
shift _i_line
if [[ $_i_tag = '#defcomp' ]]; then
compdef -na "${_i_file:t}" "${_i_line[@]}"
elif [[ $_i_tag = '#defpatcomp' ]]; then
compdef -pa "${_i_file:t}" "${_i_line[@]}"
elif [[ $_i_tag = '#defkeycomp' ]]; then
compdef -ka "${_i_file:t}" "${_i_line[@]}"
elif [[ $_i_tag = '#autoload' ]]; then
autoload ${_i_file:t}
fi
case $_i_tag in
(\#compdef)
if [[ $_i_line[1] = -[pPkK](n|) ]]; then
compdef ${_i_line[1]}na "${_i_file:t}" "${(@)_i_line[2,-1]}"
else
compdef -na "${_i_file:t}" "${_i_line[@]}"
fi
;;
(\#autoload)
autoload -U "$_i_line[@]" ${_i_file:t}
[[ "$_i_line" != \ # ]] && _compautos[${_i_file:t}]="$_i_line"
;;
esac
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
# If autodumping was requested, do it now.
(( _i_autodump )) && builtin . ${_i_initname:h}/compdump
if [[ $_i_autodump = 1 ]]; then
compdump
fi
fi
[[ -z "$_i_noextglob" ]] || unsetopt extendedglob
unset _i_files _i_initname _i_done _i_autodump _i_noextglob
unfunction compinit
autoload -U compinit

View file

@ -1,72 +1,149 @@
# This script is to be run by a user to setup the new function based
# This script is to be run by a user to set up the new function based
# completion system. The functions themselves are assumed to be already
# available in some directory; they should have been installed with the
# the shell (except we haven't written that yet).
# the shell. If they have been, the commands `autoload -U compinit; compinit'
# in the shell startup file should be enough, although you can run
# compinstall for more configuration choices.
#
# Run it as a script under zsh and answer the questions.
# You can run it as `zsh compinstall $FPATH' and it will be able to check
# your function path for the completion functions.
#
# Normally, this will alter ~/.zshrc (or wherever ZDOTDIR puts it),
# but you can make that unwritable and it will leave the lines in a
# temporary file instead.
#
# You can use this script to modify what compinstall previously
# added to ~/.zshrc.
# Simply run this script as a function and answer the questions.
# Normally it will alter ~/.zshrc (or wherever ZDOTDIR puts it), but you
# can make that unwritable and it will leave the lines in a temporary file
# instead. It doesn't matter if .zshrc didn't exist before. If your
# .zshrc usually exits before the end, then you should take the code added
# by compinstall and put it (including the comment lines at the start and
# end) at the point you want it to be executed. If you run compinstall
# again it will find and replace those lines, so you can use this script to
# modify what compinstall previously added to ~/.zshrc.
#
# It is safe to abort with ^C any time you are being prompted for
# information; your .zshrc will not be altered.
#
# To do:
# - Maybe this should be sourced, then it can check the user's current
# setup better. But then there is a potentially horrendous option
# setting/resetting problem. (Maybe we need another way of doing that.)
# - Should probably offer to set different options for _approximate than
# for _complete if both are used.
# - Could add code for setting other completers and options.
# - Could add keys for context-sensitive help.
# - Probably should allow a set of directories to be added to $fpath,
# like Core, Base, etc.
# In case a startup script changed options
emulate zsh
[[ -n $1 ]] && FPATH=$1
emulate -L zsh
for f in $fpath; do
if [[ $f != . && -f $f/compinit && -f $f/compdump ]]; then
fdir=$f
break
fi
done
typeset _ci_options _ci_f _ci_fdir _ci_files _ci_dumpfile _ci_lines
typeset _ci_type _ci_completer _ci_accept _ci_cprompt _ci_startline
typeset _ci_endline _ci_ifile _ci_tmpf _ci_compstyle _ci_warn
typeset _ci_dtype _ci_existing _ci_line _ci_end
if [[ -z $fdir ]]; then
print "Trying to find where the completion functions are..."
if [[ $0 = */* && -f $0:h/compinit && -f $0:h/compdump ]]; then
fdir=$0:h
else
# more guesses?
print \
# Look for the defaults.
_ci_startline='# The following lines were added by compinstall'
_ci_endline='# End of lines added by compinstall'
_ci_ifile=${ZDOTDIR:-~}/.zshrc
_ci_lines=''
_ci_existing=''
typeset -A _ci_defaults
if [[ -f $_ci_ifile ]]; then
# This assumes the lines haven't been altered by the user too much
# after they were added.
_ci_compstyle=0
sed -n "/^$_ci_startline/,/^$_ci_endline/p" $_ci_ifile |
while read -rA _ci_line; do
if (( $_ci_compstyle )); then
# parse a compstyle component as first argument
if [[ $_ci_line[-1] != \\ ]]; then
_ci_end=-1
_ci_compstyle=0
else
_ci_end=-2
fi
if [[ $_ci_line[1] = *=* ]]; then
_ci_f="${${_ci_line[1,$_ci_end]}#*=}"
if [[ $_ci_f = \'*\' ]]; then
# strip quotes
_ci_f=${_ci_f[2,-2]//\'\\\'\'/\'}
fi
_ci_defaults[${_ci_line[1]%%\=*}]=$_ci_f
fi
_ci_existing="${_ci_existing} $_ci_line
"
elif [[ $_ci_line[1] = compinit ]]; then
# parse the line running compinit
[[ $_ci_line[2] = -f ]] && _ci_fdir=$_ci_line[3]
[[ $_ci_line[-2] = -d ]] && _ci_dumpfile=$_ci_line[-1]
elif [[ $_ci_line[1] = _compdir=* ]]; then
_ci_fdir=${_ci_line[1]##_compdir=}
elif [[ $_ci_line[1] = compstyle ]]; then
# parse a compstyle component as second argument (should be completer)
[[ $_ci_line[3] = completer ]] &&
_ci_completer=${_ci_line[3,-1]}
[[ $_ci_line[-1] == \\ ]] && _ci_compstyle=1
_ci_existing="${_ci_existing}$_ci_line
"
elif [[ $_ci_line[1] != \#* && $_ci_line[1] != (autoload|\[\[) ]]; then
if [[ -z $_ci_warn ]]; then
_ci_warn=1
print "Warning: existing lines in compinstall setup not understood:"
fi
print - $_ci_line
_ci_existing="${_ci_existing}$_ci_line
"
fi
done
fi
# Find out where the completion functions are kept.
if [[ -z $_ci_fdir || ! -f ${~_ci_fdir}/compinit ||
! -f ${~_ci_fdir}/compdump ]]; then
for _ci_f in $fpath; do
if [[ $_ci_f != . && -f $_ci_f/compinit && -f $_ci_f/compdump ]]; then
_ci_fdir=$_ci_f
break
elif [[ $_ci_f != . && -f $_ci_f/Core/compinit &&
-f $_ci_f/Core/compdump ]]
then
_ci_fdir=$_ci_f/Core
break
fi
done
fi
if [[ -z $_ci_fdir || ! -d ${~_ci_fdir} ]]; then
print \
"Please edit the name of the directory where the completion functions are
installed. If they are not installed, you will need to find them in the
Completion/* directories of the zsh distribution and install them yourself,
or insult your system manager for incompetence."
vared -c fdir
while [[ ! -d ${~fdir} || ! -f ${~fdir}/compinit ||
! -f ${~fdir}/compdump ]]; do
print "I can't find them in that directory. Try again or abort."
vared fdir
done
vared -c _ci_fdir
while [[ ! -d ${~_ci_fdir} ||
((! -f ${~_ci_fdir}/compinit || ! -f ${~_ci_fdir}/compdump) &&
(! -f ${~_ci_fdir}/Core/compinit || ! -f ${~_ci_fdir}/Core/compdump)) ]]
do
print "I can't find them in that directory. Try again or abort."
vared _ci_fdir
done
if [[ -f ${~_ci_fdir}/Core/compinit && ! -f ${~_ci_fdir}/compinit ]]; then
_ci_fdir=$_ci_fdir/Core
fi
eval "fpath=($fdir \$fpath)"
fdir=${fdir/#$HOME/\~}
lines="fpath=($fdir \$fpath)\n"
else
print "Found completion functions in your fpath, will not alter it."
print "Keeping existing completion directiory $_ci_fdir"
fi
files=( ${^~fpath:/.}/_(|*[^~])(N:t) )
if [[ $#files -lt 20 ]]; then
if [[ ${~_ci_fdir} != /* ]]; then
_ci_fdir=$(cd $_ci_fdir;builtin pwd)
fi
# Check if this is in fpath already, else put it there (with ~'s expanded).
_ci_f=${~_ci_fdir}
[[ -z ${fpath[(r)$_ci_f]} ]] && fpath=($fpath $_ci_f)
# Contract $HOME to ~ in the parameter to be used for writing.
_ci_fdir=${_ci_fdir/#$HOME/\~}
# Now check the fpath, ignoring the directory .
_ci_files=( ${^~fpath:/.}/_(|*[^~])(N:t) )
if [[ $#_ci_files -lt 20 ]]; then
print "
Hmmm, completion functions seem a bit thin on the ground. There should
be lots of files with names beginning with an underscore (_). You should
@ -75,12 +152,20 @@ look and see what's happened to these.
read
fi
if [[ -w ${~fdir} && ( ! -f ${~fdir}/compinit.dump ||
-w ${~fdir}/compinit.dump ) ]]
# Set up the dumpfile
_ci_dtype=existing
if [[ -z $_ci_dumpfile ]]; then
_ci_dumpfile="${ZDOTDIR:-$HOME}/.zcompdump"
_ci_dtype=standard
fi
if [[ -w ${~_ci_dumpfile:h} && ( ! -f ${~_ci_dumpfile} ||
-w ${~_ci_dumpfile} ) ]]
then
print "
Using standard dumpfile
${~fdir}/compinit.dump
Using $_ci_dtype dumpfile
${_ci_dumpfile}
to speed up initialisation.
[Hit return to continue]"
read
@ -88,23 +173,32 @@ else
print "
I will force completion to dump its status, which will speed up the shell's
start-up considerably. However, I can't write the file I'd like to, namely
$fdir/compinit.dump. Please edit a replacement."
dumpfile='~/.compinit.dump'
vared dumpfile
while ! touch ${~dumpfile} >& /dev/null; do
${_ci_dumpfile}. Please edit a replacement."
vared _ci_dumpfile
while ! touch ${~_ci_dumpfile} >& /dev/null; do
print "Sorry, I can't write that either. Try again."
vared dumpfile
vared _ci_dumpfile
done
[[ -s $dumpfile ]] || rm -f $dumpfile
dumpfile=" $dumpfile"
[[ -s $_ci_dumpfile ]] || rm -f $_ci_dumpfile
fi
fdir=${fdir/#$HOME/\~}
lines="${lines}. $fdir/compinit -d$dumpfile\n"
_ci_lines="${_ci_lines}_compdir=$_ci_fdir
[[ -z \$fpath[(r)\$_compdir] ]] && fpath=(\$fpath \$_compdir)
autoload -U compinit
compinit"
[[ $_ci_dtype != standard ]] && _ci_lines="${_ci_lines} $_ci_dumpfile"
_ci_lines="${_ci_lines}
"
print "
Would you like to set some more advanced options? Otherwise, you
can re-run compinstall later to set these. [n]"
# The whole of the next part should be indented, but I can't be bothered.
if read -q; then
print "
In addition to completion, zsh can also perform correction of the
current word, or approximate completion, i.e. completion where the part of
the word typed so far can be corrected; or it can try correction, then
@ -112,105 +206,156 @@ approximate completion if that fails. Would you like:
0: Just ordinary completion
C: Correction
A: Approximate completion
B: Both?
Please type one of the keys above:"
while read -k type; do
print
case $type in
0*) completer=_complete
break
;;
[cC]*) completer=_complete:_correct
break
;;
[aA]*) completer=_complete:_approximate
break;
;;
[bB]*) completer=_complete:_correct:_approximate
break
;;
*) print Try again
;;
esac
done
B: Both"
if [[ -n $_ci_completer ]]; then
print " Default: use the current completers:\n$_ci_completer"
else
print "Please type one of the keys above."
fi
while read -k _ci_type; do
print
case $_ci_type in
0*) _ci_completer=_complete
break
;;
[cC]*) _ci_completer='_complete _correct'
break
;;
[aA]*) _ci_completer='_complete _approximate'
break;
;;
[bB]*) _ci_completer='_complete _correct _approximate'
break
;;
*) [[ -n $_ci_completer ]] && break
print Try again
;;
esac
done
lines="${lines}compconf completer=$completer"
_ci_lines="${_ci_lines}zstyle ':completion*' completer $_ci_completer"
if [[ $completer = *(correct|approx)* ]]; then
print "
Correction and approximation will normally allow up to two errors,
and you will be able to use a numeric prefix (e.g. <Esc>4) to allow
more. The standard prompt is \`correct to:'. Do you want to change
any of this? [n]"
if read -q; then
print "Number of errors to accept normally (0 is OK):"
read accept
while [[ $accept != <-> ]]; do
read accept"?Please enter a number: "
done
print \
if [[ $_ci_completer = *(correct|approx)* ]]; then
_ci_accept=${_ci_defaults[correct_accept]}
_ci_cprompt=${_ci_defaults[correct_prompt]}
print "
Correction and approximation will allow up to ${${_ci_accept:-2}%%[^0-9]*} \
errors. "
case $_ci_accept in
*n*!*|*!*n) print "A numeric prefix, if not 1, will cause correction \
not to be done."
;;
*n*) print "A numeric prefix gives the maximum number of errors which \
will be accepted."
;;
*) print "The numeric prefix will not be used."
esac
print "The correction prompt is \`${_ci_cprompt:-correct to:}'.
Do you want to change any of this? [n]"
if read -q; then
print "Number of errors to accept normally (0 is OK):"
_ci_accept=${_ci_accept%%[^0-9]*}
vared _ci_accept
while [[ $_ci_accept != <-> ]]; do
print "Please enter a number:"
vared _ci_accept
done
print \
"How would you like the numeric prefix to be treated:
0: Not used by correction
U: Used to given the number of errors
U: The number gives the largest number of errors which will be
accepted when correcting
I: If present, and not 1, do not perform correction?
Please type one of the keys above:"
while read -k type; do
print
case $type in
0*) break
;;
[uU]*) accept="${accept}n"
break
;;
[Ii]*) accept="${accept}!n"
break
;;
*) print Try again
;;
esac
done
lines="$lines \\\\
correct_accept='$accept'"
print "
while read -k _ci_type; do
print
case $_ci_type in
0*) break
;;
[uU]*) _ci_accept="${_ci_accept}n"
break
;;
[Ii]*) _ci_accept="${_ci_accept}!n"
break
;;
*) print Try again
;;
esac
done
print "
Instead of the prompt \`correct to:', you can have no prompt, or a
prompt of your choosing which can display the number of errors found by
containing the string \`%e'. Do you wish to change the correction
prompt? [n]"
if read -q; then
cprompt=''
print "Edit a new prompt (may be empty):"
vared cprompt
lines="$lines \\\\
correct_prompt='${cprompt//\'/\'\\\'\'}'"
if read -q; then
print "Edit a new prompt (may be empty):"
vared _ci_cprompt
[[ -z $_ci_cprompt ]] && _ci_cprompt=':empty:'
fi
fi
if [[ -n $_ci_accept ]]; then
_ci_lines="$_ci_lines \\
correct_accept='$_ci_accept'"
unset '_ci_defaults[correct_accept]'
fi
if [[ -n $_ci_cprompt ]]; then
_ci_cprompt=${_ci_cprompt##:empty:}
_ci_lines="$_ci_lines \\
correct_prompt='${_ci_cprompt//\'/\'\\\'\'}'"
unset '_ci_defaults[correct_prompt]'
fi
fi
fi
lines="$lines\n"
_ci_warn=''
for _ci_f in ${(k)_ci_defaults}; do
if [[ -z $_ci_warn ]]; then
print "
(Keeping other existing configuration settings...)"
_ci_warn=1
fi
_ci_lines="$_ci_lines \\
${_ci_f}='${_ci_defaults[$_ci_f]//\'/\'\\\'\'}'"
done
_ci_lines="$_ci_lines
"
startline='# The following lines were added by compinstall'
endline='# End of lines added by compinstall'
ifile=${ZDOTDIR:-~}/.zshrc
[[ -f $ifile ]] || touch $ifile
tmpf=${TMPPPREFIX:-/tmp/zsh}compinstall$$
if [[ ! -w $ifile ]]; then
print "\nI can't write to $ifile. I will leave the lines to add in
\`$tmpf' and you must add them by hand."
print "\n$startline\n$lines\n$endline" >$tmpf
return 0
fi
if grep $endline $ifile >& /dev/null; then
print -- "$startline\n$lines$endline" >$tmpf
sed -e "/^$endline/r $tmpf
/^$startline/,/^$endline/d" $ifile >${tmpf}2 && mv ${tmpf}2 $ifile &&
print "\nSuccesfully modified old compinstall lines in $ifile."
rm -f $tmpf ${tmpf}2
else
print "\n$startline\n$lines\n$endline" >>$ifile &&
print "\nSuccessfully appended lines to $ifile."
if [[ -n $_ci_existing ]]; then
print -nr "
I will retain the following lines from the existing completion setup:
$_ci_existing"
_ci_lines="$_ci_lines${_ci_existing}"
fi
fi # End of advanced options
[[ -f $_ci_ifile ]] || touch $_ci_ifile
_ci_tmpf=${TMPPPREFIX:-/tmp/zsh}compinstall$$
if [[ ! -w $_ci_ifile ]]; then
print "\nI can't write to $_ci_ifile. I will leave the lines to add in
\`$_ci_tmpf' and you must add them by hand."
print -r - "$_ci_startline
$_ci_lines$_ci_endline" >$_ci_tmpf
elif grep $_ci_endline $_ci_ifile >& /dev/null; then
print -r - "$_ci_startline
$_ci_lines$_ci_endline" >$_ci_tmpf
sed -e "/^$_ci_endline/r $_ci_tmpf
/^$_ci_startline/,/^$_ci_endline/d" $_ci_ifile >${_ci_tmpf}2 &&
mv ${_ci_tmpf}2 $_ci_ifile &&
print "\nSuccesfully modified old compinstall lines in $_ci_ifile."
rm -f $_ci_tmpf ${_ci_tmpf}2
else
print -r - "$_ci_startline
$_ci_lines$_ci_endline" >>$_ci_ifile &&
print "\nSuccessfully appended lines to $_ci_ifile."
fi
unfunction compinstall
autoload -U compinstall
return 0

View file

@ -3,7 +3,7 @@
# This uses `_arguments' in a state-machine kind of way. These states
# have names and before executing the default action for such a state
# we try to call a function with the name `_rpm_<state>'. If such a
# function exists, we return with it's return status immediatly. This
# function exists, we return with its return status immediately. This
# allows users to override the default completions by simply defining
# these functions.
# The states (and possible values for the `<state>' above) are:
@ -43,28 +43,36 @@ local ret=1 tmp expl
# Used by `_arguments', made local here.
local state lstate line
tyeset -A options
local curcontext="$curcontext" state lstate line
typeset -A opt_args
state=''
# Do simple completions or get the first state.
_arguments \
_arguments -C -s \
'--rcfile:resource file:_files' \
'--ftpproxy:FTP proxy server:_hosts' \
'--ftpport:FTP port number:' \
'-q:*:query:->query' \
-{V,v,vv,y,-{setperms,setugids,querytags,initdb,showrc}} \
'-pipe:*:pipe command:_command_names -e' \
'--verify:*:verify:->verify' \
-{i,-install}':*:install:->install' \
-{U,-upgrade}':*:upgrade:->upgrade' \
-{e,-erase}':*:uninstall:->uninstall' \
-'b+:build stage:((p\:execute\ \%prep\ stage l\:do\ a\ list\ check c\:execute\ build\ stage i\:execute\ install\ stage b\:build\ a\ binary\ package a\:build\ binary\ and\ source\ packages)):*:build:->build_b' \
-'t+:build stage:((p\:execute\ \%prep\ stage l\:do\ a\ list\ check c\:execute\ build\ stage i\:execute\ install\ stage b\:build\ a\ binary\ package a\:build\ binary\ and\ source\ packages)):*:build:->build_t' \
'-q+[query mode]:*:query:->query' \
'*-v[verbose mode]' \
--{setperms,setugids,querytags,initdb,showrc} \
'--pipe:pipe command:_command_names -e' \
-{V,y}'[verify mode]:*:verify:->verify' \
'--verify[verify mode]:*:verify:->verify' \
'-i+[install mode]:*:install:->install' \
'--install:*:install:->install' \
'-U+[upgrade mode]:*:upgrade:->upgrade' \
'--upgrade:*:upgrade:->upgrade' \
'-F+[freshen mode]:*:upgrade:->upgrade' \
'--freshen:*:upgrade:->upgrade' \
'-e+[uninstall mode]:*:uninstall:->uninstall' \
'--erase:*:uninstall:->uninstall' \
-'b+[build mode (spec file)]:build stage:((p\:execute\ \%prep\ stage l\:do\ a\ list\ check c\:execute\ build\ stage i\:execute\ install\ stage b\:build\ a\ binary\ package a\:build\ binary\ and\ source\ packages)):*:build:->build_b' \
-'t+[build mode (tar file)]:build stage:((p\:execute\ \%prep\ stage l\:do\ a\ list\ check c\:execute\ build\ stage i\:execute\ install\ stage b\:build\ a\ binary\ package a\:build\ binary\ and\ source\ packages)):*:build:->build_t' \
--{rebuild,rmsource,recompile,resign,addsign}':*:RPM package:->package' \
-{K,-checksig}':*:sigcheck:->sigcheck' \
'-K+[signature check mode]:*:sigcheck:->sigcheck' \
'--checksig:*:sigcheck:->sigcheck' \
'--rebuilddb:*:rebuild:->rebuild' && ret=0
# As long as we have a state name...
@ -73,7 +81,7 @@ while [[ -n "$state" ]]; do
# First try to call a user-defined function.
funcall ret _rpm_$state && return ret
_funcall ret _rpm_$state && return ret
# Copy the state and reset `state', to simplify the test above.
@ -85,24 +93,24 @@ while [[ -n "$state" ]]; do
case "$lstate" in
query)
_arguments \
-{v,vv} \
_arguments -s \
'*-v[verbose mode]' -q \
'--rcfile:resource file:_files' \
'--ftpproxy:FTP proxy server:_hosts' \
'--ftpport:FTP port number:' \
'--root:RPM root directory:_files -/' \
'--dbpath:RPM database path:_files -/' \
'--queryformat:RPM query format:->tags' \
'-f:file:_files' \
'-p:RPM package file:->package_file' \
'-f[specify file to query owner of]:file:_files' \
'-p+[specify uninstalled package file to query]:*:RPM package file:->package_file' \
'--triggeredby:RPM package:->package' \
'--whatprovides:RPM capability:->capability' \
'--whatrequires:RPM capability:->capability' \
'*:RPM package:->package_or_file' && ret=0
;;
verify)
_arguments \
-{v,vv} \
_arguments -s \
'*-v[verbose mode]' '(-y)-V' '(-V)-y' \
'--rcfile:resource file:_files' \
'--ftpproxy:FTP proxy server:_hosts' \
'--ftpport:FTP port number:' \
@ -112,15 +120,18 @@ while [[ -n "$state" ]]; do
'*:RPM package:->package' && ret=0
;;
upgrade)
tmp=( --oldpackage )
tmp=( -U --oldpackage )
;&
install)
_arguments "$tmp[@]" \
-{v,vv} \
(( $#tmp )) || tmp=(-i)
_arguments -s "$tmp[@]" \
'*-v[verbose mode]' \
'--rcfile:resource file:_files' \
'--ftpproxy:FTP proxy server:_hosts' \
'--ftpport:FTP port number:' \
-{-{badreloc,excludedocs,force,hash,allfiles,ignorearch,ignoreos,includedocs,justdb,nodeps,noorder,noscripts,notriggers,percent,replacefiles,replacepkgs,test},h} \
'(-h)--hash' '(--hash)-h' \
'(--replacepkgs --replacefiles --oldpackage)--force' \
--{badreloc,excludedocs,allfiles,ignorearch,ignoreos,includedocs,justdb,nodeps,noorder,noscripts,notriggers,percent,replacefiles,replacepkgs,test} \
'--relocate:relocate:->relocate' \
'--prefix:package prefix directory:_files -/' \
'--root:RPM root directory:_files -/' \
@ -128,8 +139,8 @@ while [[ -n "$state" ]]; do
'*:pkg file:->package_file' && ret=0
;;
uninstall)
_arguments \
-{v,vv} \
_arguments -s \
'*-v[verbose mode]' -e \
'--rcfile:resource file:_files' \
'--ftpproxy:FTP proxy server:_hosts' \
'--ftpport:FTP port number:' \
@ -139,13 +150,13 @@ while [[ -n "$state" ]]; do
'*:RPM package:->package' && ret=0
;;
build_b)
tmp=( '*:RPM package:->package' )
tmp=( '*:spec file:_files -g \*.spec' )
;&
build_t)
(( $#tmp )) || tmp=( '*:tar file:_files -g \*.\(\#i\)tar\(.\*\|\)' )
_arguments \
-{v,vv} \
_arguments -s \
'*-v[verbose mode]' \
'--rcfile:resource file:_files' \
'--ftpproxy:FTP proxy server:_hosts' \
'--ftpport:FTP port number:' \
@ -156,8 +167,8 @@ while [[ -n "$state" ]]; do
'--timecheck:time check (seconds):' "$tmp[1]" && ret=0
;;
sigcheck)
_arguments \
-{v,vv} \
_arguments -s \
'*-v[verbose mode]' -K \
'--rcfile:resource file:_files' \
'--ftpproxy:FTP proxy server:_hosts' \
'--ftpport:FTP port number:' \
@ -165,8 +176,8 @@ while [[ -n "$state" ]]; do
'*:RPM package file:->package_or_file' && ret=0
;;
rebuild)
_arguments \
-{v,vv} \
_arguments -s \
'*-v[verbose mode]' \
'--rcfile:resource file:_files' \
'--ftpproxy:FTP proxy server:_hosts' \
'--ftpport:FTP port number:' \
@ -178,21 +189,23 @@ while [[ -n "$state" ]]; do
state=package_file
;&
package)
_description expl 'RPM package'
compadd "$expl[@]" -M 'r:|-=* r:|=*' - $(rpm -qa) && ret=0
_wanted packages expl 'RPM package' \
compadd -M 'r:|-=* r:|=*' - $(_call packages rpm -qa) && ret=0
;;
package_file)
if compset -P ftp:; then
if compset -P ftp://; then
_hosts -S/ && ret=0
else
_files -g '*.(#i)rpm' && ret=0
_alternative \
'files:RPM package file:_files -g \*.\(\#i\)rpm' \
'prefixes:ftp URL prefix:compadd ftp://' && ret=0
fi
;;
tags)
if compset -P '*\{'; then
_description expl 'RPM tag'
compadd "$expl[@]" -M 'm:{a-z}={A-Z}' -S '}' - \
"${(@)${(@f)$(rpm --querytags)}#RPMTAG_}" && ret=0
_wanted tags expl 'RPM tag' \
compadd -M 'm:{a-z}={A-Z}' -S '\}' - \
"${(@)${(@f)$(_call tags rpm --querytags)}#RPMTAG_}" && ret=0
else
_message 'RPM format'
fi
@ -201,10 +214,10 @@ while [[ -n "$state" ]]; do
_message 'RPM capability'
;;
relocate)
if compset -P '*\='; then
_description expl 'new path'
if compset -P '*='; then
_description directories expl 'new path'
else
_description expl 'old path'
_description directories expl 'old path'
fi
_files "$expl[@]" -/ && ret=0

View file

@ -1,36 +1,44 @@
#compdef gdb
# This uses the configuration keys `ps_args' and `ps_listargs'
# described in the `_wait' function.
local cur="$words[CURRENT]" prev w list ret=1 expl
local cur="$words[CURRENT]" prev w list ret=1
_long_options -t '*=(CORE|SYM)FILE' '_files' \
'*=EXECFILE' '_files *(*)' \
'*=TTY' 'compadd /dev/tty*' && return 0
[[ "$PREFIX" = --* ]] &&
_arguments -- '*=(CORE|SYM)FILE:core file:_files' \
'*=EXECFILE:executable:_files \*\(-\*\)' \
'*=TTY:terminal device:compadd /dev/tty\*' && return 0
if compset -P '-(cd|directory)='; then
_files -/
elif compset -P '-tty='; then
compadd - /dev/tty*
_wanted devices expl 'terminal device' compadd - /dev/tty*
elif compset -P '-(exec|se)='; then
_files -/g '*(*)'
_description files expl executable
_files "$expl[@]" -g '*(-*)'
elif compset -P '-(symbols|core|command)='; then
_files
elif compset -P -; then
compadd -QS '' - symbols\= exec\= se\= core\= command\= directory\= \
cd\= tty\=
compadd - help h s e c x d nx n quiet q batch fullname f b
elif [[ "$PREFIX" = -* ]]; then
if _wanted options; then
while _next_label options expl option; do
compadd "$expl[@]" -QS '' - -symbols\= -exec\= -se\= -core\= -command\= \
-directory\= -cd\= -tty\= && ret=0
compadd "$expl[@]" - -help -h -s -e -c -x -d -nx -n -quiet -q \
-batch -fullname -f -b && ret=0
(( ret )) || return 0
done
fi
else
prev="$words[CURRENT-1]"
case "$prev" in
(-d) _files -/ && return 0 ;;
(-e) _files -/g '*(*)' && return 0 ;;
(-d) _files -/ && return 0 ;;
(-[csx]) _files && return 0 ;;
(-b) compadd -V baud 0 50 75 110 134 150 200 300 600 1200 1800 2400 4800 \
9600 19200 38400 57600 115200 230400 && return 0 ;;
(-e) _description files expl executable
_files "$expl[@]" -g '*(-*)' && return 0 ;;
(-b) _wanted -V values expl 'baud rate' \
compadd 0 50 75 110 134 150 200 300 600 1200 1800 2400 4800 \
9600 19200 38400 57600 115200 230400 && return 0 ;;
esac
w=( "${(@)words[2,-1]}" )
while [[ "$w[1]" = -* ]]; do
[[ "$w[1]" = -[decsxb] ]] && shift 1 w
@ -38,13 +46,9 @@ else
done
if [[ $#w -gt 1 ]]; then
_files && ret=0
list=("${(F)${(@Mr:COLUMNS-1:)${(f)$(ps ${compconfig[ps_listargs]:-$compconfig[ps_args]} 2>/dev/null)}[2,-1]:#[ ]#${PREFIX}[0-9]#${SUFFIX}[ ]*${w[1]:t}}}
")
compadd -y list - ${${${(M)${(f)"$(ps $compconfig[ps_args] 2>/dev/null)"}:#*${w[1]:t}*}## #}%% *} && ret=0
return ret
_alternative 'files:: _files' "processes:: _pids -m ${w[1]:t}"
else
_files -/g '*(*)'
_description files expl executable
_files "$expl[@]" -g '*(-*)'
fi
fi

View file

@ -1,20 +1,19 @@
#compdef getconf
local expl
local expl ret=1
if [[ CURRENT -eq 2 ]]; then
_tags syswideconfig pathconfig standardsconfig
while _tags; do
if _requested -V syswideconfig expl 'systemwide configuration variables'
then
compadd "$expl[@]" -S '' ARG_MAX BC_BASE_MAX BC_DIM_MAX BC_SCALE_MAX \
_requested -V syswideconfig expl 'systemwide configuration variables' \
compadd -S '' ARG_MAX BC_BASE_MAX BC_DIM_MAX BC_SCALE_MAX \
BC_STRING_MAX CHILD_MAX COLL_WEIGHTS_MAX EXPR_NEST_MAX LINE_MAX \
NGROUPS_MAX OPEN_MAX RE_DUP_MAX STREAM_MAX TZNAME_MAX
fi
if _requested -V standardsconfig \
expl 'system-standards configuration variables'; then
compadd "$expl[@]" -S '' _POSIX_CHILD_MAX _POSIX_LINK_MAX \
NGROUPS_MAX OPEN_MAX RE_DUP_MAX STREAM_MAX TZNAME_MAX && ret=0
_requested -V standardsconfig \
expl 'system-standards configuration variables' \
compadd -S '' _POSIX_CHILD_MAX _POSIX_LINK_MAX \
_POSIX_MAX_CANON _POSIX_MAX_INPUT _POSIX_NAME_MAX _POSIX_NGROUPS_MAX \
_POSIX_OPEN_MAX _POSIX_PATH_MAX _POSIX_PIPE_BUF _POSIX_SSIZE_MAX \
_POSIX_STREAM_MAX _POSIX_TZNAME_MAX _POSIX_VERSION \
@ -22,15 +21,17 @@ if [[ CURRENT -eq 2 ]]; then
POSIX2_BC_STRING_MAX POSIX2_COLL_WEIGHTS_MAX POSIX2_EXPR_NEST_MAX \
POSIX2_LINE_MAX POSIX2_RE_DUP_MAX POSIX2_VERSION POSIX2_C_BIND \
POSIX2_C_DEV POSIX2_FORT_DEV POSIX2_FORT_RUN POSIX2_LOCALEDEF \
POSIX2_SW_DEV _XOPEN_VERSION
fi
if _requested -V pathconfig expl 'system path configuration variables'
then
compadd "$expl[@]" -S '' PIPE_BUF _POSIX_CHOWN_RESTRICTED \
_POSIX_NO_TRUNC _POSIX_VDISABLE
compadd "$expl[@]" -S ' ' LINK_MAX MAX_CANON MAX_INPUT NAME_MAX PATH_MAX \
PIPE_BUF
fi
POSIX2_SW_DEV _XOPEN_VERSION && ret=0
_requested pathconfig &&
while _next_label -V pathconfig expl 'system path configuration variables'; do
compadd "$expl[@]" -S '' PIPE_BUF _POSIX_CHOWN_RESTRICTED \
_POSIX_NO_TRUNC _POSIX_VDISABLE && ret=0
compadd "$expl[@]" -S ' ' LINK_MAX MAX_CANON MAX_INPUT NAME_MAX \
PATH_MAX PIPE_BUF && ret=0
(( ret )) || break
done
(( ret )) || return 0
done
else
_files -/

View file

@ -1,6 +1,19 @@
#compdef newgrp
: ${(A)groups:=${${(s: :)$(</etc/group)}%%:*}}
# : ${(A)groups:=${${(s: :)$(ypcat group.byname)}%%:*}} # If you use NIS
local expl groups tmp
compadd $groups
_wanted groups || return 1
if ! zstyle -a ":completion:${curcontext}:" groups groups; then
(( $+_cache_groups )) ||
if (( ${+commands[ypcat]} )) &&
tmp=$(_call groups ypcat group.byname); then
: ${(A)_cache_groups:=${${(f)tmp}%%:*}} # If you use YP
else
: ${(A)_cache_groups:=${${(s: :)$(</etc/group)}%%:*}}
fi
groups=( "$_cache_groups[@]" )
fi
_all_labels groups expl group compadd "$@" - "$groups[@]"

View file

@ -1,50 +1,98 @@
#compdef lp lpr lpq lprm
local file expl ret=1 list disp strs shown
local expl ret=1 printer list disp strs shown
if (( ! $+_lp_cache )); then
local file entry names i
file=( /etc/(printcap|printers.conf)(N) )
if (( $#file )); then
_lp_cache=( "${(@)${(@s:|:)${(@)${(@f)$(< $file[1])}:#[ \#]*}%%:*}%%[ ]*}" )
else
# Default value. Could probably be improved
_lp_cache=()
_lp_alias_cache=()
_lp_cache=( lp0 )
if (( $#file )); then
while read entry; do
if [[ "$entry" = [^[:blank:]\#\*_]*:* ]]; then
names=( "${(s:|:)entry%%:*}" )
if [[ "$entry" = *:description=* ]]; then
disp="${${entry##*:description=}%%:*}"
elif [[ $#names -gt 1 && "$names[-1]" = *\ * ]] ;then
disp="$names[-1]"
else
disp=''
fi
if [[ -n "$disp" ]]; then
_lp_cache=( "$_lp_cache[@]" "${names[1]}:${disp}" )
_lp_alias_cache=( "$_lp_alias_cache[@]" "${(@)^names[2,-1]:#*\ *}:${disp}" )
else
_lp_cache=( "$_lp_cache[@]" "${names[1]}" )
_lp_alias_cache=( "$_lp_alias_cache[@]" "${(@)names[2,-1]:#*\ *}" )
fi
fi
done < $file[1]
fi
(( $#_lp_cache )) || _lp_cache=( 'lp0:Guessed default printer' )
(( $#_lp_alias_cache )) || unset _lp_alias_cache
fi
if compset -P -P || [[ "$words[CURRENT-1]" = -P ]]; then
_wanted printers expl printer && compadd "$expl" - "$_lp_cache[@]"
if _wanted printers; then
if zstyle -T ":completion:${curcontext}:printers" verbose; then
zformat -a list ' -- ' "$_lp_cache[@]"
disp=(-ld list)
else
disp=()
fi
_all_labels printers expl printer \
compadd "$disp[@]" - "${(@)_lp_cache%%:*}" && return 0
(( $+_lp_alias_cache )) || return 1
if zstyle -T ":completion:${curcontext}:printers" verbose; then
zformat -a list ' -- ' "$_lp_alias_cache[@]"
disp=(-ld list)
else
disp=()
fi
compadd "$expl[@]" "$disp[@]" - "${(@)_lp_alias_cache%%:*}"
else
return 1
fi
else
if [[ "$words[1]" = (lpq|lprm) ]]; then
list=( "${(@M)${(f@)$(lpq)}:#[0-9]*}" )
if [[ "$words" = *-P* ]]; then
printer=(-P "${${words##*-P( |)}%% *}")
else
printer=()
fi
list=( ${(M)"${(f@)$(_call jobs lpq $printer 2> /dev/null)}":#[0-9]*} )
if (( $#list )); then
_tags users jobs
while _tags; do
if _requested users expl user; then
if _requested users; then
strs=( "${(@)${(@)list##[^ ]##[ ]##[^ ]##[ ]##}%%[ ]*}" )
if [[ -z "$shown" ]] &&
zstyle -t ":completion:${curcontext}:users" verbose; then
zstyle -T ":completion:${curcontext}:users" verbose; then
disp=(-ld list)
shown=yes
else
disp=()
fi
compadd "$expl[@]" "$disp[@]" - "$strs[@]" || _users && ret=0
_all_labels users expl user compadd "$disp[@]" - "$strs[@]" ||
_users && ret=0
fi
if _requested jobs expl job; then
if _requested jobs; then
strs=( "${(@)${(@)list##[^ ]##[ ]##[^ ]##[ ]##[^ ]##[ ]##}%%[ ]*}" )
if [[ -z "$shown" ]] &&
zstyle -t ":completion:${curcontext}:jobs" verbose; then
zstyle -T ":completion:${curcontext}:jobs" verbose; then
disp=(-ld list)
shown=yes
else
disp=()
fi
compadd "$expl[@]" "$disp[@]" - "$strs[@]" && ret=0
_all_labels jobs expl job compadd "$disp[@]" - "$strs[@]" && ret=0
fi
(( ret )) || return 0
done

View file

@ -1,3 +1,32 @@
#defcomp make gmake pmake
#compdef make gmake pmake
complist -s "\$(awk '/^[a-zA-Z0-9][^/ ]+:/ {print \$1}' FS=: [mM]akefile)"
local prev="$words[CURRENT-1]" file expl tmp
if [[ "$prev" = -[CI] ]]; then
_files -/
elif [[ "$prev" = -[foW] ]]; then
_files
else
file="$words[(I)-f]"
if (( file )); then
file="$words[file+1]"
elif [[ -e Makefile ]]; then
file=Makefile
elif [[ -e makefile ]]; then
file=makefile
else
file=''
fi
if [[ -n "$file" ]] && _wanted targets; then
tmp=(
$(awk '/^[a-zA-Z0-9][^\/ \t]+:/ {print $1}
/^\.include *<bsd\.port\.(subdir\.|pre\.)?mk>/ || /^\.include *".*mk\/bsd\.pkg\.(subdir\.)?mk"/ {
print "fetch fetch-list extract patch configure build install reinstall deinstall package describe checkpatch checksum makesum" }' \
FS=: $file)
)
_all_labels targets expl 'make target' compadd "$tmp[@]" && return 0
fi
compset -P 1 '*='
_files
fi

View file

@ -1,28 +1,36 @@
#defcomp folder comp inc mark refile repl scan show next prev rmm pick whom mhn mhpath mhpatch
#compdef folder folders comp inc mark refile repl scan show next prev rmm pick whom mhn mhpath
# 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
local prev="$words[CURRENT-1]" expl
# To be on the safe side, check this exists and if not, get it anyway.
[[ -d $mymhdir ]] || mymhdir=$(mhpath +)
if [[ -iprefix - ]]; then
if compset -P 1 -; 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
if _wanted options; then
_all_labels options expl option \
compadd - $($words[1] -help | perl -ne 'if (/^\s*-\(?(\S+)/) {
$n = $1;
$n =~ s/\)//g;
print $n =~ s/^\[([a-z]+)\]// ? "$n\n$1$n\n" : "$n\n";
}')
return
fi
return 1
elif compset -P 1 '[+@]' || [[ "$prev" = -draftfolder ]]; then
# Complete folder names.
local mhpath
if [[ $IPREFIX != '@' ]]; then
[[ $IPREFIX = '+' ]] || IPREFIX=+
mhpath=$mymhdir
@ -30,13 +38,12 @@ elif [[ -iprefix '+' || -iprefix '@' || -current -1 -draftfolder ]]; then
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
_wanted files expl 'MH folder' _path_files -W mhpath -/
elif [[ "$prev" = -(editor|(whatnow|rmm|show|more)proc) ]]; then
_command_names -e
elif [[ "$prev" = -file ]]; then
_files
elif [[ "$prev" = -(form|audit|filter) ]]; then
# Need some MH template file, which may be in our own MH directory
# or with the standard library.
local mhfpath
@ -44,15 +51,16 @@ elif [[ -mcurrent -1 -(form|audit|filter) ]]; then
[[ -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
_wanted files expl 'MH template file' _files -W mhfpath -g '*(.)'
elif [[ "$prev" = -(no|)cc ]]; then
_wanted -C "$prev" values expl 'CC address' compadd all to cc me
elif [[ "$prev" = -[rw]cache ]]; then
_wanted -C "$prev" values expl cache compadd public private never ask
else
# Generate sequences.
local foldnam folddir f
for f in $argv; do
local foldnam folddir f ret
for f in $words; do
[[ $f = [@+]* ]] && foldnam=$f
done
if [[ $foldnam = '+'* ]]; then
@ -64,7 +72,14 @@ else
# 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 '<->'
if _wanted sequences; then
while _next_label sequences expl sequence; do
compadd "$expl[@]" $(mark $foldnam 2>/dev/null | awk -F: '{ print $1 }') &&
ret=0
compadd "$expl[@]" reply next cur prev first last all unseen && ret=0
_files "$expl[@]" -W folddir -g '<->' && ret=0
(( ret )) || return 0
done
fi
return ret
fi

View file

@ -40,10 +40,11 @@ else
'(-background)-bg[specify background color]:background color:_x_color' \
'(-fg)-foreground:foreground color:_x_color' \
'(-foreground)-fg[specify foreground color]:foreground color:_x_color' \
'-import[load additional preferences file]:nedit preferences file:_files' \
'*-import[load additional preferences file]:nedit preferences file:_files' \
"$nedit_common[@]"
fi
[[ $state = lang ]] && _wanted neditlanguages expl 'language mode' &&
compadd "$expl[@]" - ${(f)"$(sed -n \
'/^nedit.languageMode/,/^nedit/ s/.* \([^:]*\).*/\1/p' < ~/.nedit)"}
[[ $state = lang ]] &&
_wanted neditlanguages expl 'language mode' \
compadd - ${(f)"$(sed -n \
'/^nedit.languageMode/,/^nedit/ s/.* \([^:]*\).*/\1/p' < ~/.nedit)"}

View file

@ -1,8 +1,9 @@
#compdef netscape
local state
local curcontext="$curcontext" state line ret=1
typeset -A opt_args
_x_arguments \
_x_arguments -C \
'-xrm:resource:_x_resource' \
'-help[show usage message]' \
'-version[show the version number and build date]' \
@ -21,55 +22,70 @@ _x_arguments \
-{,no-}{,irix-}session-management \
-{done-save,ignore}-geometry-prefs \
-{component-bar,composer,edit,messenger,mail,discussions,news} \
'*:location:->urls'
'*:location:->urls' && ret=0
[[ "$state" = "urls" ]] &&
_files "$@" && return 0
[ "$state" = "urls" ] && _files "$@" && return
# Handle netscape remote commands
if [ "$state" = "remote" ]; then
if [[ "$state" = "remote" ]]; then
local -a remote_commands
remote_commands=(openURL openFile saveAs mailto addBookmark)
[[ $compstate[quoting] = (double|single) ]] && compset -q
compset -P '*\('
case $IPREFIX in
openURL*|addBookmark* ) state=urls;;
openFile* ) _files -W ~;;
saveAs* )
openURL*|addBookmark*) state=urls;;
openFile*) _files -W ~;;
saveAs*)
if compset -P "*,"; then
compadd -s")" -M 'm:{a-zA-Z}={A-Za-z}' HTML Text PostScript
_wanted types expl 'data type' \
compadd -s")" -M 'm:{a-zA-Z}={A-Za-z}' HTML Text PostScript &&
ret=0
else
_path_files -W ~
_files -W ~ && ret=0
fi
;;
mailto* )
mailto*)
compset -P "*,"
if compset -P '*@'; then
_description expl 'remote host name'
_hosts "$expl[@]" -q -S,
_wanted hosts expl 'remote host name' _hosts -q -S, && ret=0
else
_description expl 'login name'
_users "$expl[@]" -q -S@
_wanted users expl 'login name' _users -q -S@ && ret=0
fi
;;
* )
if [ "$QIPREFIX" ]; then
compadd -q -S '(' -M 'm:{a-zA-Z}={A-Za-z}' $remote_commands
else
compadd -s'(' -S '' -M 'm:{a-zA-Z}={A-Za-z}' $remote_commands
*)
if _wanted commands; then
if [[ -z "$QIPREFIX" ]]; then
_all_labels commands expl 'remote commands' \
compadd -s'(' -S '' -M 'm:{a-zA-Z}={A-Za-z}' - \
$remote_commands && ret=0
else
_all_labels commands expl 'remote commands' \
compadd -qS '(' -M 'm:{a-zA-Z}={A-Za-z}' - \
$remote_commands && ret=0
fi
fi
;;
esac
fi
if [ "$state" = "urls" ]; then
if [[ "$state" = "urls" ]]; then
# Complete netscape urls
if [[ -prefix about: ]]; then
compset -P about:
compadd authors blank cache document fonts global hype image-cache \
license logo memory-cache mozilla plugins
if compset -P about: ; then
_wanted values expl 'about what' \
compadd authors blank cache document fonts global hype image-cache \
license logo memory-cache mozilla plugins && ret=0
else
compadd -S '' about: mocha: javascript:
_urls "$@"
if _wanted prefixes; then
while _next_label prefixes expl 'URL prefix'; do
compadd "$expl[@]" -S '' about: mocha: javascript: && ret=0
_urls "$@" && ret=0
(( ret )) || return 0
done
fi
fi
fi
return ret

View file

@ -10,21 +10,22 @@ fi
if [[ $# -ne 0 || $+_in_tiff -ne 0 ]]; then
if (( ! $# )); then
_description expl 'picture file'
_description files expl 'picture file'
set -- "$expl[@]"
fi
_path_files "$@" -g "$pat" || _files "$@" -g '*.(#i)tiff'
_wanted files expl 'picture file' _path_files "$@" -g "$pat" - ||
_files "$@" "$expl[@]" -g '*.(#i)tiff'
return
fi
local _in_tiff=yes
local state line ret=1
typeset -A options
local curcontext="$curcontext" state line ret=1
typeset -A opt_args
case "$words[1]" in
tiff2bw)
_arguments \
_arguments -C \
'-c[specify compression scheme]:compression scheme:->compress' \
'-r[specify rows per strip]:rows per strip:' \
'-R[specify percentage of red channel]:percentage of red channel:' \
@ -59,7 +60,7 @@ tiffcmp)
':second input TIFF file:_files -g \*.\(\#i\)' && ret=0
;;
tiffcp)
_arguments \
_arguments -C \
'-B[write output in bin-endian byte order]' \
'-c[specify compression scheme]:compression scheme:->compress' \
'-o[set initial TIFF directory (file offset)]:file offset:' \
@ -74,7 +75,7 @@ tiffcp)
'*:input TIFF file:_files -g \*.\(\#i\)' && ret=0
;;
tiffdither)
_arguments \
_arguments -C \
'-c[specify compression scheme]:compression scheme:->compress' \
'-f[specify fill order]:fill order:(lsb2msb msb2lsb)' \
'-r[specify rows per strip]:rows per strip:' \
@ -102,7 +103,7 @@ tiffinfo)
'*:input TIFF file:_files -g \*.\(\#i\)' && ret=0
;;
tiffmedian)
_arguments \
_arguments -C \
'-r[specify rows per strip]:rows per strip:' \
'-C[specify number of colormap entries]:number of colormap entries:' \
'-c[specify compression scheme]:compression scheme:->compress' \
@ -135,14 +136,14 @@ fax2tiff)
':FAX input file:_files -g \*.\(\#i\)\(g\[34\]\|fax\)' && ret=0
;;
gif2tiff)
_arguments \
_arguments -C \
'-r[specify rows per strip]:rows per strip:' \
'-c[specify compression scheme]:compression scheme:->compress' \
':input GIF file:_files -g \*.\(\#i\)gif' \
':output file:_files -g \*.\(\#i\)tiff' && ret=0
;;
ppm2tiff)
_arguments \
_arguments -C \
'-r[specify rows per strip]:rows per strip:' \
'-c[specify compression scheme]:compression scheme:->compress' \
'-R[specify resolution]:resolution:' \
@ -150,14 +151,14 @@ ppm2tiff)
':output file:_files -g \*.\(\#i\)tiff' && ret=0
;;
ras2tiff)
_arguments \
_arguments -C \
'-r[specify rows per strip]:rows per strip:' \
'-c[specify compression scheme]:compression scheme:->compress' \
':input raster image file:_files -g \*.\(\#i\)ras\(\|t\)' \
':output file:_files -g \*.\(\#i\)tiff' && ret=0
;;
pal2rgb)
_arguments \
_arguments -C \
'-C[specify number of bits for colormap entries]:bits for colormap entries:(8 16)' \
'-p[set sample packing]:sample packing:(contig separate)' \
'-c[specify compression scheme]:compression scheme:->compress' \
@ -166,7 +167,7 @@ pal2rgb)
':output file:_files -g \*.\(\#i\)tiff' && ret=0
;;
*)
_description expl 'picture file'
_description files expl 'picture file'
_files "$expl[@]" -g "$pat" && ret=0
esac
@ -194,9 +195,13 @@ if [[ -n "$state" ]]; then
;;
esac
else
_description expl 'compression scheme'
compadd "$expl[@]" - none g4 packbits && ret=0
compadd "$expl[@]" -qS: - lzw zip jpeg g3 && ret=0
if _wanted values; then
while _next_label values expl 'compression scheme'; do
compadd "$expl[@]" - none g4 packbits && ret=0
compadd "$expl[@]" -qS: - lzw zip jpeg g3 && ret=0
(( ret )) || return 0
done
fi
fi
fi

View file

@ -1,65 +1,155 @@
#autoload
#compdef curl
# Usage: _urls [-f]
# Options:
# -f : complete files.
# To complete URLs, you must make a URL database locally such as:
# -f : complete files first.
#
# % cd ~/.zsh/urls
# % find . -ls
# ... drwxr-xr-x ... 512 Sep 3 02:46 .
# ... drwxr-xr-x ... 512 Sep 3 02:48 ./http
# ... drwxr-xr-x ... 512 Sep 3 02:52 ./http/www.zsh.org
# ... drwxr-xr-x ... 512 Sep 3 03:01 ./http/www.zsh.org/mla
# ... drwxr-xr-x ... 512 Sep 3 03:01 ./http/www.zsh.org/mla/workers
# ... drwxr-xr-x ... 512 Sep 3 03:01 ./http/www.zsh.org/mla/workers/1999
# ... -rw-r--r-- ... 0 Sep 3 03:01 ./http/www.zsh.org/mla/workers/1999/index.html
# ... drwxr-xr-x ... 512 Sep 3 02:48 ./http/sunsite.auc.dk
# ... drwxr-xr-x ... 512 Sep 3 02:48 ./http/sunsite.auc.dk/zsh
# ... drwxr-xr-x ... 512 Sep 3 02:47 ./bookmark
# ... drwxr-xr-x ... 512 Sep 3 02:48 ./bookmark/zsh
# ... -rw-r--r-- ... 27 Sep 3 02:47 ./bookmark/zsh/home
# ... -rw-r--r-- ... 20 Sep 3 02:48 ./bookmark/zsh/meta
# Configuration styles used:
#
# path
# The path to a directory containing a URL database, such as:
#
# % cd ~/.zsh/urls
# % find . -ls
# ... drwxr-xr-x ... 512 Sep 3 02:46 .
# ... drwxr-xr-x ... 512 Sep 3 02:48 ./http
# ... drwxr-xr-x ... 512 Sep 3 02:52 ./http/www.zsh.org
# ... drwxr-xr-x ... 512 Sep 3 03:01 ./http/www.zsh.org/mla
# ... drwxr-xr-x ... 512 Sep 3 03:01 ./http/www.zsh.org/mla/workers
# ... drwxr-xr-x ... 512 Sep 3 03:01 ./http/www.zsh.org/mla/workers/1999
# ... -rw-r--r-- ... 0 Sep 3 03:01 ./http/www.zsh.org/mla/workers/1999/index.html
# ... drwxr-xr-x ... 512 Sep 3 02:48 ./http/sunsite.auc.dk
# ... drwxr-xr-x ... 512 Sep 3 02:48 ./http/sunsite.auc.dk/zsh
# ... drwxr-xr-x ... 512 Sep 3 02:47 ./bookmark
# ... drwxr-xr-x ... 512 Sep 3 02:48 ./bookmark/zsh
# ... -rw-r--r-- ... 27 Sep 3 02:47 ./bookmark/zsh/home
# ... -rw-r--r-- ... 20 Sep 3 02:48 ./bookmark/zsh/meta
# % cat bookmark/zsh/home
# http://sunsite.auc.dk/zsh/
# % cat bookmark/zsh/meta
# http://www.zsh.org/
#
# local
# Specify a local web server as an array with three elements:
# <hostname> <doc root> <user area>
# where hostname is the name of the web server, doc root is the path to
# the default web pages for the server and user area is the directory
# name used by a user placing web pages within their home area.
# E.g.:
# zstyle ':completion:*:urls' local www /usr/local/apache/htdocs public_html
local ipre scheme dirs files
local ipre scheme host user uhosts ret=1 expl
local urls_path localhttp
zstyle -s ":completion:${curcontext}:urls" path urls_path ||
urls_path="${ZDOTDIR:-$HOME}/.zsh/urls"
zstyle -a ":completion:${curcontext}:urls" local localhttp
local localhttp_servername="$localhttp[1]"
local localhttp_documentroot="$localhttp[2]"
local localhttp_userdir="$localhttp[3]"
if [[ "$1" = -f ]]; then
shift
_files "$@" && return
fi
if [[ -z "$compconfig[_urls_dir]" ]]; then
compconfig[_urls_dir]=${ZDOTDIR:-$HOME}/.zsh/urls
_wanted -C -f files && _files "$@" && return
fi
ipre="$IPREFIX"
if [[ -prefix [-+.a-z0-9]#: ]]; then
scheme="${PREFIX%%:*}"
compset -P "[-+.a-z0-9]#:"
else
compadd -S '' http:// ftp:// bookmark:
return
if ! compset -P '(#b)([-+.a-z0-9]#):' && _wanted -C argument prefixes; then
while _next_label prefixes expl 'URL prefix' "$@"; do
[[ -d $urls_path/bookmark ]] &&
compadd "$expl[@]" -S '' bookmark: && ret=0
compadd "$expl[@]" -S '' file: ftp:// gopher:// http:// && ret=0
(( ret )) || return 0
done
return ret
fi
scheme="$match[1]"
case "$scheme" in
http) compset -P // || { compadd "$@" -S '' //; return };;
ftp) compset -P // || { compadd "$@" -S '' //; return };;
http|ftp|gopher)
if ! compset -P //; then
_wanted -C "$scheme" prefixes expl 'end of prefix' compadd "$@" -S '' //
return
fi
;;
file)
if ! compset -P //; then
_wanted -C file files || return 1
while _next_label files expl 'local file' "$@"; do
if [[ -prefix / ]]; then
_path_files "$expl[@]" -S '' -g '*(^/)' && ret=0
_path_files "$expl[@]" -S/ -r '/' -/ && ret=0
elif [[ -z "$PREFIX" ]]; then
compadd "$expl[@]" -S '/' -r '/' - "${PWD%/}" && ret=0
fi
(( ret )) || return 0
done
return ret
fi
;;
bookmark)
if [[ -f "$urls_path/$scheme/${(Q)PREFIX}${(Q)SUFFIX}" &&
-s "$urls_path/$scheme/${(Q)PREFIX}${(Q)SUFFIX}" ]]; then
_wanted -C bookmark bookmarks expl bookmarks \
compadd "$@" -U - \
"$ipre$(<"$urls_path/$scheme/${(Q)PREFIX}${(Q)SUFFIX}")" && ret=0
else
if _wanted -C bookmark files; then
while _next_label files expl 'bookmark'; do
_path_files -W "$urls_path/$scheme" "$expl[@]" -S '' -g '*(^/)' &&
ret=0
_path_files -W "$urls_path/$scheme" -S/ -r '/' -/ && ret=0
(( ret )) || return 0
done
fi
fi
return ret
;;
esac
if [[ "$scheme" = bookmark &&
-f "$compconfig[_urls_dir]/$scheme/$PREFIX$SUFFIX" &&
-s "$compconfig[_urls_dir]/$scheme/$PREFIX$SUFFIX" ]]; then
compadd "$@" -QU -- "$ipre$(<"$compconfig[_urls_dir]/$scheme/$PREFIX$SUFFIX")"
else
dirs=($compconfig[_urls_dir]/$scheme/$PREFIX*$SUFFIX(/:t))
files=($compconfig[_urls_dir]/$scheme/$PREFIX*$SUFFIX(.:t))
compset -P '*/'
compadd "$@" -Q -S '/' - $dirs
if [[ "$scheme" = bookmark ]]; then
compadd "$@" -QS '' - $files
else
compadd "$@" -Q - $files
fi
# Complete hosts
if ! compset -P '(#b)([^/]#)/' && _wanted hosts; then
uhosts=($urls_path/$scheme/$PREFIX*$SUFFIX(/:t))
while _next_label hosts expl host "$@"; do
(( $#uhosts )) || _hosts -S/ && ret=0
[[ "$scheme" = http ]] && uhosts=($uhosts $localhttp_servername)
compadd "$expl[@]" -S/ - $uhosts && ret=0
(( ret )) || return 0
done
return ret
fi
host="$match[1]"
# Complete part after hostname
_wanted -C local files || return 1
if [[ "$localhttp_servername" = "$host" ]]; then
if compset -P \~; then
if ! compset -P '(#b)([^/]#)/'; then
_users -S/
return
fi
user="$match[1]"
while _next_label files expl 'local file'; do
_path_files "$expl[@]" -W ~$user/$localhttp_userdir -g '*(^/)' && ret=0
_path_files "$expl[@]" -W ~$user/$localhttp_userdir -S/ -r '/' -/ && ret=0
(( ret )) || return 0
done
else
while _next_label files expl 'local file'; do
_path_files "$expl[@]" -W $localhttp_documentroot -g '*(^/)' && ret=0
_path_files "$expl[@]" -W $localhttp_documentroot -S/ -r '/' -/ && ret=0
(( ret )) || return 0
done
fi
else
while _next_label files expl 'local file'; do
_path_files "$expl[@]" -W $urls_path/$scheme/$host -g '*(^/)' && ret=0
_path_files "$expl[@]" -W $urls_path/$scheme/$host -S/ -r '/' -/ && ret=0
(( ret )) || return 0
done
fi
return $ret

View file

@ -1,6 +1,10 @@
#autoload
#compdef last passwd groups
local expl
local expl users
_description expl user
compgen "$@" "$expl[@]" -u
_wanted users || return 1
zstyle -a ":completion:${curcontext}:" users users &&
_all_labels users expl user compadd "$@" - "$users[@]" && return 0
_all_labels users expl user compadd "$@" - "${(@k)userdirs}"

View file

@ -1,10 +1,12 @@
#autoload write
#compdef write
local expl
_wanted users || return 1
if which users >/dev/null; then
_description expl users logged on
compadd "$@" "$expl[@]" - $(users) && return 0
_all_labels users expl 'users logged on' \
compadd "$@" - $(_call users users) && return 0
else
# Other methods of finding out users logged on should be added here
return 1

View file

@ -2,7 +2,7 @@
local expl list desc
_wanted colormapids expl 'colormap id' || return 1
_wanted colormapids || return 1
list=(${(f)"$(xprop -root -f RGB_COLOR_MAP 32xcccccccxx ': $0\n'|awk -F'[ ():]' '/^[a-zA-Z_]+\(RGB_COLOR_MAP\)/ {print $5, "--", $1}')"})
@ -12,4 +12,5 @@ else
desc=()
fi
compadd "$expl[@]" "$@" "$desc[@]" - "${(@)list%% *}"
_all_labels colormapids expl 'colormap id' \
compadd "$@" "$desc[@]" - "${(@)list%% *}"

View file

@ -2,16 +2,18 @@
local expl
(( $+_xe_cache )) || _xe_cache=( "${(@)${(@f)$(xdpyinfo)}[(r)number of extensions:*,-1][2,(r)default screen number:*][1,-2]//[ ]}" )
_wanted extensions || return 1
_description expl 'X extension'
(( $+_xe_cache )) || _xe_cache=( "${(@)${(@f)$(xdpyinfo)}[(r)number of extensions:*,-1][2,(r)default screen number:*][1,-2]//[ ]}" )
if [[ "$1" = -a ]]; then
shift
compadd "$@" "$expl[@]" -M 'm:{a-z}={A-Z} r:|-=* r:|=*' - all "$_xe_cache[@]"
_all_labels extensions expl 'X extensions' \
compadd "$@" -M 'm:{a-z}={A-Z} r:|-=* r:|=*' - all "$_xe_cache[@]"
else
[[ "$1" = - ]] && shift
compadd "$@" "$expl[@]" -M 'm:{a-z}={A-Z} r:|-=* r:|=*' - "$_xe_cache[@]"
_all_labels extensions expl 'X extensions' \
compadd "$@" -M 'm:{a-z}={A-Z} r:|-=* r:|=*' - "$_xe_cache[@]"
fi

View file

@ -1,3 +1,16 @@
#autoload
_message 'font'
local expl
_wanted fonts || return 1
# This *has* to be improved some day...
if (( ! $+_font_cache )); then
typeset -gU _font_cache
_font_cache=( "${(@)^${(@f)$(_call fonts xlsfonts)}%%--*}--" )
fi
_all_labels fonts expl font \
compadd -M 'r:|-=* r:|=*' "$@" -S '' - "$_font_cache[@]"

View file

@ -2,6 +2,8 @@
local expl
_wanted keysyms || return 1
if (( ! $+_keysym_cache )); then
local file
@ -16,5 +18,5 @@ if (( ! $+_keysym_cache )); then
fi
fi
_description expl 'key symbol'
compadd "$@" "$expl[@]" -M 'm:{a-z}={A-Z} r:|-=* r:|=*' - $_keysym_cache
_all_labels keysyms expl 'key symbol' \
compadd "$@" -M 'm:{a-z}={A-Z} r:|-=* r:|=*' - $_keysym_cache

View file

@ -1,19 +1,18 @@
#autoload
setopt localoptions extendedglob
local list expl
list=( "${(@)${(M@)${(@f)$(xwininfo -root -tree)}:#[ ]#0x[0-9a-f]# \"*}##[ ]#}" )
_wanted windows || return 1
list=( "${(@)${(M@)${(@f)$(_call windows xwininfo -root -tree)}:#[ ]#0x[0-9a-f]# \"*}##[ ]#}" )
if [[ "$1" = -n ]]; then
shift
_description expl 'window name'
compadd "$@" "$expl[@]" -d list - "${(@)${(@)list#*\"}%%\"*}"
_all_labels windows expl 'window name' \
compadd "$@" -d list - "${(@)${(@)list#*\"}%%\"*}"
else
[[ "$1" = - ]] && shift
_description expl 'window ID'
compadd "$@" "$expl[@]" -d list - "${(@)list%% *}"
_all_labels windows expl 'window ID' compadd "$@" -d list - "${(@)list%% *}"
fi

View file

@ -1,11 +1,9 @@
#compdef xmodmap
setopt localoptions extendedglob
local curcontext="$curcontext" state line ret=1
typeset -A opt_args
local state line ret=1
typeset -A options
_x_arguments \
_x_arguments -C \
-{help,grammar,verbose,quiet} \
'-n[only show what would be done]' \
'*-e[specify expression]:expression:->expr' \
@ -57,7 +55,7 @@ if [[ -n "$state" ]]; then
pointer*)
if compset -P '*=[ ]#'; then
compset -P '*[ ]'
_description expl 'button code'
_description values expl 'button code'
compadd "$expl[@]" -qS ' ' 1 2 3 4 5 default
return
else
@ -84,9 +82,13 @@ if [[ -n "$state" ]]; then
[[ "$what" = *ksym* ]] && _x_keysym "$suf[@]" && ret=0
else
_description expl command
compadd "$expl[@]" -S ' ' keycode keysym clear add remove && ret=0
compadd "$expl[@]" -S ' = ' pointer && ret=0
if _wanted commands; then
while _next_label commands expl command; do
compadd "$expl[@]" -S ' ' keycode keysym clear add remove && ret=0
compadd "$expl[@]" -S ' = ' pointer && ret=0
(( ret )) || return 0
done
fi
fi
fi

View file

@ -8,7 +8,7 @@ xdpyinfo)
;;
xwininfo)
_x_arguments \
-{help,int,stats,bits,events,size,wm,shape,frame,all,english,metric} \
-{help,int,children,tree,stats,bits,events,size,wm,shape,frame,all,english,metric} \
'(-id -name)-root' \
'(-id -root)-name:name: _x_window -n' \
'(-name -root)-id:id: _x_window'
@ -46,12 +46,33 @@ xev)
'-rv'
;;
xhost)
local expl type ret=1
local expl type ret=1 tmp
if compset -P '-'; then
_description expl 'disallow access'
compadd "$expl[@]" -M 'm:{a-z}={A-Z} r:|[:.]=* r:|=*' - \
"${${(@M)${(@f)$(xhost)}[2,-1]:#LOCAL:*}#INET:}"
tmp=(${(f)"$(xhost)"})
shift tmp
tmp=(${tmp:#LOCAL:|<*>})
if [[ "$tmp" = *:* ]]; then
if compset -P '(#b)(*):'; then
type="$match[1]"
_wanted displays &&
while _next_label displays expl 'disallow access'; do
{ compadd "$expl[@]" -M 'm:{a-z}={A-Z} r:|[:.]=* r:|=*' - \
${${(M)tmp:#(#i)$type:*}#(#i)$type:} ||
_hosts "$expl[@]" } && return 0
done
else
_alternative \
'types:name family:compadd -S: ${(L)tmp%%:*}' \
'hosts:host:compadd ${(@)tmp#*:}' && ret=0
fi
else
_wanted displays &&
while _next_label displays expl 'disallow access'; do
{ compadd "$expl[@]" -M 'm:{a-z}={A-Z} r:|[:.]=* r:|=*' - $tmp ||
_hosts "$expl[@]" } && return 0
done
fi
else
compset -P +
@ -66,9 +87,9 @@ xhost)
krb) _message 'Kerberos V5 principal';;
esac
else
_description expl 'name family'
compadd -S: - inet dnet nis krb && ret=0
_hosts && ret=0
_alternative \
'types:name family:compadd -S: - inet dnet nis krb' \
'hosts:: _hosts' && ret=0
fi
return ret
fi
@ -120,7 +141,7 @@ xrdb)
'(-global -all -screens)-screen' \
'(-global -all -screen)-screens' \
'-n[only display on stdout]' \
'(-nocpp)-cpp:preprocessor program:_files -g \*\(\*\)' \
'(-nocpp)-cpp:preprocessor program:_files -g \*\(-\*\)' \
'(-cpp)-nocpp' \
'(-load -override -merge -remove)-query' \
'(-query -override -merge -remove)-load' \
@ -131,6 +152,7 @@ xrdb)
'-backup:backup extension:' \
'*-D-:symbol to define:' \
'*-U-:symbol to undefine:' \
'*-I-:include directory:_files -/'
'*-I-:include directory:_files -/' \
'*:defaults file:_files'
;;
esac

View file

@ -16,8 +16,8 @@ _xwit_guard () {
_xwit_compopts () {
local expl
_description options expl option
compadd "$expl[@]" - ${(k)no[(R)*~0]} || compadd "$expl[@]" - ${(k)no}
_wanted options expl option compadd - ${(k)no[(R)*~0]} ||
_all_labels options expl option compadd - ${(k)no}
}
_regex_arguments _xwit_parse \
@ -39,8 +39,8 @@ _regex_arguments _xwit_parse \
\| "/iconmove$nul/" "$guard" "/$word/" ":_message x" "/$word/" ":_message y" \
\| "/id$nul/" "$guard" "/$word/" ":_x_window" \
\| "/(no|)keyrepeat$nul/" "$guard" \
\( "/[0-9]##$nul/" ":_message keycode" \
\( "/-$nul/" "/[0-9]##$nul/" ":_message 'last keycode'" \| \) \) \# \
\( "/[0-9]##$nul/" ":[[ -prefix [0-9]# ]] && _message keycode" \
\( "/-$nul/" "/[0-9]##$nul/" ":[[ -prefix [0-9]# ]] && _message 'last keycode'" \| \) \) \# \
\| "/names$nul/" "$guard" "/$word/" ":_x_window -n" \# \
\| "/[]/" ':_xwit_compopts' \
\) \

View file

@ -27,5 +27,5 @@
# This must also serve as a shell script, so do not add spaces around the
# `=' signs.
VERSION=3.1.5
VERSION_DATE='October 29, 1998'
VERSION=3.1.6-dev-21
VERSION_DATE='April 1, 2000'

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,25 @@
texinode(Programmable Completion)(Zsh Modules)(Zsh Line Editor)(Top)
chapter(Programmable Completion)
texinode(Completion Using compctl)(Completion Widgets)(Zsh Line Editor)(Top)
chapter(Completion Using compctl)
cindex(completion, programmable)
cindex(completion, controlling)
ifzman(\
sect(Synopsis)
This version of zsh has two ways of performing completion of words on the
command line. New users of the shell may prefer to use the newer
and more powerful system based on shell functions; this is described in
zmanref(zshcompsys), and the basic shell mechanisms which support it are
described in zmanref(zshcompwid). This manual entry describes the older
tt(compctl) command.
)\
ifnzman(\
sect(Types of completion)
This version of zsh has two ways of performing completion of words on the
command line. New users of the shell may prefer to use the newer
and more powerful system based on shell functions; this is described
in noderef(Completion System), and the basic shell mechanisms which support
it are described in noderef(Completion Widgets). This chapter describes
the older tt(compctl) command.
)\
findex(compctl)
sect(Description)
startlist()
@ -10,7 +28,8 @@ list(tt(compctl) [ tt(-CDT) ] var(options) \
[ tt(-x) var(pattern) var(options) tt(-) ... tt(--) ] \
[ tt(PLUS()) var(options) [ tt(-x) ... tt(--) ] ... [tt(PLUS())] ] \
[ var(command) ... ])
list(tt(compctl) tt(-L) [ tt(-CDT) ] [ var(command) ... ])
list(tt(compctl) tt(-M) var(match-specs) ...)
list(tt(compctl) tt(-L) [ tt(-CDTM) ] [ var(command) ... ])
list(tt(compctl) tt(PLUS()) var(command) ...)
endlist()
@ -30,7 +49,8 @@ menu(Alternative Completion)
menu(Extended Completion)
menu(Example)
endmenu()
texinode(Command Flags)(Option Flags)()(Programmable Completion)
texinode(Command Flags)(Option Flags)()(Completion Using compctl)
sect(Command Flags)
Completion of the arguments of a command may be different for each
command or may use the default. The behavior when completing the
@ -44,9 +64,23 @@ item(var(command) ...)(
controls completion for the named commands, which must be listed last
on the command line. If completion is attempted for a command with a
pathname containing slashes and no completion definition is found, the
search is retried with the last pathname component. Note that aliases
search is retried with the last pathname component. If the command starts
with a tt(=), completion is tried with the pathname of the command.
Any of the var(command) strings may be patterns of the form normally
used for filename generation. These should be be quoted to protect them
from immediate expansion; for example the command string tt('foo*')
arranges for completion of the words of any command beginning with
tt(foo). When completion is attempted, all pattern completions are
tried in the reverse order of their definition until one matches. By
default, completion then proceeds as normal, i.e. the shell will try to
generate more matches for the specific command on the command line; this
can be overridden by including tt(-tn) in the flags for the pattern
completion.
Note that aliases
are expanded before the command name is determined unless the
tt(COMPLETE_ALIASES) option is set. Commands should not be combined
tt(COMPLETE_ALIASES) option is set. Commands may not be combined
with the tt(-C), tt(-D) or tt(-T) flags.
)
item(tt(-C))(
@ -62,8 +96,8 @@ been issued, filenames are completed.
)
item(tt(-T))(
supplies completion flags to be used before any other processing is
done, even those given to specific commands with other compctl
definitions. This is only useful when combined with extended
done, even before processing for tt(compctl)s defined for specific
commands. This is especially useful when combined with extended
completion (the tt(-x) flag, see noderef(Extended Completion) below).
Using this flag you can define default behavior
which will apply to all commands without exception, or you can alter
@ -71,41 +105,59 @@ the standard behavior for all commands. For example, if your access
to the user database is too slow and/or it contains too many users (so
that completion after `tt(~)' is too slow to be usable), you can use
nofill(tt(compctl -Tx 'C[0,*/*]' -f - 's[~]' -k friends -S/))
example(compctl -T -x 's[~] C[0,[^/]#]' -k friends -S/ -tn)
to complete the strings in the array tt(friends) after a `tt(~)'.
The first argument is necessary so that this form of ~-completion is
The tt(C[...]) argument is necessary so that this form of ~-completion is
not tried after the directory name is finished.
)
item(tt(-L))(
lists the existing completion behavior in a manner suitable for
putting into a start-up script; the existing behavior is not changed.
Any combination of the above forms may be specified, otherwise all
defined completions are listed. Any other flags supplied
are ignored.
Any combination of the above forms, or the tt(-M) flag (which must
follow the tt(-L) flag), may be specified, otherwise all defined
completions are listed. Any other flags supplied are ignored.
)
item(em(no argument))(
If no argument is given, tt(compctl) lists all defined completions
in an abbreviated form; with a list of var(options), all completions
with those flags set (not counting extended completion) are listed.
)
endlist()
enditem()
If the tt(PLUS()) flag is alone and followed immediately by the var(command)
list, the completion behavior for all the commands in the list is reset to
the default. In other words, completion will subsequently use the
options specified by the tt(-D) flag.
texinode(Option Flags)(Alternative Completion)(Command Flags)(Programmable Completion)
The form with tt(-M) as the first and only option defines global
matching specifications (see
ifzman(zshcompwid)\
ifnzman(noderef(Matching Control))\
). The match specifications given will be used for every completion
attempt (only when using tt(compctl), not with the new completion
system) and are tried in the order in which they are defined until one
generates at least one match. E.g.:
example(compctl -M '' 'm:{a-zA-Z}={A-Za-z}')
This will first try completion without any global match specifications
(the empty string) and, if that generates no matches, will try case
insensitive completion.
texinode(Option Flags)(Alternative Completion)(Command Flags)(Completion Using compctl)
sect(Option Flags)
startlist()
list([ tt(-fcFBdeaRGovNAIOPZEnbjrzu/) ])
list([ tt(-fcFBdeaRGovNAIOPZEnbjrzu/12) ])
list([ tt(-k) var(array) ] [ tt(-g) var(globstring) ] \
[ tt(-s) var(subststring) ])
list([ tt(-K) var(function) ] [ tt(-H) var(num pattern) ])
list([ tt(-K) var(function) ])
list([ tt(-Q) ] [ tt(-P) var(prefix) ] [ tt(-S) var(suffix) ])
list([ tt(-W) var(file-prefix) ])
list([ tt(-W) var(file-prefix) ] [ tt(-H) var(num pattern) ])
list([ tt(-q) ] [ tt(-X) var(explanation) ] [ tt(-Y) var(explanation) ])
list([ tt(-y) var(func-or-var) ] [ tt(-l) var(cmd) ] [ tt(-U) ])
list([ tt(-y) var(func-or-var) ] [ tt(-l) var(cmd) ] [ tt(-h) var(cmd) ] [ tt(-U) ])
list([ tt(-t) var(continue) ] [ tt(-J) var(name) ] [ tt(-V) var(name) ])
list([ tt(-M) var(match-spec) ])
endlist()
The remaining var(options) specify the type of command arguments
@ -117,6 +169,7 @@ menu(Simple Flags)
menu(Flags with Arguments)
menu(Control Flags)
endmenu()
texinode(Simple Flags)(Flags with Arguments)()(Option Flags)
subsect(Simple Flags)
These produce completion lists made up by the shell itself:
@ -215,6 +268,7 @@ item(tt(-u))(
User names.
)
enditem()
texinode(Flags with Arguments)(Control Flags)(Simple Flags)(Option Flags)
subsect(Flags with Arguments)
These have user supplied arguments to determine how the list of
@ -229,8 +283,8 @@ of space- or comma-separated values in parentheses, in which any
delimiter may be escaped with a backslash; in this case the argument
should be quoted. For example,
nofill(tt(compctl -k "(cputime filesize datasize stacksize
coredumpsize resident descriptors)" limit))
example(compctl -k "(cputime filesize datasize stacksize
coredumpsize resident descriptors)" limit)
)
item(tt(-g) var(globstring))(
The var(globstring) is expanded using filename globbing; it should be
@ -251,20 +305,21 @@ completions. The tt(fignore) special parameter is not applied to the
resulting files. Note that tt(-g) is faster for filenames.
)
item(tt(-K) var(function))(
Call the given function to get the completions. The function is
Call the given function to get the completions. Unless the name
starts with an underscore, the function is
passed two arguments: the prefix and the suffix of the word on which
completion is to be attempted, in other words those characters before
the cursor position, and those from the cursor position onwards. The
whole command line can be accessed with the tt(-c) and tt(-l) flags
of the tt(read) builtin. The
of the tt(read) builtin. The
function should set the variable tt(reply) to an array containing
the completions (one completion per element); note that tt(reply)
should not be made local to the function. From such a function the
command line can be accessed with the tt(-c) and tt(-l) flags to
the tt(read) builtin. For example,
nofill(tt(function whoson { reply=(`users`); }
compctl -K whoson talk))
example(function whoson { reply=(`users`); }
compctl -K whoson talk)
completes only logged-on users after `tt(talk)'. Note that `tt(whoson)' must
return an array, so `tt(reply=`users`)' would be incorrect.
@ -276,12 +331,13 @@ zero or negative the whole history is searched and if var(pattern) is
the empty string all words are taken (as with `tt(*)'). A typical
use is
nofill(tt(compctl -D -f PLUS() -H 0 ''))
example(compctl -D -f PLUS() -H 0 '')
which forces completion to look back in the history list for a word if
no filename matches.
)
enditem()
texinode(Control Flags)()(Flags with Arguments)(Option Flags)
subsect(Control Flags)
These do not directly specify types of name to be completed, but
@ -303,7 +359,7 @@ The var(prefix) is inserted just before the completed string; any
initial part already typed will be completed and the whole var(prefix)
ignored for completion purposes. For example,
nofill(tt(compctl -j -P "%" kill))
example(compctl -j -P "%" kill)
inserts a `%' after the kill command and then completes job names.
)
@ -318,20 +374,25 @@ With directory var(file-prefix): for command, file, directory and
globbing completion (options tt(-c), tt(-f), tt(-/), tt(-g)), the file
prefix is implicitly added in front of the completion. For example,
nofill(tt(compctl -/ -W ~/Mail maildirs))
example(compctl -/ -W ~/Mail maildirs)
completes any subdirectories to any depth beneath the directory
tt(~/Mail), although that prefix does not appear on the command line.
The var(file-prefix) may also be of the form accepted by the tt(-k)
flag, i.e. the name of an array or a literal list in parenthesis. In
this case all the directories in the list will be searched for
possible completions.
)
item(tt(-q))(
If used with a suffix as specified by the tt(-S) option, this
causes the suffix to be removed if the next character typed is a blank
or does not insert anything (the same rule as used for the
tt(AUTO_REMOVE_SLASH) option). The option is most useful for list
or does not insert anything or if the suffix consists of only one character
and the next character typed is the same character; this the same rule used
for the tt(AUTO_REMOVE_SLASH) option. The option is most useful for list
separators (comma, colon, etc.).
)
item(tt(-l) var(cmd))(
This option cannot be combined with any other. It restricts the range
This option restricts the range
of command line words that are considered to be arguments. If
combined with one of the extended completion patterns `tt(p[)...tt(])',
`tt(r[)...tt(])', or `tt(R[)...tt(])' (see noderef(Extended Completion)
@ -342,12 +403,21 @@ option. If the var(cmd) string is empty the first word in the range
is instead taken as the command name, and command name completion
performed on the first word in the range. For example,
nofill(tt(compctl -x 'r[-exec,;]' -l '' -- find))
example(compctl -x 'r[-exec,;]' -l '' -- find)
completes arguments between `tt(-exec)' and the following `tt(;)' (or the end
of the command line if there is no such string) as if they were
a separate command line.
)
item(tt(-h) var(cmd))(
Normally zsh completes quoted strings as a whole. With this option,
completion can be done separately on different parts of such
strings. It works like the tt(-l) option but makes the completion code
work on the parts of the current word that are separated by
spaces. These parts are completed as if they were arguments to the
given var(cmd). If var(cmd) is the empty string, the first part is
completed as a command name, as with tt(-l).
)
item(tt(-U))(
Use the whole list of possible completions, whether or not they
actually match the word on the command line. The word typed so far
@ -355,7 +425,10 @@ will be deleted. This is most useful with a function (given by the
tt(-K) option) which can examine the word components passed to it
(or via the tt(read) builtin's tt(-c) and tt(-l) flags) and
use its own criteria to decide what matches. If there is no
completion, the original word is retained.
completion, the original word is retained. Since the produced
possible completions seldom have interesting common prefixes
and suffixes, menucompletion is started immediately if tt(AUTO_MENU) is
set and this flag is used.
)
item(tt(-y) var(func-or-var))(
The list provided by var(func-or-var) is displayed instead of the list
@ -379,9 +452,22 @@ printed literally and if they appear output in columns is suppressed.
)
item(tt(-X) var(explanation))(
Print var(explanation) when trying completion on the current set of
options. A `tt(%n)' in this string is replaced by the number of matches.
options. A `tt(%n)' in this string is replaced by the number of
matches that were added for this explanation string.
The explanation only appears if completion was tried and there was
no unique match, or when listing completions.
no unique match, or when listing completions. Explanation strings
will be listed together with the matches of the group specified
together with the tt(-X) option (using the tt(-J) or tt(-V)
option). If the same explanation string is given to multiple tt(-X)
options, the string appears only once (for each group) and the number
of matches shown for the `tt(%n)' is the total number of all matches
for each of these uses. In any case, the explanation string will only
be shown if there was at least one match added for the explanation
string.
The sequences tt(%B), tt(%b), tt(%S), tt(%s), tt(%U), and tt(%u) specify
output attributes (bold, standout, and underline) and tt(%{...%}) can
be used to include literal escape sequences as in prompts.
)
item(tt(-Y) var(explanation))(
Identical to tt(-X), except that the var(explanation) first undergoes
@ -389,8 +475,72 @@ expansion following the usual rules for strings in double quotes.
The expansion will be carried out after any functions are called for
the tt(-K) or tt(-y) options, allowing them to set variables.
)
item(tt(-t) var(continue))(
The var(continue)-string contains a character that specifies which set
of completion flags should be used next. It is useful:
(i) With tt(-T), or when trying a list of pattern completions, when
tt(compctl) would usually continue with ordinary processing after
finding matches; this can be suppressed with `tt(-tn)'.
(ii) With a list of alternatives separated by tt(+), when tt(compctl)
would normally stop when one of the alternatives generates matches. It
can be forced to consider the next set of completions by adding `tt(-t+)'
to the flags of the alternative before the `tt(+)'.
(iii) In an extended completion list (see below), when tt(compctl) would
normally continue until a set of conditions succeeded, then use only
the immediately following flags. With `tt(-t-)', tt(compctl) will
continue trying extended completions after the next `tt(-)'; with
`tt(-tx)' it will attempt completion with the default flags, in other
words those before the `tt(-x)'.
)
item(tt(-J) var(name))(
This gives the name of the group the matches should be placed in. Groups
are listed and sorted separately; likewise, menucompletion will offer
the matches in the groups in the order in which the groups were
defined. If no group name is explicitly given, the matches are stored in
a group named var(default). The first time a group name is encountered,
a group with that name is created. After that all matches with the same
group name are stored in that group.
This can be useful with non-exclusive alternative completions. For
example, in
example(compctl -f -J files -t+ + -v -J variables foo)
both files and variables are possible completions, as the tt(-t+) forces
both sets of alternatives before and after the tt(+) to be considered at
once. Because of the tt(-J) options, however, all files are listed
before all variables.
)
item(tt(-V) var(name))(
Like tt(-J), but matches within the group will not be sorted in listings
nor in menucompletion. These unsorted groups are in a different name
space from the sorted ones, so groups defined as tt(-J files) and tt(-V
files) are distinct.
)
item(tt(-1))(
If given together with the tt(-V) option, makes
only consecutive duplicates in the group be removed. Note that groups
with and without this flag are in different name spaces.
)
item(tt(-2))(
If given together with the tt(-J) or tt(-V) option, makes all
duplicates be kept. Again, groups with and without this flag are in
different name spaces.
)
item(tt(-M) var(match-spec))(
This defines additional matching control specifications that should be used
only when testing words for the list of flags this flag appears in. The format
of the var(match-spec) string is described in
ifzman(zshcompwid)\
ifnzman(noderef(Matching Control))\
.
)
enditem()
texinode(Alternative Completion)(Extended Completion)(Option Flags)(Programmable Completion)
texinode(Alternative Completion)(Extended Completion)(Option Flags)(Completion Using compctl)
sect(Alternative Completion)
startlist()
list(tt(compctl) [ tt(-CDT) ] var(options) tt(PLUS()) var(options) [ tt(PLUS()) ... ] \
@ -402,16 +552,19 @@ tried with the options before the first `tt(PLUS())'. If this produces no
matches completion is tried with the flags after the `tt(PLUS())' and so on. If
there are no flags after the last `tt(PLUS())' and a match has not been found
up to that point, default completion is tried.
texinode(Extended Completion)(Example)(Alternative Completion)(Programmable Completion)
If the list of flags contains a tt(-t) with a tt(PLUS()) character, the next
list of flags is used even if the current list produced matches.
texinode(Extended Completion)(Example)(Alternative Completion)(Completion Using compctl)
sect(Extended Completion)
startlist()
list(tt(compctl) [ tt(-CDT) ] var(options) \
tt(-x) var(pattern) var(options) tt(-) ... tt(--) \
[ var(command) ... ])
list(tt(compctl) [ tt(-CDT) ] var(options) \
[ tt(-x) var(pattern) var(options) tt(-) ... tt(--) ] \
[ tt(PLUS()) var(options) [ tt(-x) ... tt(--) ] ... [tt(PLUS())] ] \
[ var(command) ... ])
list(nofill(tt(compctl) [ tt(-CDT) ] var(options) \
tt(-x) var(pattern) var(options) tt(-) ... tt(--)
[ var(command) ... ]))
list(nofill(tt(compctl) [ tt(-CDT) ] var(options) \
[ tt(-x) var(pattern) var(options) tt(-) ... tt(--) ]
[ tt(PLUS()) var(options) [ tt(-x) ... tt(--) ] ... [tt(PLUS())] ] \
[ var(command) ... ]))
endlist()
The form with `tt(-x)' specifies extended completion for the
@ -478,7 +631,7 @@ considered part of the completion, but the rest will. var(index) may
be negative to count from the end: in most cases, var(index) will be
1 or -1. For example,
nofill(tt(compctl -s '`users`' -x 'n[1,@]' -k hosts -- talk))
example(compctl -s '`users`' -x 'n[1,@]' -k hosts -- talk)
will usually complete usernames, but if you insert an tt(@) after the
name, names from the array var(hosts) (assumed to contain hostnames,
@ -497,17 +650,27 @@ var(max) inclusive.
)
item(tt(r[)var(str1)tt(,)var(str2)tt(])...)(
Matches if the cursor is after a word with prefix var(str1). If there
is also a word with prefix var(str2) on the command line it matches
only if the cursor is before this word.
is also a word with prefix var(str2) on the command line after the one
matched by var(str1) it matches
only if the cursor is before this word. If the comma and var(str2) are
omitted, it matches if the cursor is after a word with prefix var(str1).
)
item(tt(R[)var(str1)tt(,)var(str2)tt(])...)(
Like tt(r) but using pattern matching instead.
)
item(tt(q[)var(str)tt(])...)(
Matches the word currently being completed is in single quotes and the
var(str) begins with the letter `s', or if completion is done in
double quotes and var(str) starts with the letter `d', or if
completion is done in backticks and var(str) starts with a `b'.
)
enditem()
texinode(Example)()(Extended Completion)(Programmable Completion)
texinode(Example)()(Extended Completion)(Completion Using compctl)
sect(Example)
nofill(tt(compctl -u -x 's[tt(PLUS())] c[-1,-f],s[-f+PLUS()]' -g '~/Mail/*(:t)' \
- 's[-f],c[-1,-f]' -f -- mail))
example(compctl -u -x 's[tt(PLUS())] c[-1,-f],s[-f+PLUS()]' \
-g '~/Mail/*(:t)' - 's[-f],c[-1,-f]' -f -- mail)
This is to be interpreted as follows:

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -11,5 +11,5 @@ list(tt(/etc/zshenv))
list(tt(/etc/zprofile))
list(tt(/etc/zshrc))
list(tt(/etc/zlogin))
list(tt(/etc/zlogout) (installation-specific - tt(/etc) is the default))
list(tt(/etc/zlogout) (installation-specific - tt(/etc) is the default))
endlist()

View file

@ -6,12 +6,17 @@ cindex(startup files)
cindex(files, shutdown)
cindex(shutdown files)
pindex(NO_RCS, use of)
Commands are first read from tt(/etc/zshenv).
If the tt(RCS) option is unset
within tt(/etc/zshenv), all other
initialization files are skipped.
Otherwise, commands are read
from tt($ZDOTDIR/.zshenv).
pindex(NO_GLOBAL_RCS, use of)
Commands are first read from tt(/etc/zshenv); this cannot be overridden.
Subsequent behaviour is modified by the tt(RCS) and
tt(GLOBAL_RCS) options; the former affects all startup files, while the
second only affects those in the tt(/etc) directory. If one of the options
is unset at any point, any subsequent startup file(s) of the corresponding
type will not be read. It is also possible for a file in tt($ZDOTDIR) to
re-enable tt(GLOBAL_RCS). Both tt(RCS) and tt(GLOBAL_RCS) are set by
default.
Commands are then read from tt($ZDOTDIR/.zshenv).
pindex(LOGIN, use of)
If the shell is a login shell, commands
are read from tt(/etc/zprofile) and then tt($ZDOTDIR/.zprofile).
@ -20,7 +25,35 @@ commands are read from tt(/etc/zshrc) and then tt($ZDOTDIR/.zshrc).
Finally, if the shell is a login shell, tt(/etc/zlogin) and
tt($ZDOTDIR/.zlogin) are read.
When a login shell exits, the files tt($ZDOTDIR/.zlogout) and then
tt(/etc/zlogout) are read. This happens with either an explicit exit
via the tt(exit) or tt(logout) commands, or an implicit exit by reading
end-of-file from the terminal. However, if the shell terminates due
to tt(exec)'ing another process, the logout files are not read.
These are also affected by the tt(RCS) and tt(GLOBAL_RCS) options.
Note also that the tt(RCS) option affects the saving of history files,
i.e. if tt(RCS) is unset when the shell exits, no history file will be
saved.
If tt(ZDOTDIR) is unset, tt(HOME) is used instead.
Those files listed above as being in tt(/etc) may be in another
directory, depending on the installation.
As tt(/etc/zshenv) is run for all instances of zsh, it is important that
it be kept as small as possible. In particular, it is a good idea to
put code that does not need to be run for every single shell behind
a test of the form `tt(if [[ -o rcs ]]; then ...)' so that it will not
be executed when zsh is invoked with the `tt(-f)' option.
ifnzman(includefile(Zsh/filelist.yo))
Any of these files may be pre-compiled with the tt(zcompile) builtin
command (\
ifzman(\
see zmanref(zshbuiltins)\
)\
ifnzman(\
noderef(Shell Builtin Commands)\
)\
). If a compiled file exists (named for the original file plus the
tt(.zwc) extension) and it is newer than the original file, the compiled
file will be used instead.

View file

@ -16,9 +16,9 @@ printindex(Options Index)(pg)
texinode(Functions Index)(Editor Functions Index)(Options Index)(Top)
printindex(Functions Index)(fn)
texinode(Editor Functions Index)(Keystroke Index)(Functions Index)(Top)
texinode(Editor Functions Index)(Style and Tag Index)(Functions Index)(Top)
printindex(Editor Functions Index)(tp)
texinode(Keystroke Index)()(Editor Functions Index)(Top)
printindex(Keystroke Index)(ky)
texinode(Style and Tag Index)()(Editor Functions Index)(Top)
printindex(Style and Tag Index)(ky)
)\

View file

@ -28,10 +28,10 @@ menu(Parameters)
menu(Options)
menu(Shell Builtin Commands)
menu(Zsh Line Editor)
menu(Programmable Completion Using compctl)
menu(Completion Using compctl)
menu(Completion Widgets)
menu(Zsh Modules)
menu(Completion System)
menu(Zsh Modules)
menu(Zftp Function System)
--- Indices ---
@ -41,7 +41,7 @@ menu(Variables Index)
menu(Options Index)
menu(Functions Index)
menu(Editor Functions Index)
menu(Keystroke Index)
menu(Style and Tag Index)
--- The Detailed Node Listing ---
@ -98,7 +98,7 @@ menu(Arguments)
menu(Completion)
menu(Miscellaneous)
Programmable Completion Using compctl
Completion Using compctl
menu(Command Flags)
menu(Option Flags)
@ -113,23 +113,18 @@ menu(Builtin Commands)
menu(Condition Codes)
menu(Examples)
Completion System
menu(Initialization)
menu(Completion System Configuration)
menu(Control Functions)
menu(Bindable Commands)
menu(Completion Functions)
menu(Completion Directories)
Zsh Modules
menu(The cap Module)
menu(The clone Module)
menu(The comp1 Module)
menu(The compctl Module)
menu(The complist Module)
menu(The deltochar Module)
menu(The example Module)
menu(The files Module)
menu(The mapfile Module)
menu(The mathfunc Module)
menu(The parameter Module)
menu(The sched Module)
menu(The stat Module)
menu(The zftp Module)
menu(The zle Module)
includefile(Zsh/manmodmenu.yo)
endmenu()
texinode(The Z Shell Manual)(Introduction)(Top)(Top)
chapter(The Z Shell Manual)

View file

@ -1,7 +1,13 @@
texinode(The compctl Module)(The deltochar Module)(The comp1 Module)(Zsh Modules)
sect(The compctl Module)
The tt(compctl) module makes available one builtin command, tt(compctl),
which is the standard way to control completions for ZLE. See
COMMENT(!MOD!zsh/compctl
The tt(compctl) builtin for controlling completion.
!MOD!)
The tt(zsh/compctl) module makes available two builtin commands. tt(compctl),
is the old, deprecated way to control completions for ZLE. See
ifzman(zmanref(zshcompctl))\
ifnzman(noderef(Programmable Completion))\
ifnzman(noderef(Completion Using compctl))\
.
The other builtin command, tt(compcall) can be used in user-defined
completion widgets, see
ifzman(zmanref(zshcompwid))\
ifnzman(noderef(Completion Widgets))\
.

View file

@ -1,6 +1,7 @@
texinode(The zle Module)()(The stat Module)(Zsh Modules)
sect(The zle Module)
The tt(zle) module contains the Zsh Line Editor. See
COMMENT(!MOD!zsh/zle
The Zsh Line Editor, including the tt(bindkey) and tt(vared) builtins.
!MOD!)
The tt(zsh/zle) module contains the Zsh Line Editor. See
ifzman(zmanref(zshzle))\
ifnzman(noderef(Zsh Line Editor))\
. It also contains three related builtin commands:
@ -41,15 +42,14 @@ and does not otherwise count as an argument.
)
enditem()
Some operations do not permit a keymap to be selected.
If a keymap selection is required and none of the options above are used, the
`tt(main)' keymap is used. These operations do not permit a keymap to be
selected:
`tt(main)' keymap is used. Some operations do not permit a keymap to be
selected, namely:
startitem()
item(tt(-l))(
List all existing keymap names. If the tt(-L)
option is used, list in the form of tt(bindkey)
option is also used, list in the form of tt(bindkey)
commands to create the keymaps.
)
item(tt(-d))(
@ -67,12 +67,24 @@ with the var(new-keymap) name, it is deleted.
item(tt(-N) var(new-keymap) [ var(old-keymap) ])(
Create a new keymap, named var(new-keymap). If a keymap already has that
name, it is deleted. If an var(old-keymap) name is given, the new keymap
is initialised to be a duplicate of it, otherwise the new keymap will
is initialized to be a duplicate of it, otherwise the new keymap will
be empty.
)
enditem()
The following operations require a keymap to be selected:
To use a newly created keymamp, it should be linked to tt(main). Hence
the sequence of commands to create and use a new keymap `tt(mymap)'
initialized from the tt(emacs) keymap (which remains unchanged) is:
example(bindkey -N mymap emacs
bindkey -A mymap main)
Note that while `tt(bindkey -A) var(newmap) tt(main)' will work when
var(newmap) is tt(emacs) or tt(viins), it will not work for tt(vicmd), as
switching from vi insert to command mode becomes impossible.
The following operations act on the `tt(main)' keymap if no keymap
selection option was given:
startitem()
item(tt(-m))(
@ -82,29 +94,34 @@ Only keys that are unbound or bound to tt(self-insert) are affected.
item(tt(-r) var(in-string) ...)(
Unbind the specified var(in-string)s in the selected keymap.
This is exactly equivalent to binding the strings to tt(undefined-key).
When tt(-R) is also used, interpret the var(in-string)s as ranges.
)
item(tt(-s) var(in-string out-string) ...)(
Bind each var(in-string) to each var(out-string).
When var(in-string) is typed, var(out-string) will be
pushed back and treated as input to the line editor.
When tt(-R) is also used, interpret the var(in-string)s as ranges.
)
item(var(in-string command) ...)(
Bind each var(in-string) to each var(command).
When tt(-R) is used, interpret the var(in-string)s as ranges.
)
item([ var(in-string) ])(
List key bindings. If an var(in-string) is specified, the binding of
that string in the selected keymap is displayed. Otherwise, all key
bindings in the selected keymap are displayed. As an exception,
if the tt(-e) or tt(-v) options are used alone, the keymap is em(not)
displayed - the implicit linking of keymaps is the only thing that happens.
bindings in the selected keymap are displayed. (As a special case,
if the tt(-e) or tt(-v) option is used alone, the keymap is em(not)
displayed - the implicit linking of keymaps is the only thing that
happens.)
When the tt(-L) option is used, the list is in the form of tt(bindkey)
commands to create the key bindings.
)
enditem()
In the binding operations, if the tt(-R) option is used, the var(in-string)s
are interpreted as ranges, instead of plain strings. A valid range
consists of two characters, with an optional `tt(-)'
between them. All characters between the two specified, inclusive,
are bound as specified.
When the tt(-R) option is used as noted above, a valid range consists of
two characters, with an optional `tt(-)' between them. All characters
between the two specified, inclusive, are bound as specified.
For either var(in-string) or var(out-string), the following
escape sequences are recognised:
@ -126,21 +143,34 @@ sitem(tt(^)var(X))(control character)
endsitem()
In all other cases, `tt(\)' escapes the following character. Delete is
written as `tt(^?)'. Note that `tt(\M^?)' and `tt(^\M?)' are not the same.
written as `tt(^?)'. Note that `tt(\M^?)' and `tt(^\M?)' are not the same,
and that (unlike emacs), the bindings `tt(\M-)var(X)' and `tt(\e)var(X)'
are entirely distinct, although they are initialized to the same bindings
by `tt(bindkey -m)'.
)
findex(vared)
cindex(parameters, editing)
cindex(editing parameters)
item(tt(vared) [ tt(-ch) ] [ tt(-p) var(prompt) ] [ tt(-r) var(rprompt) ] var(name))(
item(tt(vared) [ tt(-Aache) ] [ tt(-p) var(prompt) ] [ tt(-r) var(rprompt) ] var(name))(
The value of the parameter var(name) is loaded into the edit
buffer, and the line editor is invoked. When the editor exits,
var(name) is set to the string value returned by the editor.
If the tt(-c) flag is given, the parameter is created if it doesn't
already exist.
When the tt(-c) flag is given, the parameter is created if it doesn't
already exist. The tt(-a) flag may be given with tt(-c) to create
an array parameter, or the tt(-A) flag to create an associative array.
If the type of an existing parameter does not match the type to be
created, the parameter is unset and recreated.
Individual elements of existing array or associative array parameters
may be edited by using subscript syntax on var(name). New elements are
created automatically, even without tt(-c).
If the tt(-p) flag is given, the following string will be taken as
the prompt to display at the left. If the tt(-r) flag is given,
the following string gives the prompt to display at the right. If the
tt(-h) flag is specified, the history can be accessed from ZLE.
tt(-h) flag is specified, the history can be accessed from ZLE. If the
tt(-e) flag is given, typing tt(^D) (Control-D) on an empty line
causes tt(vared) to exit immediatly with a non-zero return value.
)
findex(zle)
cindex(widgets, rebinding)
@ -153,11 +183,16 @@ cindex(widgets, calling)
cindex(calling widgets)
cindex(widgets, defining)
cindex(defining widgets)
xitem(tt(zle) tt(-l) [ tt(-L) ])
xitem(tt(zle) tt(-l) [ tt(-L) ] [ tt(-a) ] [ var(string) ... ])
xitem(tt(zle) tt(-D) var(widget) ...)
xitem(tt(zle) tt(-A) var(old-widget) var(new-widget))
xitem(tt(zle) tt(-N) var(widget) [ var(function) ])
item(tt(zle) var(widget))(
xitem(tt(zle) tt(-C) var(widget) var(completion-widget) var(function))
xitem(tt(zle) tt(-R) [ tt(-c) ] [ var(display-string) ] [ var(string) ... ])
xitem(tt(zle) tt(-M) var(string))
xitem(tt(zle) tt(-U) var(string))
xitem(tt(zle) var(widget) tt([ -n) var(num) tt(]) tt([ -N ]) var(args) ...)
item(tt(zle))(
The tt(zle) builtin performs a number of different actions concerning
ZLE. Which operation it performs depends on its options:
@ -166,7 +201,15 @@ item(tt(-l) [ tt(-L) ])(
List all existing user-defined widgets. If the tt(-L)
option is used, list in the form of tt(zle)
commands to create the widgets.
Built-in widgets are not listed.
When combined with the tt(-a) option, all widget names are listed,
including the builtin ones. In this case the tt(-L) option is ignored.
If at least one var(string) is given, nothing will be printed but the
return status will be zero if all var(string)s are names of existing
widgets (or of user-defined widgets if the tt(-a) flag is not given)
and non-zero if at least one var(string) is not a name of an defined
widget.
)
item(tt(-D) var(widget) ...)(
Delete the named var(widget)s.
@ -182,12 +225,86 @@ Create a user-defined widget. If there is already a widget with the
specified name, it is overwritten. When the new
widget is invoked from within the editor, the specified shell var(function)
is called. If no function name is specified, it defaults to
the same name as the widget.
the same name as the widget. For further information, see the section
em(Widgets) in
ifzman(zmanref(zshzle))\
ifnzman(noderef(Zsh Line Editor))\
.
)
item(var(widget))(
citem(completion widgets, creating)
item(tt(-C) var(widget) var(completion-widget) var(function))(
Create a user-defined completion widget named var(widget). The
completion widget will behave like the built-in completion-widget
whose name is given as var(completion-widget). To generate the
completions, the shell function var(function) will be called.
For further information, see
ifzman(zmanref(zshcompwid))\
ifnzman(noderef(Completion Widgets))\
.
)
item(tt(-R) [ tt(-c) ] [ var(display-string) ] [ var(string) ... ])(
Redisplay the command line; this is to be called from within a user-defined
widget to allow changes to become visible. If a var(display-string) is
given and not empty, this is shown in the status line (immediately
below the line being edited).
If the optional var(string)s are given they are listed below the
prompt in the same way as completion lists are printed. If no
var(string)s are given but the tt(-c) option is used such a list is
cleared.
Note that this option is only useful for widgets that do not exit
immediatly after using it because the strings displayed will be erased
immediatly after return from the widget.
)
item(tt(-M) var(string))(
As with the tt(-R) option, the var(string) will be displayed below the
command line. But unlike the tt(-R) option the string not be put into
the status line but will instead be printed normally below the
prompt. This means that the var(string) will still be displayed after
the widget returns (until it is overwritten by subsequent commands).
)
item(tt(-U) var(string))(
This pushes the characters in the var(string) onto the input stack of
ZLE. After the widget currently executed finishes ZLE will behave as
if the characters in the var(string) were typed by the user.
Note that since ZLE uses a stack, using tt(zle) with this option more
than once will make the last string pushed be used first. The
characters in each var(string) will be used in the order in which they
appear in the string, though.
)
item(var(widget) tt([ -n) var(num) tt(]) tt([ -N ]) var(args) ...)(
Invoke the specified widget. This can only be done when ZLE is
active; normally this will be within a user-defined widget.
With the options tt(-n) and tt(-N), the current numerical argument will be
saved and then restored after the call to tt(widget); `tt(-n) var(num)'
sets the numerical argument temporarily to var(num), while `tt(-N)' sets it
to the default, i.e. as if there were none.
Any further arguments will be passed to the widget. If it is a shell
function, these are passed down as positional parameters; for builtin
widgets it is up to the widget in question what it does with them.
Currently arguments are only handled by the incremental-search commands,
the tt(history-search-forward) and tt(-backward) and the corresponding
functions prefixed by tt(vi-), and by tt(universal-argument). No error is
flagged if the command does not use the arguments, or only uses some of
them.
The return status reflects the success or failure of the operation carried
out by the widget, or if it is a user-defined widget the return status of
the shell function.
A non-zero return status causes the shell to beep when the widget exits,
unless the tt(BEEP) options was unset or the widget was called via the
tt(zle) command. Thus if a user defined widget requires an immediate beep,
it should call the tt(beep) widget directly.
)
enditem()
With no options and no arguments, only the returns status will be
set. It is zero if ZLE is currently active and widgets could be
invoked using this builtin command and non-zero if ZLE is not active.
)
enditem()

View file

@ -1,9 +1,12 @@
texinode(The zutil Module)(The complete Module)(The clone Module)(Zsh Modules)
sect(The zutil Module)
COMMENT(!MOD!zsh/zutil
Some utility builtins, e.g. the one for supporting configuration via
styles.
!MOD!)
cindex(builtins, utility)
The tt(zutil) module only adds some builtins:
The tt(zsh/zutil) module only adds some builtins:
startitem()
findex(zstyle)
xitem(tt(zstyle) [ tt(-L) ])
xitem(tt(zstyle) [ tt(-) | tt(-)tt(-) ] var(pattern) var(style) var(strings) ...)
xitem(tt(zstyle -d) [ var(pattern) [ var(styles) ... ] ])
@ -13,6 +16,7 @@ xitem(tt(zstyle -b) var(context) var(style) var(name))
xitem(tt(zstyle -a) var(context) var(style) var(name))
xitem(tt(zstyle -h) var(context) var(style) var(name))
xitem(tt(zstyle -t) var(context) var(style) [ var(strings) ...])
xitem(tt(zstyle -T) var(context) var(style) [ var(strings) ...])
item(tt(zstyle -m) var(context) var(style) var(pattern))(
This builtin command is used to define and lookup styles. Styles are
pairs of names and values, where the values consist of any number of
@ -61,17 +65,22 @@ makes it be returned as an associative array (with the first, third,
etc. string being used as the keys and the other strings being used as
the values).
The tt(-t) option can be used to test the value of a style, i.e. it
The tt(-t) options can be used to test the value of a style, i.e. it
only sets the return value. Without any var(strings) arguments it is
zero if the style is defined for at least one matching pattern, has
only one string in its value and that is equal to one of tt(true),
tt(yes), tt(on) or tt(1). If any var(strings) are given the return
zero if and only if at least one of the var(strings) is equal to at
least one of the strings in the value.
least one of the strings in the value. If the style is not defined,
the return value is tt(2).
The tt(-T) option is like tt(-t) but returns zero if the style is not
set for any matching pattern.
The tt(-m) option can be used to match a value. It returns zero if the
var(pattern) matches at least one of the strings in the value.
)
findex(zformat)
xitem(tt(zformat -f) var(param) var(format) var(specs) ...)
item(tt(zformat -a) var(array) var(sep) var(specs) ...)(
This builtin provides to different forms of formatting. The first form
@ -106,4 +115,52 @@ trailing colon removed. In both cases the lengths of the strings
are not used to determine how the other strings have to be aligned.
The resulting strings are stored in the var(array).
)
findex(zregexparse)
item(tt(zregexparse))(
This implements the internals of the `tt(_regex_arguments)'.
)
findex(zparseopts)
item(tt(zparseopts) [ tt(-D) ] [ tt(-a) var(array) ] [ tt(-A) var(assoc) ] var(specs))(
This builtin simplifies the parsing of options in the positional
parameters. Each var(spec) describes one option and should be of the
form `var(name)[tt(+)][tt(:)[tt(:)][tt(-)]][tt(=)var(array)]'. The var(name)
is the name of the option (without the leading `tt(-)'). If only that
is given, the option takes no argument and if it is found in the
positional parameters it will be placed in the var(array) given with
the tt(-a) option. If the optional `tt(=)var(array)' is given, it will
be put into that array instead. If one or two colons are given, the
option takes an argument. With one colon, this argument is mandatory
and with two colons it is optional. The argument will be inserted into
the var(array), too. For mandatory arguments it is added as a separate
string and for optional arguments it is put into one string together
with the option name unless the `tt(-)' option is given. In this case
the argument will be put into the same word even for mandatory
arguments (note that this makes empty strings as arguments
indistinguishable). Finally, if the `tt(+)' is given and the option
appears more than once in the positional parameters, it will be
inserted more than once in the var(array), too. Without the `tt(+)'
the option will be inserted only once in the var(array) with arguments
of later options overwriting earlier once. If any of the special
character needs to appear in the option name it must be preceded by a
backslash.
If the tt(-A) option is given, the options and their values will also
be put into an associative array with the option names as keys and the
arguments (if any) as the values. Note that it is an error to give
var(specs) without a `tt(=)var(array)' and not use either the tt(-a)
or tt(-A) option.
If the tt(-D) option is given, all options found are removed from the
positional parameters leaving only the strings from the first one that
was not described by any of the var(specs) to the last (note that this
is the usual rule used by tt(zparseopts) to find out when to stop
processing options).
For example, calling `tt(zparseopts a=foo b:=bar c+:=bar)' with the
strings `tt(-a)', `tt(-bx)', `tt(-c)', `tt(y)', `tt(-cz)', `tt(baz)'
and `tt(-cend)' as positional arguments will set the array tt(foo) to
contain the element `tt(-a)' and the array tt(bar) to the strings
`tt(-b)', `tt(x)', `tt(-c)', `tt(y)', `tt(-c)', and `tt(z)'. The
`tt(baz)' and all strings after it will not be used.
)
enditem()

View file

@ -1,4 +1,4 @@
texinode(Zsh Modules)()(Programmable Completion)(Top)
texinode(Zsh Modules)(Zftp Function System)(Completion System)(Top)
chapter(Zsh Modules)
cindex(modules)
sect(Description)
@ -6,59 +6,7 @@ Some optional parts of zsh are in modules, separate from the core
of the shell. Each of these modules may be linked in to the
shell at build time,
or can be dynamically linked while the shell is running
if the installation supports this feature. The modules available are:
if the installation supports this feature. The modules that
are bundled with the zsh distribution are:
startitem()
item(tt(cap))(
Builtins for manipulating POSIX.1e (POSIX.6) capability (privilege) sets.
)
item(tt(clone))(
A builtin that can clone a running shell onto another terminal.
)
item(tt(comp1))(
Base of the completion system. Used by the tt(compctl) and tt(zle) modules.
)
item(tt(compctl))(
The tt(compctl) builtin for controlling completion.
)
item(tt(deltochar))(
A ZLE function duplicating EMACS' tt(zap-to-char).
)
item(tt(example))(
An example of how to write a module.
)
item(tt(files))(
Some basic file manipulation commands as builtins.
)
item(tt(sched))(
A builtin that provides a timed execution facility within the shell.
)
item(tt(stat))(
A builtin command interface to the tt(stat) system call.
)
item(tt(zle))(
The Zsh Line Editor, including the tt(bindkey) and tt(vared) builtins.
)
enditem()
startmenu()
menu(The cap Module)
menu(The clone Module)
menu(The comp1 Module)
menu(The compctl Module)
menu(The deltochar Module)
menu(The example Module)
menu(The files Module)
menu(The sched Module)
menu(The stat Module)
menu(The zle Module)
endmenu()
includefile(Zsh/mod_cap.yo)
includefile(Zsh/mod_clone.yo)
includefile(Zsh/mod_comp1.yo)
includefile(Zsh/mod_compctl.yo)
includefile(Zsh/mod_deltochar.yo)
includefile(Zsh/mod_example.yo)
includefile(Zsh/mod_files.yo)
includefile(Zsh/mod_sched.yo)
includefile(Zsh/mod_stat.yo)
includefile(Zsh/mod_zle.yo)
includefile(Zsh/modlist.yo)

View file

@ -7,7 +7,8 @@ A name may be any sequence of alphanumeric
characters and underscores, or the single characters
`tt(*)', `tt(@)', `tt(#)', `tt(?)', `tt(-)', `tt($)', or `tt(!)'.
The value may be a em(scalar) (a string),
an integer, or an array.
an integer, an array (indexed numerically), or an em(associative)
array (an unordered set of name-value pairs, indexed by name).
To assign a scalar or integer value to a parameter,
use the tt(typeset) builtin.
findex(typeset, use of)
@ -15,45 +16,41 @@ To assign an array value, use `tt(set -A) var(name) var(value) ...'.
findex(set, use of)
The value of a parameter may also be assigned by writing:
nofill(var(name)tt(=)var(value))
indent(var(name)tt(=)var(value))
If the integer attribute, tt(-i), is set for var(name),
the var(value) is subject to arithmetic evaluation.
If the integer attribute, tt(-i), is set for var(name), the var(value)
is subject to arithmetic evaluation. See noderef(Array Parameters)
for additional forms of assignment.
In the parameter lists, the mark `<S>' indicates that the parameter is special.
In the parameter lists that follow, the mark `<S>' indicates that the
parameter is special.
Special parameters cannot have their type changed, and they stay special even
if unset. `<Z>' indicates that the parameter does not exist when the shell
initialises in tt(sh) or tt(ksh) emulation mode.
initializes in tt(sh) or tt(ksh) emulation mode.
startmenu()
menu(Local Parameters)
menu(Array Parameters)
menu(Positional Parameters)
menu(Local Parameters)
menu(Parameters Set By The Shell)
menu(Parameters Used By The Shell)
endmenu()
texinode(Local Parameters)(Array Parameters)()(Parameters)
sect(Local Parameters)
Shell function executions delimit scopes for shell parameters.
(Parameters are dynamically scoped.) The tt(typeset) builtin, and its
alternative forms tt(declare), tt(integer), tt(local) and tt(readonly)
(but not tt(export)), can be used to declare a parameter as being local
to the innermost scope.
When a parameter is read or assigned to, the
innermost existing parameter of that name is used. (That is, the
local parameter hides any less-local parameter.) However, assigning
to a non-existent parameter, or declaring a new parameter with tt(export),
causes it to be created in the em(outer)most scope.
Local parameters disappear when their scope ends.
tt(unset) can be used to delete a parameter while it is still in scope; this
will reveal the next outer parameter of the same name. However, em(special)
parameters are still special when unset.
texinode(Array Parameters)(Positional Parameters)(Local Parameters)(Parameters)
texinode(Array Parameters)(Positional Parameters)()(Parameters)
sect(Array Parameters)
The value of an array parameter may be assigned by writing:
nofill(var(name)tt(=LPAR())var(value) ...tt(RPAR()))
indent(var(name)tt(=LPAR())var(value) ...tt(RPAR()))
If no parameter var(name) exists, an ordinary array parameter is created.
Associative arrays must be declared first, by `tt(typeset -A) var(name)'.
When var(name) refers to an associative array, the parenthesized list is
interpreted as alternating keys and values:
indent(var(name)tt(=LPAR())var(key) var(value) ...tt(RPAR()))
Every var(key) must have a var(value) in this case. To create an empty
array or associative array, use:
indent(var(name)tt(=LPAR()RPAR()))
Individual elements of an array may be selected using a
subscript. A subscript of the form `tt([)var(exp)tt(])'
@ -62,8 +59,12 @@ an arithmetic expression which will be subject to arithmetic
expansion as if it were surrounded by `tt($LPAR()LPAR())...tt(RPAR()RPAR())'.
The elements are numbered beginning with 1 unless the
tt(KSH_ARRAYS) option is set when they are numbered from zero.
cindex(subscripts)
pindex(KSH_ARRAYS, use of)
The same subscripting syntax is used for associative arrays,
except that no arithmetic expansion is applied to var(exp).
A subscript of the form `tt([*])' or `tt([@])' evaluates to all
elements of an array; there is no difference between the two
except when they appear within double quotes.
@ -72,8 +73,8 @@ except when they appear within double quotes.
A subscript of the form `tt([)var(exp1)tt(,)var(exp2)tt(])'
selects all elements in the range var(exp1) to var(exp2),
inclusive.
If one of the subscripts evaluates to a negative number,
inclusive. (Associative arrays are unordered, and so do not support
ranges.) If one of the subscripts evaluates to a negative number,
say tt(-)var(n), then the var(n)th element from the end
of the array is used. Thus `tt($foo[-3])' is the third element
from the end of the array tt(foo), and
@ -90,22 +91,29 @@ option is set, the braced form is the only one that will
work, the subscript otherwise not being treated specially.
If a subscript is used on the left side of an assignment the selected
range is replaced by the expression on the right side.
element or range is replaced by the expression on the right side. An
array (but not an associative array) may be created by assignment to a
range or element. Arrays do not nest, so assigning a parenthesized list
of values to an element or range changes the number of elements in the
array, shifting the other elements to accommodate the new values. (This
is not supported for associative arrays.)
To delete an element of an ordinary array, assign `tt(LPAR()RPAR())' to
that element.
To delete an element of an associative array, use the tt(unset) command.
If the opening bracket or the comma is directly followed by an opening
parentheses the string up to the matching closing one is considered to
be a list of flags. The flags currently understood are:
startitem()
item(tt(e))(
this option has no effect and retained for backward compatibility only.
)
item(tt(w))(
if the parameter subscripted is a scalar than this flag makes
subscription work on a per-word basis instead of characters.
If the parameter subscripted is a scalar than this flag makes
subscripting work on words instead of characters. The default word
separator is whitespace.
)
item(tt(s:)var(string)tt(:))(
this gives the var(string) that separates words (for use with the
This gives the var(string) that separates words (for use with the
tt(w) flag).
)
item(tt(p))(
@ -113,44 +121,117 @@ Recognize the same escape sequences as the tt(print) builtin in
the string argument of a subsequent `tt(s)' flag.
)
item(tt(f))(
if the parameter subscripted is a scalar than this flag makes
subscription work on a per-line basis instead of characters.
This is a shorthand for `tt(pws:\n:)'.
If the parameter subscripted is a scalar than this flag makes
subscripting work on lines instead of characters, i.e. with elements
separated by newlines. This is a shorthand for `tt(pws:\n:)'.
)
item(tt(r))(
if this flag is given the var(exp) is taken as a pattern and the
result is the first matching array element, substring or word (if the
parameter is an array, if it is a scalar, or if it is a scalar and the
`tt(w)' flag is given, respectively); note that this is like giving a
number: `tt($foo[(r))var(??)tt(,3])' and `tt($foo[(r))var(??)tt(,(r)f*])' work.
Reverse subscripting: if this flag is given, the var(exp) is taken as a
pattern and the result is the first matching array element, substring or
word (if the parameter is an array, if it is a scalar, or if it is a scalar
and the `tt(w)' flag is given, respectively). The subscript used is the
number of the matching element, so that pairs of subscripts such as
`tt($foo[(r))var(??)tt(,3])' and `tt($foo[(r))var(??)tt(,(r)f*])'
are possible. If the parameter is an associative array, only the value part
of each pair is compared to the pattern.
)
item(tt(R))(
like `tt(r)', but gives the last match.
Like `tt(r)', but gives the last match. For associative arrays, gives
all possible matches.
)
item(tt(k))(
If used in a subscript on a parameter that is not an associative
array, this behaves like `tt(r)', but if used on an association, it
makes the keys be interpreted as patterns and returns the first value
whose key matches the var(exp).
)
item(tt(K))(
On an associtation this is like `tt(k)' but returns all values whose
keys match the var(exp). On other types of parameters this has the
same effect as `tt(R)'.
)
item(tt(i))(
like `tt(r)', but gives the index of the match instead; this may not
be combined with a second argument.
be combined with a second argument. For associative arrays, the key
part of each pair is compared to the pattern, and the first matching
key found is used.
)
item(tt(I))(
like `tt(i), but gives the index of the last match.
like `tt(i)', but gives the index of the last match, or all possible
matching keys in an associative array.
)
item(tt(n:)var(expr)tt(:))(
if combined with `tt(r)', `tt(R)', `tt(i)' or `tt(I)', makes them give
the var(n)th or var(n)th last match (if var(expr) evaluates to
var(n)).
var(n)). This flag is ignored when the array is associative.
)
item(tt(b:)var(expr)tt(:))(
if combined with `tt(r)', `tt(R)', `tt(i)' or `tt(I)', makes them begin
at the var(n)th or var(n)th last element, word, or character (if var(expr)
evaluates to var(n)). This flag is ignored when the array is associative.
)
item(tt(e))(
This option has no effect and retained for backward compatibility only.
)
enditem()
texinode(Positional Parameters)(Parameters Set By The Shell)(Array Parameters)(Parameters)
texinode(Positional Parameters)(Local Parameters)(Array Parameters)(Parameters)
sect(Positional Parameters)
Positional parameters are set by the shell on invocation,
by the tt(set) builtin, or by direct assignment.
The positional parameters provide access to the command-line arguments
of a shell function, shell script, or the shell itself; see
noderef(Invocation), and also noderef(Functions).
The parameter var(n), where var(n) is a number,
is the var(n)th positional parameter.
The parameters tt(*), tt(@) and tt(argv) are
arrays containing all the positional parameters;
thus `tt($argv[)var(n)tt(])', etc., is equivalent to simply `tt($)var(n)'.
texinode(Parameters Set By The Shell)(Parameters Used By The Shell)(Positional Parameters)(Parameters)
Positional parameters may be changed after the shell or function starts by
using the tt(set) builtin, by assigning to the tt(argv) array, or by direct
assignment of the form `var(n)tt(=)var(value)' where var(n) is the number of
the positional parameter to be changed. This also creates (with empty
values) any of the positions from 1 to var(n) that do not already have
values. Note that, because the positional parameters form an array, an
array assignment of the form `var(n)tt(=LPAR())var(value) ...tt(RPAR())' is
allowed, and has the effect of shifting all the values at positions greater
than var(n) by as many positions as necessary to accommodate the new values.
texinode(Local Parameters)(Parameters Set By The Shell)(Positional Parameters)(Parameters)
sect(Local Parameters)
Shell function executions delimit scopes for shell parameters.
(Parameters are dynamically scoped.) The tt(typeset) builtin, and its
alternative forms tt(declare), tt(integer), tt(local) and tt(readonly)
(but not tt(export)), can be used to declare a parameter as being local
to the innermost scope.
When a parameter is read or assigned to, the
innermost existing parameter of that name is used. (That is, the
local parameter hides any less-local parameter.) However, assigning
to a non-existent parameter, or declaring a new parameter with tt(export),
causes it to be created in the em(outer)most scope.
Local parameters disappear when their scope ends.
tt(unset) can be used to delete a parameter while it is still in scope;
any outer parameter of the same name remains hidden.
Special parameters may also be made local; they retain their special
attributes unless either the existing or the newly-created parameter
has the tt(-h) (hide) attribute. This may have unexpected effects.
Firstly, there is no default value, so if there is no assigment at the
point the variable is made local, it will be set to an empty value (or zero
in the case of integers). Secondly, special parameters which are made
local will not be exported (as with other parameters), so that the global
value of the parameter remains present in the environment if it is already
there. This should be particularly noted in the case of tt(PATH): the
shell will use the local version of tt(PATH) for finding programmes, but
programmes using the shell's environment will inherit the global version.
The following:
example(typeset PATH=/new/directory:$PATH)
is valid for temporarily allowing the shell to find the programs in
tt(/new/directory) inside a function.
texinode(Parameters Set By The Shell)(Parameters Used By The Shell)(Local Parameters)(Parameters)
sect(Parameters Set By The Shell)
The following parameters are automatically set by the shell:
@ -182,11 +263,15 @@ An array containing the positional parameters.
)
vindex(argv)
item(tt(argv) <S> <Z>)(
Same as tt(*).
Same as tt(*). Assigning to tt(argv) changes the local positional
parameters, but tt(argv) is em(not) itself a local parameter.
Deleting tt(argv) with tt(unset) in any function deletes it everywhere,
although only the innermost positional parameter array is deleted (so
tt(*) and tt(@) in other scopes are not affected).
)
vindex(@)
item(tt(@) <S>)(
Same as tt(argv[@]).
Same as tt(argv[@]), even when tt(argv) is not set.
)
vindex(?)
item(tt(?) <S>)(
@ -202,12 +287,22 @@ vindex(status)
item(tt(status) <S> <Z>)(
Same as tt(?).
)
vindex(pipestatus)
item(tt(pipestatus) <S> <Z>)(
An array containing the exit values returned by all commands in the
last pipeline.
)
vindex(_)
item(tt(_) <S>)(
The last argument of the previous command.
Also, this parameter is set in the environment of every command
executed to the full pathname of the command.
)
vindex(CPUTYPE)
item(tt(CPUTYPE))(
The machine type (microprocessor class or machine model),
as determined at run time.
)
vindex(EGID)
item(tt(EGID) <S>)(
The effective group ID of the shell process. If you have sufficient
@ -245,8 +340,11 @@ The current hostname.
)
vindex(LINENO)
item(tt(LINENO) <S>)(
The line number of the current line within the current script
being executed.
The line number of the current line within the current script, sourced
file, or shell function being executed, whichever was started most
recently. Note that in the case of shell functions the line
number refers to the function as it appeared in the original definition,
not necesarily as displayed by the tt(functions) builtin.
)
vindex(LOGNAME)
item(tt(LOGNAME))(
@ -262,7 +360,7 @@ as determined at compile time.
)
vindex(OLDPWD)
item(tt(OLDPWD))(
The previous working directory. This is set when the shell initialises
The previous working directory. This is set when the shell initializes
and whenever the directory changes.
)
vindex(OPTARG)
@ -285,7 +383,7 @@ The process ID of the parent of the shell.
)
vindex(PWD)
item(tt(PWD))(
The present working directory. This is set when the shell initialises
The present working directory. This is set when the shell initializes
and whenever the directory changes.
)
vindex(RANDOM)
@ -356,7 +454,7 @@ The following parameters are used by the shell:
startitem()
vindex(ARGV0)
item(tt(ARGV0))(
If exported, its value is used as tt(argv[0]) of external commands.
If exported, its value is used as the tt(argv[0]) of external commands.
Usually used in constructs like `tt(ARGV0=emacs nethack)'.
)
vindex(BAUD)
@ -417,7 +515,7 @@ vindex(histchars)
item(tt(histchars) <S>)(
Three characters used by the shell's history and lexical analysis
mechanism. The first character signals the start of a history
substitution (default `tt(!)'). The second character signals the
expansion (default `tt(!)'). The second character signals the
start of a quick history substitution (default `tt(^)'). The third
character is the comment character (default `tt(#)').
)
@ -432,7 +530,10 @@ If unset, the history is not saved.
)
vindex(HISTSIZE)
item(tt(HISTSIZE) <S>)(
The maximum size of the history list.
The maximum number of events stored in the internal history list.
If you use the tt(HIST_EXPIRE_DUPS_FIRST) option, setting this value
larger than the tt(SAVEHIST) size will give you the difference as a
cushion for saving duplicated history events.
)
vindex(HOME)
item(tt(HOME) <S>)(
@ -442,7 +543,7 @@ vindex(IFS)
item(tt(IFS) <S>)(
Internal field separators (by default space, tab, newline and NUL), that
are used to separate words which result from
command or parameter substitution and words read by
command or parameter expansion and words read by
the tt(read) builtin. Any characters from the set space, tab and
newline that appear in the IFS are called em(IFS white space).
One or more IFS white space characters or one non-IFS white space
@ -481,6 +582,13 @@ item(tt(LC_MESSAGES) <S>)(
This variable determines the language in which messages should be
written. Note that zsh does not use message catalogs.
)
vindex(LC_NUMERIC)
item(tt(LC_NUMERIC) <S>)(
This variable affects the decimal point character and thousands
separator character for the formatted input/output functions
and string conversion functions. Note that zsh ignores this
setting when parsing floating point mathematical expressions.
)
vindex(LC_TIME)
item(tt(LC_TIME) <S>)(
This variable determines the locale category for date and time
@ -493,7 +601,9 @@ Used for printing select lists and for the line editor.
)
vindex(LISTMAX)
item(tt(LISTMAX))(
In the line editor, the number of filenames to list without asking first.
In the line editor, the number of matches to list without asking
first. If the value is negative, the list will be shown if it spans at
most as many lines as given by the absolute value.
If set to zero, the shell asks only if the top of the listing would scroll
off the screen.
)
@ -518,7 +628,7 @@ An array (colon-separated list) of filenames to check for
new mail. Each filename can be followed by a `tt(?)' and a
message that will be printed. The message will undergo
parameter expansion, command substitution and arithmetic
substitution with the variable tt($_) defined as the name
expansion with the variable tt($_) defined as the name
of the file that has changed. The default message is
`tt(You have new mail)'. If an element is a directory
instead of a file the shell will recursively check every
@ -538,7 +648,7 @@ item(tt(module_path) <S> <Z> (tt(MODULE_PATH) <S>))(
An array (colon-separated list)
of directories that tt(zmodload)
searches for dynamically loadable modules.
This is initialised to a standard pathname,
This is initialized to a standard pathname,
usually `tt(/usr/local/lib/zsh/$ZSH_VERSION)'.
(The `tt(/usr/local/lib)' part varies from installation to installation.)
For security reasons, any value set in the environment when the shell
@ -593,7 +703,9 @@ The default is `tt(?# )'.
)
vindex(PS4)
item(tt(PS4) <S>)(
The execution trace prompt. Default is `tt(PLUS() )'.
The execution trace prompt. Default is `tt(PLUS()%N:%i> )', which displays
the name of the current shell structure and the line number within it.
In sh or ksh emulation, the default is `tt(PLUS() )'.
)
vindex(PROMPT)
xitem(tt(PROMPT) <S> <Z>)
@ -656,12 +768,12 @@ set up the terminal before executing the command. The modes apply only to the
command, and are reset when it finishes or is suspended. If the command is
suspended and continued later with the tt(fg) or tt(wait) builtins it will
see the modes specified by tt(STTY), as if it were not suspended. This
(intentionally) does not apply if the command is continued via `tt(kill -CONT)'.
tt(STTY) is ignored if the command is run in the background, or if it is in the
environment of the shell but not explicitly assigned to in the input line. This
avoids running stty at every external command by accidentally exporting it.
Also note that tt(STTY) should not be used for window size specifications; these
will not be local to the command.
(intentionally) does not apply if the command is continued via `tt(kill
-CONT)'. tt(STTY) is ignored if the command is run in the background, or
if it is in the environment of the shell but not explicitly assigned to in
the input line. This avoids running stty at every external command by
accidentally exporting it. Also note that tt(STTY) should not be used for
window size specifications; these will not be local to the command.
)
vindex(TERM)
item(tt(TERM) <S>)(
@ -804,6 +916,19 @@ item(tt(WORDCHARS) <S>)(
A list of non-alphanumeric characters considered part of a word
by the line editor.
)
vindex(ZBEEP)
item(tt(ZBEEP))(
If set, this gives a string of characters, which can use all the same codes
as the tt(bindkey) command as described in
ifzman(the zsh/zle module entry in zmanref(zshmodules))\
ifnzman(noderef(The zsh/zle Module))\
, that will be output to the terminal
instead of beeping. This may have a visible instead of an audible effect;
for example, the string `tt(\e[?5h\e[?5l)' on a vt100 or xterm will have
the effect of flashing reverse video on and off (if you usually use reverse
video, you should use the string `tt(\e[?5l\e[?5h)' instead). This takes
precedence over the tt(NOBEEP) option.
)
vindex(ZDOTDIR)
item(tt(ZDOTDIR))(
The directory to search for shell startup files (.zshrc, etc),

View file

@ -16,7 +16,7 @@ input/output specifications.
The following may appear anywhere in a simple command
or may precede or follow a complex command.
Substitution occurs before var(word) or var(digit)
Expansion occurs before var(word) or var(digit)
is used except as noted below.
If the result of substitution on var(word)
produces more than one filename,
@ -57,7 +57,7 @@ exist, even if tt(CLOBBER) is unset.
item(tt(<<)[tt(-)] var(word))(
The shell input is read up to a line that is the same as
var(word), or to an end-of-file.
No parameter substitution, command substitution or
No parameter expansion, command substitution or
filename generation is performed on var(word).
The resulting document, called a
em(here-document), becomes the standard input.
@ -77,10 +77,10 @@ item(tt(<<<) var(word))(
Perform shell expansion on var(word) and pass the result
to standard input. This is known as a em(here-string).
)
xitem(tt(<&) var(digit))
item(tt(>&) var(digit))(
xitem(tt(<&) var(number))
item(tt(>&) var(number))(
The standard input/output is duplicated from file descriptor
var(digit) (see manref(dup)(2)).
var(number) (see manref(dup2)(2)).
)
xitem(tt(<& -))
item(tt(>& -))(
@ -90,11 +90,33 @@ xitem(tt(<& p))
item(tt(>& p))(
The input/output from/to the coprocess is moved to the standard input/output.
)
item(tt(>&) var(word))(
Same as `tt(>) var(word) tt(2>&1)'.
xitem(tt(>&) var(word))
item(tt(&>) var(word))(
(Except where `tt(>&) var(word)' matches one of the above syntaxes;
`tt(&>)' can always be used to avoid this ambiguity.)
Redirects both standard output and standard error (file descriptor 2)
in the manner of `tt(>) var(word)'.
Note that this does em(not) have the same effect as `tt(>) var(word) tt(2>&1)'
in the presence of multios (see the section below).
)
item(tt(>>&) var(word))(
Same as `tt(>>) var(word) tt(2>&1)'.
xitem(tt(>&|) var(word))
xitem(tt(>&!) var(word))
xitem(tt(&>|) var(word))
item(tt(&>!) var(word))(
Redirects both standard output and standard error (file descriptor 2)
in the manner of `tt(>|) var(word)'.
)
xitem(tt(>>&) var(word))
item(tt(&>>) var(word))(
Redirects both standard output and standard error (file descriptor 2)
in the manner of `tt(>>) var(word)'.
)
xitem(tt(>>&|) var(word))
xitem(tt(>>&!) var(word))
xitem(tt(&>>|) var(word))
item(tt(&>>!) var(word))(
Redirects both standard output and standard error (file descriptor 2)
in the manner of `tt(>>|) var(word)'.
)
enditem()
@ -107,7 +129,7 @@ The shell evaluates each redirection in terms of the
association at the time of evaluation.
For example:
nofill(... tt(1>)var(fname) tt(2>&1))
indent(... tt(1>)var(fname) tt(2>&1))
first associates file descriptor 1 with file var(fname).
It then associates file descriptor 2 with the file associated with file
@ -123,12 +145,12 @@ the shell opens the file descriptor as a pipe to a process that copies
its input to all the specified outputs, similar to bf(tee),
provided the tt(MULTIOS) option is set. Thus:
nofill(tt(date >foo >bar))
example(date >foo >bar)
writes the date to two files, named `tt(foo)' and `tt(bar)'.
Note that a pipe is an implicit redirection; thus
nofill(tt(date >foo | cat))
example(date >foo | cat)
writes the date to the file `tt(foo)', and also pipes it to cat.
@ -136,14 +158,14 @@ If the tt(MULTIOS)
option is set, the word after a redirection operator is also subjected
to filename generation (globbing). Thus
nofill(tt(: > *))
example(: > *)
will truncate all files in the current directory,
assuming there's at least one. (Without the tt(MULTIOS)
option, it would create an empty file called `tt(*)'.)
Similarly, you can do
nofill(tt(echo exit 0 >> *.sh))
example(echo exit 0 >> *.sh)
If the user tries to open a file descriptor for reading more than once,
the shell opens the file descriptor as a pipe to a process that copies
@ -151,17 +173,17 @@ all the specified inputs to its output in the order
specified, similar to bf(cat),
provided the tt(MULTIOS) option is set. Thus
nofill(tt(sort <foo <fubar))
example(sort <foo <fubar)
or even
nofill(tt(sort <f{oo,ubar}))
example(sort <f{oo,ubar})
is equivalent to `tt(cat foo fubar | sort)'.
Note that a pipe is an implicit redirection; thus
nofill(tt(cat bar | sort <foo))
example(cat bar | sort <foo)
is equivalent to `tt(cat bar foo | sort)' (note the order of the inputs).
@ -169,15 +191,35 @@ If the tt(MULTIOS) option is em(un)set,
each redirection replaces the previous redirection for that file descriptor.
However, all files redirected to are actually opened, so
nofill(tt(echo foo > bar > baz))
example(echo foo > bar > baz)
when tt(MULTIOS) is unset will truncate bar, and write `tt(foo)' into baz.
If a simple command consists of one or more redirection operators
and zero or more parameter assignments, but no command name,
the command named in the shell variable tt(READNULLCMD) is assumed.
(If tt(READNULLCMD) is empty or not set, `tt(cat)' is used.) Thus
sect(Redirections with no command)
vindex(NULLCMD, use of)
vindex(READNULLCMD, use of)
pindex(CSH_NULLCMD, use of)
pindex(SH_NULLCMD, use of)
When a simple command consists of one or more redirection operators
and zero or more parameter assignments, but no command name, zsh can
behave in several ways.
nofill(tt(< file))
If the parameter tt(NULLCMD) is not set or the option tt(CSH_NULLCMD) is
set, an error is caused. This is the bf(csh) behavior and tt(CSH_NULLCMD)
is set by default when emulating bf(csh).
If the option tt(SH_NULLCMD) is set, the builtin `tt(:)' is inserted as a
command with the given redirections. This is the default when emulating
bf(sh) or bf(ksh).
Otherwise, if the parameter tt(NULLCMD) is set, its value will be used as a
command with the given redirections. If both tt(NULLCMD) and
tt(READNULLCMD) are set, then the value of the latter will be used instead
of that of the former when the redirection is an input. The default for
tt(NULLCMD) is `tt(cat)' and for tt(READNULLCMD) is `tt(more)'. Thus
example(< file)
shows the contents of tt(file) on standard output, with paging if that is a
terminal. tt(NULLCMD) and tt(READNULLCMD) may refer to shell functions.
prints the contents of tt(file).

View file

@ -1,30 +1,31 @@
texinode(Zftp Function System)()(Completion System)(Top)
texinode(Zftp Function System)()(Zsh Modules)(Top)
chapter(Zftp Function System)
cindex(zftp, function system)
cindex(zftp function system)
cindex(FTP, functions for using shell as client)
sect(Description)
This describes the set of shell functions supplied with the source
distribution as an interface to the tt(zftp) builtin command, allowing you
to perform FTP operations from the shell command line or within functions
or scripts. The interface is similar to a traditional FTP client (e.g. the
manref(ftp)(1) command itself), but as it is entirely done within the shell
all the familar completion, editing and globbing features, and so on, are
present, and macros are particularly simple to write as they are just
ordinary shell functions.
tt(ftp) command itself, see manref(ftp)(1)), but as it is entirely done
within the shell all the familiar completion, editing and globbing features,
and so on, are present, and macros are particularly simple to write as they
are just ordinary shell functions.
The prerequisite is that the tt(zftp) command, as described in
ifzman(\
zmanref(zshmodules)
)\
ifnzman(\
noderef(The zftp Module)
noderef(The zsh/zftp Module)
), must be available in the
version of tt(zsh) installed at your site. If the shell is configured to
load new commands at run time, it probably is: typing tt(zmodload zftp)
load new commands at run time, it probably is: typing `tt(zmodload zsh/zftp)'
will make sure (if that runs silently, it has worked). If this is not the
case, it is possible tt(zftp) was linked into the shell anyway: to test
this, type tt(which zftp) and if tt(zftp) is available you will get the
message tt(zftp: shell built-in command).
this, type `tt(which zftp)' and if tt(zftp) is available you will get the
message `tt(zftp: shell built-in command)'.
Commands given directly with tt(zftp) builtin may be interspersed between
the functions in this suite; in a few cases, using tt(zftp) directly may
@ -43,63 +44,85 @@ sect(Installation)
You should make sure all the functions from the tt(Functions/Zftp)
directory of the source distribution are available; they all begin with the
two letters tt(zf). They may already have been installed on your system;
two letters `tt(zf)'. They may already have been installed on your system;
otherwise, you will need to find them and copy them. The directory should
appear as one of the elements of the tt($fpath) array, and the functions
should be autoloaded. Finally, to initialise the use of the system you
need to call the tt(zfinit) function. The following code in your
tt(.zshrc) will arrange for this; assume the functions are stored in the
directory tt(~/myfns):
appear as one of the elements of the tt($fpath) array (this should already
be the case if they were installed), and at least the function tt(zfinit)
should be autoloaded; it will autoload the rest. Finally, to initialize
the use of the system you need to call the tt(zfinit) function. The
following code in your tt(.zshrc) will arrange for this; assume the
functions are stored in the directory tt(~/myfns):
tt(indent(
nofill(fpath=(~/myfns $fpath))
nofill(autoload ~/myfns/zf*(:t))
nofill(zfinit)
))
example(fpath=(~/myfns $fpath)
autoload -U zfinit
zfinit)
Note that tt(zfinit) assumes you are using the tt(zmodload) method to
load the tt(zftp) command. If it is already built into the shell, change
tt(zfinit) to tt(zfinit -n).
tt(zfinit) to tt(zfinit -n). It is helpful (though not essential) if the
call to tt(zfinit) appears after any code to initialize the new completion
system, else unnecessary tt(compctl) commands will be given.
texinode(Zftp Functions)(Miscellaneous Features)(Installation)(Zftp Function System)
sect(Functions)
The sequence of operations in performing a file transfer is essentially the
same as that in a standard FTP client.
same as that in a standard FTP client. Note that, due to a quirk of the
shell's tt(getopts) builtin, for those functions that handle options you
must use `tt(-)tt(-)' rather than `tt(-)' to ensure the remaining arguments
are treated literally (a single `tt(-)' is treated as an argument).
subsect(Opening a connection)
startitem()
findex(zfparams)
item(tt(zfparams [ var(host) [ var(user) [ var(password) ... ] ] ]))(
Set or show the parameters for a future tt(zfopen) with no arguments. If
no arguments are given, the current parameters are displayed (the password
will be shown as a line of asterisks). If a host is given, and either the
var(user) or var(password) is not, they will be prompted for; also, any
parameter given as `tt(?)' will be prompted for.
parameter given as `tt(?)' will be prompted for, and if the `tt(?)' is
followed by a string, that will be used as the prompt. As tt(zfopen) calls
tt(zfparams) to store the parameters, this usually need not be called
directly.
As tt(zfopen) calls tt(zfparams) to store the parameters, this usually need
not be called directly.
A single argument `tt(-)' will delete the stored parameters. This will
also cause the memory of the last directory (and so on) on the other host
to be deleted.
)
findex(zfopen)
item(tt(zfopen [ -1 ] [ var(host) [ var(user) [ var(password) [ var(account) ] ] ] ]))(
If var(host) is present, open a connection to that host under username
var(user) with password var(password) (and, on the rare occasions when it
is necessary account var(account)). If a necessary parameter is missing or
is necessary, account var(account)). If a necessary parameter is missing or
given as `tt(?)' it will be prompted for. If var(host) is not present, use
a previously stored set of parameters.
If the command was successful, and the terminal is an tt(xterm), a summary
will appear in the title bar, giving the local tt(host:directory) and the
remote tt(host:directory); this is handled by the function tt(zftp_chpwd),
described below.
If the command was successful, and the terminal is compatible with
tt(xterm) or is tt(sun-cmd), a summary will appear in the title bar,
giving the local tt(host:directory) and the remote tt(host:directory);
this is handled by the function tt(zftp_chpwd), described below.
Normally, the var(host), var(user) and var(password) are internally
recorded for later re-opening, either by a tt(zfopen) with no arguments, or
automatically (see below). With the option tt(-1), no information is
stored.
automatically (see below). With the option `tt(-1)', no information is
stored. Also, if an open command with arguments failed, the parameters
will not be retained (and any previous parameters will also be deleted).
A tt(zfopen) on its own, or a tt(zfopen -1), never alters the stored
parameters.
Both tt(zfopen) and tt(zfanon) (but not tt(zfparams)) understand URLs of
the form tt(ftp://)var(host)/var(path...) as meaning to connect to the
var(host), then change directory to var(path) (which must be a directory,
not a file). The `tt(ftp://)' can be omitted; the trailing `tt(/)' is enough
to trigger recognition of the var(path). Note prefixes other than
`tt(ftp:)' are not recognized, and that all characters after the first
slash beyond var(host) are significant in var(path).
)
findex(zfanon)
item(tt(zfanon [ -1 ] var(host)))(
Open a connection var(host) for anonymous FTP. The username used is
tt(anonymous). The password (which will be reported the first time) is
generated from var(user)tt(@)tt(host); this is then stored in the shell
`tt(anonymous)'. The password (which will be reported the first time) is
generated as var(user)tt(@)var(host); this is then stored in the shell
parameter tt($EMAIL_ADDR) which can alternatively be set manually to a
suitable string.
)
@ -107,6 +130,7 @@ enditem()
subsect(Directory management)
startitem()
findex(zfcd)
xitem(tt(zfcd [ var(dir) ]))
xitem(tt(zfcd -))
item(tt(zfcd var(old) var(new)))(
@ -114,9 +138,9 @@ Change the current directory on the remote server: this is implemented to
have many of the features of the shell builtin tt(cd).
In the first form with var(dir) present, change to the directory var(dir).
The command tt(zfcd ..) is treated specially, so is guaranteed to work on
non-UNIX servers (note this is handled internall by tt(zftp)). If var(dir)
is omitted, has the effect of tt(zfcd ~).
The command `tt(zfcd ..)' is treated specially, so is guaranteed to work on
non-UNIX servers (note this is handled internally by tt(zftp)). If var(dir)
is omitted, has the effect of `tt(zfcd ~)'.
The second form changes to the directory previously current.
@ -125,56 +149,63 @@ first occurrence of the string var(old) with the string var(new) in the
current directory.
Note that in this command, and indeed anywhere a remote filename is
expected, the string which on the local host corresponds to tt(~) is
converted back to a tt(~) before being passed to the remote machine.
expected, the string which on the local host corresponds to `tt(~)' is
converted back to a `tt(~)' before being passed to the remote machine.
This is convenient because of the way expansion is performed on the command
line before tt(zfcd) receives a string. For example, suppose the command
is tt(zfcd ~/foo). The shell will expand this to a full path as in tt(zfcd
/home/user2/pws/foo). At this stage, tt(zfcd) recognises the initial path
as tt(~), and the directory sent to the remote host is tt(~/foo), so that
the tt(~) will be expanded by the server to the correct remote host
directory. Other named directories of the form tt(~name) are not treated
in this fashion.
is `tt(zfcd ~/foo)'. The shell will expand this to a full path such as
`tt(zfcd /home/user2/pws/foo)'. At this stage, tt(zfcd) recognises the
initial path as corresponding to `tt(~)' and will send the directory to
the remote host as tt(~/foo), so that the `tt(~)' will be expanded by the
server to the correct remote host directory. Other named directories of
the form `tt(~name)' are not treated in this fashion.
)
findex(zfhere)
item(tt(zfhere))(
Change directory on the remote server to the one corresponding to the
current local directory, with special handling of tt(~) as in tt(zfcd).
current local directory, with special handling of `tt(~)' as in tt(zfcd).
For example, if the current local directory is tt(~/foo/bar), then
tt(zfhere) performs the effect of tt(zfcd ~/foo/bar).
tt(zfhere) performs the effect of `tt(zfcd ~/foo/bar)'.
)
findex(zfdir)
item(tt(zfdir [ -rfd ] [ - ] [ var(dir-options) ] [ var(dir) ]))(
Produce a long directory listing. The arguments var(dir-options) and
var(dir) are passed directly to the server and their effect is
implementation dependent, but specifying a particular remote directory
var(dir) is usually possible. The output is passed through pager.
var(dir) is usually possible. The output is passed through a pager
given by the environment variable tt($PAGER) or defaulting to `tt(more)'.
The directory is usually cached for re-use. In fact, two caches are
maintained. One is for use when there is no var(dir-options) or var(dir),
i.e. a full listing of the current remote directory; it is flushed
when the current remote directory changes. The other is
kept for repeated use of tt(zfdir) with the same arguments; for example,
repeated use of tt(zfdir /pub/gnu) will only require the directory to be
repeated use of `tt(zfdir /pub/gnu)' will only require the directory to be
retrieved on the first call. Alternatively, this cache can be re-viewed with
the tt(-r) option. As relative directories will confuse
tt(zfdir), the tt(-f) option can be used to force the cache to be flushed.
Also, the option tt(-d) will delete both caches without showing a directory
listing.
tt(zfdir), the tt(-f) option can be used to force the cache to be flushed
before the directory is listed. The option tt(-d) will delete both
caches without showing a directory listing; it will also delete the cache
of file names in the current remote directory, if any.
)
findex(zfls)
item(tt(zfls) [ var(ls-options) ] [ var(dir) ])(
List files on the remote server. With no arguments, this will produce a
simple list of file names for the current remote directory. Any arguments
are passed directory to the server. No pager and no caching is used.
are passed directly to the server. No pager and no caching is used.
)
enditem()
subsect(Status commands)
startitem()
findex(zftype)
item(tt(zftype) [ var(type) ])(
With no arguments, show the type of data to be transferred, usually ASCII
or binary. With an argument, change the type: the types tt(A) or
tt(ASCII) for ASCII data and tt(B) or tt(BINARY), tt(I) or tt(IMAGE) for
binary data are understood case-insensitively.
or binary. With an argument, change the type: the types `tt(A)' or
`tt(ASCII)' for ASCII data and `tt(B)' or `tt(BINARY)', `tt(I)' or
`tt(IMAGE)' for binary data are understood case-insensitively.
)
findex(zfstat)
item(tt(zfstat) [ -v ])(
Show the status of the current or last connection, as well as the status of
some of tt(zftp)'s status variables. With the tt(-v) option, a more
@ -192,12 +223,16 @@ this requires version 5 of tt(perl), see the description of the function
tt(zfrtime) below for more information.
startitem()
item(tt(zfget [ -Gt ] var(file1) ...))(
findex(zfget)
item(tt(zfget [ -Gtc ] var(file1) ...))(
Retrieve all the listed files var(file1) ... one at a time from the remote
server. If a file contains a `tt(/)', the full name is passed to the
remote server, but the file is stored locally under the name given by the
part after the final `tt(/)'.
part after the final `tt(/)'. The option tt(-c) (cat) forces all files to
be sent as a single stream to standard output; in this case the tt(-t)
option has no effect.
)
findex(zfuget)
item(tt(zfuget [ -Gvst ] var(file1) ...))(
As tt(zfget), but only retrieve files where the version on the remote
server is newer (has a later modification time), or where the local file
@ -208,6 +243,7 @@ and will always retrieve the file in either of those two cases. With the
option tt(-v), the command prints more information about the files while it
is working out whether or not to transfer them.
)
findex(zfcget)
item(tt(zfcget [ -Gt ] var(file1) ...))(
As tt(zfget), but if any of the local files exists, and is shorter than
the corresponding remote file, the command assumes that it is the result of
@ -217,6 +253,7 @@ file. This is useful on a poor connection which keeps failing.
Note that this requires a commonly implemented, but non-standard, version
of the FTP protocol, so is not guaranteed to work on all servers.
)
findex(zfgcp)
xitem(tt(zfgcp [ -Gt ] var(remote-file) var(local-file)))
item(tt(zfgcp [ -Gt ] var(rfile1) ... var(ldir)))(
This retrieves files from the remote server with arguments behaving
@ -233,16 +270,24 @@ enditem()
subsect(Sending files)
startitem()
item(tt(zfput var(file1) ...))(
findex(zfput)
item(tt(zfput [ -r ] var(file1) ...))(
Send all the var(file1) ... given separately to the remote server. If a
filename contains a `tt(/)', the full filename is used locally to find the
file, but only the basename is used for the remote file name.
With the option tt(-r), if any of the var(files) are directories they are
sent recursively with all their subdirectories, including files beginning
with `tt(.)'. This requires that the remote machine understand UNIX file
semantics. as `tt(/)' is used as a directory separator.
)
findex(zfuput)
item(tt(zfuput [ -vs ] var(file1) ...))(
As tt(zfput), but only send files which are newer than their local
equivalents, or if the remote file does not exist. The logic is the same
as for tt(zfuget), but reversed between local and remote files.
)
findex(zfcput)
item(tt(zfcput var(file1) ...))(
As tt(zfput), but if any remote file already exists and is shorter than the
local equivalent, assume it is the result of an incomplete transfer and
@ -250,6 +295,7 @@ send the rest of the file to append to the existing part. As the FTP
append command is part of the standard set, this is in principle more
likely to work than tt(zfcget).
)
findex(zfpcp)
xitem(tt(zfpcp var(local-file) var(remote-file)))
item(tt(zfpcp var(lfile1) ... var(rdir)))(
This sends files to the remote server with arguments behaving similarly to
@ -266,32 +312,117 @@ A problem arises if you attempt to use tt(zfpcp) var(lfile1) var(rdir),
i.e. the second form of copying but with two arguments, as the command has
no simple way of knowing if var(rdir) corresponds to a directory or a
filename. It attempts to resolve this in various ways. First, if the
var(rdir) argument is tt(.) or tt(..) or ends in a slash, it is assumed to
be a directory. Secondly, if the operation of copying to a remote file in
the first form failed, and the remote server sends back the expected
var(rdir) argument is `tt(.)' or `tt(..)' or ends in a slash, it is assumed
to be a directory. Secondly, if the operation of copying to a remote file
in the first form failed, and the remote server sends back the expected
failure code 553 and a reply including the string `tt(Is a directory)',
then tt(zfpcp) will retry using the second form.
)
enditem()
subsect(Closing the connectino)
subsect(Closing the connection)
startitem()
findex(zfclose)
item(tt(zfclose))(
Close the connection.
)
enditem()
subsect(Session management)
startitem()
findex(zfsession)
item(tt(zfsession) [ tt(-lvod) ] [ var(sessname) ])(
Allows you to manage multiple FTP sessions at once. By default,
connections take place in a session called `tt(default)'; by giving the
command `tt(zfsession) var(sessname)' you can change to a new or existing
session with a name of your choice. The new session remembers its own
connection, as well as associated shell parameters, and also the host/user
parameters set by tt(zfparams). Hence you can have different sessions set
up to connect to different hosts, each remembering the appropriate host,
user and password.
With no arguments, tt(zfsession) prints the name of the current session;
with the option tt(-l) it lists all sessions which currently exist, and
with the option tt(-v) it gives a verbose list showing the host and
directory for each session, where the current session is marked with an
asterisk. With tt(-o), it will switch to the most recent previous session.
With tt(-d), the given session (or else the current one) is removed;
everything to do with it is completely forgotten. If it was the only
session, a new session called `tt(default)' is created and made current.
It is safest not to delete sessions while background commands using
tt(zftp) are active.
)
findex(zftransfer)
item(tt(zftransfer) var(sess1)tt(:)var(file1) var(sess2)tt(:)var(file2))(
Transfer files between two sessions; no local copy is made. The file
is read from the session var(sess1) as var(file1) and written to session
var(sess1) as file var(file2); var(file1) and var(file2) may be relative to
the current directories of the sesssion. Either var(sess1) or var(sess2)
may be omitted (though the colon should be retained if there is a
possibility of a colon appearing in the file name) and defaults to the
current session; var(file2) may be omitted or may end with a slash, in
which case the basename of var(file1) will be added. The sessions
var(sess1) and var(sess2) must be distinct.
The operation is performed using pipes, so it is required that the
connections still be valid in a subshell, which is not the case under some
operating systems.
)
enditem()
subsect(Bookmarks)
The two functions tt(zfmark) and tt(zfgoto) allow you to `bookmark' the
present location (host, user and directory) of the current FTP connection
for later use. The file to be used for storing and retrieving bookmarks is
given by the parameter tt($ZFTP_BMFILE); if not set when one of the two
functions is called, it will be set to the file tt(.zfbfmarks) in the
directory where your zsh startup files live (usually tt(~)).
startitem()
findex(zfmark)
item(tt(zfmark [ )var(bookmark)tt( ]))(
If given an argument, mark the current host, user and directory under the
name var(bookmark) for later use by tt(zfgoto). If there is no connection
open, use the values for the last connection immediately before it was
closed; it is an error if there is none. Any existing bookmark
under the same name will be silently replaced.
If not given an argument, list the existing bookmarks and the points to
which they refer in the form var(user)tt(@)var(host)tt(:)var(directory);
this is the format in which they are stored, and the file may be edited
directly.
)
findex(zfgoto)
item(tt(zfgoto [ -n ] )var(bookmark))(
Return to the location given by var(bookmark), as previously set by
tt(zfmark). If the location has user `tt(ftp)' or `tt(anonymous)', open
the connection with tt(zfanon), so that no password is required. If the
user and host parameters match those stored for the current session, if
any, those will be used, and again no password is required. Otherwise a
password will be prompted for.
With the option tt(-n), the bookmark is taken to be a nickname stored by
the tt(ncftp) program in its bookmark file, which is assumed to be
tt(~/.ncftp/bookmarks). The function works identically in other ways.
Note that there is no mechanism for adding or modifying tt(ncftp) bookmarks
from the zftp functions.
)
enditem()
subsect(Other functions)
Mostly, these functions will not be called directly (apart from
tt(zfinit)), but are described here for completeness. You may wish to
alter tt(zftp_chpwd) and tt(zftp_progress), in particular.
startitem()
findex(zfinit)
item(tt(zfinit [ -n ]))(
As decribed above, this is used to initialise the zftp function system.
As described above, this is used to initialize the zftp function system.
The tt(-n) option should be used if the zftp command is already built into
the shell.
)
findex(zfautocheck)
item(tt(zfautocheck [ -dn ]))(
This function is called to implement automatic reopening behaviour, as
described in more detail below. The options must appear in the first
@ -302,6 +433,7 @@ transfer. The host and directory for the last session are stored in the
variable tt($zflastsession), but the internal host/user/password parameters
must also be correctly set.
)
findex(zfcd_match)
item(tt(zfcd_match var(prefix) var(suffix)))(
This performs matching for completion of remote directory names. If the
remote server is UNIX, it will attempt to persuade the server to list the
@ -310,6 +442,7 @@ guaranteed. On other hosts it simply calls tt(zfget_match) and hence
completes all files, not just directories. On some systems, directories
may not even look like filenames.
)
findex(zfget_match)
item(tt(zfget_match var(prefix) var(suffix)))(
This performs matching for completion of remote filenames. It caches files
for the current directory (only) in the shell parameter tt($zftp_fcache).
@ -317,12 +450,14 @@ It is in the form to be called by the tt(-K) option of tt(compctl), but
also works when called from a widget-style completion function with
var(prefix) and var(suffix) set appropriately.
)
findex(zfrglob)
item(tt(zfrglob var(varname)))(
Perform remote globbing, as describes in more detail below. var(varname)
is the name of a variable containing the pattern to be expanded; if there
were any matches, the same variable will be set to the exanded set of
were any matches, the same variable will be set to the expanded set of
filenames on return.
)
findex(zfrtime)
item(tt(zfrtime var(lfile) var(rfile) [ var(time) ]))(
Set the local file var(lfile) to have the same modification time as the
remote file var(rfile), or the explicit time var(time) in FTP format
@ -332,41 +467,129 @@ Currently this requires tt(perl) version 5 to perform the conversion from
GMT to local time. This is unfortunately difficult to do using shell code
alone.
)
findex(zftp_chpwd, supplied version)
item(tt(zftp_chpwd))(
This function is called every time a connection is opened, or closed, or
the remote directory changes. This version alters the title bar of an
tt(xterm) or tt(sun-cmd) terminal emulator to reflect the local and remote
hostnames and current directories. It works best when combined with the
function tt(chpwd). In particular, a function of the form
tt(xterm) compatible or tt(sun-cmd) terminal emulator to reflect the
local and remote hostnames and current directories. It works best when
combined with the function tt(chpwd). In particular, a function of
the form
tt(indent(
nofill(chpwd() {)
nofill( if [[ -n $ZFTP_USER ]]; then)
nofill( zftp_chpwd)
nofill( else)
nofill( # usual chpwd e.g put host:directory in title bar)
nofill( fi)
nofill(})
))
example(chpwd() {
if [[ -n $ZFTP_USER ]]; then
zftp_chpwd
else
# usual chpwd e.g put host:directory in title bar
fi
})
fits in well.
)
findex(zftp_progress, supplied version)
item(tt(zftp_progress))(
This function shows the status of the transfer as the percentage of the
total so far transferred. It will not write anything unless the output is
going to a terminal; however, if you transfer files in the background, you
should tt(unfunction) this first. (Background file transfers don't work on
all OSes.) Note also that if you alter it, any output em(must) be to
standard error, as standard output may be a file being received.
This function shows the status of the transfer. It will not write anything
unless the output is going to a terminal; however, if you transfer files in
the background, you should turn off progress reports by hand using
`tt(zstyle ':zftp:*' progress none)'. Note also that if you alter it, any
output em(must) be to standard error, as standard output may be a file
being received. The form of the progess meter, or whether it is used at
all, can be configured without altering the function, as described in the
next section.
)
findex(zffcache)
item(tt(zffcache))(
This is used to implement caching of files in the current directory for
each session separately. It is used by tt(zfget_match) and tt(zfrglob).
)
enditem()
texinode(Miscellaneous Features)()(Zftp Functions)(Zftp Function System)
sect(Miscellaneous Features)
subsect(Remote globbing)
subsect(Configuration)
cindex(zftp function system, configuration)
cindex(zftp function system, styles)
cindex(styles in zftp functions)
The commands for retrieving files usually perform filename expansion
Various styles are available using the standard shell style mechanism,
described in
ifzman(zmanref(zshmodules))\
ifnzman(noderef(The zsh/zutil Module)). Briefly, the
command `tt(zstyle ':zftp:*') var(style) var(value) ...'.
defines the var(style) to have value var(value) (more than one may be
given, although that is not useful in the cases described here). These
values will then be used throughout the zftp function system. For more
precise control, the first argument, which gives a context in which the
style applies, can be modified to include a particular function, as for
example `tt(:zftp:zfget:)': the style will then have the given value only
in the tt(zfget) function. Values for the same style in different contexts
may be set; the most specific function will be used, where
strings are held to be more specific than patterns, and longer patterns and
shorter patterns. Note that only the top level function name, as called by
the user, is used; calling of lower level functions is transparent to the
user. Hence modifications to the title bar in tt(zftp_chpwd) use the
contexts tt(:zftp:zfopen:), tt(:zftp:zfcd:), etc., depending where it was
called from. The following styles are understood:
startitem()
kindex(progress, zftp style)
item(tt(progress))(
Controls the way that tt(zftp_progress) reports on the progress of a
transfer. If empty, unset, or `tt(none)', no progress report is made; if
`tt(bar)' a growing bar of inverse video is shown; if `tt(percent)' (or any
other string, though this may change in future), the percentage of the file
transferred is shown. The bar meter requires that the width of the
terminal be available via the tt($COLUMNS) parameter (normally this is set
automatically). If the size of the file being transferred is not
available, tt(bar) and tt(percent) meters will simply show the number of
bytes transferred so far.
When tt(zfinit) is run, if this style is not defined for the context
tt(:zftp:*), it will be set to `bar'.
)
kindex(update, zftp style)
item(tt(update))(
Specifies the minimum time interval between updates of the progress meter
in seconds. No update is made unless new data has been received, so the
actual time interval is limited only by tt($ZFTP_TIMEOUT).
As described for tt(progress), tt(zfinit) will force this to default to 1.
)
kindex(remote-glob, zftp style)
item(tt(remote-glob))(
If set to `1', `yes' or `true', filename generation (globbing) is
performed on the remote machine instead of by zsh itself; see below.
)
kindex(titlebar, zftp style)
item(tt(titlebar))(
If set to `1', `yes' or `true', tt(zftp_chpwd) will put the remote host and
remote directory into the titlebar of terminal emulators such as xterm or
sun-cmd that allow this.
As described for tt(progress), tt(zfinit) will force this to default to 1.
)
kindex(chpwd, zftp style)
item(tt(chpwd))(
If set to `1' `yes' or `true', tt(zftp_chpwd) will call the function
tt(chpwd) when a connection is closed. This is useful if the remote host
details were put into the terminal title bar by tt(zftp_chpwd) and your
usual tt(chpwd) also modifies the title bar.
When tt(zfinit) is run, it will determine whether tt(chpwd) exists and if
so it will set the default value for the style to 1 if none exists
already.
)
enditem()
Note that there is also an associative array tt(zfconfig) which contains
values used by the function system. This should not be modified or
overwritten.
subsect(Remote globbing)
cindex(zftp function system, remote globbing)
The commands for retrieving files usually perform filename generation
(globbing) on their arguments; this can be turned off by passing the option
tt(-G) to each of the commands. Normally this operates by retrieving a
complete list of files for the directory in question, then matching these
@ -378,16 +601,17 @@ remote server does not support the UNIX directory semantics, directory
handling is problematic and it is recommended that globbing only be used
within the current directory. The list of files in the current directory,
if retrieved, will be cached, so that subsequent globs in the same
directory without an interventing tt(zfcd) are fast.
directory without an intervening tt(zfcd) are much faster.
If the variable tt($zfrglob) is set to a non-zero length, globbing is
instead performed on the remote host: the server is asked for a list of
matching files. This is highly dependent on how the server is implemented,
though typically UNIX servers will provide support for basic glob
patterns. This may in some cases be faster, as it avoids retrieving the
entire list of directory contents.
If the tt(remote-glob) style (see above) is set, globbing is instead
performed on the remote host: the server is asked for a list of matching
files. This is highly dependent on how the server is implemented, though
typically UNIX servers will provide support for basic glob patterns. This
may in some cases be faster, as it avoids retrieving the entire list of
directory contents.
subsect(Automatic and temporary reopening)
cindex(zftp function system, automatic reopening)
As described for the tt(zfopen) command, a subsequent tt(zfopen) with no
parameters will reopen the connection to the last host (this includes
@ -415,21 +639,24 @@ never close the connection automatically.
Information about the previous connection is given by the tt(zfstat)
function. So, for example, if that reports:
tt(indent(
nofill(Not connected.)
nofill(Last session: ftp.bar.com:/pub/textfiles)
))
example(Session: default
Not connected.
Last session: ftp.bar.com:/pub/textfiles)
then the command tt(zfget file.txt) will attempt to reopen a connection to
tt(ftp.bar.com), retrieve the file tt(/pub/textfiles/file.txt), and
immediately close the connection again. On the other hand, tt(zfcd ..)
will open the connection in the directory tt(/pub) and leave it open.
Note that all the above is local to each session; if you return to a
previous session, the connection for that session is the one which will be
reopened.
subsect(Completion)
Completion of remote files and directories is supported. The older,
tt(compctl)-style completion is defined when tt(zfinit) is called; support
for the new widget-based completion system is provided in the function
tt(Completion/Builtins/_zftp), which should be installed with the other
functions of the completion system and hence should automatically be
available.
Completion of local and remote files, directories, sessions and bookmarks
is supported. The older, tt(compctl)-style completion is defined when
tt(zfinit) is called; support for the new widget-based completion system is
provided in the function tt(Completion/Builtins/_zftp), which should be
installed with the other functions of the completion system and hence
should automatically be available.

View file

@ -1,12 +1,13 @@
texinode(Zsh Line Editor)(Programmable Completion)(Shell Builtin Commands)(Top)
texinode(Zsh Line Editor)(Completion Using compctl)(Shell Builtin Commands)(Top)
chapter(Zsh Line Editor)
cindex(line editor)
cindex(editor, line)
cindex(ZLE)
sect(Description)
pindex(ZLE, use of)
If the tt(ZLE) option is set (it is by default)
If the tt(ZLE) option is set (which it is by default in interactive shells)
and the shell input is attached to the terminal, the user
is allowed to edit command lines.
is able to edit command lines.
There are two display modes. The first, multiline mode, is the
default. It only works if the tt(TERM) parameter is set to a valid
@ -67,7 +68,8 @@ that is bound to some command and is also a prefix of a longer bound string.
In this case ZLE will wait a certain time to see if more characters
are typed, and if not (or they don't match any longer string) it will
execute the binding. This timeout is defined by the tt(KEYTIMEOUT) parameter;
its default is 0.4 sec. No timeout is done if the prefix string is not bound.
its default is 0.4 sec. There is no timeout if the prefix string is not
itself bound to a command.
As well as ZLE commands, key sequences can be bound to other strings, by using
`tt(bindkey -s)'.
@ -83,7 +85,7 @@ simply to perform some small action. The ZLE commands that key sequences
in keymaps are bound to are in fact widgets. Widgets can be user-defined
or built in.
There are 162 standard widgets built in to ZLE (see sectref(Standard Widgets)).
The standard widgets built in to ZLE are listed in Standard Widgets below.
Other built-in widgets can be defined by other modules (see
ifzman(zmanref(zshmodules))\
ifnzman(noderef(Zsh Modules))\
@ -102,7 +104,8 @@ cindex(widgets, user-defined)
User-defined widgets, being implemented as shell functions,
can execute any normal shell command. They can also run other widgets
(whether built-in or user-defined) using the tt(zle) builtin command.
Finally, they can examine and edit the ZLE buffer being edited by
They can use tt(read -k) or tt(read -q) to read characters from standard
input. Finally, they can examine and edit the ZLE buffer being edited by
reading and setting the special parameters described below.
cindex(parameters, editor)
@ -113,6 +116,9 @@ outside ZLE, that value is temporarily inaccessible, but will return
when the widget function exits. These special parameters in fact have
local scope, like parameters created in a function using tt(local).
Inside completion widgets and traps called while ZLE is active, these
parameters are available read-only.
startitem()
vindex(BUFFER)
item(tt(BUFFER) (scalar))(
@ -127,6 +133,10 @@ The offset of the cursor, within the edit buffer. This is in the range
Attempts to move the cursor outside the buffer will result in the
cursor being moved to the appropriate end of the buffer.
)
vindex(MARK)
item(tt(MARK) (integer))(
Like tt(CURSOR), but for the mark.
)
vindex(LBUFFER)
item(tt(LBUFFER) (scalar))(
The part of the buffer that lies to the left of the cursor position.
@ -139,6 +149,42 @@ The part of the buffer that lies to the right of the cursor position.
If it is assigned to, only that part of the buffer is replaced, and the
cursor remains between the old tt($LBUFFER) and the new tt($RBUFFER).
)
vindex(BUFFERLINES)
item(tt(BUFFERLINES))(
The number of screen lines needed for the edit buffer currently
displayed on screen (i.e. without any changes to the preceding
parameters done after the last redisplay).
)
vindex(PREBUFFER)
item(tt(PREBUFFER) (scalar))(
In a multi-line input at the secondary prompt, this read-only parameter
contains the contents of the lines before the one the cursor is
currently in.
)
vindex(WIDGET)
item(tt(WIDGET) (scalar))(
The name of the widget currently being executed.
)
vindex(LASTWIDGET)
item(tt(LASTWIDGET) (scalar))(
The name of the last widget that was executed.
)
vindex(KEYS)
item(tt(KEYS) (scalar))(
The keys typed to invoke this widget, as a literal string.
)
vindex(NUMERIC)
item(tt(NUMERIC) (integer))(
The numeric argument. If no numeric argument was given, this parameter
is unset. When this is set inside a widget function, builtin widgets
called with the tt(zle) builtin command will use the value
assigned. If it is unset inside a widget function, builtin widgets
called behave as if no numeric argument was given.
)
vindex(HISTNO)
item(tt(HISTNO) (integer))(
The current history number.
)
enditem()
sect(Standard Widgets)
cindex(widgets, standard)
@ -317,6 +363,10 @@ item(tt(down-line-or-search))(
Move down a line in the buffer, or if already at the bottom line,
search forward in the history for a line beginning with the first
word in the buffer.
If called from a function by the tt(zle) command with arguments, the first
argument is taken as the string for which to search, rather than the
first word in the buffer.
)
tindex(down-history)
item(tt(down-history) (unbound) (^N) (unbound))(
@ -385,6 +435,17 @@ search, leaving the last found line in the buffer. Any single character that
is not bound to one of the above functions, or tt(self-insert) or
tt(self-insert-unmeta), will have the same effect but the function will be
executed.
When called from a widget function by the tt(zle) command, the incremental
search commands can take a string argument. This will be treated as a
string of keys, as for arguments to the tt(bindkey) command, and used as
initial input for the command. Any characters in the string which are
unused by the incremental search will be silently ignored. For example,
example(zle history-incremental-search-backward forceps)
will search backwards for tt(forceps), leaving the minibuffer containing
the string `tt(forceps)'.
)
tindex(history-incremental-search-forward)
item(tt(history-incremental-search-forward) (^S ^Xs) (unbound) (unbound))(
@ -398,6 +459,10 @@ tindex(history-search-backward)
item(tt(history-search-backward) (ESC-P ESC-p) (unbound) (unbound))(
Search backward in the history for a line beginning with the first
word in the buffer.
If called from a function by the tt(zle) command with arguments, the first
argument is taken as the string for which to search, rather than the
first word in the buffer.
)
tindex(vi-history-search-backward)
item(tt(vi-history-search-backward) (unbound) (/) (unbound))(
@ -425,18 +490,27 @@ tt(magic-space) is treated as a space.
Any other character that is not bound to self-insert or
self-insert-unmeta will beep and be ignored. If the function is called from vi
command mode, the bindings of the current insert mode will be used.
If called from a function by the tt(zle) command with arguments, the first
argument is taken as the string for which to search, rather than the
first word in the buffer.
)
tindex(history-search-forward)
item(tt(history-search-forward) (ESC-N ESC-n) (unbound) (unbound))(
Search forward in the history for a line beginning with the first
word in the buffer.
If called from a function by the tt(zle) command with arguments, the first
argument is taken as the string for which to search, rather than the
first word in the buffer.
)
tindex(vi-history-search-forward)
item(tt(vi-history-search-forward) (unbound) (?) (unbound))(
Search forward in the history for a specified string.
The string may begin with `tt(^)' to anchor the search to the
beginning of the line. The functions available in the mini-buffer are the same
as for tt(vi-history-search-backward).
as for tt(vi-history-search-backward). Argument handling is also the same
as for that command.
)
tindex(infer-next-history)
item(tt(infer-next-history) (^X^N) (unbound) (unbound))(
@ -449,7 +523,10 @@ Insert the last word from the previous history event at the
cursor position. If a positive numeric argument is given,
insert that word from the end of the previous history event.
If the argument is zero or negative insert that word from the
left (zero inserts the previous command word).
left (zero inserts the previous command word). Repeating this command
replaces the word just inserted with the last word from the
history event prior to the one just used; numeric arguments can be used in
the same way to pick a word from that event.
)
tindex(vi-repeat-search)
item(tt(vi-repeat-search) (unbound) (n) (unbound))(
@ -475,6 +552,10 @@ item(tt(up-line-or-search))(
Move up a line in the buffer, or if already at the top line,
search backward in the history for a line beginning with the
first word in the buffer.
If called from a function by the tt(zle) command with arguments, the first
argument is taken as the string for which to search, rather than the
first word in the buffer.
)
tindex(up-history)
item(tt(up-history) (unbound) (^P) (unbound))(
@ -771,7 +852,11 @@ startitem()
tindex(digit-argument)
item(tt(digit-argument) (ESC-0..ESC-9) (1-9) (unbound))(
Start a new numeric argument, or add to the current one.
See also tt(vi-digit-or-beginning-of-line).
See also tt(vi-digit-or-beginning-of-line). This only works if bound to a
key sequence ending in a decimal digit.
Inside a widget function, a call to this function treats the last key of
the key sequence which called the widget as the digit.
)
tindex(neg-argument)
item(tt(neg-argument) (ESC--) (unbound) (unbound))(
@ -786,6 +871,10 @@ repeated using this command. For example, if this command occurs
twice, followed immediately by tt(forward-char), move forward sixteen
spaces; if instead it is followed by tt(-2), then tt(forward-char),
move backward two spaces.
Inside a widget function, if passed an argument, i.e. `tt(zle
universal-argument) var(num)', the numerical argument will be set to
var(num); this is equivalent to `tt(NUMERIC=)var(num)'.
)
enditem()
texinode(Completion)(Miscellaneous)(Arguments)(Zsh Line Editor)
@ -857,6 +946,11 @@ Perform menu completion, like tt(menu-complete), except that if
a menu completion is already in progress, move to the em(previous)
completion rather than the next.
)
tindex(end-of-list)
item(tt(end-of-list))(
When a previous completion displayed a list below the prompt, this
widget can be used to move the prompt below the list.
)
enditem()
texinode(Miscellaneous)()(Completion)(Zsh Line Editor)
subsect(Miscellaneous)
@ -882,6 +976,10 @@ item(tt(accept-line-and-down-history) (^O) (unbound) (unbound))(
Execute the current line, and push the next history
event on the the buffer stack.
)
tindex(beep)
item(tt(beep))(
Beep, unless the tt(BEEP) option is unset.
)
tindex(vi-cmd-mode)
item(tt(vi-cmd-mode) (^X^V) (unbound) (^[))(
Enter command mode; that is, select the `tt(vicmd)' keymap.

View file

@ -61,10 +61,10 @@ ifnzman(includefile(Zsh/params.yo))
ifnzman(includefile(Zsh/options.yo))
ifnzman(includefile(Zsh/builtins.yo))
ifnzman(includefile(Zsh/zle.yo))
ifnzman(includefile(Zsh/compwid.yo))
ifnzman(includefile(Zsh/compctl.yo))
ifnzman(includefile(Zsh/modules.yo))
ifnzman(includefile(Zsh/compwid.yo))
ifnzman(includefile(Zsh/compsys.yo))
ifnzman(includefile(Zsh/modules.yo))
ifnzman(includefile(Zsh/zftpsys.yo))
ifzshall(\
def(source)(1)(NOTRANS(.so )man1/ARG1NOTRANS(.)1)\
@ -75,10 +75,10 @@ source(zshparam)
source(zshoptions)
source(zshbuiltins)
source(zshzle)
source(zshcompwid)
source(zshcompctl)
source(zshmodules)
source(zshcompwid)
source(zshcompsys)
source(zshmodules)
source(zshzftpsys)
manpage(ZSHALL)(1)(date())(zsh version())
)\

View file

@ -11,7 +11,6 @@ def(CMT)(0)(NOTRANS(@c))
ATEXIT(\
NL()\
NOTRANS(@setchapternewpage odd)NL()\
NOTRANS(@contents)NL()\
NOTRANS(@bye)NL()\
)
@ -33,7 +32,7 @@ COMMENT(--- emphasised text ---)
def(em)(1)(NOTRANS(@emph{)ARG1NOTRANS(}))
def(bf)(1)(NOTRANS(@cite{)ARG1NOTRANS(}))
def(tt)(1)(NOTRANS(@code{)ARG1NOTRANS(}))
def(tt)(1)(NOTRANS(@t{)ARG1NOTRANS(}))
def(var)(1)(NOTRANS(@var{)ARG1NOTRANS(}))
COMMENT(--- man page headers ---)
@ -47,16 +46,26 @@ def(texinfo)(2)(\
STDPAR()\
NOTRANS(\input texinfo.tex)NL()\
NOTRANS(@c %**start of header)NL()\
NOTRANS(@iftex)NL()\
NOTRANS(@afourpaper)NL()\
NOTRANS(@setchapternewpage off)NL()\
NOTRANS(@end iftex)NL()\
NOTRANS(@setfilename )ARG1NL()\
NOTRANS(@settitle )ARG2NL()\
NOTRANS(@c %**end of header)NL()\
NL()\
NOTRANS(@ifinfo)NL()\
NOTRANS(@set dsq @'@')NL()\
NOTRANS(@set dsq '@:')NL()\
NOTRANS(@end ifinfo)NL()\
NOTRANS(@iftex)NL()\
NOTRANS(@set dsq '{}')NL()\
NOTRANS(@end iftex)NL()\
NOTRANS(@ifinfo)NL()\
NOTRANS(@dircategory Utilities)NL()\
NOTRANS(@direntry)NL()\
NOTRANS( * ZSH: (zsh). The Z Shell Manual.)NL()\
NOTRANS(@end direntry)NL()\
NOTRANS(@end ifinfo)NL()\
)
def(texiifinfo)(1)(\
@ -171,6 +180,7 @@ def(startlist)(0)(\
startitem()\
)
def(endlist)(0)(\
NOTRANS(@item)NL()\
enditem()\
)
def(list)(1)(\
@ -201,8 +211,16 @@ def(nofill)(1)(\
USECHARTABLE(standard)\
)
def(indent)(1)(\
def(example)(1)(\
NOTRANS(@example)NL()\
ARG1\
NL()NOTRANS(@end example)\
)
def(indent)(1)(\
NOTRANS(@quotation)NL()\
ARG1\
NL()NOTRANS(@end quotation)\
)
COMMENT(--- hyperlink menus ---)

File diff suppressed because it is too large Load diff

View file

@ -1,44 +1,394 @@
For now this is just a list of things one should or shouldn't do.
Contexts, tags and all that
---------------------------
1) Use the functions `_files' and `_path_files' instead of `compgen'
with the `-f', `-/', or `-g' options.
2) *Never* use `compgen' with the `-s' option. This can always be done
by a call to `compadd' which is faster.
3) Using `compgen' with the `-k' option should only be done if a) the
array is already existent or b) it is very large (several hundred
or thousend elements). In other cases using `compadd' is faster.
4) Supply match specifications to `compadd' and `compgen' if there are
sensible ones.
5) Use `_description' when adding matches with `compadd' or
`compgen'. Use `_message' in places where no matches can be
generated. If you want to add different types of matches, add them
with multiple calls to `compadd' or `compgen', supplying different
descriptions.
6) Use helper functions that do option completion for you (like
`_arguments' and `_long_options') -- it will make your life much
The completion system keeps track of the current context in the
parameter `curcontext'. It's content is the hierarchical name for the
current context sans the `:completion:' and the last colon and the tag
currently tried. The tags represent different types of matches. So,
whenever you are about to add matches, you should use a tag for them
and test if the user wants this type of matches to be generated.
However, this only really needs to be done if no other function in the
call chain has tested that already or if you can offer different types
of matches or if you can handle tag aliases in some sophisticated way.
Most of the utility functions do the testing themselves, so you don't
have to worry about that at all. For example if you are adding matches
with `_files', `_hosts' or functions like these, you can just call
them and they do the tests needed and the loops over the tag aliases.
The functions `_arguments' and `_values' do that too, but there is a
small difference. These functions effectively change the context
name and if you are using the `->state' form for actions, this changed
name component has to be reported back to the function calling
`_arguments' or `_values'. This is done with the parameter `context',
so you have to make that local in the calling function in the same way
as you have to make local `line', `state', and `{opt,val}_args'. This
parameter `context' should then be used when you start adding matches
by giving it to functions like `_tags' via the `-C' options, as in:
local context ...
...
_arguments ... '-foo:foo:->foo'
...
if [[ "$state" = foo ]]; then
_tags -C "$context" ...
...
fi
This will put the context name given in the argument field of the
`curcontext' parameter and this context will then be used to look
up styles for the tags.
But since this is often used, `_arguments' and `_values' have support
to make your life easier in such cases. With the `-C' option, these
functions set the parameter `curcontext', thus modifying the globally
used hierarchical context name. This means, that you have to make that
local, but then you don't have to worry about giving the context name
reported back to functions you call. E.g.:
local curcontext="$curcontext" ...
...
_arguments -C ... 'foo:foo:->foo'
...
if [[ "$state" = foo ]]; then
_tags ...
...
fi
In this case the parameter `context' is not set, so you don't have to
make that local. But make sure that `curcontext' is local so that the
value changed by `_arguments' and `_values' is only used in your
function (and make sure to initialise it to its old value as in the
example).
Then, before adding the matches, see if matches of that type are
requested by the user in the current context. If you will add only one
type of matches, this is very simple. You can use the function
`_wanted' for this. Its return value is zero only if the type of
matches is requested by the user, so you can just do:
_wanted names || return 1
_all_labels names expl 'name' compadd - alice bob
The `_all_labels' function implements the loop over the tag aliases and
handles the user-defined description, using (in the example) the
parameter `expl' to store options to give to the command. These option
are inserted into the command line either directly before a single
hyphen if there is such an argument or after the first word if there
is no single hyphen. Since using `_all_labels' is so much more conveient
than writing the loop with the `_next_label' function (see below), but
some function called to generate matches don't accept a single hyphen
as argument anywhere but want the options built as their last arguments,
`_all_labels' will *replace* the hyphen with the options if the hyphen is
the last argument. A good example for such a function is
`_combination' which can be called like:
_all_labels foo expl 'descr...' _combination ... -
And the `-' will be replaced by the options that are to be given to
`compadd'.
Since the above sequence of command is used so often, the `_wanted'
function can also accept the same arguments as `_all_labels'. In this
case it will do the test for the requested tag and then just call
`_all_labels', so:
_wanted names expl 'name' compadd - alice bob
Note that you can also give the `-J' and `-V' options with the
optional `1' or `2' preceding them supported by `_description':
_wanted -2V names expl 'name' compadd ...
In some cases one needs to call multiple functions or call `compadd'
more than once to generate the matches. In such a case one needs to
implement the loop over the tag aliases directly. This is done with the
`_next_label' function. Like this:
while _next_label names expl 'name'; do
compadd "$expl[@]" - alice bob && ret=0
_other_names "$expl[@]" && ret=0
done
return ret
Simple enough, I hope. But `_next_label' can do some more: utility
functions normally accept options which are then given to `compadd'.
Since these may contain options for the description and `_next_label' may
generate such options, too, it isn't entirely trivial to decide which
of these options should take precedence. But `_next_label' can do the work
for you here. All you have to do is to give the options your utility
function gets to `_next_label', as in:
while _next_label names expl 'name' "$@"; do
compadd "$expl[@]" - alice bob
...
done
That's all. Note that the positional argument "$@" are *not* given to
`compadd'. They will be stuffed into the `expl' array by `_next_label'.
The most complicated case is where you can offer multiple types of
matches. In this case the user should be able to say which types he
wants to see at all and of those which he wants to see he should be
able to say which types should be tried first. The generic solution
for this uses `_tags' and `_requested':
local expl ret=1
_tags friends users hosts
while _tags; do
_requested friends expl friend compad alice bob && ret=0
_requested users && _users && ret=0
_requested hosts && _hosts && ret=0
(( ret )) || break # leave the loop if matches were added
done
`_tags' with tags as arguments registers those tags and checks which
of them the user wants to see and in which order the tags are to be
tried. This means that internally these tags are stored in multiple
sets. The types of matches represented by the tags from the first set
should be tried first. If that generates no matches, the second set is
tried and so on. `_tags' without arguments just makes the next set be
tried (on the first call it makes the first set be used). The function
`_requested' then tests if the tag given as its first argument is in
the set currently used and returns zero if it is, i.e. if matches of
that type should be added now. The arguments accepted by `_requested'
are the same as for `_wanted'. I.e. you can call it with only the tag
to test, with the `tag array description' or with that plus the
command to execute.
In some cases (like the `users' and `hosts' tags in the example) you
don't need do the loop over the tag aliases yourself, because the
utility functions like `_users' and `_hosts' do it automatically.
This looks good already. But in many cases such as this one you can
also use the function `_alternative' which simply implements a loop
like the one above. It gets arguments of the form `tag:descr:action'.
E.g.:
_alternative \
'friends:friend:(alice bob)' \
'users:: _users' \
'hosts:: _hosts'
Which does the same as the previous example. (Note the empty
descriptions in the last two arguments -- the actions start with a
space so that they are executed without giving the description
build by `_alternative', i.e. we just use the description added by
`_users' and `_hosts').
In cases where you have to keep track of the context yourself, you can
give the sub-context you want to use to `_tags', `_wanted' and
`_alternative' with the `-C' option as described above. You don't need
to give it to `_requested' -- that function will work on the context
used by the corresponding call to `_tags' automatically.
For the names of the tags: choose simple (short, if at all possible)
names in plural. Also, first have a look at the tag names already used
by other functions and if any of these names seem sensible for the
type of matches you are about to add, the use those names. This will
allow users to define styles for certain types of matches independent
of the place where they are added.
One final comment about when to use your own argument-contexts: do
this when the command you are writing a completion function for has
different `modes'. E.g. if it accepts host names after a `-h' option
and users or hosts after `-u' and for some reason you can't use
`_arguments' to do the work for you, then use context names as in:
case "$1" in
-h)
_tags -C -h hosts && _hosts && ret=0
;;
-u)
_alternative -C -u 'users:: _users' 'hosts:: _hosts' && ret=0
;;
esac
Styles
------
Users can associate patterns for hierarchical context names with
certain styles using the `zstyle' builtin. The completion code
should then use these styles to decide how matches should be added and
to get user-configured values. This, too, is done using the builtin
`zstyle'.
Basically styles map names to a bunch of strings (the `value'). In
many cases you want to treat the value as a boolean, so let's start
with that. To test if, for example, the style `verbose' is set for
the tag `options' in the context you are currently in, you can just do:
if zstyle -t ":completion:${curcontext}:options" verbose; then
# yes, it is set...
fi
I.e. with the -t option and two arguments `zstyle' takes the first one
as a context and the second one as a style name and returns zero if that
style has the boolean value `true'. Internally it checks if the style
is set to one of `yes', `true', `on', or `1' and interprets that as
`true' and every other value as `false'.
For more complicated styles for which you want to test if the value
matches a certain pattern, you can use `zstyle' with the -m option and
three arguments:
if zstyle -m ":completion:${curcontext}:foo" bar '*baz*'; then
...
fi
This tests if the value of the style `bar' for the tag `foo' matches
the pattern `*baz*' and returns zero if it does.
If you just want to see if one of the strings in the value is exactly
equal to any of a number of a strings, you can use the -t option and
give the strings after the style name:
if zstyle -t ":completion:${curcontext}:foo" bar str1 str2; then
...
fi
But sometimes you want to actually get the value stored for a certain
style instead of just testing it. For this `zstyle' supports four
options: `-b', `-s', `-a', and `-h'. After these options, three
arguments are expected, the context, the style, and a parameter name.
The parameter will then be set to the value of the style and the option
says how the strings stored as a value will be stored in the
parameter:
- `-b': the parameter will be set to a either `yes' or `no'
- `-s': the parameter will be set to all strings in the value
concatenated (separated by spaces) to one string
- `-a': the parameter will be set to an array containing the strings
from the value as elements
- `-h': the parameter will be set to an association with the strings
from the value being interpreted alternatingly as keys and
values
Some random comments about style names. Use the ones already in use if
possible. Especially, use the `verbose' style if you can add
matches in a simple and a verbose way. Use the verbose form only if
the `verbose' style is `true' for the current context. Also, if
the matches you want to add have a common prefix which is somehow
special, use the `prefix-needed' and `prefix-hidden' styles. The first
one says if the user has to give the prefix on the line to make these
matches be added and the second one says if the prefix should be
visible in the list.
And finally, if you need a style whose value can sensibly be
interpreted as a list of words, use array or association styles with
the `-a' or `-h' options to `zstyle'. Otherwise you should only make
sure that an empty value for a style is treated in the same way as if
the style wasn't set at all (this is used elsewhere and we want to
keep things consistent).
Descriptions
------------
Always use description. This is important. Really. *Always* use
descriptions. If you have just written down a `compadd' without a
"$expl[@]" (or equivalent), you have just made an error. Even in
helper functions where you use a "$@": if you can't be sure that there
is a description in the arguments, add one. You can (and, in most
cases, should) then give the description you generated after the
"$@". This makes sure that the, probably more specific, description
given by the calling function takes precedence over the generic one
you have just generated.
And it really isn't that complicated, is it? Think about a string
people might want to see above the matches (in singular -- that's used
throughout the completion system) and do:
local expl
_description tag expl <descr>
compadd "$expl@]" - <matches ...>
Note that this function also accepts `-V' und `-J', optionally (in the
same word) preceded by `1' or `2' to describe the type of group you
want to use. For example:
_description tag expl '...'
compadd "$expl[@]" -1V foo - ... # THIS IS WRONG!!!
is *not* the right way to use a unsorted group. Instead do:
_description -1V tag expl '...'
compadd "$expl[@]" - ...
and everything will work fine.
Also, if you are about to add multiple different types of matches, use
multiple calls to `_description' and add them with multiple calls to
`compadd'. But in almost all cases you should then add them using
different tags anyway, so, see above.
And since a tag directly corresponds to a group of matches, you'll
often be using the tags function that allows you to give the
explanation to the same function that is used to test if the tags are
requested (again: see above). Just as a reminder:
_wanted [ -[1,2]V | -[1,2]J ] <tag> expl <descr>
and
_requested [ -[1,2]V | -[1,2]J ] <tag> expl <descr>
is all you need to make your function work correctly with both tags
and description at the same time.
Misc. remarks
-------------
1) Supply match specifications to `compadd' if there are sensible ones.
2) Use helper functions that do option completion for you (like
`_arguments' and `_values') -- it will make your life much
easier.
7) Use helper functions like `_users' and `_groups' instead of direct
calls to `compgen -u' or some ad hoc mechanisms to generate such
information. This ensures that user can change the way these things
will be completed everywhere by just using their own implementations
for these functions.
8) Make sure that the return value of your functions is correct: zero
3) Use helper functions like `_users' and `_groups' instead of some ad hoc
mechanisms to generate such information. This ensures that users can
change the way these things will be completed everywhere by just using
their own implementations for these functions.
4) Make sure that the return value of your functions is correct: zero
if matches where added and non-zero if no matches were found.
In some cases you'll need to test the value of `$compstate[nmatches]'
for this. This should always be done by first saving the old value
(`local nm="$compstate[nmatches]"') and later comparing this with
the current value after all matches have been added (e.g. by
writing `[[ nmm -ne compstate[nmatches] ]]' at the end of your
function). This guarantees that your functions will be re-usable
because calling functions may rely on the correct return value.
9) In places where different behaviors may be useful, add a
configuration key to allow users to select the behavior they
prefer. Names for configuration keys should look like `prefix_name',
where `prefix' is the (probably abbreviated) name of your function
and `name' describes what can be configured.
When testing the values of configuration keys, the empty string
should result in the same behavior as if the key were unset. This
can be achieved by the test `[[ -n "$compconfig[prefix_name]" ]]'.
10) When writing helper functions that generate matches, the arguments
of these should be given unchanged to `compadd' or `compgen' (if
they are not used by the helper function itself).
writing `[[ nm -ne compstate[nmatches] ]]' at the end of your
function).
This guarantees that your functions will be re-usable because calling
functions may rely on the correct return value.
5) When writing helper functions that generate matches, the arguments
of these should be given unchanged to `compadd' (if they are not
used by the helper function itself).
6) When matches with a common prefix such as option names are generated,
add them *with* the prefix (like `-', `+', or `--' for options).
Then check the `prefix-needed' style to see if the matches are to be
added when the prefix is on the line and use the `prefix-hidden'
style to see if the prefix should be listed or not.
7) If at all possible, completion code for a command or a suite of
commands should go into only one file. If a command has sub-commands,
implementing a state-machine might be a good idea. See the `_rpm'
and `_pbm' files for examples of different styles. Also see the
documentation for `_arguments' and `_values' for two functions
that may help you with this.
8) If a completion function generates completely different types of
completions (for example, because the comamnd has several
completely different modes), it should allow users to define
functions that separately override the behavior for these
different types. This can easily be achieved by using the
`_funcall' utility function, as in:
_funcall ret _command_$subcommand && return ret
This will try to call the function `_command_$subcommand' and if
it exists, it will be called and the completion function exits
with its exit status. After this call to `funcall' the completion
function would contain the code for the default way to generate
the matches.
See the `_rpm' and `_nslookup' files for examples.

25
LICENCE Normal file
View file

@ -0,0 +1,25 @@
The Z Shell is copyright (c) 1992-2000 Paul Falstad, Richard Coleman,
Zoltán Hidvégi, Andrew Main, Peter Stephenson, Sven Wischnowsky, and
others. All rights reserved. Individual authors, whether or not
specifically named, retain copyright in all changes; in what follows, they
are referred to as `the Zsh Development Group'. This is for convenience
only and this body has no legal status. The Z shell is distributed under
the following licence; any provisions made in individual files take
precedence.
Permission is hereby granted, without written agreement and without
licence or royalty fees, to use, copy, modify, and distribute this
software and to distribute modified versions of this software for any
purpose, provided that the above copyright notice and the following
two paragraphs appear in all copies of this software.
In no event shall the Zsh Development Group be liable to any party for
direct, indirect, special, incidental, or consequential damages arising out
of the use of this software and its documentation, even if and the Zsh
Development Group have been advised of the possibility of such damage.
The Zsh Development Group specifically disclaim any warranties, including,
but not limited to, the implied warranties of merchantability and fitness
for a particular purpose. The software provided hereunder is on an "as is"
basis, and the Zsh Development Group have no obligation to provide
maintenance, support, updates, enhancements, or modifications.