1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-06-17 09:08:04 +02:00

zsh-3.1.5-pws-14

This commit is contained in:
Tanaka Akira 1999-04-15 18:24:09 +00:00
parent 640a840d2e
commit 6c1fb551ba
64 changed files with 3788 additions and 3632 deletions

View file

@ -1,6 +1,6 @@
DISTFILES_SRC='
.distfiles
_brace_parameter _command_names _condition _default _equal
_long_options _match_pattern _match_pattern.orig _match_test _parameter
_long_options _match_pattern _match_test _math _parameter
_precommand _redirect _subscript _tilde _vars
'

View file

@ -1,5 +1,9 @@
#defcomp -brace-parameter-
# Simple but without spiffy suffix handling: compgen -v -S '} '
compadd -S '} ' -r '-:?#%+=[/' - "${(@)${(@)${(@f)$(set)}%%\=*}:gs/'//}"
if [[ "$SUFFIX" = *\}* ]]; then
ISUFFIX="${SUFFIX#*\}}$ISUFFIX"
SUFFIX="${SUFFIX%%\}*}"
_parameters -S '} ' -r '-:?#%+=[/'
else
_parameters -S '} ' -r '-:?#%+=[/'
fi

View file

@ -3,7 +3,7 @@
local prev="$words[CURRENT-1]"
if [[ "$prev" = -o ]]; then
compgen -o -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}'
_options
elif [[ "$prev" = -([no]t|ef) ]]; then
_files
else

View file

@ -212,6 +212,7 @@ if [[ "$str" = *\=* ]]; then
pat="${pre}*"
patflags=''
_match_pattern _long_options pat patflags
[[ -n "$_comp_correct" ]] && patflags="$patflags(#a$_comp_correct)"
# Then we walk through the array names. For each array we test if it

18
Completion/Base/_math Normal file
View file

@ -0,0 +1,18 @@
#defcomp -math-
if [[ "$PREFIX" = *[^a-zA-Z0-9_]* ]]; then
IPREFIX="$IPREFIX${PREFIX%%[a-zA-Z0-9_]#}"
PREFIX="${PREFIX##*[^a-zA-Z0-9_]}"
fi
if [[ "$SUFFIX" = *[^a-zA-Z0-9_]* ]]; then
ISUFFIX="${SUFFIX##[a-zA-Z0-9_]#}$ISUFFIX"
SUFFIX="${SUFFIX%%[^a-zA-Z0-9_]*}"
fi
compgen -v
#defcomp -math-
IPREFIX="$IPREFIX${PREFIX%[a-zA-Z0-9_]*}"
PREFIX="${PREFIX##*[^a-zA-Z0-9_]}"
compgen -v

View file

@ -7,4 +7,10 @@
# `(( compstate[nmatches] )) || compgen -nu -qS/'
# below that.
compgen -nu -qS/
if [[ "$SUFFIX" = */* ]]; then
ISUFFIX="/${SUFFIX#*/}$ISUFFIX"
SUFFIX="${SUFFIX%%/*}"
compgen -nu -S ''
else
compgen -nu -qS/
fi

View file

@ -17,7 +17,7 @@ local pushdminus
emulate -LR zsh
setopt extendedglob
if [[ -position 3 ]]; then
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

View file

@ -1,6 +1,7 @@
#defcomp command
if [[ -position 3 -1 ]]; then
if [[ CURRENT -ge 3 ]]; then
compset -n 2
_normal
else
compgen -em

View file

@ -1,12 +1,12 @@
#defcomp hash
if [[ "$words[2]" = -*d* ]]; then
if [[ -string 1 '=' ]]; then
if compset -P 1 '*\='; then
_path_files -g '*(-/)'
else
compgen -n -q -S '='
fi
elif [[ -string 1 '=' ]]; then
elif compset -P 1 '*\='; then
_files -/g '*(*)'
else
compgen -m -q -S '='

View file

@ -2,7 +2,7 @@
local list
if [[ -iprefix '-' ]]; then
if compset -P 1 -; then
compgen -k "($signals[1,-3])"
else
local ret=1

View file

@ -1,3 +1,3 @@
#defcomp sched
[[ -position 3 -1 ]] && _normal
compset -n 3 && _normal

View file

@ -1,11 +1,10 @@
#defcomp setopt
local nm=$compstate[nmatches] ret=1
# If you first want to complete only unset options, un-comment the lines
# setting the _unset_options array and then use:
#
# _unset_options || _options
#
# here.
compgen -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' \
-s '$({ unsetopt kshoptionprint; unsetopt } 2>/dev/null)' && ret=0
[[ compstate[nmatches] -eq nm ]] &&
compgen -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' -o && ret=0
return ret
_options

View file

@ -1,6 +1,7 @@
#defcomp source
if [[ -position 3 -1 ]]; then
if [[ CURRENT -ge 3 ]]; then
compset -n 2
_normal
else
_files

View file

@ -1,11 +1,10 @@
#defcomp unsetopt
local nm=$compstate[nmatches] ret=1
# If you first want to complete only unset options, uncomment the lines
# setting the _set_options array and then use:
#
# _set_options || _options
#
# here.
compgen -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' \
-s '$({ unsetopt kshoptionprint; setopt } 2>/dev/null)' && ret=0
[[ compstate[nmatches] -eq nm ]] &&
compgen -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' -o && ret=0
return ret
_options

View file

@ -2,7 +2,7 @@
local fl="$words[2]"
if [[ "$fl" = -*(a*u|u*a)* || "$fl" = -*a* && -position 4 -1 ]]; then
if [[ "$fl" = -*(a*u|u*a)* || "$fl" = -*a* && CURRENT -ge 4 ]]; then
compgen -B
elif [[ "$fl" = -*u* ]]; then
compgen -s '$(zmodload)'

View file

@ -45,7 +45,7 @@ fi
if [[ -z $testcmd && -e "$file" ]] ||
{ [[ -n $testcmd ]] && whence "$file" >&/dev/null }; then
if [[ -n $WIDGET ]]; then
compadd -QUf -i "$IPREFIX" "${file/#$etilde/$tilde}"
compadd -QUf -i "$IPREFIX" -I "$ISUFFIX" "${file/#$etilde/$tilde}"
[[ -n "$compstate[insert]" ]] && compstate[insert]=menu
else
print "$file"
@ -65,7 +65,7 @@ done
(( $#trylist )) || return 1
if [[ -n $WIDGET ]]; then
compadd -QUf -i "$IPREFIX" "${trylist[@]/#$etilde/$tilde}"
compadd -QUf -i "$IPREFIX" -I "$ISUFFIX" "${trylist[@]/#$etilde/$tilde}"
[[ -n "$compstate[insert]" ]] && compstate[insert]=menu
else
print "$IPREFIX${^trylist[@]}"

View file

@ -19,4 +19,4 @@ if [[ $PREFIX = \~*/* ]]; then
else
file=($~PREFIX*$~SUFFIX(om[$NUMERIC]N))
fi
(( $#file )) && compadd -U -f -Q $file
(( $#file )) && compadd -U -i "$IPREFIX" -I "$ISUFFIX" -f -Q $file

View file

@ -1,5 +1,6 @@
DISTFILES_SRC='
.distfiles
_compalso _files _main_complete _multi_parts _normal _path_files
_sep_parts compdump compinit
_approximate _compalso _complete _correct _expand _files _list
_main_complete _match _multi_parts _normal _options _parameters
_path_files _sep_parts _set_options _unset_options compdump compinit
'

View file

@ -0,0 +1,197 @@
#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.
local _comp_correct _correct_prompt comax
local cfgacc cfgorig cfgps cfgins
# Only if all global matchers hav been tried.
[[ compstate[matcher] -ne compstate[total_matchers] ]] && return 1
# 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
# Get the number of errors to accept.
if [[ "$cfgacc" = *[nN]* && NUMERIC -ne 1 ]]; then
# Stop if we also have a `!'.
[[ "$cfgacc" = *\!* ]] && return 1
# Prefer the numeric argument if that has a sensible value.
comax="$NUMERIC"
else
comax="${cfgacc//[^0-9]}"
fi
# If the number of errors to accept is too small, give up.
[[ "$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
# ignored prefix).
compadd() {
[[ "$*" != *-([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 compadd -X "$_correct_prompt" -J _correct "$@"
else
builtin compadd -J _correct "$@"
fi
}
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
if _complete; then
if [[ "$cfgins" = unambig* &&
"${#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
# If you always want to see the list of possible corrections,
# set `compstate[list]=list' here.
compstate[force_list]=list
fi
compstate[matcher]="$compstate[total_matchers]"
unfunction compadd compgen
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
return 1

52
Completion/Core/_complete Normal file
View file

@ -0,0 +1,52 @@
#autoload
# 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.
local comp name
# An entry for `-first-' is the replacement for `compctl -T'
# Completion functions may set `_compskip' to any value to make the
# main loops stop calling other completion functions.
comp="$_comps[-first-]"
if [[ ! -z "$comp" ]]; then
"$comp"
if (( $+_compskip )); then
unset _compskip
(( compstate[nmatches] ))
return
fi
fi
# For arguments and command names we use the `_normal' function.
if [[ "$compstate[context]" = command ]]; then
_normal
else
# Let's see if we have a special completion definition for the other
# possible contexts.
comp=''
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
# If not, we use default completion, if any.
[[ -z "$comp" ]] && comp="$_comps[-default-]"
[[ -z "$comp" ]] || "$comp"
fi
(( compstate[nmatches] ))

19
Completion/Core/_correct Normal file
View file

@ -0,0 +1,19 @@
#autoload
# 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
# with the corrected prefix and something after it.
#
# Supported configuration keys are the same as for `_approximate', only
# starting with `correct'.
local ret=1 opm="$compstate[pattern_match]"
compstate[pattern_match]='-'
_approximate && ret=0
compstate[pattern_match]="$opm"
return ret

149
Completion/Core/_expand Normal file
View file

@ -0,0 +1,149 @@
#autoload
# This completer function is intended to be used as the first completer
# function and allows one to say more explicitly when and how the word
# from the line should be expanded than expand-or-complete.
# 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
# Do this only for the first global matcher.
[[ "$compstate[matcher]" -le 1 ]] || return 1
# In exp we will collect the expansion.
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 ]] &&
exp=( "${(e)exp//\\[
]/ }" )
# If the array is empty, store the original string again.
[[ -z "$exp" ]] && exp=("$word")
# Now try globbing.
[[ -z "$compconfig[expand_glob]" ||
"${(e):-\$[$compconfig[expand_glob]]}" -eq 1 ]] &&
exp=( ${~exp}(N) )
# 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
# We have expansions, should we menucomplete them?
if [[ -z "$compconfig[expand_menu]" ]]; then
# 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.
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"
compadd -UQ -V _expand - "$exp"
[[ -n "$compconfig[expand_original]" &&
"$compconfig[expand_original]" = *last* ]] &&
compadd -UnQ -V _expand_original - "$word"
compstate[insert]=menu
fi
else
# Sorting? We just use a different group type then.
[[ "$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[@]"
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"
compstate[insert]=menu
fi
return 0

61
Completion/Core/_list Normal file
View file

@ -0,0 +1,61 @@
#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.
local pre suf
# Get the strings to compare.
if [[ -z "$compconfig[list_word]" ]]; then
pre="$HISTNO$LBUFFER"
suf="$RBUFFER"
else
pre="$PREFIX"
suf="$SUFFIX"
fi
# Should we only show a list now?
if [[ ( -z "$compconfig[list_condition]" ||
"${(e):-\$[$compconfig[expand_glob]]}" -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
_list_prefix="$pre"
_list_suffix="$suf"
fi
# We always return one, because we don't really do any work here.
return 1

View file

@ -3,229 +3,56 @@
# The main loop of the completion code. This is what is called when
# completion is attempted from the command line.
#
# This code will automatically try to correct the string on the line
# based on the strings generated for the context if
# `compconfig[correct]' is set and normal completion didn't yield any
# matches. These corrected strings will be shown in a list and one can
#cycle through them as in a menucompletion. To use this feature,
#`compconfig[correct]' 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
# `compconfig[correct]' will be used. E.g. with `compconfig[correct]=2n'
# two errors will be accepted, but if the user gives another number
# with the numeric argument, this will be prefered. Also, with
# `compconfig[correct]=0n',normally no automatic correction will be
# tried, but if a numeric argument is given, automatic correction will
# be used. 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.
# The value of `compconfig[correct_orig]' 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 apear 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 immediatly). Also, if the value of
# `compconfig[correct_orig]' 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.
# Finally, `compconfig[correct_prompt]' may 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.
# Configuration keys used:
#
# completer
# This should be set to the names of the functions to generate the
# matches separated by colons. E.g. with
#
# compconf completer=_complete:_correct:_approximate
#
# the code will first try normal completion. If that doesn't yield
# any matches, correction is tried and if that doesn't yield
# anything either, correcting completion is attempted.
#
# These completer functions are only used when this function is called
# without arguments. If arguments are given, they should be names of
# completer functions which will then be called.
local comp name _comp_correct _correct_prompt comax
# 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=("${(@f)$({ unsetopt kshoptionprint; setopt } 2>/dev/null)}")
# _unset_options=("${(@f)$({ unsetopt kshoptionprint; unsetopt } 2>/dev/null)}")
#
# This is needed because completion function 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.
local comp
setopt localoptions nullglob rcexpandparam
unsetopt markdirs globsubst shwordsplit nounset ksharrays
# Special completion contexts after `~' and `='.
if [[ -iprefix '=' ]]; then
if compset -P 1 '\='; then
compstate[context]=equal
elif [[ "$PREFIX$SUFFIX" != */* && -iprefix '~' ]]; then
elif [[ "$PREFIX" != */* && "$PREFIX[1]" = '~' ]]; then
compset -p 1
compstate[context]=tilde
fi
# This is not an endless loop.
# Get the names of the completers to use in the positional parameters.
while true; do
(( $# )) || set ${(s.:.)compconfig[completer]}
# 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.
# And now just call the completer functions defined.
comp="$_comps[-first-]"
if [[ ! -z "$comp" ]]; then
"$comp"
if (( $+_compskip )); then
unset _compskip
return
fi
fi
# For arguments and command names we use the `_normal' function.
if [[ "$compstate[context]" = command ]]; then
_normal
else
# Let's see if we have a special completion definition for the other
# possible contexts.
comp=''
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
# If not, we use default completion, if any.
[[ -z "$comp" ]] && comp="$_comps[-default-]"
[[ -z "$comp" ]] || "$comp"
fi
# Use automatic correction?
if (( $+compconfig[correct] )); then
# Do we have matches?
if (( compstate[nmatches] )); then
# Yes, were they added using correction? (More than one match?)
if [[ -n "$_comp_correct" &&
( "$compconfig[correct_orig]" = *always* ||
compstate[nmatches] -gt 1 ) ]]; then
if [[ "$compconfig[correct_orig]" = *last* ]]; then
builtin compadd -V _correct_orig -nQ - "$PREFIX$SUFFIX"
elif [[ -n "$compconfig[correct_orig]" ]]; then
builtin compadd -nQ - "$PREFIX$SUFFIX"
fi
# If you always want to see the list of possible corrections,
# set `compstate[list]=list' here.
compstate[force_list]=list
fi
# Since we have matches, we don't want to try again.
break
fi
# No matches, so let's see if we already tried correction.
if [[ -n "$_comp_correct" ]]; then
# Yes, give up if we reached the maximum number of tries or the
# string from the line is too short, otherwise increment our
# counter.
[[ _comp_correct -eq comax ||
"${#${:-$PREFIX$SUFFIX}}" -le _comp_correct+1 ]] && break
(( _comp_correct++ ))
_correct_prompt="${compconfig[correct_prompt]//\%e/$_comp_correct}"
elif [[ compstate[matcher] -eq compstate[total_matchers] ]]; then
# We don't try correction if the string is too short.
[[ "${#${:-$PREFIX$SUFFIX}}" -le 1 ]] && return
# No matches and no correction tried yet, but we just tried the
# last global match specification, so let's see if we should use
# correction now. First, get the maximum number of errors.
if [[ "$compconfig[correct]" = *[nN]* && NUMERIC -ne 1 ]]; then
# Prefer the numeric argument if that has a sensible value.
comax="$NUMERIC"
else
comax="${compconfig[correct]//[^0-9]}"
fi
# If the number of errors to accept is too small, give up.
[[ "$comax" -lt 1 ]] && break
# 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
# ignored prefix).
compadd() {
[[ "$*" != *-([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 compadd -X "$_correct_prompt" -J _correct "$@"
else
builtin compadd -J _correct "$@"
fi
}
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="${compconfig[correct_prompt]//\%e/$_comp_correct}"
# We also need to set `extendedglob' and to make the completion
# code behave as if globcomplete were set.
setopt extendedglob
compstate[pattern_match]=yes
else
# We are still trying global match specifications...
break
fi
else
# No automatic correction to try, just give up.
break
fi
for comp; do
"$comp" && return
done
# If we added wrapper functions, remove them.
[[ -n "$_comp_correct" ]] && unfunction compadd compgen

53
Completion/Core/_match Normal file
View file

@ -0,0 +1,53 @@
#autoload
# This is intended to be used as a completer function after the normal
# completer as in: `compconf 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
# Do nothing if we don't have a pattern or there are still global
# match specifications to try.
tmp="${${:-$PREFIX$SUFFIX}#[~=]}"
[[ "$tmp:q" = "$tmp" ||
compstate[matcher] -ne compstate[total_matchers] ]] && return 1
# Try completion without inserting a `*'?
if [[ -n "$compconfig[match_original]" ]]; then
compstate[matcher]=-1
compstate[pattern_match]='-'
_complete && ret=1
compstate[pattern_match]="$opm"
compstate[matcher]="$compstate[total_matchers]"
(( ret )) && return 0
fi
# No completion with inserting `*'?
[[ "$compconfig[match_original]" = only ]] && return 1
compstate[matcher]=-1
compstate[pattern_match]='*'
_complete && ret=1
compstate[pattern_match]="$opm"
compstate[matcher]="$compstate[total_matchers]"
return 1-ret

View file

@ -45,7 +45,11 @@ fi
# the original string in `orig'.
if [[ $#compstate[pattern_match] -ne 0 ]]; then
patstr="${PREFIX}*${SUFFIX}*"
if [[ "${compstate[pattern_match]-*}" = \** ]]; then
str="${PREFIX}*${SUFFIX}*"
else
str="${PREFIX}${SUFFIX}"
fi
else
patstr="${PREFIX:q}*${SUFFIX:q}*"
fi
@ -145,7 +149,8 @@ if (( $#tmp1 )); then
# found. Strings that have a separator will be added with a suffix.
if [[ -z "$orig" && "$PREFIX$SUFFIX" != "$pref$orig" ]]; then
compadd -QU "$group[@]" "$expl[@]" -i "$IPREFIX" -S '' - "${pref}${orig}"
compadd -QU "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" -S '' - \
"${pref}${orig}"
elif [[ -n "$menu" ]]; then
if [[ "$orig" = *${sep}* ]]; then
orig="${sep}${orig#*${sep}}"
@ -154,20 +159,21 @@ if (( $#tmp1 )); then
fi
for i in "$matches[@]" ; do
if [[ "$i" = *${sep}* ]]; then
compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" \
compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \
-p "$pref" -s "$orig" - "${i%%${sep}*}${sep}"
else
compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" \
compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \
-p "$pref" -s "$orig" - "${i%%${sep}*}"
fi
done
else
for i in "$matches[@]" ; do
if [[ "$i" = *${sep}* ]]; then
compadd -U -i "$IPREFIX" -p "$pref" -s "${i#*${sep}}" \
compadd -U -i "$IPREFIX" -I "$ISUFFIX" -p "$pref" -s "${i#*${sep}}" \
"$group[@]" "$expl[@]" -M "r:|${sep:q}=*" - "${i%%${sep}*}${sep}"
else
compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" -p "$pref" - "$i"
compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \
-p "$pref" - "$i"
fi
done
fi
@ -201,8 +207,8 @@ elif [[ "$patstr" = *${sep}* ]]; then
# the completion code together with our prefix and the rest of
# the string from the line as the suffix.
compadd -U "$group[@]" "$expl[@]" -S '' -i "$IPREFIX" -p "$pref" \
-s "${sep}${orig#*${sep}}" - "${(@)matches%%${sep}*}"
compadd -U "$group[@]" "$expl[@]" -S '' -i "$IPREFIX" -I "$ISUFFIX" \
-p "$pref" -s "${sep}${orig#*${sep}}" - "${(@)matches%%${sep}*}"
return 0
fi
@ -218,7 +224,8 @@ elif [[ "$patstr" = *${sep}* ]]; then
# Finally, add the unambiguous prefix and the rest of the string
# from the line.
compadd -U "$group[@]" "$expl[@]" -S '' -i "$IPREFIX" -p "$pref" - "$orig"
compadd -U "$group[@]" "$expl[@]" -S '' -i "$IPREFIX" -I "$ISUFFIX" \
-p "$pref" - "$orig"
fi
# This sets the return value to indicate that we added matches (or not).

5
Completion/Core/_options Normal file
View file

@ -0,0 +1,5 @@
#autoload
# This should be used to complete all option names.
compgen "$@" -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' -o

View file

@ -0,0 +1,8 @@
#autoload
# This should be used to complete parameter names if you need some of the
# extra options of compadd. It first tries to complete only non-local
# parameters. All arguments are given to compadd.
compadd "$@" - "${(@)${(@)${(@)${(@f)$(typeset)}:#*local *\=*}%%\=*}##* }" ||
compadd "$@" - "${(@)${(@)${(@f)$(typeset)}%%\=*}##* }"

View file

@ -12,6 +12,14 @@
# like files with one of the suffixes in the `fignore' array in normal
# completion.
#
# This function supports one configuration key:
#
# path_expand
# If this is set to a non-empty string, the partially typed path
# from the line will be expanded as far as possible even if trailing
# pathname components can not be completed.
#
#
# This function uses the helper functions `_match_test' and `_match_pattern'.
# First see if we should generate matches for the global matcher in use.
@ -20,14 +28,17 @@ _match_test _path_files || return 1
# Yes, so...
local nm prepaths str linepath realpath donepath patstr prepath testpath rest
local nm 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 orig ostr nm=$compstate[nmatches] menu remsfx patlast
local origflags mflags
local origflags mflags tmp3 tmp4 exppaths
typeset -U prepaths
setopt localoptions nullglob rcexpandparam extendedglob
unsetopt markdirs globsubst shwordsplit nounset
exppaths=()
prepaths=('')
ignore=()
group=()
@ -102,7 +113,11 @@ fi
# the prefix and the suffix. Then we see if we will do menucompletion.
if [[ $#compstate[pattern_match] -ne 0 ]]; then
str="${PREFIX}*${SUFFIX}"
if [[ "${compstate[pattern_match]-*}" = \** ]]; then
str="${PREFIX}*${SUFFIX}"
else
str="${PREFIX}${SUFFIX}"
fi
else
str="${PREFIX:q}*${SUFFIX:q}"
[[ "$str" = \\\~* ]] && str="$str[2,-1]"
@ -200,7 +215,7 @@ origflags="$matchflags"
# 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/**/*/:gs-.*/-./-"
patstr="$patstr:gs-/-*/-:gs/*.*./../:gs/**/*/:gs-.*/-./-"
# We take the last pathname component from the pattern and store it in
# `patlast', replacing `*'s in it with patterns that match any character
@ -214,16 +229,16 @@ patstr="$patstr:gs-/-*/-:gs/*.*./../:gs-/*.-/.-:gs/**/*/:gs-.*/-./-"
if [[ "$patstr" = */* ]]; then
if [[ -n "$_comp_correct" && "${#orig##*/}" -le _comp_correct ]]; then
patlast="*/${origflags}${${patstr##*/}//\*/[^/]#}"
patlast="*/${origflags}${${${patstr##*/}//\*/[^/]#}:gs.\[^/]#.\\\*.}"
else
patlast="*/${matchflags}${${patstr##*/}//\*/[^/]#}"
patlast="*/${matchflags}${${${patstr##*/}//\*/[^/]#}:gs.\[^/]#.\\\*.}"
fi
patstr="${patstr%/*}/"
else
if [[ -n "$_comp_correct" && "$#orig" -le _comp_correct ]]; then
patlast="${origflags}${patstr//\*/[^/]#}"
patlast="${origflags}${${patstr//\*/[^/]#}:gs.\[^/]#.\\\*.}"
else
patlast="${matchflags}${patstr//\*/[^/]#}"
patlast="${matchflags}${${patstr//\*/[^/]#}:gs.\[^/]#.\\\*.}"
fi
patstr=""
fi
@ -234,7 +249,7 @@ fi
# to `donepath'.
while [[ "$orig" = */* ]] do
tmp1=( $realpath$donepath${orig%%/*}/${~matchflags}${~patstr#*/}$^pats )
tmp1=( $realpath$donepath${orig%%/*}/${~matchflags}${~patstr#*/}${^~pats} )
tmp1=("${(@M)tmp1:#$~patlast}")
[[ $#tmp1 -gt 0 && -e "$realpath$donepath${orig%%/*}" ]] || break
donepath="$donepath${orig%%/*}/"
@ -311,6 +326,24 @@ for prepath in "$prepaths[@]"; do
# next `-W' path.
if [[ $#collect -eq 0 ]]; then
# Before giving, we first try to get the longest expandable path-
# prefix, though. The result is stored in `exppaths'
tmp2=()
tmp3="$rest"
tmp4="${ostr##*/}"
ostr="${ostr%/*}"
while [[ "$tmp3" = */* ]]; do
tmp2=( ${^tmp1}/${~mflags}${~tmp3} )
if [[ $#tmp2 -eq 1 ]]; then
exppaths=( "$exppaths[@]" "${tmp2[1]}${tmp4}" )
exppaths=( "${(@)exppaths#${prepath}${realpath}}" )
break;
fi
tmp3="${tmp3%/*}"
tmp4="${ostr##*/}/${tmp4}"
ostr="${ostr%/*}"
done
continue 2
elif [[ $#collect -ne 1 ]]; then
# If we have more than one possible match, this means that the
@ -338,13 +371,14 @@ for prepath in "$prepaths[@]"; do
if [[ -n "$menu" ]]; then
compadd -QU "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" \
-i "$IPREFIX" -p "$linepath${testpath:q}" \
-i "$IPREFIX" -I "$ISUFFIX" -p "$linepath${testpath:q}" \
-s "/${ostr#*/}" \
-W "$tmp1" -f "$ignore[@]" - "${(@)${(@)collect%%/*}:q}"
else
for i in $collect; do
compadd -QU "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" \
-i "$IPREFIX" -p "$linepath${testpath:q}" -s "/${${i#*/}:q}" \
-i "$IPREFIX" -I "$ISUFFIX" \
-p "$linepath${testpath:q}" -s "/${${i#*/}:q}" \
-M 'r:|/=*' -W "$tmp1" -f "$ignore[@]" - "${${i%%/*}:q}"
done
fi
@ -371,7 +405,8 @@ for prepath in "$prepaths[@]"; do
if [[ $#tmp1 -ne $#tmp2 ]]; then
compadd -QU "$addpfx[@]" -S '' "$group[@]" "$expl[@]" \
-i "$IPREFIX" -p "$linepath${testpath:q}" -s "/${ostr#*/}" \
-i "$IPREFIX" -I "$ISUFFIX" \
-p "$linepath${testpath:q}" -s "/${ostr#*/}" \
- "${${tmp1#${prepath}${realpath}${testpath}}:q}"
continue 2
fi
@ -399,8 +434,11 @@ for prepath in "$prepaths[@]"; do
suffixes=( $str$^pats )
suffixes=( "${(@)suffixes:gs.**.*.}" )
tmp2=( ${~tmp1}${~matchflags}${~suffixes} )
tmp2=("${(@M)tmp2:#$~patlast}")
if [[ "$tmp1" = */* && "$patlast" != \*/* ]]; then
tmp2=("${(@M)tmp2:#*${~patlast}}")
else
tmp2=("${(@M)tmp2:#$~patlast}")
fi
if [[ $#tmp2 -eq 0 ]]; then
# No match, insert the expanded path and add the original tail.
@ -409,17 +447,29 @@ for prepath in "$prepaths[@]"; do
[[ -n "$ostr" && -n "$linepath$testpath" ]] && ostr="/$ostr"
# But only if something changed.
[[ "$linepath$testpath$ostr" = "$PREFIX$SUFFIX" ]] && return 1
[[ "${PREFIX}${SUFFIX}" = $linepath$testpath$ostr(|/) ]] && return 1
compadd -QU -S '' "$group[@]" "$expl[@]" \
-i "$IPREFIX" -f - "$linepath${testpath:q}$ostr"
-i "$IPREFIX" -I "$ISUFFIX" -f - "$linepath${testpath:q}$ostr"
else
compadd -QU "$addpfx[@]" "$addsfx[@]" "$remsfx[@]" "$group[@]" "$expl[@]" \
-i "$IPREFIX" -p "$linepath${testpath:q}" -f "$ignore[@]" \
-i "$IPREFIX" -I "$ISUFFIX" \
-p "$linepath${testpath:q}" -f "$ignore[@]" \
-W "$prepath$realpath$testpath" - "${(@)${(@)tmp2#$tmp1}:q}"
fi
done
# If no matches were found but we have expanded paths which are different
# from the original string, use them.
exppaths=( "${(@)exppaths:#$orig}" )
if [[ -n "$compconfig[path_expand]" &&
nm -eq compstate[nmatches] && $#exppaths -ne 0 ]]; then
compadd -UQ -S '' "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" - \
"${linepath}${(@)^exppaths}"
fi
# This sets the return value to indicate that we added matches (or not).
[[ nm -ne compstate[nmatches] ]]

View file

@ -101,6 +101,8 @@ if [[ $# -le 1 || "$str" != *${2}* ]]; then
_match_pattern _sep_parts test matchflags
[[ -n "$_comp_correct" ]] && matchflags="$matchflags(#a$_comp_correct)"
[[ "${compstate[pattern_match]-*}" != \** ]] && test="$test:gs/*//"
test="${matchflags}${test}"
testarr=( "${(@M)${(@P)arr}:#${~test}*}" )
testarr=( "${(@)testarr:#}" )
@ -131,6 +133,9 @@ while [[ $# -gt 0 && "$str" == *${1}* ]]; do
matchflags=""
_match_pattern _sep_parts test matchflags
[[ -n "$_comp_correct" ]] && matchflags="$matchflags(#a$_comp_correct)"
[[ "${compstate[pattern_match]-*}" != \** ]] && test="$test:gs/*//"
test="${matchflags}${test}"
# We incrementally add suffixes by appending to them the seperators
@ -163,7 +168,7 @@ done
# Add the matches for each of the suffixes.
for i in "$suffixes[@]"; do
compadd -U "$group[@]" "$expl[@]" "$matchers[@]" "$autosuffix[@]" \
-i "$IPREFIX" -p "$prefix" -s "$i" - "$testarr[@]"
-i "$IPREFIX" -I "$ISUFFIX" -p "$prefix" -s "$i" - "$testarr[@]"
done
# This sets the return value to indicate that we added matches (or not).

View file

@ -0,0 +1,7 @@
#autoload
# Complete all set options. This relies on `_main_complete' to store the
# names of the options that were set when it was called in the array
# `_set_options'.
compadd "$@" -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' - $=_set_options

View file

@ -0,0 +1,7 @@
#autoload
# Complete all unset options. This relies on `_main_complete' to store the
# names of the options that were set when it was called in the array
# `_set_options'.
compadd "$@" -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' - $=_unset_options

View file

@ -15,7 +15,7 @@
# 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=${compconfig[dump_file]-${0:h}/compinit.dump}
_d_file=${compconfig[dumpfile]-${0:h}/compinit.dump}
typeset -U _d_files
_d_files=( ${^~fpath}/_*~*~(N:t) )

View file

@ -71,11 +71,12 @@ typeset -A compconfig
# Standard initialisation for `compconfig'.
(( $# )) && compconfig[dump_file]="$1"
[[ -z "$compconfig[dump_file]" ]] && compconfig[dump_file]="$0.dump"
(( $# )) && compconfig[dumpfile]="$1"
[[ -z "$compconfig[dumpfile]" ]] && compconfig[dumpfile]="$0.dump"
compconfig[correct_accept]=2n
compconfig[correct_prompt]='correct to:'
compconfig[completer]=_complete
# This function is used to register or delete completion functions. For
# registering completion functions, it is invoked with the name of the
@ -246,10 +247,10 @@ _i_done=''
# If we have a dump file, load it.
if [[ -f "$compconfig[dump_file]" ]]; then
read -rA _i_line < "$compconfig[dump_file]"
if [[ -f "$compconfig[dumpfile]" ]]; then
read -rA _i_line < "$compconfig[dumpfile]"
if [[ _i_autodump -eq 1 && $_i_line[2] -eq $#_i_files ]]; then
builtin . "$compconfig[dump_file]"
builtin . "$compconfig[dumpfile]"
_i_done=yes
fi
unset _i_line

View file

@ -14,7 +14,7 @@ The name of the file to use may be given as an extra argument.
This will rebind any keys which do completion to use the new system.
For more detailed instructions, including how to add new completions, see
the top of Core/compinit. For information about how to configure the code,
see the comment at the top of Core/_main_complete.
see the section below.
The subdirectories contain:
@ -30,32 +30,61 @@ Core:
This dumps the completions status for faster initialisation. The
easiest way of doing this is to use the -d option to compinit rather
than calling compdump directly.
_sep_parts
Utility used for completing words with multiple separate parts, such as
`<user>@<host>'
_multi_parts
Utility for completion parts of words given a separator character and
a list of words.
_approximate
A completer function that does correcting completion.
_compalso
Utility for calling a function to add additional completions to an
already existing set.
_complete
The main completer function that generates the completions by calling
the context and command specific functions.
_correct
A completer function that attempts correction on the word from the
line. Unlike _approximate this does only correction, not completion.
_expand
A completer function for expanding the word on the line.
_files
A frontend to _path_files which will default to any old file if the
specified file was not found.
_list
A completer function that allows showing only a list on the first
TAB and insert completions on the second one.
_match
A completer function that temporarily swicthes on pattern matching
when comparing the string from the line with possible completions.
_main_complete
The main entry point called by the key bindings which compinit sets
up (the main `completion widget' in zsh jargon).
up (the main `completion widget' in zsh jargon). This mainly calls
completer functions like _complete, either those given as arguments
or (if it is called without arguments) those from the completer
configuration key (see below).
_multi_parts
Utility for completion parts of words given a separator character and
a list of words.
_normal
The function called by _main_complete to handle the most common
cases, such as completing a command name or its arguments. This
function dispatches to the various other functions for individual
commands. (Actually, the system is fairly context-sensitive, so
it is wider than just command+argument.)
_options
Utility to complete option names, allowing the optional `no' prefix
and correctly handling upper case letters and underscores.
_parameters
This can be used to complete parameter names if you need some of the
options of compadd not supported by compgen.
_path_files
The function usually called to complete filenames and directories. It
replaces the standard -f, -g and -/ options for the basic completion
commands: it can do various extra tricks, such as expanding a whole
path at once, e.g. F/C/C/_p<TAB> -> Functions/Completion/Core/_path_files
_sep_parts
Utility used for completing words with multiple separate parts, such as
`<user>@<host>'
_set_options
_unset_options
These can be used to complete only set or unset options. For this to
work, you'll have to un-comment a few lines in _main_complete.
Base:
You will almost certainly want these files, too, which handle standard
tasks like completing files. However, you may want to edit them for
@ -127,3 +156,201 @@ Commands:
_most_recent_file, bound to \C-xm
Insert the name of the most recent file matching the pattern
so far on the command line.
Configuration
You can configure several aspects of the completion functions and the
overall completion behavior using the compconf shell function defined
in compinit. This function gets any number of arguments of the form
`key=value', where `key' is one of the keys described below and `value'
is any string. Most configuration keys are defined by the completer
functions.
The completion widget function _main_complete currently understands
one configuration key:
completer
This should be set to the names of the functions to generate the
matches separated by colons. E.g. with
compconf completer=_complete:_correct:_approximate
the code will first try normal completion. If that doesn't yield
any matches, correction is tried and if that doesn't yield
anything either, correcting completion is attempted.
The keys understood by the _approximate completer function are:
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. The forms beginning with `correct' are also used by the
_correct completer function, and this function uses only them, not
the ones starting with `approximate'. This allows one to give
different value to be used with correction and correcting
completion. For example, with:
compconf completer=_complete:_correct:_approximate
compconf correct_accept='2n!' approximate_accept=3n
correction will accept up to two errors. If a numeric argument is
given, correction will not be used, but correcting completion will
and it will accept as many errors as given by the numeric argument.
Without a numeric argument first correction and then correcting
completion will be tried, with the first one accepting two errors
and the second one accepting three errors.
The _match completer function, which allows to give patterns on the
command line and complete all strings matching it from the set of
possible completions, understands the following key:
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.
The _expand completer allows one to do expansion on the word from the
line. Note that you may either want to use the configuration keys or
not use this completer at all if you also use the _match completer
because the _expand completer will otherwise expand patterns before
they are seen by the _match completer.
Configuration keys supported are:
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.
The _list completer allows one to delay the insertion of matches until
completion is attempted a second time without the word on the line
being changed. On the first attempt, only the list of matches will
be shown. Configuration keys understood are:
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.
For more information about what the completers do, see the files
containing them (_complete, _correct, _approximate, _match, and
_expand in the Core directory).
The _path_files function used to complete filenames has one
configuration key:
path_expand
If this is set to a non-empty string, the partially typed path
from the line will be expanded as far as possible even if trailing
pathname components can not be completed.

View file

@ -1,12 +1,12 @@
#defcomp dd
if [[ -iprefix conv= ]]; then
if compset -P 1 'conv\='; then
# If there's a comma present, ignore up to the last one. The
# test alone will have that effect.
[[ -string , ]]
compset -p '*,'
compgen -S, -q \
-k '(ascii ebcdic ibm block unblock lcase ucase swab noerror sync)'
elif [[ -iprefix 'if=' || -iprefix 'of=' ]]; then
elif compset -P 1 '[io]f\='; then
_files
else
compgen -S '=' -k '(if of ibs obs bs cbs skip files seek count conv)'

View file

@ -2,14 +2,14 @@
local prev="$words[CURRENT-1]"
if [[ -mbetween -(ok|exec) \\\; ]]; then
if compset -N '-(ok|exec)' '\;' then
_normal
elif [[ -iprefix - ]]; then
elif compset -P 1 -; then
compgen -s 'daystart {max,min,}depth follow noleaf version xdev \
{a,c,}newer {a,c,m}{min,time} empty false {fs,x,}type gid inum links \
{i,}{l,}name {no,}{user,group} path perm regex size true uid used \
exec {f,}print{f,0,} ok prune ls'
elif [[ -position 2 ]]; then
elif [[ CURRENT -eq 2 ]]; then
local ret=1
compgen -g '. ..' && ret=0

View file

@ -13,7 +13,7 @@ local prev="$words[CURRENT-1]"
# 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.
@ -23,7 +23,7 @@ if [[ -iprefix - ]]; then
print $n =~ s/^\[([a-z]+)\]// ? "$n\n$1$n\n" : "$n\n";
}')
return
elif [[ -iprefix '+' || -iprefix '@' || "$prev" = -draftfolder ]]; then
elif compset -P 1 '[+@] || [ "$prev" = -draftfolder ]]; then
# Complete folder names.
local mhpath

View file

@ -5,7 +5,7 @@ if [[ "$words[CURRENT-1]" = \
then
compadd -Q '^-' '^h' '^?' '^c' '^u'
else
[[ -string '-' || -string '+' ]]
compset -P '[-+]'
compadd rows columns intr quit erase kill eof eol \
eol2 start stop susp dsusp reprint discard werase lnext \
parenb parodd cs8 cstopb hupcl cread clocal parext \

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-pws-13
VERSION_DATE='March 20, 1999'
VERSION=3.1.5-pws-14
VERSION_DATE='March 26, 1999'

View file

@ -50,7 +50,7 @@ from the completion code to the completion widget and can be set to
give information to the completion code from the completion
widget. Some of the builtin commands and the condition codes use or
change the current values of these parameters. While the completion
widget is active, these parameters are reseton each function exit to
widget is active, these parameters are reset on each function exit to
the values they had when the function was entered.
startitem()
@ -80,6 +80,10 @@ taken as the string every possible match has to end with. The
completion code sets this to the part of the current word from the
cursor position to the end.
)
item(tt(ISUFFIX))(
Like tt(IPREFIX), but for a suffix that should not be considered part
of the matches.
)
item(tt(compstate))(
This is an associative array with various keys and values the
completion uses to give informtaion to the completion widget and to
@ -201,11 +205,30 @@ otherwise.
)
item(tt(pattern_match))(
If the option tt(GLOB_COMPLETE) is set, this is initially set to
tt(yes) and unset otherwise. If the completion widget sets it to a
non-empty string, the completion code will from then on behave as if
tt(GLOB_COMPLETE) is set, i.e.. if the strings in tt(PREFIX) and
`tt(*)' and unset otherwise. If the completion widget sets it to a
`tt(*)', the completion code will from then on behave as if
tt(GLOB_COMPLETE) is set, i.e. if the strings in tt(PREFIX) and
tt(SUFFIX) contain unquoted metacharacters, they will be treated as
patterns.
patterns. If the string is set to any other non-empty string, the
strings will be treated as patterns but the code will not automatically
insert a star at the cursor position.
)
item(tt(pattern_insert))(
Normally this is set to tt(menu) which means that menu-completion will be
used whenever the matches were generated using pattern matching. If this
is set to any other non-empty string by the user and menu-completion is
not selected by other option settings, the code will insert an
unambiguous string for the generated matches as with normal completion.
)
item(tt(unambiguous))(
This key is read-only and will always be set to the unambiguous string
the completion code has generated for all matches added so far.
)
item(tt(unambiguous_cursor))(
This gives the position the cursor would be placed at when the
unambiguous string would be inserted, relative to the value of the
tt(unambiguous) key. The cursor would be placed before the character
whise index is given by this key.
)
enditem()
)
@ -241,7 +264,8 @@ if at least one match was added and non-zero otherwise.
xitem(tt(compadd) [ tt(-qQfnUam) ] [ tt(-F) var(array) ])
xitem([ tt(-P) var(prefix) ] [ tt(-S) var(suffix) ])
xitem([ tt(-p) var(hidden-prefix) ] [ tt(-s) var(hidden-suffix) ])
xitem([ tt(-i) var(ignored-prefix) ] [ tt(-W) var(file-prefix) ])
xitem([ tt(-i) var(ignored-prefix) ] [ tt(-I) var(ignored-suffix) ])
xitem([ tt(-W) var(file-prefix) ])
xitem([ tt(-J) var(name) ] [ tt(-V) var(name) ] [ tt(-X) var(explanation) ])
xitem([ tt(-r) var(remove-chars) ] [ tt(-R) var(remove-func) ])
item([ tt(-M) var(match-spec) ] [ tt(--) ] [ var(words) ... ])(
@ -255,7 +279,7 @@ The completion code breaks the string to complete into six fields in
the order:
indent(
var(<ipre><apre><hpre><word><hsuf><asuf>)
var(<ipre><apre><hpre><word><hsuf><asuf><isuf>)
)
The first field
@ -273,7 +297,8 @@ appear in the list of completions, one of the tt(words) given at the
end. The field var(<hsuf>) is like var(<hpre>) but gives a suffix that
should be matched but will not be listed. Finally, var(<asuf>) is the
suffix given with tt(-S) that should automatically be added by the
completion code.
completion code and var(<isuf>) is like var(<ipre>), but taken from
the tt(ISUFFIX) parameter and the tt(-I) option.
The supported flags are:
@ -301,6 +326,9 @@ string given with the `tt(-P)' option. Without `tt(-P)' the string is
inserted before the string given with `tt(-p)' or directly before the
match.
)
item(tt(-I) var(ignored-suffix))(
Like tt(-i), but gives an ignored suffix.
)
item(tt(-J) var(name))(
As for tt(compctl) and tt(compgen) this gives the name of the group
of matches the words should be stored in.
@ -416,6 +444,87 @@ hyphens.
)
enditem()
)
xitem(tt(compset -p) var(number))
xitem(tt(compset -P) [ var(number) ] var(pattern))
xitem(tt(compset -s) var(number))
xitem(tt(compset -S) [ var(number) ] var(pattern))
xitem(tt(compset -n) var(begin) [ var(end) ])
item(tt(compset -p) var(beg-pat) [ var(end-pat) ])(
This builtin allows to easily modify the special parameters and at
the same time, to do tests on their values.
The options are:
startitem()
item(tt(-p) var(number))(
If the contents of the tt(PREFIX) parameter is longer than var(number)
characters, the first var(number) characters are removed from it and
appended to the contents of the tt(IPREFIX) parameter.
)
item(tt(-P) [ var(number) ] var(pattern))(
If the value of the tt(PREFIX) parameter begins with anything that
matches the var(pattern), the matched portion is removed from
tt(PREFIX) and appended to tt(IPREFIX).
Without the optional var(number), the longest match is taken, but
if var(number) is given, anything up to the var(number)'th match is
moved. If the var(number) is negative, the var(number)'th longest
match is moved. For example, if tt(PREFIX) contains the string
`tt(a=b=c)' doing tt(compset -P '*\=') will move the string `tt(a=b=)'
into the tt(IPREFIX) parameter, but tt(compset -P 1 '*\=') moves only
the string `tt(a=)'.
)
item(tt(-s) var(number))(
Like tt(-p), but prepend the last var(number) characters from the
parameter tt(SUFFIX) to the contents of the parameter tt(ISUFFIX).
)
item(tt(-S) [ var(number) ] var(pattern))(
Like tt(-P), but matching from the end of tt(SUFFIX) and moving the
matched portion into the parameter tt(ISUFFIX).
)
item(tt(-n) var(begin) [ var(end) ])(
If the current word position as specified by the parameter tt(CURRENT)
is greater than or equal to var(begin), anything up to the
var(begin)'th word is removed from the tt(words) array and the value
of the parameter tt(CURRENT) is decremented by var(begin).
If the optional var(end) is given, the modification is done only if
the current word position is also less than or equal to var(end). In
this case, the words from position var(end) onwards are removed from
the tt(words) array, too.
Both of these numbers may be negative to make them count backwards
from the last element of the tt(words) array.
)
item(tt(-N) var(beg-pat) [ var(end-pat) ])(
If one of the elements of the tt(words) array up to the one at the
index given by the value of the parameter tt(CURRENT) matches the
pattern var(beg-pat), all elements up to the matching one are removed
from the tt(words) array and the value of tt(CURRENT) is changed to
point to the same word in the changed array.
If the optional pattern var(end-pat) is also given and there is an
element in the tt(words) array matching this pattern, the parameters
are modified only if the index of this word is higher than the one
given by the tt(CURRENT) parameter (meaning that the matching word has
to be after the cursor). In this case, the words from the word
matching tt(end-pat) onwards are also removed from the tt(words)
array. If tt(words) contains no word matching var(end-pat), the
testing and modification is done as if it were not given.
)
enditem()
In all of these cases the return value is zero if the test succeded
and the parameters were modified, and non-zero otherwise. This allows
one to use this builtin in tests as in:
indent(
tt(if compset -P '*\='; then ...)
)
Which makes anything up to and including the last equal sign be
ignored by the completion code.
)
item(tt(compcall) [ tt(-TD) ])(
This allows one to use completion definitions given with the
@ -441,84 +550,26 @@ Inside completion widgets not only the builtin commands described
above can be used, but also some additional condition codes. These
work on the special parameters and can be used to easily build
completion functions that generate different matches depending on the
strings on the line.
strings on the line. All of these condition codes perform tests also
done by the tt(compset) builtin, but they don't modify the contents of
the special parameters.
The following condition codes are made available inside completion
widgets:
startitem()
item(tt(-prefix) var(string))(
true if the content of tt(PREFIX) starts with var(string)
item(tt(-prefix) [ var(number) ] var(pattern))(
true if the test for the tt(-P) option of tt(compset) would succeed
)
item(tt(-iprefix) var(string))(
like tt(-prefix), but the var(string) is removed from tt(PREFIX) and
added to tt(IPREFIX)
item(tt(-suffix) [ var(number) ] var(pattern))(
true if the test for the tt(-S) option of tt(compset) would succeed
)
item(tt(-position) var(beg) [ var(end) ])(
true if tt(CURRENT) is equal to var(beg) or, if var(end) is given,
equal to or greater than var(beg) and equal to or less than var(end);
both of var(beg) and var(end) may be arithmetic expressions, if they
are less than zero the number of words in tt(words) are added to them
before comparing them to tt(CURRENT); thus, tt(-1) is the last word,
tt(-2) is the word before that and so on; note that positions are
taken as indexes into the tt(words) array and thus are counted as if
the tt(ksharray) is not set
item(tt(-after) var(beg-pat))(
true if the test of the tt(-N) option with only the var(beg-pat) given
would succeed
)
item(tt(-word) var(index) var(string))(
true if the word number var(index) in tt(words) is equal to
var(string); again, var(index) may be negative, counting backwards
)
item(tt(-mword) var(index) var(pattern))(
like tt(-word) but using pattern matching
)
item(tt(-current) var(offset) var(string))(
like tt(-word) but var(offset) is relative to the value of
tt(CURRENT)
)
item(tt(-mcurrent) var(offset) var(pattern))(
like tt(-current) but using pattern matching
)
item(tt(-string) [ var(number) ] var(string))(
true if the current word contains var(string); anything up to the last
occurrence of this string will be ingnored by removing it from
tt(PREFIX) and adding it to tt(IPREFIX); if var(number) is given,
anything up to the var(number)'th occurrence of the var(string) will
be ignored; again, var(number) may be any arithmetic expression and
negative values count backward
)
item(tt(-class) [ var(number) ] var(class))(
like tt(-string) but the var(class) is used as a character class so
that anything up to and including the last or the var(number)'th
occurrence of any character from the string var(class) is ignored
)
item(tt(-words) var(min) [ var(max) ])(
true if the number of words is equal to var(min); if var(max) is
given, it is true if the number of words is equal to or greater than
var(min) and equal to or less than var(max)
)
item(tt(-after) var(string))(
true if the cursor is after a word that is equal to var(string); this
removes all words up to and including the matched word from the
tt(words) array
)
item(tt(-mafter) var(pattern))(
like tt(-after) but using pattern matching
)
item(tt(-between) var(string1) var(string2))(
true if the cursor is after a word that is equal to var(string1), if
there is also a word that is equal to var(string2), this is true only
if the cursor is before it; as a side effect, all words before
var(string1) and after var(string2) (both inclusive) are removed from
the tt(words) array
)
item(tt(-mbetween) var(pattern1) var(pattern2))(
like tt(-between) but using pattern matching
)
item(tt(-nmatches) var(number))(
true if the the value of tt(compstate[nmatches]) is equal to var(number)
)
item(tt(-matcher) var(number))(
true if the value of tt(compstate[matcher]) is equal to var(number)
item(tt(-between) var(beg-pat end-pat))(
true if the test for the tt(-N) option with both patterns would succeed
)
enditem()

View file

@ -329,7 +329,12 @@ item(tt(${)var(name)tt(}))(
The value, if any, of the parameter var(name) is substituted.
The braces are required if the expansion is to be followed by
a letter, digit, or underscore that is not to be interpreted
as part of var(name).
as part of var(name). In addition, more complicated forms of substitution
usually require the braces to be present; exceptions, which only apply if
the option tt(KSH_ARRAYS) is not set, are a single subscript or any colon
modifiers appearing after the name, or any of the characters tt(^), tt(=),
tt(~), tt(#) or tt(+) appearing before the name, all of which work with or
without braces.
If var(name) is an array parameter, then the value of each
element of var(name) is substituted, one element per word.
@ -492,14 +497,9 @@ tt($LPAR())...tt(RPAR()) type command substitution is used in place of
var(name) above, it is expanded first and the result is used as if
it were the value of var(name). Thus it is
possible to perform nested operations: tt(${${foo#head}%tail})
substitues the value of tt($foo) with both tt(head) and tt(tail)
substitutes the value of tt($foo) with both tt(head) and tt(tail)
deleted. The form with tt($LPAR())...tt(RPAR()) is often useful in
combination with the flags described next; see the example below.
Note that when nested parameter expansion takes place the flags are em(not)
propagated back. Each level of expansion uses three factors: whether it
is in double quotes, what flags it has been provided with, and whether the
value it has is a scalar or an array. Some examples are given below.
combination with the flags described next; see the examples below.
subsect(Parameter Expansion Flags)
cindex(parameter expansion flags)
@ -681,7 +681,7 @@ flag, or with tt(${)...tt(/)...tt(}) (only the var(expr)th match is
substituted) or tt(${)...tt(//)...tt(}) (all matches from the
var(expr)th on are substituted). The var(expr)th match is counted
such that there is either one or zero matches from each starting
position in the string, although for global subsitution matches
position in the string, although for global substitution matches
overlapping previous replacements are ignored.
)
item(tt(M))(
@ -703,57 +703,82 @@ enditem()
subsect(Rules)
Here is a summary of the rules for substitution. Some particular examples
are given below. Note that the Zsh Development Group accepts em(no
responsibility) for any brain damage which may occur during the reading of
the following rules.
Here is a summary of the rules for substitution; this assumes that braces
are present around the substitution, i.e. tt(${...}). Some particular
examples are given below. Note that the Zsh Development Group accepts
em(no responsibility) for any brain damage which may occur during the
reading of the following rules.
startitem()
item(tt(1.))(
item(tt(1.) em(Nested Substitution))(
If multiple nested tt(${...}) forms are present, substitution is
performed from the inside outwards. At each level, the substitution takes
account of whether the current value is a scalar or an array, whether the
whole substitution is in double quotes, and what flags are supplied to the
current level of substitution. If the value is a raw parameter reference
with a subscript, such as tt(${)var(var)tt([3]}), the effect of
subscripting is applied directly to the parameter. The value passed back
to an enclosing substitution is always an array, which however will consist
of one word if the value was not itself an array.
current level of substitution; the flags are not propagated up to enclosing
substitutions. The value passed back to an enclosing substitution is
always an array, which however will consist of one word if the value was
not itself an array. All the following steps take place where applicable
at all levels of substitution.
)
item(tt(2.))(
item(tt(2.) em(Parameter Subscripting))(
If the value is a raw parameter reference with a subscript, such as
tt(${)var(var)tt([3]}), the effect of subscripting is applied directly to
the parameter. If the parameter is an array, any second subscript,
indexing on the character in the word, may appear,
e.g. tt(${)var(var)tt([1][2]}).
)
item(tt(3.) em(Parameter Name Replacement))(
The effect of any tt((P)) flag, which treats the value so far as a
parameter name and replaces it with the corresponding value, is applied.
)
item(tt(4.) em(Double-Quoted Joining))(
If the value after this process is an array, and the substitution
appears in double quotes, and no tt((@)) flag is present at the current
level, the words of the value are joined with the first character of the
parameter tt($IFS), by default a space, between each word (single word
arrays are not modified). If the tt((j)) flag is present, that is used for
joining instead of tt($IFS). Any remaining subscript is evaluated at
this point, based on whether the value is an array or a scalar.
joining instead of tt($IFS).
)
item(tt(3.))(
item(tt(5.) em(Nested Subscripting))(
Any remaining subscript (i.e. of a nested substitution) is evaluated at
this point, based on whether the value is an array or a scalar; if it was
an array, a second subscript for the character in the word may also appear.
)
item(tt(6.) em(Modifiers))(
Any modifiers, as specified by a trailing tt(#), tt(%), tt(/)
(possibly doubled) or by a set of modifiers of the form tt(:...) (see
noderef(Modifiers) in noderef(History Expansion)), are applied to the words
of the value at this level.
)
item(tt(4.))(
item(tt(7.) em(Forced Joining))(
If the tt((j)) flag is present, or no tt((j)) flag is present but
the string is to be split as given by rules tt(5.) or tt(6.), and joining
did not take place at step tt(2.), any words in the value are joined
the string is to be split as given by rules tt(8.) or tt(9.), and joining
did not take place at step tt(4.), any words in the value are joined
together using the given string or the first character of tt($IFS) if none.
Note that the tt((F)) flag implicitly supplies a string for joining in this
manner.
)
item(tt(5.))(
item(tt(8.) em(Forced Splitting))(
If one of the tt((s)) or tt((f)) flags are present, or the tt(=)
specifier was present (e.g. tt(${=)var(var)tt(})), the word is joined on
specifier was present (e.g. tt(${=)var(var)tt(})), the word is split on
occurrences of the specified string, or (for tt(=) with neither of the two
flags present) any of the characters in tt($IFS).
)
item(tt(6.))(
item(tt(9.) em(Shell Word Splitting))(
If no tt((s)), tt((f)) or tt(=) was given, but the word is not
quoted and the option tt(SH_WORD_SPLIT) is set, the word is split on
occurrences of any of the characters in tt($IFS). Note that all steps,
including this one, take place at all levels of a nested substitution.
occurrences of any of the characters in tt($IFS). Note this step, too,
take place at all levels of a nested substitution.
)
item(tt(10.) em(Re-Evaluation))(
Any tt((e)) flag is applied to the value, forcing it to be re-examined for
new parameter substitutions, but also for command and arithmetic
substitutions.
)
item(tt(11.) em(Padding))(
Any padding of the value by the tt(LPAR()l.)var(fill)tt(.RPAR()) or
tt(LPAR()r.)var(fill)tt(.RPAR()) flags is applied.
)
enditem()
@ -1272,13 +1297,13 @@ item(tt(f)var(spec))(
files with access rights matching var(spec). This var(spec) may be a
octal number optionally preceded by a `tt(=)', a `tt(PLUS())', or a
`tt(-)'. If none of these characters is given, the behavior is the
same as for `tt(=)'. The octal number decribes the mode bits to be
same as for `tt(=)'. The octal number describes the mode bits to be
expected, if combined with a `tt(=)', the value given must match the
file-modes exactly, with a `tt(PLUS())', at least the bits in the
given number must be set in the file-modes, and with a `tt(-)', the
bits in the number must not be set. Giving a `tt(?)' instead of a
octal digit anywhere in the number ensures that the corresponding bits
inthe file-modes are not checked, this is only useful in combination
in the file-modes are not checked, this is only useful in combination
with `tt(=)'.
If the qualifier `tt(f)' is followed by any other character anything
@ -1290,7 +1315,7 @@ described above or a list of any of the characters `tt(u)', `tt(g)',
`tt(o)', and `tt(a)', followed by a `tt(=)', a `tt(PLUS())', or a
`tt(-)', followed by a list of any of the characters `tt(r)', `tt(w)',
`tt(x)', `tt(s)', and `tt(t)', or a octal digit. The first list of
characters specify which acess rights are to be checked. If a `tt(u)'
characters specify which access rights are to be checked. If a `tt(u)'
is given, those for the owner of the file are used, if a `tt(g)' is
given, those of the group are checked, a `tt(o)' means to test those
of other users, and the `tt(a)' says to test all three groups. The
@ -1308,7 +1333,7 @@ no rights, independent of the permissions for other user. The pattern
`tt(*(f-100))' gives all files for which the owner does not have
execute permission, and `tt(*(f:gu+w,o-rx))' gives the files for which
the owner and the other members of the group have at least write
permission, and fo which other users don't have read or execute
permission, and for which other users don't have read or execute
permission.
)
item(tt(d)var(dev))(

View file

@ -20,6 +20,13 @@ 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.
If the option tt(GLOBAL_RCS_FIRST) is set when the shell is invoked or in
the file tt(/etc/zshenv), then all the applicable global startup files are
read before all the users', so that the order becomes tt(/etc/zshenv)
... tt(/etc/zlogin), tt($ZDOTDIR/.zshenv) ... tt($ZDOTDIR/.zlogin).
After tt(/etc/zshenv) has been read, changing the option has no further
effect.
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 implict exit by reading

View file

@ -326,6 +326,16 @@ item(tt(GLOB) (tt(PLUS()F), ksh: tt(PLUS()f)))(
Perform filename generation (globbing).
(See noderef(Filename Generation).)
)
pindex(GLOBAL_RCS_FIRST)
cindex(startup files, changing order)
cindex(files, startup, changing order)
item(tt(GLOBAL_RCS_FIRST) (tt(-d)))(
If this option is set, and the tt(RCS) option is also set (as it is by
default), then the order in which startup files are sourced after
tt(/etc/zshenv) changes to tt(/etc/zprofile), tt(/etc/zshrc),
tt(/etc/zlogin), tt(.zshenv), tt(.zprofile), tt(.zshrc), tt(.zlogin).
The order of tt(.zlogout) and tt(/etc/zlogout) is not affected.
)
pindex(GLOB_ASSIGN)
item(tt(GLOB_ASSIGN))(
If this option is set, filename generation (globbing) is
@ -343,11 +353,11 @@ pindex(GLOB_COMPLETE)
item(tt(GLOB_COMPLETE))(
When the current word has a glob pattern, do not insert all the words
resulting from the expansion but generate matches as for completion and
cycle through them like tt(MENU_COMPLETE). If no matches are found, a
`tt(*)' is added to the end of the word or inserted at the cursor if
tt(COMPLETE_IN_WORD) is set, and completion is attempted again using
pattern matching. Since this doesn't use globbing, it works not only for
files but for all completions, such as options, user names, etc.
cycle through them like tt(MENU_COMPLETE). The matches are generated
as if a `tt(*)' is added to the end of the word or inserted at the cursor if
tt(COMPLETE_IN_WORD) is set. Since this doesn't use globbing, it
works not only for files but for all completions, such as options,
user names, etc.
)
pindex(GLOB_DOTS)
cindex(globbing, of . files)
@ -1049,6 +1059,7 @@ endsitem()
subsect(Also note)
startsitem()
sitem(tt(-A))(Used by tt(set) for setting arrays)
sitem(tt(-b))(Used on the command line to specify end of option processing)
sitem(tt(-c))(Used on the command line to specify a single command)
sitem(tt(-m))(Used by tt(setopt) for pattern-matching option setting)
sitem(tt(-o))(Used in all places to allow use of long option names)

View file

@ -158,6 +158,10 @@ vindex(NUMERIC)
item(tt(NUMERIC) (integer))(
The numeric argument.
)
vindex(HISTNO)
item(tt(HISTNO) (integer))(
The current history number.
)
enditem()
sect(Standard Widgets)
cindex(widgets, standard)

View file

@ -391,7 +391,7 @@ zfpipe()
/**/
static void
zfunalarm()
zfunalarm(void)
{
if (oalremain) {
/*
@ -670,7 +670,7 @@ zfgetline(char *ln, int lnsize, int tmout)
/**/
static int
zfgetmsg()
zfgetmsg(void)
{
char line[256], *ptr, *verbose;
int stopit, printing = 0, tmout;

View file

@ -36,7 +36,6 @@ typedef struct patcomp *Patcomp;
typedef struct cmatcher *Cmatcher;
typedef struct cmlist *Cmlist;
typedef struct cpattern *Cpattern;
typedef struct cline *Cline;
/* node for compctl hash table (compctltab) */
@ -203,6 +202,7 @@ struct cmatch {
char *str; /* the match itself */
char *ipre; /* ignored prefix, has to be re-inserted */
char *ripre; /* ignored prefix, unquoted */
char *isuf; /* ignored suffix */
char *ppre; /* the path prefix */
char *psuf; /* the path suffix */
char *prpre; /* path prefix for opendir */
@ -255,28 +255,6 @@ struct cpattern {
int equiv; /* if this is a {...} class */
};
struct cline {
Cline next; /* next chunk */
char *line; /* string to insert if !word */
int llen; /* length of line */
char *word; /* prefered string to insert */
int wlen; /* length of word */
int flags; /* see CLF_* below */
Cline prefix; /* prefix we've build for new parts */
Cline suffix; /* suffix we've build for new parts */
};
#define CLF_END 1
#define CLF_MID 2
#define CLF_MISS 4
#define CLF_DIFF 8
#define CLF_SUF 16
#define CLF_PNEW 32
#define CLF_SNEW 64
#define CLF_VAR 128
#define CLF_JOIN 256
/* Flags for makecomplist*(). Things not to do. */
#define CFN_FIRST 1
@ -296,27 +274,31 @@ struct cline {
#define CP_PREFIX (1 << 2)
#define CP_SUFFIX (1 << 3)
#define CP_IPREFIX (1 << 4)
#define CP_COMPSTATE (1 << 5)
#define CP_ISUFFIX (1 << 5)
#define CP_COMPSTATE (1 << 6)
#define CP_REALPARAMS 6
#define CP_REALPARAMS 7
#define CP_NMATCHES (1 << 6)
#define CP_MATCHER (1 << 7)
#define CP_MATCHERSTR (1 << 8)
#define CP_MATCHERTOT (1 << 9)
#define CP_CONTEXT (1 << 10)
#define CP_PARAMETER (1 << 11)
#define CP_REDIRECT (1 << 12)
#define CP_QUOTE (1 << 13)
#define CP_QUOTING (1 << 14)
#define CP_RESTORE (1 << 15)
#define CP_LIST (1 << 16)
#define CP_FORCELIST (1 << 17)
#define CP_INSERT (1 << 18)
#define CP_EXACT (1 << 19)
#define CP_EXACTSTR (1 << 20)
#define CP_PATMATCH (1 << 21)
#define CP_NMATCHES (1 << 7)
#define CP_MATCHER (1 << 8)
#define CP_MATCHERSTR (1 << 9)
#define CP_MATCHERTOT (1 << 10)
#define CP_CONTEXT (1 << 11)
#define CP_PARAMETER (1 << 12)
#define CP_REDIRECT (1 << 13)
#define CP_QUOTE (1 << 14)
#define CP_QUOTING (1 << 15)
#define CP_RESTORE (1 << 16)
#define CP_LIST (1 << 17)
#define CP_FORCELIST (1 << 18)
#define CP_INSERT (1 << 19)
#define CP_EXACT (1 << 20)
#define CP_EXACTSTR (1 << 21)
#define CP_PATMATCH (1 << 22)
#define CP_PATINSERT (1 << 23)
#define CP_UNAMBIG (1 << 24)
#define CP_UNAMBIGC (1 << 25)
#define CP_NUM 22
#define CP_NUM 26
#define CP_ALLMASK ((1 << CP_NUM) - 1)

View file

@ -52,10 +52,10 @@ void (*comp_setunsetptr) _((int, int));
/* pointers to functions required by compctl and defined by zle */
/**/
int (*addmatchesptr) _((char *, char *, char *, char *, char *, char *, char *, char *, char *, char *, int, int, Cmatcher, char *, char **));
int (*addmatchesptr) _((char *, char *, char *, char *, char *, char *, char *, char *, char *, char *, char *, int, int, Cmatcher, char *, char **));
/**/
char *(*comp_strptr) _((int*, int*, int));
char *(*comp_strptr) _((int *, int *, int));
/**/
int (*getcpatptr) _((char *, int, char *, int));
@ -66,6 +66,9 @@ int (*makecomplistcallptr) _((Compctl));
/**/
int (*makecomplistctlptr) _((int));
/**/
char *(*unambig_dataptr) _((int *));
/* Hash table for completion info for commands */
/**/
@ -107,6 +110,7 @@ char **compwords,
*compprefix,
*compsuffix,
*compiprefix,
*compisuffix,
*compmatcherstr,
*compcontext,
*compparameter,
@ -119,7 +123,8 @@ char **compwords,
*compinsert,
*compexact,
*compexactstr,
*comppatmatch;
*comppatmatch,
*comppatinsert;
/**/
Param *comppms;
@ -430,10 +435,11 @@ setup_comp1(Module m)
cc_first.mask2 = CC_CCCONT;
comppms = NULL;
compwords = NULL;
compprefix = compsuffix = compiprefix = compmatcherstr =
compprefix = compsuffix = compiprefix = compisuffix = compmatcherstr =
compcontext = compparameter = compredirect = compquote =
compquoting = comprestore = complist = compinsert =
compexact = compexactstr = comppatmatch = compforcelist = NULL;
compexact = compexactstr = comppatmatch = comppatinsert =
compforcelist = NULL;
makecompparamsptr = NULL;
comp_setunsetptr = NULL;
return 0;
@ -466,6 +472,7 @@ finish_comp1(Module m)
zsfree(compprefix);
zsfree(compsuffix);
zsfree(compiprefix);
zsfree(compisuffix);
zsfree(compmatcherstr);
zsfree(compcontext);
zsfree(compparameter);
@ -479,6 +486,7 @@ finish_comp1(Module m)
zsfree(compexact);
zsfree(compexactstr);
zsfree(comppatmatch);
zsfree(comppatinsert);
return 0;
}

View file

@ -18,12 +18,14 @@ compexactstr
compforcelist
compinsert
compiprefix
compisuffix
complist
compmatcher
compmatcherstr
compmatchertot
compnmatches
compparameter
comppatinsert
comppatmatch
comppms
compprefix
@ -48,3 +50,4 @@ makecomplistctlptr
makecompparamsptr
patcomps
rembslash
unambig_dataptr

View file

@ -1406,7 +1406,7 @@ printcompctl(char *s, Compctl cc, int printflags, int ispat)
untokenize(p);
quotedzputs(p, stdout);
} else
quotedzputs(bslashquote(s, NULL, NULL, NULL, 0), stdout);
quotedzputs(bslashquote(s, NULL, 0), stdout);
}
/* loop through flags w/o args that are set, printing them if so */
@ -1537,7 +1537,7 @@ printcompctl(char *s, Compctl cc, int printflags, int ispat)
char *p = dupstring(s);
untokenize(p);
quotedzputs(bslashquote(p, NULL, NULL, NULL, 0), stdout);
quotedzputs(bslashquote(p, NULL, 0), stdout);
}
}
putchar('\n');
@ -1692,7 +1692,7 @@ static int
bin_compadd(char *name, char **argv, char *ops, int func)
{
char *p, **sp, *e;
char *ipre = NULL, *ppre = NULL, *psuf = NULL, *prpre = NULL;
char *ipre = NULL, *isuf = NULL, *ppre = NULL, *psuf = NULL, *prpre = NULL;
char *pre = NULL, *suf = NULL, *group = NULL, *m = NULL, *rs = NULL;
char *ign = NULL, *rf = NULL, *expl = NULL;
int f = 0, a = CAF_MATCH, dm;
@ -1753,6 +1753,10 @@ bin_compadd(char *name, char **argv, char *ops, int func)
sp = &ipre;
e = "string expected after -%c";
break;
case 'I':
sp = &isuf;
e = "string expected after -%c";
break;
case 'p':
sp = &ppre;
e = "string expected after -%c";
@ -1821,13 +1825,286 @@ bin_compadd(char *name, char **argv, char *ops, int func)
return 1;
match = cpcmatcher(match);
a = addmatchesptr(ipre, ppre, psuf, prpre, pre, suf, group,
a = addmatchesptr(ipre, isuf, ppre, psuf, prpre, pre, suf, group,
rs, rf, ign, f, a, match, expl, argv);
freecmatcher(match);
return a;
}
#define CVT_RANGENUM 0
#define CVT_RANGEPAT 1
#define CVT_PRENUM 2
#define CVT_PREPAT 3
#define CVT_SUFNUM 4
#define CVT_SUFPAT 5
static void
ignore_prefix(int l)
{
char *tmp, sav = compprefix[l];
compprefix[l] = '\0';
tmp = tricat(compiprefix, compprefix, "");
zsfree(compiprefix);
compiprefix = tmp;
compprefix[l] = sav;
tmp = ztrdup(compprefix + l);
zsfree(compprefix);
compprefix = tmp;
}
static void
ignore_suffix(int l)
{
char *tmp, sav;
l = strlen(compsuffix) - l;
tmp = tricat(compsuffix + l, compisuffix, "");
zsfree(compisuffix);
compisuffix = tmp;
sav = compsuffix[l];
compsuffix[l] = '\0';
tmp = ztrdup(compsuffix);
compsuffix[l] = sav;
zsfree(compsuffix);
compsuffix = tmp;
}
/**/
static void
restrict_range(int b, int e)
{
int i = e - b + 1;
char **p = (char **) zcalloc((i + 1) * sizeof(char *)), **q, **pp;
for (q = p, pp = compwords + b; i; i--, q++, pp++)
*q = ztrdup(*pp);
freearray(compwords);
compwords = p;
compcurrent -= b;
}
static int
do_comp_vars(int test, int na, char *sa, int nb, char *sb, int mod)
{
switch (test) {
case CVT_RANGENUM:
{
int l = arrlen(compwords);
if (na < 0)
na += l;
else
na--;
if (nb < 0)
nb += l;
else
nb--;
if (compcurrent - 1 < na || compcurrent - 1 > nb)
return 0;
restrict_range(na, nb);
return 1;
}
case CVT_RANGEPAT:
{
char **p;
int i, l = arrlen(compwords), t = 0, b = 0, e = l - 1;
Comp c;
i = compcurrent - 1;
if (i < 0 || i >= l)
return 0;
singsub(&sa);
c = parsereg(sa);
for (i--, p = compwords + i; i >= 0; p--, i--) {
if (domatch(*p, c, 0)) {
b = i + 1;
t = 1;
break;
}
}
if (t && sb) {
int tt = 0;
singsub(&sb);
c = parsereg(sb);
for (i++, p = compwords + i; i < l; p++, i++) {
if (domatch(*p, c, 0)) {
e = i - 1;
tt = 1;
break;
}
}
if (tt && i < compcurrent)
t = 0;
}
if (e < b)
t = 0;
if (t)
restrict_range(b, e);
return t;
}
case CVT_PRENUM:
case CVT_SUFNUM:
if (!na)
return 1;
if (na > 0 &&
strlen(test == CVT_PRENUM ? compprefix : compsuffix) >= na) {
if (mod) {
if (test == CVT_PRENUM)
ignore_prefix(na);
else
ignore_suffix(na);
return 1;
}
return 0;
}
case CVT_PREPAT:
case CVT_SUFPAT:
{
Comp c;
if (!na)
return 0;
if (!(c = parsereg(sa)))
return 0;
if (test == CVT_PREPAT) {
int l, add;
char *p, sav;
if (!(l = strlen(compprefix)))
return 0;
if (na < 0) {
p = compprefix + l;
na = -na;
add = -1;
} else {
p = compprefix + 1;
add = 1;
}
for (; l; l--, p += add) {
sav = *p;
*p = '\0';
test = domatch(compprefix, c, 0);
*p = sav;
if (test && !--na)
break;
}
if (!l)
return 0;
ignore_prefix(p - compprefix);
} else {
int l, ol, add;
char *p;
if (!(ol = l = strlen(compsuffix)))
return 0;
if (na < 0) {
p = compsuffix;
na = -na;
add = 1;
} else {
p = compsuffix + l - 1;
add = -1;
}
for (; l; l--, p += add)
if (domatch(p, c, 0) && !--na)
break;
if (!l)
return 0;
ignore_suffix(ol - (p - compsuffix));
}
return 1;
}
}
return 0;
}
/**/
static int
bin_compset(char *name, char **argv, char *ops, int func)
{
int test = 0, na = 0, nb = 0;
char *sa = NULL, *sb = NULL;
if (incompfunc != 1) {
zerrnam(name, "can only be called from completion function", NULL, 0);
return 1;
}
if (argv[0][0] != '-') {
zerrnam(name, "missing option", NULL, 0);
return 1;
}
switch (argv[0][1]) {
case 'n': test = CVT_RANGENUM; break;
case 'N': test = CVT_RANGEPAT; break;
case 'p': test = CVT_PRENUM; break;
case 'P': test = CVT_PREPAT; break;
case 's': test = CVT_SUFNUM; break;
case 'S': test = CVT_SUFPAT; break;
default:
zerrnam(name, "bad option -%c", NULL, argv[0][1]);
return 1;
}
if (argv[0][2]) {
sa = argv[0] + 2;
sb = argv[1];
na = 2;
} else {
if (!(sa = argv[1])) {
zerrnam(name, "missing string for option -%c", NULL, argv[0][1]);
return 1;
}
sb = argv[2];
na = 3;
}
if (((test == CVT_PRENUM || test == CVT_SUFNUM) ? !!sb :
(sb && argv[na]))) {
zerrnam(name, "too many arguments", NULL, 0);
return 1;
}
switch (test) {
case CVT_RANGENUM:
na = atoi(sa);
nb = (sb ? atoi(sb) : -1);
break;
case CVT_RANGEPAT:
tokenize(sa);
sa = rembslash(sa);
if (sb) {
tokenize(sb);
sb = rembslash(sb);
}
break;
case CVT_PRENUM:
case CVT_SUFNUM:
na = atoi(sa);
break;
case CVT_PREPAT:
case CVT_SUFPAT:
if (sb) {
na = atoi(sa);
sa = sb;
} else
na = -1;
tokenize(sa);
sa = rembslash(sa);
break;
}
return !do_comp_vars(test, na, sa, nb, sb, 1);
}
/**/
static int
bin_compcall(char *name, char **argv, char *ops, int func)
@ -1843,36 +2120,40 @@ bin_compcall(char *name, char **argv, char *ops, int func)
/* Definitions for the special parameters. Note that these have to match the
* order of the CP_* bits in comp.h */
#define VAR(X) ((void *) (&(X)))
#define VAL(X) ((void *) (&(X)))
static struct compparam {
char *name;
int type;
void *var;
void *var, *set, *get;
} compparams[] = {
{ "words", PM_ARRAY, VAR(compwords) },
{ "CURRENT", PM_INTEGER, VAR(compcurrent) },
{ "PREFIX", PM_SCALAR, VAR(compprefix) },
{ "SUFFIX", PM_SCALAR, VAR(compsuffix) },
{ "IPREFIX", PM_SCALAR, VAR(compiprefix) },
{ NULL, 0, NULL },
{ "words", PM_ARRAY, VAL(compwords), NULL, NULL },
{ "CURRENT", PM_INTEGER, VAL(compcurrent), NULL, NULL },
{ "PREFIX", PM_SCALAR, VAL(compprefix), NULL, NULL },
{ "SUFFIX", PM_SCALAR, VAL(compsuffix), NULL, NULL },
{ "IPREFIX", PM_SCALAR, VAL(compiprefix), NULL, NULL },
{ "ISUFFIX", PM_SCALAR, VAL(compisuffix), NULL, NULL },
{ NULL, 0, NULL, NULL, NULL },
{ "nmatches", PM_INTEGER, VAR(compnmatches) },
{ "matcher", PM_INTEGER, VAR(compmatcher) },
{ "matcher_string", PM_SCALAR, VAR(compmatcherstr) },
{ "total_matchers", PM_INTEGER, VAR(compmatchertot) },
{ "context", PM_SCALAR, VAR(compcontext) },
{ "parameter", PM_SCALAR, VAR(compparameter) },
{ "redirect", PM_SCALAR, VAR(compredirect) },
{ "quote", PM_SCALAR, VAR(compquote) },
{ "quoting", PM_SCALAR, VAR(compquoting) },
{ "restore", PM_SCALAR, VAR(comprestore) },
{ "list", PM_SCALAR, VAR(complist) },
{ "force_list", PM_SCALAR, VAR(compforcelist) },
{ "insert", PM_SCALAR, VAR(compinsert) },
{ "exact", PM_SCALAR, VAR(compexact) },
{ "exact_string", PM_SCALAR, VAR(compexactstr) },
{ "pattern_match", PM_SCALAR, VAR(comppatmatch) },
{ NULL, 0, NULL }
{ "nmatches", PM_INTEGER, VAL(compnmatches), NULL, NULL },
{ "matcher", PM_INTEGER, VAL(compmatcher), NULL, NULL },
{ "matcher_string", PM_SCALAR, VAL(compmatcherstr), NULL, NULL },
{ "total_matchers", PM_INTEGER, VAL(compmatchertot), NULL, NULL },
{ "context", PM_SCALAR, VAL(compcontext), NULL, NULL },
{ "parameter", PM_SCALAR, VAL(compparameter), NULL, NULL },
{ "redirect", PM_SCALAR, VAL(compredirect), NULL, NULL },
{ "quote", PM_SCALAR, VAL(compquote), NULL, NULL },
{ "quoting", PM_SCALAR, VAL(compquoting), NULL, NULL },
{ "restore", PM_SCALAR, VAL(comprestore), NULL, NULL },
{ "list", PM_SCALAR, VAL(complist), NULL, NULL },
{ "force_list", PM_SCALAR, VAL(compforcelist), NULL, NULL },
{ "insert", PM_SCALAR, VAL(compinsert), NULL, NULL },
{ "exact", PM_SCALAR, VAL(compexact), NULL, NULL },
{ "exact_string", PM_SCALAR, VAL(compexactstr), NULL, NULL },
{ "pattern_match", PM_SCALAR, VAL(comppatmatch), NULL, NULL },
{ "pattern_insert", PM_SCALAR, VAL(comppatinsert), NULL, NULL },
{ "unambiguous", PM_SCALAR | PM_READONLY, NULL, NULL, VAL(get_unambig) },
{ "unambiguous_cursor", PM_INTEGER | PM_READONLY, NULL, NULL, VAL(get_unambig_curs) },
{ NULL, 0, NULL, NULL, NULL }
};
#define COMPSTATENAME "compstate"
@ -1883,28 +2164,32 @@ addcompparams(struct compparam *cp)
Param *pp = comppms + (cp - compparams);
for (; cp->name; cp++, pp++) {
Param pm = createparam(cp->name, cp->type | PM_SPECIAL|PM_REMOVABLE);
Param pm = createparam(cp->name, cp->type | PM_SPECIAL | PM_REMOVABLE);
if (!pm)
pm = (Param) paramtab->getnode(paramtab, cp->name);
DPUTS(!pm, "param not set in addcompparams");
*pp = pm;
pm->level = locallevel;
pm->u.data = cp->var;
switch(PM_TYPE(cp->type)) {
case PM_SCALAR:
pm->sets.cfn = strvarsetfn;
pm->gets.cfn = strvargetfn;
break;
case PM_INTEGER:
pm->sets.ifn = intvarsetfn;
pm->gets.ifn = intvargetfn;
pm->ct = 10;
break;
case PM_ARRAY:
pm->sets.afn = arrvarsetfn;
pm->gets.afn = arrvargetfn;
break;
if ((pm->u.data = cp->var)) {
switch(PM_TYPE(cp->type)) {
case PM_SCALAR:
pm->sets.cfn = strvarsetfn;
pm->gets.cfn = strvargetfn;
break;
case PM_INTEGER:
pm->sets.ifn = intvarsetfn;
pm->gets.ifn = intvargetfn;
pm->ct = 10;
break;
case PM_ARRAY:
pm->sets.afn = arrvarsetfn;
pm->gets.afn = arrvargetfn;
break;
}
} else {
pm->sets.cfn = (void (*) _((Param, char *))) cp->set;
pm->gets.cfn = (char *(*) _((Param))) cp->get;
}
pm->unsetfn = compunsetfn;
}
@ -1975,6 +2260,24 @@ set_compstate(Param pm, HashTable ht)
}
}
/**/
static char *
get_unambig(Param pm)
{
return unambig_dataptr(NULL);
}
/**/
static long
get_unambig_curs(Param pm)
{
int c;
unambig_dataptr(&c);
return c;
}
/**/
static void
compunsetfn(Param pm, int exp)
@ -2017,7 +2320,7 @@ comp_wrapper(List list, FuncWrap w, char *name)
if (incompfunc != 1)
return 1;
else {
char *orest, *opre, *osuf, *oipre, **owords;
char *orest, *opre, *osuf, *oipre, *oisuf, **owords;
long ocur;
int unset = 0, m, sm;
Param *pp;
@ -2034,6 +2337,7 @@ comp_wrapper(List list, FuncWrap w, char *name)
opre = dupstring(compprefix);
osuf = dupstring(compsuffix);
oipre = dupstring(compiprefix);
oisuf = dupstring(compisuffix);
HEAPALLOC {
owords = arrdup(compwords);
@ -2049,6 +2353,8 @@ comp_wrapper(List list, FuncWrap w, char *name)
compsuffix = ztrdup(osuf);
zsfree(compiprefix);
compiprefix = ztrdup(oipre);
zsfree(compisuffix);
compisuffix = ztrdup(oisuf);
freearray(compwords);
PERMALLOC {
compwords = arrdup(owords);
@ -2067,22 +2373,6 @@ comp_wrapper(List list, FuncWrap w, char *name)
}
}
/**/
static void
ignore_prefix(int l)
{
char *o, sav = compprefix[l];
compprefix[l] = '\0';
o = compiprefix;
compiprefix = tricat(o, compprefix, "");
zsfree(o);
compprefix[l] = sav;
o = compprefix;
compprefix = ztrdup(o + l);
zsfree(o);
}
/**/
static int
comp_check(void)
@ -2094,133 +2384,16 @@ comp_check(void)
return 1;
}
/**/
static void
restrict_range(int b, int e)
{
int i = e - b + 1;
char **p = (char **) zcalloc((i + 1) * sizeof(char *)), **q, **pp;
for (q = p, pp = compwords + b; i; i--, q++, pp++)
*q = ztrdup(*pp);
freearray(compwords);
compwords = p;
compcurrent -= b;
}
/**/
static int
cond_prefix(char **a, int id)
{
if (comp_check())
return strpfx(cond_str(a, 0), compprefix);
return 0;
}
/**/
static int
cond_iprefix(char **a, int id)
cond_psfix(char **a, int id)
{
if (comp_check()) {
char *s = cond_str(a, 0);
if (strpfx(s, compprefix)) {
ignore_prefix(strlen(s));
return 1;
}
}
return 0;
}
/**/
static int
cond_position(char **a, int id)
{
if (comp_check()) {
int b = cond_val(a, 0), e = (a[1] ? cond_val(a, 1) : b);
int l = arrlen(compwords), t, i = compcurrent - 1;
if (b > 0)
b--;
if (e > 0)
e--;
if (b < 0)
b += l;
if (e < 0)
e += l;
t = (b >= 0 && e >= 0 && i >= b && i <= e && b <= e);
if (t && a[1]) {
if (b > l)
b = l;
if (e > l)
e = l;
restrict_range(b, e);
}
return t;
}
return 0;
}
/**/
static int
cond_word(char **a, int id)
{
if (comp_check()) {
int o = ((id & 2) ? compcurrent : 0) + cond_val(a, 0);
int l = arrlen(compwords);
char *s;
if (o < 0)
o += l;
o--;
if (o < 0 || o >= l)
return 0;
s = compwords[o];
return ((id & 1) ? cond_match(a, 1, s) : !strcmp(s, cond_str(a, 1)));
}
return 0;
}
/**/
static int
cond_strcl(char **a, int id)
{
if (comp_check()) {
char *s;
int i, ipl;
if (a[1]) {
s = cond_str(a, 1);
i = cond_val(a, 0);
} else {
s = cond_str(a, 0);
i = -1;
}
if (!getcpatptr) {
zerr("zle not loaded, zle condition not available", NULL, 0);
return 1;
}
i = getcpatptr(comp_strptr(&ipl, NULL, 1), i, s, id);
if (i != -1 && i >= ipl) {
ignore_prefix(i - ipl);
return 1;
}
}
return 0;
}
/**/
static int
cond_words(char **a, int id)
{
if (comp_check()) {
int b = cond_val(a, 0), e = (a[1] ? cond_val(a, 1) : -1);
int l = arrlen(compwords);
return (l >= b && l <= e);
if (a[1])
return do_comp_vars(id, cond_val(a, 0), cond_str(a, 1),
0, NULL, 0);
else
return do_comp_vars(id, -1, cond_str(a, 0), 0, NULL, 0);
}
return 0;
}
@ -2229,100 +2402,23 @@ cond_words(char **a, int id)
static int
cond_range(char **a, int id)
{
if (comp_check()) {
char *s, **p;
int i, l = arrlen(compwords), t = 0, b = 0, e = l - 1;
Comp c = NULL;
i = compcurrent - 1;
if (i < 0 || i >= l)
return 0;
if (id & 1) {
s = a[0];
singsub(&s);
c = parsereg(s);
} else
s = cond_str(a, 0);
for (i--, p = compwords + i; i >= 0; p--, i--) {
if (((id & 1) ? domatch(*p, c, 0) : !strcmp(*p, s))) {
b = i + 1;
t = 1;
break;
}
}
if (t && (id & 2)) {
int tt = 0;
if (id & 1) {
s = a[1];
singsub(&s);
c = parsereg(s);
} else
s = cond_str(a, 1);
for (i++, p = compwords + i; i < l; p++, i++) {
if (((id & 1) ? domatch(*p, c, 0) : !strcmp(*p, s))) {
e = i - 1;
tt = 1;
break;
}
}
if (tt && i < compcurrent)
t = 0;
}
if (e < b)
t = 0;
if (t)
restrict_range(b, e);
return t;
}
return 0;
}
/**/
static int
cond_nmatches(char **a, int id)
{
if (comp_check())
return compnmatches == cond_val(a, 0);
return 0;
}
/**/
static int
cond_matcher(char **a, int id)
{
if (comp_check())
return compmatcher == cond_val(a, 0);
return 0;
return do_comp_vars(CVT_RANGEPAT, 0, cond_str(a, 0), 0,
(id ? cond_str(a, 1) : NULL), 0);
}
static struct builtin bintab[] = {
BUILTIN("compctl", 0, bin_compctl, 0, -1, 0, NULL, NULL),
BUILTIN("compgen", 0, bin_compgen, 1, -1, 0, NULL, NULL),
BUILTIN("compadd", 0, bin_compadd, 0, -1, 0, NULL, NULL),
BUILTIN("compset", 0, bin_compset, 1, 3, 0, NULL, NULL),
BUILTIN("compcall", 0, bin_compcall, 0, 0, 0, "TD", NULL),
};
static struct conddef cotab[] = {
CONDDEF("prefix", 0, cond_prefix, 1, 1, 0),
CONDDEF("iprefix", 0, cond_iprefix, 1, 1, 0),
CONDDEF("position", 0, cond_position, 1, 2, 0),
CONDDEF("word", 0, cond_word, 2, 2, 0),
CONDDEF("mword", 0, cond_word, 2, 2, 1),
CONDDEF("current", 0, cond_word, 2, 2, 2),
CONDDEF("mcurrent", 0, cond_word, 2, 2, 3),
CONDDEF("string", 0, cond_strcl, 1, 2, 0),
CONDDEF("class", 0, cond_strcl, 1, 2, 1),
CONDDEF("words", 0, cond_words, 1, 2, 0),
CONDDEF("between", 0, cond_range, 2, 2, 2),
CONDDEF("mbetween", 0, cond_range, 2, 2, 3),
CONDDEF("prefix", 0, cond_psfix, 1, 2, CVT_PREPAT),
CONDDEF("suffix", 0, cond_psfix, 1, 2, CVT_SUFPAT),
CONDDEF("between", 0, cond_range, 2, 2, 1),
CONDDEF("after", 0, cond_range, 1, 1, 0),
CONDDEF("mafter", 0, cond_range, 1, 1, 1),
CONDDEF("nmatches", 0, cond_nmatches, 1, 1, 0),
CONDDEF("matcher", 0, cond_matcher, 1, 1, 0),
};
static struct funcwrap wrapper[] = {

View file

@ -1,7 +1,7 @@
moddeps="comp1"
autobins="compctl complist compadd"
autobins="compctl complist compadd compset"
autoprefixconds="prefix iprefix position word mword current mcurrent string class words between mbetween after mafter nmatches"
autoprefixconds="prefix suffix between after"
objects="compctl.o"

View file

@ -918,6 +918,7 @@ setup_zle(Module m)
getcpatptr = getcpat;
makecomplistcallptr = makecomplistcall;
makecomplistctlptr = makecomplistctl;
unambig_dataptr = unambig_data;
/* initialise the thingies */
init_thingies();
@ -989,6 +990,7 @@ finish_zle(Module m)
getcpatptr = NULL;
makecomplistcallptr = NULL;
makecomplistctlptr = NULL;
unambig_dataptr = NULL;
return 0;
}

View file

@ -30,7 +30,7 @@
#include "zle.mdh"
#include "zle_move.pro"
static vimarkcs[27], vimarkline[27];
static int vimarkcs[27], vimarkline[27];
/**/
void

View file

@ -67,7 +67,9 @@ static struct zleparam {
zleunsetfn, NULL },
{ "keys", PM_ARRAY | PM_READONLY, NULL, FN(get_keys),
zleunsetfn, NULL },
{ "NUMERIC", PM_INTEGER | PM_READONLY, FN(set_numeric), FN(get_numeric),
{ "NUMERIC", PM_INTEGER, FN(set_numeric), FN(get_numeric),
zleunsetfn, NULL },
{ "HISTNO", PM_INTEGER | PM_READONLY, NULL, FN(get_histno),
zleunsetfn, NULL },
{ NULL, 0, NULL, NULL, NULL, NULL }
};
@ -261,3 +263,10 @@ get_numeric(Param pm)
{
return zmult;
}
/**/
static long
get_histno(Param pm)
{
return histline;
}

View file

@ -492,7 +492,7 @@ bin_zle_complete(char *name, char **args, char *ops, char func)
t = rthingy(args[1]);
cw = t->widget;
unrefthingy(t);
if (!(cw->flags & ZLE_ISCOMP)) {
if (!cw || !(cw->flags & ZLE_ISCOMP)) {
zerrnam(name, "invalid widget `%s'", args[1], 0);
return 1;
}

File diff suppressed because it is too large Load diff

View file

@ -583,7 +583,7 @@ compalloc(void)
/**/
static int
getglobflags()
getglobflags(void)
{
char *nptr;
/* (#X): assumes we are still positioned on the initial '(' */

View file

@ -757,25 +757,43 @@ run_init_scripts(void)
source(GLOBAL_ZSHENV);
#endif
if (isset(RCS)) {
int globalfirst = isset(GLOBALRCSFIRST);
if (globalfirst) {
#ifdef GLOBAL_ZPROFILE
if (islogin)
source(GLOBAL_ZPROFILE);
#endif
#ifdef GLOBAL_ZSHRC
if (interact)
source(GLOBAL_ZSHRC);
#endif
#ifdef GLOBAL_ZLOGIN
if (islogin)
source(GLOBAL_ZLOGIN);
#endif
}
if (unset(PRIVILEGED))
sourcehome(".zshenv");
if (islogin) {
#ifdef GLOBAL_ZPROFILE
source(GLOBAL_ZPROFILE);
if (!globalfirst)
source(GLOBAL_ZPROFILE);
#endif
if (unset(PRIVILEGED))
sourcehome(".zprofile");
}
if (interact) {
#ifdef GLOBAL_ZSHRC
source(GLOBAL_ZSHRC);
if (!globalfirst)
source(GLOBAL_ZSHRC);
#endif
if (unset(PRIVILEGED))
sourcehome(".zshrc");
}
if (islogin) {
#ifdef GLOBAL_ZLOGIN
source(GLOBAL_ZLOGIN);
if (!globalfirst)
source(GLOBAL_ZLOGIN);
#endif
if (unset(PRIVILEGED))
sourcehome(".zlogin");

View file

@ -114,6 +114,7 @@ static struct optname optns[] = {
{NULL, "flowcontrol", OPT_ALL, FLOWCONTROL},
{NULL, "functionargzero", OPT_EMULATE|OPT_NONBOURNE, FUNCTIONARGZERO},
{NULL, "glob", OPT_ALL, GLOBOPT},
{NULL, "globalrcsfirst", 0, GLOBALRCSFIRST},
{NULL, "globassign", OPT_EMULATE|OPT_CSH, GLOBASSIGN},
{NULL, "globcomplete", 0, GLOBCOMPLETE},
{NULL, "globdots", 0, GLOBDOTS},
@ -228,7 +229,7 @@ static short zshletters[LAST_OPT - FIRST_OPT + 1] = {
/* > */ 0,
/* ? */ 0,
/* @ */ 0,
/* A */ 0,
/* A */ 0, /* use with set for arrays */
/* B */ -BEEP,
/* C */ -CLOBBER,
/* D */ PUSHDTOHOME,
@ -261,9 +262,9 @@ static short zshletters[LAST_OPT - FIRST_OPT + 1] = {
/* _ */ 0,
/* ` */ 0,
/* a */ ALLEXPORT,
/* b */ 0,
/* c */ 0,
/* d */ 0,
/* b */ 0, /* in non-Bourne shells, end of options */
/* c */ 0, /* command follows */
/* d */ GLOBALRCSFIRST,
/* e */ ERREXIT,
/* f */ -RCS,
/* g */ HISTIGNORESPACE,
@ -274,7 +275,7 @@ static short zshletters[LAST_OPT - FIRST_OPT + 1] = {
/* l */ LOGINSHELL,
/* m */ MONITOR,
/* n */ -EXECOPT,
/* o */ 0,
/* o */ 0, /* long option name follows */
/* p */ PRIVILEGED,
/* q */ 0,
/* r */ RESTRICTED,

View file

@ -2709,6 +2709,8 @@ printparamnode(HashNode hn, int printflags)
printf("array ");
else if (p->flags & PM_HASHED)
printf("association ");
if (p->level)
printf("local ");
if (p->flags & PM_LEFT)
printf("left justified %d ", p->ct);
if (p->flags & PM_RIGHT_B)

View file

@ -702,7 +702,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
int spbreak = isset(SHWORDSPLIT) && !ssub && !qt;
char *val = NULL, **aval = NULL;
unsigned int fwidth = 0;
Value v;
Value v = NULL;
int flags = 0;
int flnum = 0;
int sortit = 0, casind = 0;
@ -1828,7 +1828,7 @@ modify(char **str, char **ptr)
subst(&copy, hsubl, hsubr, gbal);
break;
case 'q':
copy = bslashquote(copy, NULL, NULL, NULL, 0);
copy = bslashquote(copy, NULL, 0);
break;
}
tc = *tt;
@ -1882,7 +1882,7 @@ modify(char **str, char **ptr)
}
break;
case 'q':
*str = bslashquote(*str, NULL, NULL, NULL, 0);
*str = bslashquote(*str, NULL, 0);
break;
}
}

View file

@ -3140,7 +3140,7 @@ hasspecial(char const *s)
/**/
char *
bslashquote(const char *s, char **e, char *te, int *pl, int instring)
bslashquote(const char *s, char **e, int instring)
{
const char *u, *tt;
char *v, buf[PATH_MAX * 2];
@ -3151,8 +3151,6 @@ bslashquote(const char *s, char **e, char *te, int *pl, int instring)
for (; *u; u++) {
if (e && *e == u)
*e = v, sf |= 1;
if (te == u)
*pl = v - tt, sf |= 2;
if (ispecial(*u) &&
(!instring || (isset(BANGHIST) &&
*u == (char)bangchar) ||
@ -3189,8 +3187,6 @@ bslashquote(const char *s, char **e, char *te, int *pl, int instring)
if (e && *e == u)
*e = v;
if (te == u)
*pl = v - tt;
return (char *) tt;
}

View file

@ -1085,6 +1085,7 @@ enum {
EXTENDEDHISTORY,
FLOWCONTROL,
FUNCTIONARGZERO,
GLOBALRCSFIRST,
GLOBOPT,
GLOBASSIGN,
GLOBCOMPLETE,

View file

@ -798,8 +798,66 @@ for some other reason).
Sven: 5831: in subscripts and math environments, the whole string is always
passed down to the function handler.
pws: 5844: don't set errflag if noerrs = 2.
Sven: 5852: warnings about _long_options
pws: 5854: man page dependencies in Doc/Makefile.in
Sven: 5862: _path_files (turning on menu) and _cd (include . in path)
pws: 5863: substitution rules
pws-14
Bart: 5868: expn.yo fixes
Sven: 5871, 5875: big zle_tricky.c cleanup, with compstate changes and
IFSUFFIX
Sven: 5872, 5881, 5889: corresponding Completion function rewrite
Sven: 5879, 5899: completion documentation
Sven: 5890: _match completer
Sven: 5895, 5898, 5906: fix completion prefixes
Sven: 5904: print local for parameters
pws: 5905: _main_complete should at least try to get _unset_options correct.
Sven: 5912: compiler warnings
Sven: 5913: zle -C test
Sven: 5914: _main_complete takes optional completer arguments
pws: 5915: minor type fixes
Sven: 5916: _expand completer
Sven: 5918: _list completer
Sven: 5925: path_expand
Sven: 5926: $HISTNO
Sven: 5928: copy context in zle_tricky
pws: 5931: more parameter substitution rules
Sven: 5933: don't complete local parameters; _setopt/_unsetopt complete all
options (code to use currently unset/set options remains in comments)
pws: 5934: option GLOBAL_RCS_FIRST runs /etc/z* files before user's files.
Sven: 5938, 5937: compset to replace modifying conditions
Sven: 5940: move cursor
Sven: 5942: spaces in file names with old completion
Sven: 5947: completion functions fix
pws: unposted: updated .distfiles under Completion