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:
parent
640a840d2e
commit
6c1fb551ba
64 changed files with 3788 additions and 3632 deletions
Completion
Base
Builtins
Commands
Core
.distfiles_approximate_complete_correct_expand_list_main_complete_match_multi_parts_options_parameters_path_files_sep_parts_set_options_unset_optionscompdumpcompinit
READMEUser
Config
Doc/Zsh
Src
Modules
Zle
comp.hcomp1.ccomp1.exportcompctl.ccompctl.mddzle_main.czle_move.czle_params.czle_thingy.czle_tricky.c
glob.cinit.coptions.cparams.csubst.cutils.czsh.h
|
@ -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
|
||||
'
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
18
Completion/Base/_math
Normal 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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#defcomp command
|
||||
|
||||
if [[ -position 3 -1 ]]; then
|
||||
if [[ CURRENT -ge 3 ]]; then
|
||||
compset -n 2
|
||||
_normal
|
||||
else
|
||||
compgen -em
|
||||
|
|
|
@ -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 '='
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
local list
|
||||
|
||||
if [[ -iprefix '-' ]]; then
|
||||
if compset -P 1 -; then
|
||||
compgen -k "($signals[1,-3])"
|
||||
else
|
||||
local ret=1
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
#defcomp sched
|
||||
|
||||
[[ -position 3 -1 ]] && _normal
|
||||
compset -n 3 && _normal
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#defcomp source
|
||||
|
||||
if [[ -position 3 -1 ]]; then
|
||||
if [[ CURRENT -ge 3 ]]; then
|
||||
compset -n 2
|
||||
_normal
|
||||
else
|
||||
_files
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)'
|
||||
|
|
|
@ -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[@]}"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
'
|
||||
|
|
197
Completion/Core/_approximate
Normal file
197
Completion/Core/_approximate
Normal 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
52
Completion/Core/_complete
Normal 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
19
Completion/Core/_correct
Normal 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
149
Completion/Core/_expand
Normal 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
61
Completion/Core/_list
Normal 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
|
|
@ -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
53
Completion/Core/_match
Normal 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
|
|
@ -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
5
Completion/Core/_options
Normal 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
|
8
Completion/Core/_parameters
Normal file
8
Completion/Core/_parameters
Normal 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)}%%\=*}##* }"
|
|
@ -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] ]]
|
||||
|
|
|
@ -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).
|
||||
|
|
7
Completion/Core/_set_options
Normal file
7
Completion/Core/_set_options
Normal 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
|
7
Completion/Core/_unset_options
Normal file
7
Completion/Core/_unset_options
Normal 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
|
|
@ -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) )
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)'
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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))(
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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[] = {
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#include "zle.mdh"
|
||||
#include "zle_move.pro"
|
||||
|
||||
static vimarkcs[27], vimarkline[27];
|
||||
static int vimarkcs[27], vimarkline[27];
|
||||
|
||||
/**/
|
||||
void
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
4929
Src/Zle/zle_tricky.c
4929
Src/Zle/zle_tricky.c
File diff suppressed because it is too large
Load diff
|
@ -583,7 +583,7 @@ compalloc(void)
|
|||
|
||||
/**/
|
||||
static int
|
||||
getglobflags()
|
||||
getglobflags(void)
|
||||
{
|
||||
char *nptr;
|
||||
/* (#X): assumes we are still positioned on the initial '(' */
|
||||
|
|
24
Src/init.c
24
Src/init.c
|
@ -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");
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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(©, 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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -1085,6 +1085,7 @@ enum {
|
|||
EXTENDEDHISTORY,
|
||||
FLOWCONTROL,
|
||||
FUNCTIONARGZERO,
|
||||
GLOBALRCSFIRST,
|
||||
GLOBOPT,
|
||||
GLOBASSIGN,
|
||||
GLOBCOMPLETE,
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue