mirror of
git://git.code.sf.net/p/zsh/code
synced 2026-01-04 09:01:06 +01:00
zsh-3.1.5-pws-15
This commit is contained in:
parent
6c1fb551ba
commit
8ceb54fbc2
101 changed files with 1931 additions and 1149 deletions
|
|
@ -1,4 +1,4 @@
|
|||
#defcomp -brace-parameter-
|
||||
#compdef -brace-parameter-
|
||||
|
||||
if [[ "$SUFFIX" = *\}* ]]; then
|
||||
ISUFFIX="${SUFFIX#*\}}$ISUFFIX"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#defcomp -command-
|
||||
#compdef -command-
|
||||
|
||||
local nm=$compstate[nmatches] ret=1
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#defcomp -condition-
|
||||
#compdef -condition-
|
||||
|
||||
local prev="$words[CURRENT-1]"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#defcomp -default-
|
||||
#compdef -default-
|
||||
|
||||
# We first try the `compctl's. This is without first (-T) and default (-D)
|
||||
# completion. If you want them add `-T' and/or `-D' to this command.
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
#defcomp -equal-
|
||||
#compdef -equal-
|
||||
|
||||
compgen -am
|
||||
|
|
|
|||
|
|
@ -32,12 +32,25 @@
|
|||
# for option descriptions containing `=FILE' and paths for option
|
||||
# descriptions that contain `=DIR' or `=PATH'. These builtin patterns
|
||||
# can be overridden by patterns given as arguments, though.
|
||||
#
|
||||
# This function accepts following options:
|
||||
#
|
||||
# -t do completion only on words starting with two hyphens
|
||||
#
|
||||
# -i list of patterns. Options, matching these patterns, are ignored.
|
||||
# The list may be given as array name or as literal list in braces.
|
||||
# E.g. _long_options -i '(--(enable|disable)-FEATURE*)' will ignore
|
||||
# --enable-FEATURE, that is listed in configure help output
|
||||
#
|
||||
# -s list of pattern/replacement pairs. The argument is the same as above.
|
||||
# E.g. configure often lists only --enable but accepts both
|
||||
# --enable and --disable options.
|
||||
# _long_options -s '(#--enable- --disable)' will accept both forms.
|
||||
#
|
||||
# This function also accepts the `-X', `-J', and `-V' options which
|
||||
# are given to `compadd'. Finally, it accepts the option `-t'. If this
|
||||
# is given, completion is only done on words starting with two hyphens.
|
||||
# are given to `compadd'.
|
||||
|
||||
local opt expl group test i name action ret=1 tmp suffix
|
||||
local opt expl group test i name action ret=1 tmp suffix iopts sopts
|
||||
|
||||
setopt extendedglob
|
||||
|
||||
|
|
@ -46,11 +59,23 @@ setopt extendedglob
|
|||
group=()
|
||||
expl=()
|
||||
if [[ $1 = -*~--* ]]; then
|
||||
while getopts "J:V:X:t" opt; do
|
||||
while getopts "J:V:X:ti:s:" opt; do
|
||||
case "$opt" in
|
||||
[JV]) group=("-$opt" "$OPTARG");;
|
||||
X) expl=(-X "$OPTARG");;
|
||||
t) test=yes;;
|
||||
i) if [[ "$OPTARG[1]" = '(' ]]; then
|
||||
iopts=( ${=OPTARG[2,-2]} )
|
||||
else
|
||||
iopts=( ${(P)${OPTARG}} )
|
||||
fi
|
||||
;;
|
||||
s) if [[ "$OPTARG[1]" = '(' ]]; then
|
||||
sopts=( ${=OPTARG[2,-2]} )
|
||||
else
|
||||
sopts=( ${(P)${OPTARG}} )
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift OPTIND-1
|
||||
|
|
@ -77,6 +102,7 @@ if [[ "$tmp" != $_lo_cache_cmd ]]; then
|
|||
(( $+_lo_cache_actions )) && unset "$_lo_cache_names[@]" _lo_cache_actions _lo_cache_names
|
||||
|
||||
local opts pattern anum=1 tmpo str
|
||||
typeset -U opts
|
||||
|
||||
# Now get the long option names by calling the command with `--help'.
|
||||
# The parameter expansion trickery first gets the lines as separate
|
||||
|
|
@ -87,11 +113,24 @@ if [[ "$tmp" != $_lo_cache_cmd ]]; then
|
|||
# the old array elements with newlines between them. Then we select
|
||||
# those elements that start with two hyphens, remove anything up to
|
||||
# those hyphens and anything from the space or comma after the
|
||||
# option up to the end. Finally all elements with option strings
|
||||
# that contain uppercase letters are removed.
|
||||
# option up to the end.
|
||||
|
||||
opts=("--${(@)^${(@)${(@)${(@M)${(@ps:\n:j:\n:)${(@)${(@M)${(@f)$("$words[1]" --help)}:#[ ]#-*}//,/
|
||||
}}:#[ ]#--*}#*--}%%[, ]*}:#(*-[A-Z]*|)}")
|
||||
opts=("--${(@)^${(@)${(@M)${(@ps:\n:j:\n:)${(@)${(@M)${(@f)$("$words[1]" --help)}:#[ ]#-*}//,/
|
||||
}}:#[ ]#--*}#*--}%%[, ]*}")
|
||||
|
||||
# Now remove all ignored options ...
|
||||
|
||||
while (($#iopts)) ; do
|
||||
opts=( ${opts:#$~iopts[1]} )
|
||||
shift iopts
|
||||
done
|
||||
|
||||
# ... and add "same" options
|
||||
|
||||
while (($#sopts)) ; do
|
||||
opts=( $opts ${opts/$sopts[1]/$sopts[2]} )
|
||||
shift 2 sopts
|
||||
done
|
||||
|
||||
# The interpretation of the options is completely table driven. We
|
||||
# use the positional parameters we were given and a few standard
|
||||
|
|
@ -173,7 +212,7 @@ if [[ "$tmp" != $_lo_cache_cmd ]]; then
|
|||
# Now filter out any option strings we don't like and stuff them
|
||||
# in an array, if there are still some.
|
||||
|
||||
tmp=("${(@)${(@)tmp%%\=*}//[^a-z0-9-]}")
|
||||
tmp=("${(@)${(@)tmp%%\=*}//[^a-zA-Z0-9-]}")
|
||||
if (( $#tmp )); then
|
||||
_lo_cache_names[anum]="$name"
|
||||
_lo_cache_actions[anum]="$action"
|
||||
|
|
@ -200,20 +239,6 @@ if [[ "$str" = *\=* ]]; then
|
|||
osuf="$SUFFIX"
|
||||
|
||||
pre="${str%%\=*}"
|
||||
IPREFIX="${IPREFIX}${pre}="
|
||||
PREFIX="${str#*\=}"
|
||||
SUFFIX=""
|
||||
|
||||
# We will check if the arrays contain an option matching what's on
|
||||
# the line. To do this good, we build a pattern.
|
||||
|
||||
[[ -n "$_comp_correct" && $#pre -le _comp_correct ]] && return 1
|
||||
|
||||
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
|
||||
# contains the option string. If so, we `invoke' the action stored
|
||||
|
|
@ -223,6 +248,9 @@ if [[ "$str" = *\=* ]]; then
|
|||
for name in "$_lo_cache_names[@]"; do
|
||||
action="$_lo_cache_actions[anum]"
|
||||
if (( ${(@)${(@P)name}[(I)$pre]} )); then
|
||||
IPREFIX="${oipre}${pre}="
|
||||
PREFIX="${str#*\=}"
|
||||
SUFFIX=""
|
||||
if [[ "$action[1]" = (\[|\() ]]; then
|
||||
compadd - ${=action[2,-2]}
|
||||
elif (( $#action )); then
|
||||
|
|
@ -240,7 +268,10 @@ if [[ "$str" = *\=* ]]; then
|
|||
# element from `_lo_actions' in `parta'. If we find more than one
|
||||
# such option or if we already had one, we set `parto' to `-'.
|
||||
|
||||
tmp=("${(@M)${(@P)name}:#${~pat}}")
|
||||
PREFIX="${str%%\=*}"
|
||||
SUFFIX=""
|
||||
compadd -O tmp -M 'r:|-=* r:|=*' - "${(@P)name}"
|
||||
|
||||
if [[ $#tmp -eq 1 ]]; then
|
||||
if [[ -z "$parto" ]]; then
|
||||
parto="$tmp[1]"
|
||||
|
|
@ -258,8 +289,9 @@ if [[ "$str" = *\=* ]]; then
|
|||
# try to complete the string after the `='.
|
||||
|
||||
if [[ -n "$parto" && "$parto" != - ]]; then
|
||||
IPREFIX="${parto}="
|
||||
|
||||
IPREFIX="${oipre}${parto}="
|
||||
PREFIX="${str#*\=}"
|
||||
SUFFIX=""
|
||||
if (( $#parta )); then
|
||||
if [[ "$parta[1]" = (\[|\() ]]; then
|
||||
compadd - ${=parta[2,-2]}
|
||||
|
|
@ -281,7 +313,7 @@ fi
|
|||
|
||||
# The string on the line did not contain a `=', or we couldn't
|
||||
# complete the option string since there were more than one matching
|
||||
# what's on the line. So we just ad the option string as possible
|
||||
# what's on the line. So we just add the option strings as possible
|
||||
# matches, giving the string from the `=' on as a suffix.
|
||||
|
||||
if [[ "$str" = *\=* ]]; then
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#defcomp -math-
|
||||
#compdef -math-
|
||||
|
||||
if [[ "$PREFIX" = *[^a-zA-Z0-9_]* ]]; then
|
||||
IPREFIX="$IPREFIX${PREFIX%%[a-zA-Z0-9_]#}"
|
||||
|
|
@ -10,7 +10,7 @@ if [[ "$SUFFIX" = *[^a-zA-Z0-9_]* ]]; then
|
|||
fi
|
||||
|
||||
compgen -v
|
||||
#defcomp -math-
|
||||
#compdef -math-
|
||||
|
||||
IPREFIX="$IPREFIX${PREFIX%[a-zA-Z0-9_]*}"
|
||||
PREFIX="${PREFIX##*[^a-zA-Z0-9_]}"
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
#defcomp -parameter-
|
||||
#compdef -parameter-
|
||||
|
||||
compgen -v
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#defcomp - nohup nice eval time rusage noglob nocorrect exec
|
||||
#compdef - nohup nice eval time rusage noglob nocorrect exec
|
||||
|
||||
shift words
|
||||
(( CURRENT-- ))
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
#defcomp -redirect-
|
||||
#compdef -redirect-
|
||||
|
||||
_files
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#defcomp -subscript-
|
||||
#compdef -subscript-
|
||||
|
||||
if [[ ${(Pt)${compstate[parameter]}} = assoc* ]]; then
|
||||
compgen -S ']' -k "( ${(kP)${compstate[parameter]}} )"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#defcomp -tilde-
|
||||
#compdef -tilde-
|
||||
|
||||
# We use all named directories and user names here. If this is too slow
|
||||
# for you or if there are too many of them, you may want to use
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
#defcomp getopts read unset vared
|
||||
#compdef getopts read unset vared
|
||||
|
||||
compgen -v
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
#defcomp unalias
|
||||
#compdef unalias
|
||||
|
||||
compgen -a
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
#defcomp shift
|
||||
#compdef shift
|
||||
|
||||
compgen -A
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
#defcomp autoload
|
||||
#compdef autoload
|
||||
|
||||
compgen -s '${^fpath}/*(N:t)'
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
#defcomp bg
|
||||
#compdef bg
|
||||
|
||||
compgen -z -P '%'
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#defcomp bindkey
|
||||
#compdef bindkey
|
||||
|
||||
# Normally, this completes names of zle widgets, whether the builtin ones
|
||||
# or ones defined by the user. Note that a - allows a wildcard before it,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#defcomp builtin
|
||||
#compdef builtin
|
||||
|
||||
if (( $CURRENT > 2 )); then
|
||||
shift words
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#defcomp cd pushd
|
||||
#compdef cd pushd
|
||||
|
||||
# Handling of cd.
|
||||
# - Normally just completes directories. Uses cdpath if that's set
|
||||
|
|
@ -55,7 +55,7 @@ elif [[ $words[1] = pu* && $PREFIX = [-+]* ]]; then
|
|||
list=(${list%%[ ]*})
|
||||
compgen -y '$lines' -Q -k list && ret=0
|
||||
[[ -z $compstate[list] ]] && compstate[list]=list && ret=0
|
||||
[[ -n $compstate[insert] ]] && compstat[insert]=menu && ret=0
|
||||
[[ -n $compstate[insert] ]] && compstate[insert]=menu && ret=0
|
||||
|
||||
return ret
|
||||
elif [[ $PREFIX != (\~|/|./|../)* && $#cdpath -ne 0 ]]; then
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#defcomp command
|
||||
#compdef command
|
||||
|
||||
if [[ CURRENT -ge 3 ]]; then
|
||||
compset -n 2
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
#defcomp rmdir df du dircmp
|
||||
#compdef rmdir df du dircmp
|
||||
|
||||
_files -/
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#defcomp disable
|
||||
#compdef disable
|
||||
|
||||
local prev="$words[CURRENT-1]" ret=1
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
#defcomp echotc
|
||||
#compdef echotc
|
||||
|
||||
compgen -k '(al dc dl do le up al bl cd ce cl cr dc dl do ho is le ma nd nl se so up)'
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#defcomp enable
|
||||
#compdef enable
|
||||
|
||||
local prev="$words[CURRENT-1]" ret=1
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#defcomp fc
|
||||
#compdef fc
|
||||
|
||||
local prev="$words[CURRENT-1]"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
#defcomp unfunction
|
||||
#compdef unfunction
|
||||
|
||||
compgen -F
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#defcomp hash
|
||||
#compdef hash
|
||||
|
||||
if [[ "$words[2]" = -*d* ]]; then
|
||||
if compset -P 1 '*\='; then
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
#defcomp fg jobs
|
||||
#compdef fg jobs
|
||||
|
||||
compgen -j -P '%'
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#defcomp kill
|
||||
#compdef kill
|
||||
|
||||
local list
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
#defcomp limit unlimit
|
||||
#compdef limit unlimit
|
||||
|
||||
compgen -k "(${(j: :)${(f)$(limit)}%% *})"
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
#defcomp sched
|
||||
#compdef sched
|
||||
|
||||
compset -n 3 && _normal
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#defcomp set
|
||||
#compdef set
|
||||
|
||||
local prev="$words[CURRENT-1]"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#defcomp setopt
|
||||
#compdef setopt
|
||||
|
||||
# If you first want to complete only unset options, un-comment the lines
|
||||
# setting the _unset_options array and then use:
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#defcomp source
|
||||
#compdef source
|
||||
|
||||
if [[ CURRENT -ge 3 ]]; then
|
||||
compset -n 2
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#defcomp trap
|
||||
#compdef trap
|
||||
|
||||
if [[ CURRENT -eq 2 ]]; then
|
||||
compgen -c
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#defcomp unhash
|
||||
#compdef unhash
|
||||
|
||||
local fl="$words[2]" ret=1
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#defcomp unsetopt
|
||||
#compdef unsetopt
|
||||
|
||||
# If you first want to complete only unset options, uncomment the lines
|
||||
# setting the _set_options array and then use:
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
#defcomp declare export integer local readonly typeset
|
||||
#compdef declare export integer local readonly typeset
|
||||
|
||||
compgen -v -q -S '='
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#defcomp wait
|
||||
#compdef wait
|
||||
|
||||
local list ret=1
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
#defcomp which whence where type
|
||||
#compdef which whence where type
|
||||
|
||||
compgen -caF
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#defpatcomp zf*
|
||||
#compdef -p zf*
|
||||
|
||||
# Don't try any more completion after this.
|
||||
_compskip=1
|
||||
|
|
@ -10,7 +10,7 @@ _compskip=1
|
|||
local subcom
|
||||
|
||||
if [[ $words[1] = zftp ]]; then
|
||||
if [[ $CURRENT -eq 1 ]]; then
|
||||
if [[ $CURRENT -eq 2 ]]; then
|
||||
compadd open params user login type ascii binary mode put \
|
||||
putat get getat append appendat ls dir local remote mkdir rmdir
|
||||
return
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#defcomp zle
|
||||
#compdef zle
|
||||
|
||||
if [[ "$words[2]" = -N && CURRENT -eq 3 ]]; then
|
||||
compgen -F
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#defcomp zmodload
|
||||
#compdef zmodload
|
||||
|
||||
local fl="$words[2]"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#defkeycomp complete-word \C-xc
|
||||
#compdef -k complete-word \C-xc
|
||||
|
||||
# Function to correct a filename. Can be used as a completion widget,
|
||||
# or as a function in its own right, in which case it will print the
|
||||
|
|
|
|||
12
Completion/Commands/_correct_word
Normal file
12
Completion/Commands/_correct_word
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
#compdef -k complete-word \C-xc
|
||||
|
||||
# Simple completion front-end implementing spelling correction.
|
||||
# The maximum number of errors is set quite high, and
|
||||
# the numeric prefix can be used to specify a different value.
|
||||
|
||||
local oca="$compconfig[correct_accept]"
|
||||
compconfig[correct_accept]=6n
|
||||
|
||||
_main_complete _correct
|
||||
|
||||
compconfig[correct_accept]=$oca
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
#defkeycomp complete-word \C-xm
|
||||
#compdef -k complete-word \C-xm
|
||||
|
||||
# Complete the most recent file matching the pattern on the line so
|
||||
# far: globbing is active, i.e. *.txt will be expanded to the most recent
|
||||
|
|
|
|||
|
|
@ -1,15 +1,17 @@
|
|||
#autoload
|
||||
|
||||
# This searches $1 in the array for normal completions and calls the result.
|
||||
# This searches $* in the array for normal completions and calls the result.
|
||||
# It is used to include completions for another command or special context
|
||||
# into the list generated by the calling function.
|
||||
# For example the function for `-subscript-' could call this as in
|
||||
# `_compalso -math-' to get the completions that would be generated for a
|
||||
# mathematical context.
|
||||
|
||||
local tmp ret=1
|
||||
local i tmp
|
||||
|
||||
tmp="$_comps[$1]"
|
||||
[[ -z "$tmp" ]] || "$tmp" && ret=0
|
||||
for i; do
|
||||
tmp="$_comps[$1]"
|
||||
[[ -z "$tmp" ]] || "$tmp" && return 0
|
||||
done
|
||||
|
||||
return ret
|
||||
return 1
|
||||
|
|
|
|||
|
|
@ -7,15 +7,8 @@
|
|||
# The parts of words from the array that are separated by the
|
||||
# separator character are then completed independently.
|
||||
|
||||
local sep matches patstr orig matchflags pref i tmp1 tmp2 nm
|
||||
local group expl menu origflags mflags
|
||||
|
||||
_match_test _multi_parts || return 1
|
||||
|
||||
# Save the current number of matches to be able to return if we added
|
||||
# matches or not.
|
||||
|
||||
nm=$compstate[nmatches]
|
||||
local sep matches pref npref i tmp1 group expl menu pre suf
|
||||
typeset -U tmp2
|
||||
|
||||
# Get the options.
|
||||
|
||||
|
|
@ -41,193 +34,159 @@ else
|
|||
matches=( "${(@P)2}" )
|
||||
fi
|
||||
|
||||
# Now build the pattern from what we have on the line. We also save
|
||||
# the original string in `orig'.
|
||||
# In `pre' and `suf' we will hold the prefix and the suffix from the
|
||||
# line while we walk through them. The original string are used
|
||||
# temporarily for matching.
|
||||
|
||||
if [[ $#compstate[pattern_match] -ne 0 ]]; then
|
||||
if [[ "${compstate[pattern_match]-*}" = \** ]]; then
|
||||
str="${PREFIX}*${SUFFIX}*"
|
||||
else
|
||||
str="${PREFIX}${SUFFIX}"
|
||||
fi
|
||||
else
|
||||
patstr="${PREFIX:q}*${SUFFIX:q}*"
|
||||
fi
|
||||
orig="${PREFIX}${SUFFIX}"
|
||||
pre="$PREFIX"
|
||||
suf="$SUFFIX"
|
||||
orig="$PREFIX$SUFFIX"
|
||||
|
||||
[[ $compstate[insert] = *menu || -n "$_comp_correct" ||
|
||||
# Special handling for menucompletion?
|
||||
|
||||
[[ $compstate[insert] = (*menu|[0-9]*) || -n "$_comp_correct" ||
|
||||
( $#compstate[pattern_match] -ne 0 &&
|
||||
"$orig" != "${orig:q}" ) ]] && menu=yes
|
||||
|
||||
matchflags=""
|
||||
_match_pattern _path_files patstr matchflags
|
||||
origflags="$matchflags"
|
||||
[[ -n "$_comp_correct" ]] && matchflags="$matchflags(#a$_comp_correct)"
|
||||
|
||||
patstr="${${patstr//$sep/*$sep}//\*##/*}"
|
||||
|
||||
# First we will skip over those parts of the matches for which we have
|
||||
# exact substrings on the line. In `pref' we will build the
|
||||
# unambiguous prefix string.
|
||||
# In `pref' we collect the unambiguous prefix path.
|
||||
|
||||
pref=''
|
||||
while [[ "$orig" = *${sep}* ]] do
|
||||
|
||||
# First build the pattern to use, then collect all strings from
|
||||
# `matches' that match the prefix we have and the exact substring in
|
||||
# the array `tmp1'.
|
||||
# If the string from the line matches at least one of the strings,
|
||||
# we use only the matching strings.
|
||||
|
||||
if [[ -n "$_comp_correct" && "${#orig%%${sep}*}" -le _comp_correct ]]; then
|
||||
mflags="$origflags"
|
||||
compadd -O tmp1 -M "r:|${sep}=* r:|=*" - "$matches[@]"
|
||||
|
||||
(( $#tmp1 )) && matches=( "$tmp1[@]" )
|
||||
|
||||
while true; do
|
||||
|
||||
# Get the prefix and suffix for matching.
|
||||
|
||||
if [[ "$pre" = *${sep}* ]]; then
|
||||
PREFIX="${pre%%${sep}*}"
|
||||
SUFFIX=""
|
||||
else
|
||||
mflags="$matchflags"
|
||||
PREFIX="${pre}"
|
||||
SUFFIX="${suf%%${sep}*}"
|
||||
fi
|
||||
|
||||
pat="${${${patstr#*${sep}}%${sep}*}//\*/[^${sep}]#}"
|
||||
tmp1=( "${(@M)matches:#${~mflags}${orig%%${sep}*}${sep}${~pat}}" )
|
||||
# Check if the component for some of the possible matches is equal
|
||||
# to the string from the line. If there are such strings, we directly
|
||||
# use the stuff from the line. This avoids having `foo' complete to
|
||||
# both `foo' and `foobar'.
|
||||
|
||||
# If there are no words matching the exact substring, stop.
|
||||
tmp1=( "${(@M)matches:#${PREFIX}${SUFFIX}${sep}*}" )
|
||||
|
||||
(( $#tmp1 )) || break
|
||||
|
||||
# Otherwise add the part to the prefix, remove it from the matches
|
||||
# (and also remove all words not matching the string at all), and
|
||||
# set `patstr' and `orig' to the next component.
|
||||
|
||||
tmp1="${orig%%${sep}*}${sep}"
|
||||
pref="$pref$tmp1"
|
||||
matches=("${(@)${(@)${(@M)matches:#${tmp1}*}#$tmp1}:#}")
|
||||
orig="${orig#*${sep}}"
|
||||
patstr="${patstr#*${sep}}"
|
||||
done
|
||||
|
||||
# Now we get all the words that still match in `tmp1'.
|
||||
|
||||
if [[ "$patstr" = *${sep}* ]]; then
|
||||
tmp1="${patstr%${sep}*}${sep}"
|
||||
pat="${tmp1//\*/[^${sep}]#}${patstr##*${sep}}"
|
||||
else
|
||||
pat="$patstr"
|
||||
fi
|
||||
if [[ -n "$_comp_correct" && "${#orig%%${sep}*}" -le _comp_correct ]]; then
|
||||
mflags="$origflags"
|
||||
else
|
||||
mflags="$matchflags"
|
||||
fi
|
||||
tmp1=( "${(@M)matches:#${~mflags}${~pat}}" )
|
||||
|
||||
if (( $#tmp1 )); then
|
||||
|
||||
# There are words that are matched, put them into `matches' and then
|
||||
# move all unambiguous components from the beginning into `pref'.
|
||||
|
||||
matches=( "$tmp1[@]" )
|
||||
while [[ "$matches[1]" = *${sep}* ]]; do
|
||||
|
||||
# We just take the first component of the first match and see if
|
||||
# there are other matches with a different prefix (these are
|
||||
# collected in `tmp2'). If there are any, we give up.
|
||||
|
||||
tmp1="${matches[1]%%${sep}*}${sep}"
|
||||
tmp2=( "${(@)matches:#${tmp1}*}" )
|
||||
(( $#tmp2 )) && break
|
||||
|
||||
# All matches have the same prefix, put it into `pref' and remove
|
||||
# it from the matches.
|
||||
|
||||
pref="$pref$tmp1"
|
||||
matches=( "${(@)${(@)matches#$tmp1}:#}" )
|
||||
|
||||
if [[ "$orig" = *${sep}* ]]; then
|
||||
orig="${orig#*${sep}}"
|
||||
else
|
||||
orig=''
|
||||
fi
|
||||
done
|
||||
|
||||
# Now we can tell the completion code about the things we
|
||||
# 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" -I "$ISUFFIX" -S '' - \
|
||||
"${pref}${orig}"
|
||||
elif [[ -n "$menu" ]]; then
|
||||
if [[ "$orig" = *${sep}* ]]; then
|
||||
orig="${sep}${orig#*${sep}}"
|
||||
else
|
||||
orig=''
|
||||
fi
|
||||
for i in "$matches[@]" ; do
|
||||
if [[ "$i" = *${sep}* ]]; then
|
||||
compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \
|
||||
-p "$pref" -s "$orig" - "${i%%${sep}*}${sep}"
|
||||
else
|
||||
compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \
|
||||
-p "$pref" -s "$orig" - "${i%%${sep}*}"
|
||||
fi
|
||||
done
|
||||
if (( $#tmp1 )); then
|
||||
npref="${PREFIX}${SUFFIX}${sep}"
|
||||
else
|
||||
for i in "$matches[@]" ; do
|
||||
if [[ "$i" = *${sep}* ]]; then
|
||||
compadd -U -i "$IPREFIX" -I "$ISUFFIX" -p "$pref" -s "${i#*${sep}}" \
|
||||
"$group[@]" "$expl[@]" -M "r:|${sep:q}=*" - "${i%%${sep}*}${sep}"
|
||||
# No exact match, see how many strings match what's on the line.
|
||||
|
||||
tmp2=( "${(@)matches%%${sep}*}" )
|
||||
compadd -O tmp1 - "$tmp2[@]"
|
||||
|
||||
if [[ $#tmp1 -eq 1 ]]; then
|
||||
|
||||
# Only one match. If there are still separators from the line
|
||||
# we just accept this component. Otherwise we insert what we
|
||||
# have collected, probably giving it a separator character
|
||||
# as a suffix.
|
||||
|
||||
if [[ "$pre$suf" = *${sep}* ]]; then
|
||||
npref="${tmp1[1]}${sep}"
|
||||
else
|
||||
matches=( "${(@M)matches:#${tmp1[1]}*}" )
|
||||
tmp2=( "${(@M)matches:#${tmp1[1]}${sep}*}" )
|
||||
|
||||
if (( $#tmp2 )); then
|
||||
compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \
|
||||
-p "$pref" -qS "$sep" - "$tmp1[1]"
|
||||
else
|
||||
compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \
|
||||
-p "$pref" - "$tmp1[1]"
|
||||
fi
|
||||
return 1
|
||||
fi
|
||||
elif (( $#tmp1 )); then
|
||||
|
||||
# More than one match. First we get all strings that match the
|
||||
# rest from the line.
|
||||
|
||||
PREFIX="$pre"
|
||||
SUFFIX="$suf"
|
||||
compadd -O matches -M "r:|${sep}=* r:|=*" - "$matches[@]"
|
||||
|
||||
if [[ -n "$menu" ]]; then
|
||||
# With menucompletion we just add matches for the matching
|
||||
# components with the prefix we collected and the rest from the
|
||||
# line as a suffix.
|
||||
|
||||
tmp2="$pre$suf"
|
||||
if [[ "$tmp2" = *${sep}* ]]; then
|
||||
compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \
|
||||
-p "$pref" -s "${sep}${tmp2#*${sep}}" - "$tmp1[@]"
|
||||
else
|
||||
compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \
|
||||
-p "$pref" - "$tmp1[@]"
|
||||
fi
|
||||
else
|
||||
# With normal completion we add all matches one-by-one with
|
||||
# the unmatched part as a suffix. This will insert the longest
|
||||
# unambiguous string for all matching strings.
|
||||
|
||||
for i in "${(@M)matches:#(${(j:|:)~tmp1})*}"; do
|
||||
if [[ "$i" = *${sep}* ]]; then
|
||||
compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \
|
||||
-S '' -p "$pref" -s "${i#*${sep}}" - "${i%%${sep}*}${sep}"
|
||||
else
|
||||
compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \
|
||||
-S '' -p "$pref" - "$i"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
return 0
|
||||
else
|
||||
# We are here if no string matched what's on the line. In this
|
||||
# case we insert the expanded prefix we collected if it differs
|
||||
# from the original string from the line.
|
||||
|
||||
[[ "$orig" = "$pref$pre$suf" ]] && return 1
|
||||
|
||||
if [[ -n "$suf" ]]; then
|
||||
compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \
|
||||
-s "$suf" - "$pref$pre"
|
||||
else
|
||||
compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \
|
||||
-p "$pref" - "$i"
|
||||
-S '' - "$pref$pre$suf"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
elif [[ "$patstr" = *${sep}* ]]; then
|
||||
|
||||
# We had no words matching the string from the line. But we want to
|
||||
# be friendly and at least expand the prefix as far as we can. So we
|
||||
# will loop through the rest of the string from the line and test
|
||||
# the components one by one.
|
||||
|
||||
while [[ "$patstr" = *${sep}* ]]; do
|
||||
|
||||
# First we get all words matching at least this component in
|
||||
# `tmp1'. If there are none, we give up.
|
||||
|
||||
if [[ -n "$_comp_correct" && "${#orig%%${sep}*}" -le _comp_correct ]]; then
|
||||
mflags="$origflags"
|
||||
else
|
||||
mflags="$matchflags"
|
||||
fi
|
||||
tmp1=( "${(@M)matches:#${~mflags}${~patstr%%${sep}*}${sep}*}" )
|
||||
(( $#tmp1 )) || break
|
||||
|
||||
# Then we check if there are words that have a different prefix.
|
||||
|
||||
tmp2=( "${(@)tmp1:#${tmp1[1]%%${sep}*}${sep}*}" )
|
||||
if (( $#tmp2 )); then
|
||||
|
||||
# There are words with another prefix, so we have found an
|
||||
# ambiguous component. So we just give all possible prefixes to
|
||||
# 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" -I "$ISUFFIX" \
|
||||
-p "$pref" -s "${sep}${orig#*${sep}}" - "${(@)matches%%${sep}*}"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# All words have the same prefix, so add it to `pref' again and
|
||||
# try the next component.
|
||||
# We just accepted and/or expanded a component from the line. We
|
||||
# remove it from the matches (using only those that have a least
|
||||
# the skipped string) and ad it the `pref'.
|
||||
|
||||
pref="$pref${tmp1[1]%%${sep}*}${sep}"
|
||||
matches=( "${(@)matches#${tmp1[1]%%${sep}*}${sep}}" )
|
||||
orig="${orig#*${sep}}"
|
||||
patstr="${patstr#*${sep}}"
|
||||
done
|
||||
matches=( "${(@)${(@)${(@M)matches:#${npref}*}#*${sep}}:#}" )
|
||||
pref="$pref$npref"
|
||||
|
||||
# Finally, add the unambiguous prefix and the rest of the string
|
||||
# from the line.
|
||||
# Now we set `pre' and `suf' to their new values.
|
||||
|
||||
compadd -U "$group[@]" "$expl[@]" -S '' -i "$IPREFIX" -I "$ISUFFIX" \
|
||||
-p "$pref" - "$orig"
|
||||
fi
|
||||
if [[ "$pre" = *${sep}* ]]; then
|
||||
pre="${pre#*${sep}}"
|
||||
elif [[ "$suf" = *${sep}* ]]; then
|
||||
pre="${suf#*${sep}}"
|
||||
suf=""
|
||||
else
|
||||
# The string from the line is fully handled. If we collected an
|
||||
# unambiguous prefix and that differs from the original string,
|
||||
# we insert it.
|
||||
|
||||
# This sets the return value to indicate that we added matches (or not).
|
||||
[[ -n "$pref" && "$orig" != "$pref" ]] &&
|
||||
compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \
|
||||
-S '' - "$pref"
|
||||
|
||||
[[ nm -ne compstate[nmatches] ]]
|
||||
return
|
||||
fi
|
||||
done
|
||||
|
|
|
|||
|
|
@ -7,10 +7,9 @@
|
|||
# the last have the same syntax and meaning as for `compgen' or
|
||||
# `compadd', respectively. The `-F <ignore>' option may be used to give
|
||||
# a list of suffixes either by giving the name of an array or
|
||||
# literally by giving them in a string surrounded by
|
||||
# parentheses. Files with one of the suffixes thus given are treated
|
||||
# like files with one of the suffixes in the `fignore' array in normal
|
||||
# completion.
|
||||
# literally by giving them in a string surrounded by parentheses. Files
|
||||
# with one of the suffixes thus given are treated like files with one
|
||||
# of the suffixes in the `fignore' array in normal completion.
|
||||
#
|
||||
# This function supports one configuration key:
|
||||
#
|
||||
|
|
@ -18,22 +17,13 @@
|
|||
# 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.
|
||||
local linepath realpath donepath prepath testpath exppath
|
||||
local tmp1 tmp2 tmp3 tmp4 i orig pre suf tpre tsuf
|
||||
local pats ignore group expl addpfx addsfx remsfx
|
||||
local nm=$compstate[nmatches] menu
|
||||
|
||||
_match_test _path_files || return 1
|
||||
|
||||
# Yes, so...
|
||||
|
||||
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 tmp3 tmp4 exppaths
|
||||
|
||||
typeset -U prepaths
|
||||
typeset -U prepaths exppaths
|
||||
|
||||
setopt localoptions nullglob rcexpandparam extendedglob
|
||||
unsetopt markdirs globsubst shwordsplit nounset
|
||||
|
|
@ -109,35 +99,27 @@ if [[ "$sopt" = - ]]; then
|
|||
fi
|
||||
fi
|
||||
|
||||
# str holds the whole string from the command line with a `*' between
|
||||
# the prefix and the suffix. Then we see if we will do menucompletion.
|
||||
# We get the prefix and the suffix from the line and save the whole
|
||||
# original string. Then we see if we will do menucompletion.
|
||||
|
||||
if [[ $#compstate[pattern_match] -ne 0 ]]; then
|
||||
if [[ "${compstate[pattern_match]-*}" = \** ]]; then
|
||||
str="${PREFIX}*${SUFFIX}"
|
||||
else
|
||||
str="${PREFIX}${SUFFIX}"
|
||||
fi
|
||||
else
|
||||
str="${PREFIX:q}*${SUFFIX:q}"
|
||||
[[ "$str" = \\\~* ]] && str="$str[2,-1]"
|
||||
fi
|
||||
pre="$PREFIX"
|
||||
suf="$SUFFIX"
|
||||
orig="${PREFIX}${SUFFIX}"
|
||||
|
||||
[[ $compstate[insert] = *menu || -n "$_comp_correct" ||
|
||||
[[ $compstate[insert] = (*menu|[0-9]*) || -n "$_comp_correct" ||
|
||||
( $#compstate[pattern_match] -ne 0 &&
|
||||
"${orig#\~}" != "${${orig#\~}:q}" ) ]] && menu=yes
|
||||
|
||||
|
||||
# We will first try normal completion called with `compgen', but only if we
|
||||
# weren't given a `-F', `-r', or `-R' option.
|
||||
# weren't given a `-F', `-r', or `-R' option or we are in the string.
|
||||
|
||||
if [[ $#ignore -eq 0 && $#remsfx -eq 0 && -z "$_comp_correct" ]]; then
|
||||
if [[ -z "$suf" && $#ignore -eq 0 && $#remsfx -eq 0 &&
|
||||
-z "$_comp_correct" ]]; then
|
||||
# First build an array containing the `-W' option, if there is any and we
|
||||
# want to use it. We don't want to use it if the string from the command line
|
||||
# is a absolute path or relative to the current directory.
|
||||
|
||||
if [[ -z "$tmp1[1]" || "$str[1]" = [~/] || "$str" = (.|..)/* ]]; then
|
||||
if [[ -z "$prepaths[1]" || "$pre[1]" = [~/] || "$pre" = (.|..)/* ]]; then
|
||||
tmp1=()
|
||||
else
|
||||
tmp1=(-W "( $prepaths )")
|
||||
|
|
@ -145,7 +127,6 @@ if [[ $#ignore -eq 0 && $#remsfx -eq 0 && -z "$_comp_correct" ]]; then
|
|||
|
||||
# Now call compgen.
|
||||
|
||||
nm=$compstate[nmatches]
|
||||
if [[ -z "$gopt" ]]; then
|
||||
compgen "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" "$tmp1[@]" $sopt
|
||||
else
|
||||
|
|
@ -157,13 +138,13 @@ if [[ $#ignore -eq 0 && $#remsfx -eq 0 && -z "$_comp_correct" ]]; then
|
|||
[[ compstate[nmatches] -eq nm ]] || return 0
|
||||
fi
|
||||
|
||||
# No `-F' option, so we want to use `fignore'.
|
||||
# If given no `-F' option, we want to use `fignore'.
|
||||
|
||||
(( $#ignore )) || ignore=(-F fignore)
|
||||
|
||||
# Now let's have a closer look at the string to complete.
|
||||
|
||||
if [[ "$str[1]" = \~ ]]; then
|
||||
if [[ "$pre[1]" = \~ ]]; then
|
||||
# It begins with `~', so remember anything before the first slash to be able
|
||||
# to report it to the completion code. Also get an expanded version of it
|
||||
# (in `realpath'), so that we can generate the matches. Then remove that
|
||||
|
|
@ -171,10 +152,10 @@ if [[ "$str[1]" = \~ ]]; then
|
|||
# paths and make sure that the loop below is run only once with an empty
|
||||
# prefix path by setting `prepaths'.
|
||||
|
||||
linepath="${str%%/*}/"
|
||||
linepath="${pre%%/*}/"
|
||||
eval realpath\=$linepath
|
||||
[[ "$realpath" = "$linepath" ]] && return 1
|
||||
str="${str#*/}"
|
||||
pre="${pre#*/}"
|
||||
orig="${orig#*/}"
|
||||
donepath=''
|
||||
prepaths=( '' )
|
||||
|
|
@ -185,12 +166,12 @@ else
|
|||
linepath=''
|
||||
realpath=''
|
||||
|
||||
if [[ "$str[1]" = / ]]; then
|
||||
if [[ "$pre[1]" = / ]]; then
|
||||
# If it is a absolut path name, we remove the first slash and put it in
|
||||
# `donepath' meaning that we treat it as the path that was already handled.
|
||||
# Also, we don't use the paths from `-W'.
|
||||
|
||||
str="$str[2,-1]"
|
||||
pre="$pre[2,-1]"
|
||||
orig="$orig[2,-1]"
|
||||
donepath='/'
|
||||
prepaths=( '' )
|
||||
|
|
@ -198,278 +179,204 @@ else
|
|||
# The common case, we just use the string as it is, unless it begins with
|
||||
# `./' or `../' in which case we don't use the paths from `-W'.
|
||||
|
||||
[[ "$str" = (.|..)/* ]] && prepaths=( '' )
|
||||
[[ "$pre" = (.|..)/* ]] && prepaths=( '' )
|
||||
donepath=''
|
||||
fi
|
||||
fi
|
||||
|
||||
# Now build the glob pattern by calling `_match_pattern'.
|
||||
patstr="$str"
|
||||
matchflags=""
|
||||
_match_pattern _path_files patstr matchflags
|
||||
origflags="$matchflags"
|
||||
[[ -n "$_comp_correct" ]] && matchflags="$matchflags(#a$_comp_correct)"
|
||||
|
||||
# We almost expect the pattern to have changed `..' into `*.*.', `/.' into
|
||||
# `/*.', and probably to contain two or more consecutive `*'s. Since these
|
||||
# have special meaning for globbing, we remove them. But before that, we
|
||||
# add the pattern for matching any characters before a slash.
|
||||
|
||||
patstr="$patstr:gs-/-*/-:gs/*.*./../:gs/**/*/:gs-.*/-./-"
|
||||
|
||||
# We take the last pathname component from the pattern and store it in
|
||||
# `patlast', replacing `*'s in it with patterns that match any character
|
||||
# but not slashes. Later we will generate matches using `patstr' with the
|
||||
# patterns we were given (like `*.c') appended to it, producing all matching
|
||||
# files. These filenames are then compared to `patlast' and all names not
|
||||
# matching that will be removed. All this is needed to be able to correctly
|
||||
# support `completeinword' as otherwise we would have something like `a*x'
|
||||
# from the line (the `*' was inserted above) and appending the `-g' pattern
|
||||
# `*.tex' would yield `a*x*.tex' which is not what we want.
|
||||
|
||||
if [[ "$patstr" = */* ]]; then
|
||||
if [[ -n "$_comp_correct" && "${#orig##*/}" -le _comp_correct ]]; then
|
||||
patlast="*/${origflags}${${${patstr##*/}//\*/[^/]#}:gs.\[^/]#.\\\*.}"
|
||||
else
|
||||
patlast="*/${matchflags}${${${patstr##*/}//\*/[^/]#}:gs.\[^/]#.\\\*.}"
|
||||
fi
|
||||
patstr="${patstr%/*}/"
|
||||
else
|
||||
if [[ -n "$_comp_correct" && "$#orig" -le _comp_correct ]]; then
|
||||
patlast="${origflags}${${patstr//\*/[^/]#}:gs.\[^/]#.\\\*.}"
|
||||
else
|
||||
patlast="${matchflags}${${patstr//\*/[^/]#}:gs.\[^/]#.\\\*.}"
|
||||
fi
|
||||
patstr=""
|
||||
fi
|
||||
|
||||
# First we skip over all pathname components in `str' which really exist in
|
||||
# the file-system, so that `/usr/lib/l<TAB>' doesn't offer you `lib' and
|
||||
# `lib5'. Pathname components skipped this way are taken from `orig' and added
|
||||
# to `donepath'.
|
||||
|
||||
while [[ "$orig" = */* ]] do
|
||||
tmp1=( $realpath$donepath${orig%%/*}/${~matchflags}${~patstr#*/}${^~pats} )
|
||||
tmp1=("${(@M)tmp1:#$~patlast}")
|
||||
[[ $#tmp1 -gt 0 && -e "$realpath$donepath${orig%%/*}" ]] || break
|
||||
donepath="$donepath${orig%%/*}/"
|
||||
orig="${orig#*/}"
|
||||
patstr="${patstr#*/}"
|
||||
done
|
||||
|
||||
# Finally, generate the matches. First we loop over all the paths from `-W'.
|
||||
# Note that in this loop `str' is used as a modifyable version of `patstr'
|
||||
# and `testpath' is a modifyable version of `donepath'.
|
||||
# Now we generate the matches. First we loop over all prefix paths given
|
||||
# with the `-W' option.
|
||||
|
||||
for prepath in "$prepaths[@]"; do
|
||||
str="$patstr"
|
||||
|
||||
# Get local copies of the prefix, suffix, and the prefix path to use
|
||||
# in the following loop, which walks through the pathname components
|
||||
# in the string from the line.
|
||||
|
||||
tpre="$pre"
|
||||
tsuf="$suf"
|
||||
testpath="$donepath"
|
||||
ostr="$orig"
|
||||
|
||||
[[ -z "$prepath" || "$prepath[-1]" = / ]] || prepath="${prepath}/"
|
||||
tmp1=( "$prepath$realpath$donepath" )
|
||||
|
||||
# The second loop tests the components of the path in `str' to get the
|
||||
# possible matches.
|
||||
while true; do
|
||||
|
||||
while [[ "$str" = */* ]] do
|
||||
# `rest' is the pathname after the first slash that is left. In `tmp1'
|
||||
# we get the globbing matches for the pathname component currently
|
||||
# handled.
|
||||
# Skip over `./' and `../'.
|
||||
|
||||
if [[ -n "$_comp_correct" && "${#ostr%%/*}" -le _comp_correct ]]; then
|
||||
mflags="$origflags"
|
||||
if [[ "$tpre" = (.|..)/* ]]; then
|
||||
tmp1=( ${^tmp1}${tpre%%/*}/ )
|
||||
tpre="${tpre#*/}"
|
||||
continue
|
||||
fi
|
||||
|
||||
# Get the prefix and suffix for matching.
|
||||
|
||||
if [[ "$tpre" = */* ]]; then
|
||||
PREFIX="${tpre%%/*}"
|
||||
SUFFIX=""
|
||||
else
|
||||
mflags="$matchflags"
|
||||
PREFIX="${tpre}"
|
||||
SUFFIX="${tsuf%%/*}"
|
||||
fi
|
||||
rest="${str#*/}"
|
||||
tmp1="${prepath}${realpath}${testpath}${~mflags}${str%%/*}(-/)"
|
||||
tmp1=( $~tmp1 )
|
||||
|
||||
if [[ $#tmp1 -eq 0 ]]; then
|
||||
# If this didn't produce any matches, we don't need to test this path
|
||||
# any further, so continue with the next `-W' path, if any.
|
||||
# Get the matching files by globbing.
|
||||
|
||||
continue 2
|
||||
elif [[ $#tmp1 -gt 1 ]]; then
|
||||
# If it produced more than one match, we want to remove those which
|
||||
# don't have possible following pathname components matching the
|
||||
# rest of the string we are completing. (The case with only one
|
||||
# match is handled below.)
|
||||
# In `collect' we will collect those of the produced pathnames that
|
||||
# have a matching possible path-suffix. In `suffixes' we build an
|
||||
# array containing strings build from the rest of the string to
|
||||
# complete and the glob patterns we were given as arguments.
|
||||
if [[ "$tpre$tsuf" = */* ]]; then
|
||||
tmp1=( ${^tmp1}*(D/) )
|
||||
else
|
||||
tmp1=( ${^tmp1}${^~pats} )
|
||||
fi
|
||||
|
||||
collect=()
|
||||
suffixes=( $rest$^pats )
|
||||
suffixes=( "${(@)suffixes:gs.**.*.}" )
|
||||
if [[ -n "$PREFIX$SUFFIX" ]]; then
|
||||
# See which of them match what's on the line.
|
||||
|
||||
if [[ -n "$_comp_correct" && "${#ostr#*/}" -le _comp_correct ]]; then
|
||||
mflags="$origflags"
|
||||
compadd -O tmp2 "$ignore[@]" - "${(@)tmp1##*/}"
|
||||
|
||||
# If no file matches, save the expanded path and continue with
|
||||
# the outer loop.
|
||||
|
||||
if [[ $#tmp2 -eq 0 ]]; then
|
||||
[[ "$tmp1[1]" = */* ]] &&
|
||||
exppaths=( "$exppaths[@]" ${^tmp1%/*}/${tpre}${tsuf} )
|
||||
continue 2
|
||||
fi
|
||||
|
||||
# Remove all files that weren't matched.
|
||||
|
||||
if [[ "$tmp1[1]" = */* ]]; then
|
||||
tmp1=( "${(@M)tmp1:#*/(${(j:|:)~${(@)tmp2:q}})}" )
|
||||
else
|
||||
mflags="$matchflags"
|
||||
fi
|
||||
|
||||
# In the loop the prefixes from the `tmp1' array produced above and
|
||||
# the suffixes we just built are used to produce possible matches
|
||||
# via globbing.
|
||||
|
||||
for i in "$tmp1[@]" ; do
|
||||
tmp2=( ${~i}/${~mflags}${~suffixes} )
|
||||
tmp2=("${(@M)tmp2:#$~patlast}")
|
||||
[[ $#tmp2 -ne 0 ]] && collect=( $collect $i )
|
||||
done
|
||||
|
||||
# If this test showed that none of the matches from the glob in `tmp1'
|
||||
# has a possible sub-path matching what's on the line, we add the
|
||||
# matches found in `tmp1' and otherwise give up and continue with the
|
||||
# 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
|
||||
# pathname component currently handled is ambiguous, so we give
|
||||
# it to the completion code.
|
||||
# First we build the full path prefix in `tmp1'.
|
||||
|
||||
tmp1="$prepath$realpath$testpath"
|
||||
|
||||
# Now produce all matching pathnames in `collect'.
|
||||
|
||||
collect=( ${~collect}/${~matchflags}${~suffixes} )
|
||||
collect=("${(@M)collect:#$~patlast}")
|
||||
|
||||
# And then remove the common path prefix from all these matches.
|
||||
|
||||
collect=( ${collect#$tmp1} )
|
||||
|
||||
# Finally, we add all these matches with the common (unexpanded)
|
||||
# pathprefix (the `-p' option), the path-prefix (the `-W' option)
|
||||
# to allow the completion code to test file type, and the path-
|
||||
# suffix (the `-s' option). We also tell the completion code that
|
||||
# these are file names and that `fignore' should be used as usual
|
||||
# (the `-f' and `-F' options).
|
||||
|
||||
if [[ -n "$menu" ]]; then
|
||||
compadd -QU "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" \
|
||||
-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" -I "$ISUFFIX" \
|
||||
-p "$linepath${testpath:q}" -s "/${${i#*/}:q}" \
|
||||
-M 'r:|/=*' -W "$tmp1" -f "$ignore[@]" - "${${i%%/*}:q}"
|
||||
done
|
||||
fi
|
||||
|
||||
# We have just finished handling all the matches from above, so we
|
||||
# can continue with the next `-W' path.
|
||||
|
||||
continue 2
|
||||
fi
|
||||
|
||||
# We reach this point if only one of the path prefixes in `tmp1'
|
||||
# has a existing path-suffix matching the string from the line.
|
||||
# In this case we accept this match and continue with the next
|
||||
# path-name component.
|
||||
|
||||
tmp1=( "$collect[1]" )
|
||||
elif [[ -n "$_comp_correct" && "$mflags" = "$matchflags" ]]; then
|
||||
|
||||
# If we got only one match with auto-correction and if we get none
|
||||
# without correction, stop now.
|
||||
|
||||
tmp2="${prepath}${realpath}${testpath}${~origflags}${str%%/*}(-/)"
|
||||
tmp2=( $~tmp2 )
|
||||
|
||||
if [[ $#tmp1 -ne $#tmp2 ]]; then
|
||||
compadd -QU "$addpfx[@]" -S '' "$group[@]" "$expl[@]" \
|
||||
-i "$IPREFIX" -I "$ISUFFIX" \
|
||||
-p "$linepath${testpath:q}" -s "/${ostr#*/}" \
|
||||
- "${${tmp1#${prepath}${realpath}${testpath}}:q}"
|
||||
continue 2
|
||||
tmp1=( "${(@M)tmp1:#(${(j:|:)~${(@)tmp2:q}})}" )
|
||||
fi
|
||||
elif (( ! $#tmp1 )); then
|
||||
[[ "$tmp1[1]" = */* ]] &&
|
||||
exppaths=( "$exppaths[@]" ${^tmp1%/*}/${tpre}${tsuf} )
|
||||
continue 2
|
||||
fi
|
||||
# This is also reached if the first globbing produced only one match
|
||||
# in this case we just continue with the next pathname component, too.
|
||||
|
||||
tmp1="$tmp1[1]"
|
||||
testpath="$testpath${tmp1##*/}/"
|
||||
str="$rest"
|
||||
ostr="${ostr#*/}"
|
||||
# Step over to the next component, if any.
|
||||
|
||||
if [[ "$tpre" = */* ]]; then
|
||||
tpre="${tpre#*/}"
|
||||
elif [[ "$tsuf" = */* ]]; then
|
||||
tpre="${tsuf#*/}"
|
||||
tsuf=""
|
||||
else
|
||||
break
|
||||
fi
|
||||
|
||||
# There are more components, so add a slash to the files we are
|
||||
# collecting.
|
||||
|
||||
tmp1=( ${^tmp1}/ )
|
||||
done
|
||||
|
||||
# We are here if all pathname components except the last one (which is still
|
||||
# not tested) are unambiguous. So we add matches with the full path prefix,
|
||||
# no path suffix, the `-W' we are currently handling, all the matches we
|
||||
# can produce in this directory, if any.
|
||||
# The next loop searches the first ambiguous component.
|
||||
|
||||
if [[ -n "$_comp_correct" && "${#ostr#*/}" -le _comp_correct ]]; then
|
||||
mflags="$origflags"
|
||||
else
|
||||
mflags="$matchflags"
|
||||
fi
|
||||
tmp1="$prepath$realpath$testpath"
|
||||
suffixes=( $str$^pats )
|
||||
suffixes=( "${(@)suffixes:gs.**.*.}" )
|
||||
tmp2=( ${~tmp1}${~matchflags}${~suffixes} )
|
||||
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.
|
||||
tmp3="$pre$suf"
|
||||
tmp1=( "${(@)tmp1#${prepath}${realpath}${testpath}}" )
|
||||
|
||||
[[ "$testpath[-1]" = / ]] && testpath="$testpath[1,-2]"
|
||||
[[ -z "$testpath" && "$linepath[-1]" = / ]] && linepath="$linepath[1,-2]"
|
||||
[[ -n "$ostr" && -n "$linepath$testpath" ]] && ostr="/$ostr"
|
||||
while true; do
|
||||
|
||||
# But only if something changed.
|
||||
[[ "${PREFIX}${SUFFIX}" = $linepath$testpath$ostr(|/) ]] && return 1
|
||||
# First we check if some of the files match the original string
|
||||
# for this component. If there are some we remove all other
|
||||
# names. This avoid having `foo' complete to `foo' and `foobar'.
|
||||
|
||||
compadd -QU -S '' "$group[@]" "$expl[@]" \
|
||||
-i "$IPREFIX" -I "$ISUFFIX" -f - "$linepath${testpath:q}$ostr"
|
||||
else
|
||||
compadd -QU "$addpfx[@]" "$addsfx[@]" "$remsfx[@]" "$group[@]" "$expl[@]" \
|
||||
-i "$IPREFIX" -I "$ISUFFIX" \
|
||||
-p "$linepath${testpath:q}" -f "$ignore[@]" \
|
||||
-W "$prepath$realpath$testpath" - "${(@)${(@)tmp2#$tmp1}:q}"
|
||||
if [[ "$tmp3" = */* ]]; then
|
||||
tmp4=( "${(@M)tmp1:#${tmp3%%/*}/*}" )
|
||||
if (( $#tmp4 )); then
|
||||
tmp1=( "$tmp4[@]" )
|
||||
fi
|
||||
fi
|
||||
|
||||
# Next we see if this component is ambiguous.
|
||||
|
||||
if [[ "$tmp3" = */* ]]; then
|
||||
tmp4=( "${(@)tmp1:#${tmp1[1]%%/*}/*}" )
|
||||
else
|
||||
tmp4=( "${(@)tmp1:#${tmp1[1]}}" )
|
||||
fi
|
||||
|
||||
if (( $#tmp4 )); then
|
||||
|
||||
# It is. For menucompletion we now add the possible completions
|
||||
# for this component with the unambigous prefix we have built
|
||||
# and the rest of the string from the line as the suffix.
|
||||
# For normal completion we add the rests of the filenames
|
||||
# collected as the suffixes to make the completion code expand
|
||||
# it as far as possible.
|
||||
|
||||
if [[ -n $menu ]]; then
|
||||
if [[ "$tmp3" = */* ]]; then
|
||||
compadd -Uf -p "$linepath$testpath" -s "/${tmp3#*/}" \
|
||||
-W "$prepath$realpath$testpath" "$ignore[@]" \
|
||||
"$addpfx[@]" "$addsfx[@]" "$remsfx[@]" \
|
||||
"$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \
|
||||
- "${(@)tmp1%%/*}"
|
||||
else
|
||||
compadd -Uf -p "$linepath$testpath" \
|
||||
-W "$prepath$realpath$testpath" "$ignore[@]" \
|
||||
"$addpfx[@]" "$addsfx[@]" "$remsfx[@]" \
|
||||
"$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \
|
||||
- "$tmp1[@]"
|
||||
fi
|
||||
else
|
||||
if [[ "$tmp3" = */* ]]; then
|
||||
for i in "$tmp1[@]"; do
|
||||
compadd -Uf -p "$linepath$testpath" -s "/${i#*/}" \
|
||||
-W "$prepath$realpath$testpath" "$ignore[@]" \
|
||||
"$addpfx[@]" "$addsfx[@]" "$remsfx[@]" -M 'r:|/=* r:|=*' \
|
||||
"$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \
|
||||
- "${i%%/*}"
|
||||
done
|
||||
else
|
||||
compadd -Uf -p "$linepath$testpath" \
|
||||
-W "$prepath$realpath$testpath" "$ignore[@]" \
|
||||
"$addpfx[@]" "$addsfx[@]" "$remsfx[@]" \
|
||||
"$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \
|
||||
- "$tmp1[@]"
|
||||
fi
|
||||
fi
|
||||
tmp4=-
|
||||
break
|
||||
fi
|
||||
|
||||
# If we have checked all components, we stop now and add the
|
||||
# strings collected after the loop.
|
||||
|
||||
if [[ "$tmp3" != */* ]]; then
|
||||
tmp4=""
|
||||
break
|
||||
fi
|
||||
|
||||
# Otherwise we add the unambiguous component to `testpath' and
|
||||
# take it from the filenames.
|
||||
|
||||
testpath="${testpath}${tmp1[1]%%/*}/"
|
||||
tmp1=( "${(@)tmp1#*/}" )
|
||||
|
||||
tmp3="${tmp3#*/}"
|
||||
done
|
||||
|
||||
if [[ -z "$tmp4" ]]; then
|
||||
compadd -Uf -p "$linepath$testpath" \
|
||||
-W "$prepath$realpath$testpath" "$ignore[@]" \
|
||||
"$addpfx[@]" "$addsfx[@]" "$remsfx[@]" \
|
||||
"$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \
|
||||
- "$tmp1[@]"
|
||||
fi
|
||||
done
|
||||
|
||||
# If no matches were found but we have expanded paths which are different
|
||||
# from the original string, use them.
|
||||
# If we are configured to expand paths as far as possible and we collected
|
||||
# expanded paths that are different from the string on the line, we add
|
||||
# them as possible matches.
|
||||
|
||||
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}"
|
||||
$#exppaths -ne 0 && nm -eq compstate[nmatches] ]]; then
|
||||
compadd -U -S '' "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" - \
|
||||
"${(@)exppaths}"
|
||||
fi
|
||||
|
||||
# This sets the return value to indicate that we added matches (or not).
|
||||
|
||||
[[ nm -ne compstate[nmatches] ]]
|
||||
[[ nm -eq compstate[nmatches] ]]
|
||||
|
|
|
|||
|
|
@ -9,24 +9,17 @@
|
|||
#
|
||||
# _sep_parts '(foo bar)' @ hosts
|
||||
#
|
||||
# This will make this function complete the strings in the array
|
||||
# `friends'. If the string on the line contains a `@', the substring
|
||||
# after it will be completed from the array `hosts'. Of course more
|
||||
# arrays may be given, each preceded by another separator string.
|
||||
# This will make this function complete the strings `foo' and `bar'
|
||||
# If the string on the line contains a `@', the substring after it
|
||||
# will be completed from the array `hosts'. Of course more arrays
|
||||
# may be given, each preceded by another separator string.
|
||||
#
|
||||
# This function understands the `-J group', `-V group', and
|
||||
# `-X explanation' options.
|
||||
#
|
||||
# This function does part of the matching itself and calls the functions
|
||||
# `_match_test' and `_match_pattern' for this.
|
||||
|
||||
local str arr sep test testarr tmparr prefix suffixes matchers autosuffix
|
||||
local matchflags opt group expl nm=$compstate[nmatches]
|
||||
|
||||
# Test if we should use this function for the global matcher in use.
|
||||
|
||||
_match_test _sep_parts || return 1
|
||||
|
||||
# Get the options.
|
||||
|
||||
group=()
|
||||
|
|
@ -42,7 +35,7 @@ shift OPTIND-1
|
|||
# Get the string from the line.
|
||||
|
||||
str="$PREFIX$SUFFIX"
|
||||
[[ $#compstate[pattern_match] -ne 0 ]] || str="$str:q"
|
||||
SUFFIX=""
|
||||
prefix=""
|
||||
|
||||
# Walk through the arguments to find the longest unambiguous prefix.
|
||||
|
|
@ -56,61 +49,49 @@ while [[ $# -gt 1 ]]; do
|
|||
tmparr=( ${=arr[2,-2]} )
|
||||
arr=tmparr
|
||||
fi
|
||||
|
||||
# Is the separator on the line?
|
||||
|
||||
[[ "$str" != *${sep}* ]] && break
|
||||
|
||||
# Build a pattern matching the possible matches and get all these
|
||||
# matches in an array.
|
||||
# Get the matching array elements.
|
||||
|
||||
test="${str%%${sep}*}"
|
||||
[[ -n "$_comp_correct" && $#test -le _comp_correct ]] && return 1
|
||||
|
||||
matchflags=""
|
||||
_match_pattern _sep_parts test matchflags
|
||||
[[ -n "$_comp_correct" ]] && matchflags="$matchflags(#a$_comp_correct)"
|
||||
|
||||
test="${matchflags}${test}"
|
||||
testarr=( "${(@M)${(@P)arr}:#${~test}*}" )
|
||||
testarr=( "${(@)testarr:#}" )
|
||||
PREFIX="${str%%${sep}*}"
|
||||
compadd -O testarr - "${(@P)arr}"
|
||||
|
||||
# If there are no matches we give up. If there is more than one
|
||||
# match, this is the part we will complete.
|
||||
|
||||
(( $#testarr )) || return 1
|
||||
[[ $#testarr -gt 1 ]] && break
|
||||
|
||||
# Only one match, add it to the prefix and skip over it in `str',
|
||||
# continuing with the next array and separator.
|
||||
|
||||
prefix="${prefix}${testarr[1]}${sep}"
|
||||
str="${str#*${sep}}"
|
||||
shift 2
|
||||
done
|
||||
|
||||
# Get the array to work upon.
|
||||
|
||||
arr="$1"
|
||||
if [[ "$arr[1]" == '(' ]]; then
|
||||
tmparr=( ${=arr[2,-2]} )
|
||||
arr=tmparr
|
||||
fi
|
||||
|
||||
if [[ $# -le 1 || "$str" != *${2}* ]]; then
|
||||
# No more separators, build the matches.
|
||||
|
||||
test="$str"
|
||||
[[ -n "$_comp_correct" && $#test -le _comp_correct ]] && return 1
|
||||
|
||||
matchflags=""
|
||||
_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:#}" )
|
||||
PREFIX="$str"
|
||||
compadd -O testarr - "${(@P)arr}"
|
||||
fi
|
||||
|
||||
[[ $#testarr -eq 0 || ${#testarr[1]} -eq 0 ]] && return 1
|
||||
|
||||
# Now we build the suffixes to give to the completion code.
|
||||
|
||||
shift
|
||||
matchers=()
|
||||
suffixes=("")
|
||||
|
|
@ -118,26 +99,18 @@ autosuffix=()
|
|||
|
||||
while [[ $# -gt 0 && "$str" == *${1}* ]]; do
|
||||
# Remove anything up to the the suffix.
|
||||
|
||||
str="${str#*${1}}"
|
||||
|
||||
# Again, we get the string from the line up to the next separator
|
||||
# and build a pattern from it.
|
||||
|
||||
if [[ $# -gt 2 ]]; then
|
||||
test="${str%%${3}*}"
|
||||
PREFIX="${str%%${3}*}"
|
||||
else
|
||||
test="$str"
|
||||
PREFIX="$str"
|
||||
fi
|
||||
|
||||
[[ -n "$_comp_correct" && $#test -le _comp_correct ]] && return 1
|
||||
|
||||
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
|
||||
# and the strings from the next array that match the pattern we built.
|
||||
|
||||
|
|
@ -146,26 +119,31 @@ while [[ $# -gt 0 && "$str" == *${1}* ]]; do
|
|||
tmparr=( ${=arr[2,-2]} )
|
||||
arr=tmparr
|
||||
fi
|
||||
tmparr=( "${(@M)${(@P)arr}:#${~test}*}" )
|
||||
tmparr=( "${(@)tmparr:#}" )
|
||||
|
||||
compadd -O tmparr - "${(@P)arr}"
|
||||
|
||||
suffixes=("${(@)^suffixes[@]}${1}${(@)^tmparr}")
|
||||
|
||||
# We want the completion code to generate the most specific suffix
|
||||
# for us, so we collect matching specifications that allow partial
|
||||
# word matching before the separators on the fly.
|
||||
|
||||
matchers=("$matchers[@]" "r:|${1:q}=*")
|
||||
shift 2
|
||||
done
|
||||
|
||||
# If we were given at least one more separator we make the completion
|
||||
# code offer it by appending it as a autoremovable suffix.
|
||||
|
||||
(( $# )) && autosuffix=(-qS "$1")
|
||||
|
||||
# If we have collected matching specifications, we build an array
|
||||
# from it that can be used as arguments to `compadd'.
|
||||
|
||||
[[ $#matchers -gt 0 ]] && matchers=(-M "$matchers")
|
||||
|
||||
# Add the matches for each of the suffixes.
|
||||
|
||||
for i in "$suffixes[@]"; do
|
||||
compadd -U "$group[@]" "$expl[@]" "$matchers[@]" "$autosuffix[@]" \
|
||||
-i "$IPREFIX" -I "$ISUFFIX" -p "$prefix" -s "$i" - "$testarr[@]"
|
||||
|
|
|
|||
|
|
@ -1,25 +1,23 @@
|
|||
# Initialisation for new style completion. This mainly contains some helper
|
||||
# function and aliases. Everything else is split into different files in this
|
||||
# directory that will automatically be made autoloaded (see the end of this
|
||||
# file).
|
||||
# functions and aliases. Everything else is split into different files that
|
||||
# will automatically be made autoloaded (see the end of this file).
|
||||
# The names of the files that will be considered for autoloading have to
|
||||
# start with a underscores (like `_setopt).
|
||||
# start with an underscores (like `_setopt).
|
||||
# The first line of these files will be read and has to say what should be
|
||||
# done with its contents:
|
||||
#
|
||||
# `#defcomp <names ...>'
|
||||
# if the first line looks like this, the file is
|
||||
# autoloaded as a function and that function will
|
||||
# be called to generate the matches when completing
|
||||
# for one of the commands whose <name> is given
|
||||
# `#compdef <names ...>'
|
||||
# If the first line looks like this, the file is autoloaded as a
|
||||
# function and that function will be called to generate the matches
|
||||
# when completing for one of the commands whose <names> are given.
|
||||
#
|
||||
# `#defpatcomp <pattern>'
|
||||
# this defines a function that should be called to generate
|
||||
# matches for commands whose name matches <pattern>; note
|
||||
# that only one pattern may be given
|
||||
# `#compdef -p <pattern>'
|
||||
# This defines a function that should be called to generate matches
|
||||
# for commands whose name matches <pattern>. Note that only one pattern
|
||||
# may be given.
|
||||
#
|
||||
# `#defkeycomp <style> [ <key-sequence> ... ]
|
||||
# this is used to bind special completions to all the given
|
||||
# `#compdef -k <style> [ <key-sequence> ... ]
|
||||
# This is used to bind special completions to all the given
|
||||
# <key-sequence>(s). The <style> is the name of one of the built-in
|
||||
# completion widgets (complete-word, delete-char-or-list,
|
||||
# expand-or-complete, expand-or-complete-prefix, list-choices,
|
||||
|
|
@ -41,11 +39,6 @@
|
|||
# were able to add matches and non-zero otherwise.
|
||||
#
|
||||
# See the file `compdump' for how to speed up initialisation.
|
||||
#
|
||||
# If you are using global matching specifications with `compctl -M ...'
|
||||
# have a look at the files `_match_test' and `_match_pattern'. To make
|
||||
# all the example functions use matching as specified with `-M' these
|
||||
# need some editing.
|
||||
|
||||
# If we got the `-d'-flag, we will automatically dump the new state (at
|
||||
# the end).
|
||||
|
|
@ -220,17 +213,34 @@ compdef() {
|
|||
# and sets the according values in `compconfig'.
|
||||
# Arguments may be `foo=bar' to set key `foo' to `bar' or `baz' to
|
||||
# set key `baz' to the empty string.
|
||||
# If no arguments are given, all configurations keys set are displayed.
|
||||
# With the option `-l' as the first argument, the other arguments are
|
||||
# taken to be key names and the values for theses keys are printed, one
|
||||
# per line.
|
||||
|
||||
compconf() {
|
||||
local i
|
||||
|
||||
for i; do
|
||||
if [[ "$i" = *\=* ]]; then
|
||||
compconfig[${i%%\=*}]="${i#*\=}"
|
||||
if (( $# )); then
|
||||
if [[ "$1" = -l ]]; then
|
||||
shift
|
||||
for i; do
|
||||
print $compconfig[$i]
|
||||
done
|
||||
else
|
||||
compconfig[$i]=''
|
||||
for i; do
|
||||
if [[ "$i" = *\=* ]]; then
|
||||
compconfig[${i%%\=*}]="${i#*\=}"
|
||||
else
|
||||
compconfig[$i]=''
|
||||
fi
|
||||
done
|
||||
fi
|
||||
done
|
||||
else
|
||||
for i in ${(k)compconfig}; do
|
||||
print ${(r:25:)i} $compconfig[$i]
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
# Now we automatically make the definition files autoloaded.
|
||||
|
|
@ -262,12 +272,12 @@ if [[ -z "$_i_done" ]]; then
|
|||
read -rA _i_line < $_i_file
|
||||
_i_tag=$_i_line[1]
|
||||
shift _i_line
|
||||
if [[ $_i_tag = '#defcomp' ]]; then
|
||||
compdef -na "${_i_file:t}" "${_i_line[@]}"
|
||||
elif [[ $_i_tag = '#defpatcomp' ]]; then
|
||||
compdef -pa "${_i_file:t}" "${_i_line[@]}"
|
||||
elif [[ $_i_tag = '#defkeycomp' ]]; then
|
||||
compdef -ka "${_i_file:t}" "${_i_line[@]}"
|
||||
if [[ $_i_tag = '#compdef' ]]; then
|
||||
if [[ $_i_line[1] = -[pk] ]]; then
|
||||
compdef ${_i_line[1]}a "${_i_file:t}" "${(@)_i_line[2,-1]}"
|
||||
else
|
||||
compdef -na "${_i_file:t}" "${_i_line[@]}"
|
||||
fi
|
||||
elif [[ $_i_tag = '#autoload' ]]; then
|
||||
autoload ${_i_file:t}
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -1,356 +1,3 @@
|
|||
The subdirectories contain code for the new function-based completion
|
||||
system. Broadly speaking, this uses shell functions defined for each
|
||||
command to determine how the arguments of a command should be completed.
|
||||
|
||||
You should copy all the files you need or want to a directory of your own,
|
||||
which should be included in your autoload path as defined by $fpath. Then
|
||||
in your .zshrc you should source the file which appears here in
|
||||
Core/compinit. It is recommnded that you use the -d option, which outputs
|
||||
a file containing the necessary variables, bindkeys etc., making later
|
||||
loading much faster. For example,
|
||||
[[ -f ~/completion/compinit ]] && . ~/completion/compinit -d
|
||||
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 section below.
|
||||
|
||||
The subdirectories contain:
|
||||
|
||||
Core:
|
||||
The basic functions and files to be sourced. You will certainly need
|
||||
these, and will most likely not want to alter them --- if you do, it
|
||||
would probably help to give your version a different name. The files
|
||||
are:
|
||||
compinit
|
||||
As already described, this is not a function, but is sourced once
|
||||
(with the `source' or `.' commands) to set up the completion system.
|
||||
compdump
|
||||
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.
|
||||
_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). 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
|
||||
your own particular setup. Files are:
|
||||
_command_names
|
||||
This handles completion of the command word, i.e. the first thing
|
||||
on the command line. You may want to alter this, for example,
|
||||
to complete parameters to assign to.
|
||||
_condition
|
||||
This handles completing inside [[ ... ]] .
|
||||
_default
|
||||
This handles completion of command arguments when no special function
|
||||
exists. Usually this means completing files, but you can modify this
|
||||
as you wish.
|
||||
_long_options
|
||||
This handles options beginning with `--', as in many GNU commands.
|
||||
The command must accept the --help option to list the possible options.
|
||||
__long_options can also take arguments to help it decide what to
|
||||
complete as the value of the option. Note that this is potentially
|
||||
dangerous because the command from the line will be called with the
|
||||
--help option and hence could cause damage if used with a command
|
||||
that does not support it.
|
||||
_match_pattern
|
||||
_match_test
|
||||
These are used by Base/_path_files (and hence also Base/_files)
|
||||
and Base/_sep_parts for file completion with control over
|
||||
matching (whether to complete case-insensitively, or to allow
|
||||
insertion before `.', etc.) See _match_test for instructions.
|
||||
Note _path_files expects these files to be present.
|
||||
_precommand
|
||||
Allows completion when the first word on the line has to be ignored,
|
||||
for example `noglob ...' should ignore the noglob and just complete
|
||||
as if it wasn't there. Add other such commands to the top line.
|
||||
_redirect
|
||||
Completes after `<' or `>': this version calls _files.
|
||||
_subscript
|
||||
For completion in subscripts of parameters, e.g $foo[...].
|
||||
_vars
|
||||
Completion for commands which need variables (so this could also be in
|
||||
the Builtins directory), but also in math environments such as ((...)).
|
||||
_tilde
|
||||
Completion after `~', defaults to user names and named directories.
|
||||
_equal
|
||||
Completion after `=', normally command and alias names are used.
|
||||
_parameter
|
||||
_brace_parameter
|
||||
For completion inside parameter expansions ($... and ${...).
|
||||
Builtins:
|
||||
Define completions for various shell builtins. The top line of each file
|
||||
says which builtins they apply to; in many cases you can guess from the
|
||||
name. Note in particular that _zftp defines completions for all commands
|
||||
beginning `zf', not just for the module command zftp. This is only
|
||||
really useful if you use zftp with the zf* function suite (zfopen, zfget,
|
||||
...).
|
||||
User:
|
||||
This contains a pot pourri of completions for various external commands.
|
||||
Not all will work unmodified on your system.
|
||||
Commands:
|
||||
These functions define separate completion commands which do not use
|
||||
the usual context information, and hence have to be bound separately
|
||||
to keys. As they appear, they have bindings which you can change or
|
||||
delete by altering the top line of the file. To bind a function
|
||||
(strictly speaking, the corresponding completion widget) yourself
|
||||
after completion is loaded, use `bindkey '<key-string>' <_function_name>'.
|
||||
The files are:
|
||||
_correct_filename, bound to \C-xc
|
||||
Correct the word under the cursor as a filename. This is significantly
|
||||
more powerful than the standard \e$ (spell-word) binding.
|
||||
_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.
|
||||
The subdirectories contain code for a shell-based system of command-line
|
||||
completion. This is considerably more powerful than the old `compctl'
|
||||
method. For details, see the compsys(1) manual page (`man zshcompsys').
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#defcomp a2ps
|
||||
#compdef a2ps
|
||||
|
||||
# This is for the GNU version of a2ps.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
#defcomp compress
|
||||
#compdef compress
|
||||
|
||||
_files -g '*~*.Z'
|
||||
|
|
|
|||
|
|
@ -1,4 +1,9 @@
|
|||
#defcomp configure
|
||||
#compdef configure
|
||||
|
||||
_long_options '*=(E|)PREFIX*' '_files -/' \
|
||||
_long_options -i '(--(disable|enable)-FEATURE* --(with|without)-PACKAGE*)' \
|
||||
-s '(#--disable- --enable-
|
||||
#--enable- --disable-
|
||||
#--with- --without-
|
||||
#--without- --with-)' \
|
||||
'*=(E|)PREFIX*' '_files -/' \
|
||||
'*=PROGRAM*' '_command_names'
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#defcomp dd
|
||||
#compdef dd
|
||||
|
||||
if compset -P 1 'conv\='; then
|
||||
# If there's a comma present, ignore up to the last one. The
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
#defcomp xdvi dvips dvibook dviconcat dvicopy dvidvi dviselect dvitodvi dvitype
|
||||
#compdef xdvi dvips dvibook dviconcat dvicopy dvidvi dviselect dvitodvi dvitype
|
||||
|
||||
_files -g '*.(dvi|DVI)'
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#defcomp find
|
||||
#compdef find
|
||||
|
||||
local prev="$words[CURRENT-1]"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
#defcomp gunzip zcat
|
||||
#compdef gunzip zcat
|
||||
|
||||
_files -g '*.[gG][z]'
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
#defcomp gzip
|
||||
#compdef gzip
|
||||
|
||||
_files -g '*~*.[gG][zZ]'
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
#defcomp ftp ncftp ping rwho rup xping traceroute nslookup
|
||||
#compdef ftp ncftp ping rwho rup xping traceroute nslookup
|
||||
|
||||
compgen -k hosts
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
#defcomp make gmake pmake
|
||||
#compdef make gmake pmake
|
||||
|
||||
compgen -s "\$(awk '/^[a-zA-Z0-9][^/ ]+:/ {print \$1}' FS=: [mM]akefile)"
|
||||
compgen -s "\$(awk '/^[a-zA-Z0-9][^\/ ]+:/ {print \$1}' FS=: [mM]akefile)"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#defcomp man
|
||||
#compdef man
|
||||
|
||||
setopt localoptions rcexpandparam
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#defcomp folder folders comp inc mark refile repl scan show next prev rmm pick whom mhn mhpath
|
||||
#compdef folder folders comp inc mark refile repl scan show next prev rmm pick whom mhn mhpath
|
||||
|
||||
# Completion for all possible MH commands.
|
||||
# Alter the following two to your own mh directory and the directory
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
#defcomp acroread
|
||||
#compdef acroread
|
||||
|
||||
_files -g '*.(pdf|PDF)'
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
#defcomp gs ghostview gview psnup psselect pswrap pstops pstruct lpr
|
||||
#compdef gs ghostview gview psnup psselect pswrap pstops pstruct lpr
|
||||
|
||||
_files -g '*([pP][sS]|eps)'
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#defcomp co ci rcs
|
||||
#compdef co ci rcs
|
||||
|
||||
local nm=$compstate[nmatches]
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#defcomp rlogin rsh ssh
|
||||
#compdef rlogin rsh ssh
|
||||
|
||||
if [[ CURRENT -eq 2 ]]; then
|
||||
compgen -k hosts
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
#defcomp strip
|
||||
#compdef strip
|
||||
|
||||
_files -g '*(*)'
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#defcomp stty
|
||||
#compdef stty
|
||||
|
||||
if [[ "$words[CURRENT-1]" = \
|
||||
(*erase|discard|status|dsusp|intr|kill|lnext|quit|reprint|start|s*p) ]]
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#defcomp tar
|
||||
#compdef tar
|
||||
|
||||
# Tar completion. Features:
|
||||
# - Tries to collect tar commands from second position, single letter
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
#defcomp tex latex slitex
|
||||
#compdef tex latex slitex
|
||||
|
||||
_files -g '*.(tex|TEX|texinfo|texi)'
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
#defcomp uncompress zmore
|
||||
#compdef uncompress zmore
|
||||
|
||||
_files -g '*.Z'
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#defpatcomp */X11/*
|
||||
#compdef -p */X11/*
|
||||
|
||||
# A simple pattern completion, just as an example.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
#defcomp xfig
|
||||
#compdef xfig
|
||||
|
||||
_files -g '*.fig'
|
||||
|
|
|
|||
|
|
@ -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-14
|
||||
VERSION_DATE='March 26, 1999'
|
||||
VERSION=3.1.5-pws-15
|
||||
VERSION_DATE='April 13, 1999'
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ TEXI2HTML = texi2html -expandinfo -split_chapter
|
|||
.SUFFIXES: .yo .1
|
||||
|
||||
# man pages to install
|
||||
MAN = zsh.1 zshbuiltins.1 zshcompctl.1 zshcompwid.1 \
|
||||
MAN = zsh.1 zshbuiltins.1 zshcompctl.1 zshcompwid.1 zshcompsys.1 \
|
||||
zshexpn.1 zshmisc.1 zshmodules.1 \
|
||||
zshoptions.1 zshparam.1 zshzle.1 zshall.1
|
||||
|
||||
|
|
@ -48,7 +48,7 @@ YODLSRC = zmacros.yo zman.yo ztexi.yo Zsh/arith.yo Zsh/builtins.yo \
|
|||
Zsh/compat.yo Zsh/compctl.yo Zsh/cond.yo Zsh/exec.yo Zsh/expn.yo \
|
||||
Zsh/filelist.yo Zsh/files.yo Zsh/func.yo Zsh/grammar.yo Zsh/guide.yo \
|
||||
Zsh/index.yo Zsh/intro.yo Zsh/invoke.yo Zsh/jobs.yo Zsh/metafaq.yo \
|
||||
Zsh/modules.yo Zsh/mod_cap.yo Zsh/compwid.yo \
|
||||
Zsh/modules.yo Zsh/mod_cap.yo Zsh/compwid.yo Zsh/compsys.yo \
|
||||
Zsh/mod_clone.yo Zsh/mod_comp1.yo Zsh/mod_compctl.yo Zsh/mod_deltochar.yo \
|
||||
Zsh/mod_example.yo Zsh/mod_files.yo Zsh/mod_stat.yo \
|
||||
Zsh/mod_zle.yo Zsh/options.yo \
|
||||
|
|
@ -115,6 +115,8 @@ zshcompctl.1: Zsh/compctl.yo
|
|||
|
||||
zshcompwid.1: Zsh/compwid.yo
|
||||
|
||||
zshcompsys.1: Zsh/compsys.yo
|
||||
|
||||
zshexpn.1: Zsh/expn.yo
|
||||
|
||||
zshmisc.1: Zsh/grammar.yo Zsh/redirect.yo Zsh/exec.yo Zsh/func.yo \
|
||||
|
|
|
|||
|
|
@ -449,7 +449,8 @@ be shown if there was at least one match added for the explanation
|
|||
string.
|
||||
|
||||
The sequences tt(%B), tt(%b), tt(%S), tt(%s), tt(%U), and tt(%u) specify
|
||||
output attributes (bold, standout, and underline) as in prompts.
|
||||
output attributes (bold, standout, and underline) and tt(%{...%}) can
|
||||
be used to include literal escape sequences as in prompts.
|
||||
)
|
||||
item(tt(-Y) var(explanation))(
|
||||
Identical to tt(-X), except that the var(explanation) first undergoes
|
||||
|
|
|
|||
691
Doc/Zsh/compsys.yo
Normal file
691
Doc/Zsh/compsys.yo
Normal file
|
|
@ -0,0 +1,691 @@
|
|||
texinode(Completion System)()(Zsh Modules)(Top)
|
||||
chapter(Completion System)
|
||||
cindex(completion, system)
|
||||
cindex(completion, programmable)
|
||||
cindex(completion, controlling)
|
||||
sect(Description)
|
||||
|
||||
This describes the shell code for the new completion system. It consists
|
||||
of two scripts and a few other files that define shell functions.
|
||||
The shell functions which implement completion behaviour and which may
|
||||
be bound to keystrokes, are referred to as `widgets'. All are contained
|
||||
in the following subdirectories of the tt(Completion) directory of the main
|
||||
distribution directory.
|
||||
|
||||
startitem()
|
||||
item(tt(Core))(
|
||||
The core scripts and functions. You will certainly need these, though will
|
||||
probably not need to alter them. The contents of this directory is
|
||||
described in more detail below.
|
||||
)
|
||||
item(tt(Base))(
|
||||
Other functions you will almost certainly want if you are going to use
|
||||
any of the standard completion functions. You may want to edit some of
|
||||
these files.
|
||||
)
|
||||
item(tt(Builtins))(
|
||||
Functions for completing arguments of shell builtin commands.
|
||||
)
|
||||
item(tt(User))(
|
||||
Functions for completing arguments of external commands and suites of
|
||||
commands. They may need modifying for your system.
|
||||
)
|
||||
item(tt(Commands))(
|
||||
Functions which implement special types of completion to be bound to
|
||||
keystrokes rather than called by context.
|
||||
)
|
||||
enditem()
|
||||
|
||||
You should decide which files you will be using and copy them to a
|
||||
directory (or multiple directories) of your own which should appear in your
|
||||
tt($fpath) variable so that the functions can be autoloaded.
|
||||
|
||||
startmenu()
|
||||
menu(Initialisation)
|
||||
menu(Control Functions)
|
||||
menu(Completion Functions)
|
||||
endmenu()
|
||||
|
||||
texinode(Initialisation)(Control Functions)()(Completion System)
|
||||
sect(Initialisation)
|
||||
|
||||
To initialise the system, the script tt(compinit) should be sourced with
|
||||
`tt(source )var(<path>)tt(/compinit)' or
|
||||
`tt(. )var(<path>)tt(/compinit)'. This will define a few utility functions,
|
||||
arrange for all the necessary shell functions to be autoloaded, and will
|
||||
then re-bind all keys that do completion to use the new system.
|
||||
|
||||
subsect(Arguments)
|
||||
|
||||
To speed up the running of tt(compinit), it can be made to produce a dumped
|
||||
configuration which will be read in on future invocations. The easiest way
|
||||
to do this is by adding the option tt(-d) whenever tt(compinit) is sourced.
|
||||
In this case the dumped file will have the same name as the sourced file,
|
||||
but with tt(.dump) appended to the end; alternatively, an explicit file
|
||||
name can be given following the tt(-d). On the next call to tt(compinit
|
||||
-d), the dumped file will be read instead.
|
||||
|
||||
If the number of completion files changes, tt(compinit) will recognise this
|
||||
and produce a new dump file. However, if the name of a function or the
|
||||
arguments in the first line of a tt(#compdef) funcion (as described below)
|
||||
change, it is easiest to delete the dump file by hand so that the next time
|
||||
tt(compinit) will re-create it.
|
||||
|
||||
The dumping is actually done by another script, tt(compdump), but you will
|
||||
only need to source this yourself if you change the configuration
|
||||
(e.g. using tt(compdef)) and then want to dump the new one. The name of
|
||||
the old dumped file will be remembered for this.
|
||||
|
||||
subsect(Autoloaded files)
|
||||
|
||||
The convention for autoloaded functions used in completion is that they
|
||||
start with an underscore; as already mentioned, the tt(fpath/FPATH)
|
||||
parameter must contain the directory in which they are stored. When
|
||||
tt(compinit) is sourced, it searches all such files accessible via
|
||||
tt(fpath/FPATH) and reads the first line of each of them. This line should
|
||||
contain one of the tags described below. Files whose first line does not
|
||||
start with one of these tags are not considered to be part of the
|
||||
completion system and will not be treated specially.
|
||||
|
||||
The tags are:
|
||||
|
||||
startitem()
|
||||
item(tt(#compdef) var(names...))(
|
||||
The file will be made autoloadable and the function defined
|
||||
in it will be called when completing var(names), each of which is
|
||||
either the name of a command whose arguments are to be completed or one of
|
||||
a number of special contexts in the form tt(-)var(context)tt(-) described
|
||||
below for the tt(_complete) function.
|
||||
)
|
||||
item(tt(#compdef -p) var(pattern))(
|
||||
The file will be made autoloadable and the function defined in it will be
|
||||
called when completing for a command whose name matches the given
|
||||
var(pattern) (a standard globbing pattern). Note that only one
|
||||
var(pattern) may be given.
|
||||
)
|
||||
item(tt(#compdef -k) var(style key-sequences...))(
|
||||
This can be used bind special completion functions to the
|
||||
var(key-sequences). It creates a widget behaving like the builtin widget
|
||||
var(style), which must be one of those that perform completion, namely
|
||||
tt(complete-word), tt(delete-char-or-list), tt(expand-or-complete),
|
||||
tt(expand-or-complete-prefix), tt(list-choices), tt(menu-complete),
|
||||
tt(menu-expand-or-complete), or tt(reverse-menu-complete).
|
||||
|
||||
The widget is then bound to all the var(key-sequences) given, if any: when
|
||||
one of the var(key-sequences) is typed, the function in the file will
|
||||
be invoked to generate the matches. The widget created has the same
|
||||
name as the file and can also be bound to other keys using tt(bindkey)
|
||||
as usual.
|
||||
)
|
||||
item(tt(#autoload))(
|
||||
This is used for files defining utility function that are not to be
|
||||
called directly as completion functions but should be loaded automatically
|
||||
when invoked. Typically they are to be called from within one of the
|
||||
completion functions.
|
||||
)
|
||||
enditem()
|
||||
|
||||
Note that the tt(#) is part of the tag name and no white space is allowed
|
||||
after it. The tt(#compdef) tags use the tt(compdef) function defined
|
||||
below; the main difference is that the name of the function is supplied
|
||||
implicitly.
|
||||
|
||||
subsect(Functions)
|
||||
|
||||
The tt(compinit) file defines the following functions, which may
|
||||
also be called directly by the user.
|
||||
|
||||
startitem()
|
||||
xitem(tt(compdef) [ tt(-an) ] var(function names...))
|
||||
xitem(tt(compdef -d) var(names...))
|
||||
xitem(tt(compdef -p) [ tt(-a) ] var(function pattern))
|
||||
item(tt(compdef -k) [ tt(-a) ] var(function style key-sequences...))(
|
||||
The first form tells the completion system to call the given
|
||||
var(function) when completing for the contexts or commands
|
||||
whose var(names) are given: this is like the tt(#compdef) tag. If the
|
||||
tt(-n) option is given, any existing completion behaviour for particular
|
||||
contexts or commands will not be altered. These definitions can be deleted
|
||||
by giving the tt(-d) option as in the second form.
|
||||
|
||||
The third form is similar to the first, but var(function) will be called
|
||||
for all commands whose name matches the var(pattern); this is like the
|
||||
tt(#compdef -p) function tag.
|
||||
|
||||
The fourth form defines a widget with the same name as the var(function)
|
||||
which will be called for each of the var(key-sequences); this is like the
|
||||
tt(#compdef -k) tag. The function should generate the completions needed
|
||||
and will otherwise behave like the builtin widget whose name is given as
|
||||
the var(style) argument. The widgets usable for this are:
|
||||
tt(complete-word), tt(delete-char-or-list), tt(expand-or-complete),
|
||||
tt(expand-or-complete-prefix), tt(list-choices), tt(menu-complete),
|
||||
tt(menu-expand-or-complete), and tt(reverse-menu-complete).
|
||||
|
||||
In each of the forms supporting it the tt(-a) option makes the
|
||||
var(function) autoloadable (exactly equivalent to
|
||||
tt(autoload )var(function)).
|
||||
)
|
||||
xitem(tt(compconf) var(definitions...))
|
||||
xitem(tt(compconf))
|
||||
item(tt(compconf) [ tt(-l) ] var(keys...))(
|
||||
Several aspects of the completion system can be configured by the
|
||||
user. The configuration values are stored under the keys described
|
||||
below in the associative array `tt(compconfig)'. After sourcing
|
||||
tt(compinit), configuration values can either be set directly as in
|
||||
`tt(compconfig[completer]=_complete)' or by calling this utility function.
|
||||
|
||||
Each var(definition) may be either a simple `var(key)', which sets this
|
||||
key in the tt(compconfig) array to an empty string, or of the form
|
||||
`var(key=value)' which stores the `var(value)' under key `var(key)'.
|
||||
|
||||
Since the completion system also uses the array for internal purposes,
|
||||
you should not set all values at once by doing `tt(compconfig=(...))'.
|
||||
|
||||
In the second form (without arguments), this function lists all keys
|
||||
and their values. If given the tt(-l) option as its first argument, as
|
||||
in the last form, the other arguments are taken as names of keys and
|
||||
the values of these keys are printed one per line.
|
||||
)
|
||||
enditem()
|
||||
|
||||
texinode(Control Functions)(Completion Functions)(Initialisation)(Completion System)
|
||||
sect(Control Functions)
|
||||
|
||||
The initialisation script tt(compinit) re-binds all the keys which perform
|
||||
completion to newly created widgets that all call the supplied widget
|
||||
function tt(_main_complete). This function acts as a wrapper calling
|
||||
the so-called `completer' functions that generate matches. If
|
||||
tt(_main_complete) is
|
||||
called with arguments, these are taken as the names of completer
|
||||
functions to be called in the order given. If no arguments are given, the
|
||||
set of functions to try is taken from the colon-separated list in the
|
||||
configuration key tt(completer). For example, to use normal
|
||||
completion and correction if that doesn't generate any matches:
|
||||
|
||||
indent(
|
||||
nofill(tt(compconf completer=_complete:_correct))
|
||||
)
|
||||
|
||||
after sourcing tt(compinit). The default value for this configuration key
|
||||
set up in tt(compinit) is `tt(_complete)', i.e. normally only ordinary
|
||||
completion is tried. The tt(_main_complete) function uses the return value
|
||||
of the completer functions to decide if other completers should be
|
||||
called. If the return value is zero, no other completers are tried and the
|
||||
tt(_main_complete) function returns.
|
||||
|
||||
The following completer functions are contained in the distribution (users
|
||||
may write their own):
|
||||
|
||||
startitem()
|
||||
item(tt(_complete))(
|
||||
This completer generates all possible completions in a context-sensitive
|
||||
manner, i.e. using the tt(compdef) function
|
||||
explained above and the current settings of all special parameters.
|
||||
|
||||
To complete arguments of commands, tt(_complete) uses the utility function
|
||||
tt(_normal), which is in turn responsible for finding the particular
|
||||
function; it is described below. Various contexts of the form
|
||||
tt(-)var(context)tt(-), as mentioned above for the tt(#compdef) tag, are
|
||||
handled specially. These are:
|
||||
|
||||
startitem()
|
||||
item(tt(-equal-))(
|
||||
for completion after an equal sign, other than one occurring in a
|
||||
shell-variable assignment.
|
||||
)
|
||||
item(tt(-tilde-))(
|
||||
for completion after a tilde (`tt(~)') character, but before a slash.
|
||||
)
|
||||
item(tt(-redirect-))(
|
||||
for completion after a redirection operator.
|
||||
)
|
||||
item(tt(-math-))(
|
||||
for completion inside mathematical contexts, such as
|
||||
`tt(LPAR()LPAR())...tt(RPAR()RPAR())'.
|
||||
)
|
||||
item(tt(-subscript-))(
|
||||
for completion inside subscripts.
|
||||
)
|
||||
item(tt(-value-))(
|
||||
for completion on the right hand side of an assignment.
|
||||
)
|
||||
item(tt(-array-value-))(
|
||||
for completion on the right hand side of an array-assignment
|
||||
(`tt(foo=LPAR()...RPAR())').
|
||||
)
|
||||
item(tt(-condition-))(
|
||||
for completion inside conditions (`tt([[...]])').
|
||||
)
|
||||
item(tt(-parameter-))(
|
||||
for completing the name of a parameter expansion (`tt($...)').
|
||||
)
|
||||
item(tt(-brace-parameter-))(
|
||||
for completing the name of a parameter expansion within braces
|
||||
(`tt(${...})').
|
||||
)
|
||||
item(tt(-first-))(
|
||||
for adding completions before any other other completion functions are
|
||||
tried (similar to the `tt(-T)' flag of tt(compctl)); if this
|
||||
function sets the tt(_compskip) parameter to any value, the completion
|
||||
system will not call any other function to generate matches.
|
||||
)
|
||||
item(tt(-default-))(
|
||||
for generating completions when no special completion function is used
|
||||
(similar to the `tt(-D)' option of tt(compctl)).
|
||||
)
|
||||
item(tt(-command-))(
|
||||
for completing in a command position (as with the `tt(-C)' option of
|
||||
tt(compctl)).
|
||||
)
|
||||
enditem()
|
||||
|
||||
Default implementations are supplied for each of these
|
||||
contexts, in most cases named after the context itself
|
||||
(e.g. completion for the `tt(-tilde-)' context is done by the function
|
||||
named `tt(_tilde)').
|
||||
)
|
||||
item(tt(_approximate))(
|
||||
This completer function uses the tt(_complete) completer to generate
|
||||
a list of strings for the context the cursor is currently in, allowing
|
||||
you to specify a maximum number of errors: see the description of
|
||||
approximate matching in
|
||||
ifzman(\
|
||||
zmanref(zshexpn)
|
||||
)\
|
||||
ifnzman(\
|
||||
noderef(Filename Generation)
|
||||
)\
|
||||
for how errors are
|
||||
counted. The resulting list of corrected and completed strings is then
|
||||
presented to the user. The intended use of this completer function is to
|
||||
try after the normal tt(_complete) completer by setting:
|
||||
|
||||
indent(
|
||||
nofill(tt(compconf completer=_complete:_approximate))
|
||||
)
|
||||
|
||||
This will give correcting completion if and only if
|
||||
normal completion doesn't yield any possible completions. When
|
||||
corrected completions are found, the completer will normally start
|
||||
menucompletion allowing you to cycle through these strings.
|
||||
|
||||
The exact behavior of this completer can be changed by using the
|
||||
following configuration keys:
|
||||
|
||||
startitem()
|
||||
item(tt(approximate_accept))(
|
||||
This should be set to the number of errors the correction code should
|
||||
accept. The completer will try to generate completions by first allowing
|
||||
one error, then two errors, and so on, until either a match
|
||||
was found or the maximum number of errors given by this key has
|
||||
been reached.
|
||||
|
||||
If the value for this key contains a lower- or upper-case `tt(n)', the
|
||||
completer function will take any numeric argument as the
|
||||
maximum number of errors allowed. For example, with
|
||||
|
||||
indent(
|
||||
nofill(tt(compconf approximate_accept=2n))
|
||||
)
|
||||
|
||||
two errors will be allowed if no numeric argument is given. However,
|
||||
with a numeric argument of six (as in `tt(ESC-6 TAB)'), up to six
|
||||
errors are accepted. Hence with a value of `tt(0n)', no correcting
|
||||
completion will be attempted unless a numeric argument is given.
|
||||
|
||||
If the value contains `tt(n)' or `tt(N)' and a exclamation mark
|
||||
(`tt(!)'), tt(_approximate) will var(not) try to generate corrected
|
||||
completions when given a numeric argument, so in this case the number given
|
||||
should be greater than zero. For example, `tt(2n!)' specifies that
|
||||
correcting completion with two errors will usually be performed, but if a
|
||||
numeric argument is given, correcting completion will not be performed.
|
||||
)
|
||||
item(tt(approximate_original))(
|
||||
This key is used to specify whether the original string on which correcting
|
||||
completion was attempted is to be included in the list of possible
|
||||
corrections. If it is set to any non-empty string, the original string
|
||||
will be offered when cycling through the completions. Normally it will
|
||||
appear as the first string, so that the command line does not change
|
||||
immediately; consecutive completion attempts will cycle through the
|
||||
corrected strings. If the value for this key contains the substring
|
||||
`tt(last)', the original string will be the last one in the list, so
|
||||
that it appears just before wrapping around to the first corrected
|
||||
string again. Also, if the value contains the substring `tt(always)',
|
||||
the original string will always be included; normally it is
|
||||
included only if more than one possible correction was generated.
|
||||
)
|
||||
item(tt(approximate_prompt))(
|
||||
This can be set to a string to be displayed on top of the
|
||||
corrected strings generated when cycling through them. This string
|
||||
may contain the control sequences `tt(%n)', `tt(%B)', etc. known from
|
||||
the `tt(-X)' option of tt(compctl). Also, the sequence `tt(%e)' will
|
||||
be replaced by the number of errors accepted to generate the corrected
|
||||
strings.
|
||||
)
|
||||
item(tt(approximate_insert))(
|
||||
If this is set to a string starting with `tt(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 tt(approximate_original). If no sensible string could be
|
||||
found, one can cycle through the corrected strings as usual.
|
||||
)
|
||||
enditem()
|
||||
|
||||
If any of these keys is not set, but the the same key with the prefix
|
||||
`tt(correct)' instead of `tt(approximate)' is set, that value will be
|
||||
used. The forms beginning with `tt(correct)' are also used by the
|
||||
tt(_correct) completer function.
|
||||
|
||||
The keys with the `tt(approximate)' prefix have no default values, but
|
||||
tt(compinit) defines default values for tt(correct_accept) (which
|
||||
is set to `tt(2n)'), and tt(correct_prompt).
|
||||
)
|
||||
item(tt(_correct))(
|
||||
Generate corrections (but not completions) for the current word; this is
|
||||
similar to spell-checking. This calls tt(_approximate), but only the
|
||||
configuration parameters beginning tt(correct_) are used.
|
||||
|
||||
For example, with:
|
||||
|
||||
indent(tt(
|
||||
nofill(compconf completer=_complete:_correct:_approximate)
|
||||
nofill(compconf correct_accept='2n!' approximate_accept=3n))
|
||||
)
|
||||
|
||||
correction will accept up to two errors. If a numeric argument is
|
||||
given, correction will not be performed, but correcting completion will be,
|
||||
and 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.
|
||||
|
||||
This completer function is intended to be used without the
|
||||
tt(_approximate) completer or, as in the example, just before
|
||||
it. Using it after the tt(_approximate) completer is useless since
|
||||
tt(_approximate) will at least generate the corrected strings
|
||||
generated by the tt(_correct) completer -- and probably more.
|
||||
)
|
||||
item(tt(_match))(
|
||||
This completer is intended to be used after the tt(_complete)
|
||||
completer. It allows one to give patterns on the command line and
|
||||
to complete all strings metching these patterns from the set of possible
|
||||
completions for the context the cursor is in, without having to set
|
||||
the tt(GLOB_COMPLETE) option.
|
||||
|
||||
Normally this will be done by taking the pattern from the line,
|
||||
inserting a `tt(*)' at the cursor position and comparing the resulting
|
||||
pattern with the possible completions generated. However, if the
|
||||
configuration key tt(match_original) has a value of `tt(only)', no
|
||||
`tt(*)' will be inserted. If tt(match_original) has any other non-empty
|
||||
string as its value, this completer will first try to generate matches
|
||||
without, then with a `tt(*)' inserted at the cursor position.
|
||||
)
|
||||
item(tt(_expand))(
|
||||
This completer function does not really do completion, but instead
|
||||
checks if the word on the command line is eligible for expansion and,
|
||||
if it is, gives detailed control over how this expansion is done. When
|
||||
using this, one should not use the tt(expand-or-complete) widget, but
|
||||
instead use tt(complete-word), as otherwise tt(expand-or-complete)
|
||||
will expand the string on the line before the completion widget is
|
||||
called. Also, this completer should be called before the tt(_complete)
|
||||
completer function.
|
||||
|
||||
Control over how the expanded string will be treated is possible with the
|
||||
following configuration keys:
|
||||
|
||||
startitem()
|
||||
item(tt(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
|
||||
`tt($LPAR()...RPAR())' and `tt(${...})'). If this is set to an
|
||||
non-empty string it should be an expression usable inside a `tt($((...)))'
|
||||
arithmetical expression. In this case, expansion of substitutions will
|
||||
be done if the expression evaluates to `tt(1)'. For example, with
|
||||
|
||||
indent(
|
||||
nofill(tt(compconf expand_substitute='NUMERIC != 1'))
|
||||
)
|
||||
|
||||
substitution will be performed only if given an explicit numeric
|
||||
argument other than `tt(1)', as by typing `tt(ESC 2 TAB)'.
|
||||
)
|
||||
item(tt(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 tt(expand_substitute).
|
||||
)
|
||||
item(tt(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 command line,
|
||||
replacing the original string. However, if this key is set to a
|
||||
non-empty string, the user can cycle through the expansion as in
|
||||
menucompletion. Unless the value contains the substring `tt(only)',
|
||||
the user will still be offered all expansions at once as one of the
|
||||
strings to insert in the command line; normally, this possibility is
|
||||
offered first, but if the value contains the
|
||||
substring `tt(last)', it is offered last. Finally, if the value contains
|
||||
the substring `tt(sort)', the expansions will be sorted alphabetically,
|
||||
normally they are kept in the order the expansion produced them in.
|
||||
)
|
||||
item(tt(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 substring
|
||||
`tt(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 immediately).
|
||||
)
|
||||
item(tt(expand_prompt))(
|
||||
This may be set to a string that should be displayed before the
|
||||
possible expansions. This is passed to the `tt(-X)' option of
|
||||
tt(compadd) and thus may contain the control sequences `tt(%n)',
|
||||
`tt(%B)', etc. Also, the sequence `tt(%o)' in this string will be
|
||||
replaced by the original string.
|
||||
)
|
||||
enditem()
|
||||
|
||||
None of these configuration keys has a default value.
|
||||
)
|
||||
item(tt(_list))(
|
||||
This 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:
|
||||
|
||||
startitem()
|
||||
item(tt(list_condition))(
|
||||
If this key is unset or set to the empty string, the insertion of
|
||||
matches will be delayed unconditionally. If this value is set, it
|
||||
should be set to an expression usable inside a `tt($((...)))'
|
||||
arithmetical expression. In this case, delaying will be done if the
|
||||
expression evaluates to `tt(1)'. For example, with
|
||||
|
||||
indent(
|
||||
nofill(tt(compconf list_condition='NUMERIC != 1'))
|
||||
)
|
||||
|
||||
delaying will be done only if given an explicit numeric argument
|
||||
other than `tt(1)'.
|
||||
)
|
||||
item(tt(list_word))(
|
||||
To find out if listing should be performed on its own, 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 when completion was called
|
||||
the last time will not delay the generation of matches.
|
||||
)
|
||||
enditem()
|
||||
)
|
||||
item(tt(_menu))(
|
||||
This completer is a simple example function implemented to show how
|
||||
menucompletion can be done in shell code. It should be used as the
|
||||
first completer and has the effect of making the code perform
|
||||
menucompletion. Note that this is independent of the setting of the
|
||||
tt(MENU_COMPLETE) option and does not work with the other
|
||||
menucompletion widgets such as tt(reverse-menu-complete), or
|
||||
tt(accept-and-menu-complete).
|
||||
)
|
||||
enditem()
|
||||
|
||||
texinode(Completion Functions)()(Control Functions)(Completion System)
|
||||
sect(Utility Functions)
|
||||
|
||||
Descriptions follow for utility functions that may be
|
||||
useful when writing completion functions. Most of these reside in the
|
||||
tt(Core) subdirectory except where noted. Like the example
|
||||
functions for commands in the distribution, the utility functions
|
||||
generating matches all follow the convention of returning zero if they
|
||||
generated completions and non-zero if no matching completions could be
|
||||
added.
|
||||
|
||||
startitem()
|
||||
item(tt(_compalso))(
|
||||
This function looks up the definitions for the context and command
|
||||
names given as arguments and calls the handler functions for them if
|
||||
there is a definition (given with the tt(compdef) function). For
|
||||
example, the function completing inside subscripts might use
|
||||
`tt(_compalso -math-)' to include the completions generated for
|
||||
mathematical environments.
|
||||
)
|
||||
item(tt(_normal))(
|
||||
This function is used for normal command completion. If
|
||||
completion is attempted on the first word, command names are
|
||||
completed. Otherwise, the arguments are completed by calling the
|
||||
functions defined for this command, including those functions defined
|
||||
for patterns matching the command name. This function can also be
|
||||
called by other completion functions if they have to complete a range
|
||||
of words as a separate command. For example, the function to complete after
|
||||
the pre-command specifiers such as tt(nohup) removes the first word from
|
||||
the tt(words) array, decrements the tt(CURRENT) parameter, then calls this
|
||||
function.
|
||||
|
||||
When calling a function defined for a pattern, this function also
|
||||
checks if the parameter tt(_compskip) is set. If it was set by the
|
||||
function called, no further completion functions are called. With this
|
||||
one can write a pattern completion function that keeps other functions
|
||||
from being tried simply by setting this parameter to any value.
|
||||
)
|
||||
item(tt(_multi_parts))(
|
||||
This functions gets two arguments: a separator character and an
|
||||
array. As usual, the array may be either the
|
||||
name of an array parameter or a literal array in the form
|
||||
`tt(LPAR()foo bar)tt(RPAR())' (i.e. a list of words separated by white
|
||||
space in parentheses). With these arguments, this function will
|
||||
complete to strings from the array where the parts separated by the
|
||||
separator character are completed independently. For example, the
|
||||
tt(_tar) function from the distribution caches the pathnames from the
|
||||
tar file in an array and then calls this function to complete these
|
||||
names in the way normal filenames are completed by the
|
||||
tt(_path_files) function.
|
||||
|
||||
Like other utility functions, this function accepts the `tt(-V)',
|
||||
`tt(-J)', and `tt(-X)' options with an argument and passes them to the
|
||||
tt(compadd) builtin.
|
||||
)
|
||||
item(tt(_sep_parts))(
|
||||
This function gets as arguments alternating arrays and separators.
|
||||
The arrays specify completions for parts of strings to be separated by the
|
||||
separators. The arrays may be the names of array parameters or
|
||||
a quoted list of words in parentheses. For example, with the array
|
||||
`tt(hosts=(ftp news))' the call `tt(_sep_parts '(foo bar)' @ hosts)' will
|
||||
complete the string `tt(f)' to `tt(foo)' and the string `tt(b@n)' to
|
||||
`tt(bar@news)'.
|
||||
|
||||
This function passes the `tt(-V)', `tt(-J)', and `tt(-X)' options and
|
||||
their arguments to the tt(compadd) builtin used to add the matches.
|
||||
)
|
||||
item(tt(_path_files) and tt(_files))(
|
||||
The function tt(_path_files) is used throughout the shell code
|
||||
to complete filenames. The advantage over the builtin
|
||||
completion functions is that it allows completion of partial paths. For
|
||||
example, the string `tt(/u/i/s/sig)' may be completed to
|
||||
`tt(/usr/include/sys/signal.h)'. The options `tt(-/)', `tt(-f)', `tt(-g)',
|
||||
and `tt(-W)' are available as for the tt(compctl)
|
||||
and tt(compgen) builtins; tt(-f) is the default. Additionally, the `tt(-F)'
|
||||
option from the tt(compadd) builtin is supported, giving direct control
|
||||
over which filenames should be ignored as done by the tt(fignore)
|
||||
parameter in normal completion.
|
||||
|
||||
The function tt(_files) calls tt(_path_files) with all the arguments
|
||||
it was passed and, if that generated no matches, call tt(_path_files) again
|
||||
without any tt(-g) or tt(-/) option, thus generating all filenames.
|
||||
|
||||
These functions also accept the `tt(-J)', `tt(-V)', `tt(-X)', `tt(-P)',
|
||||
`tt(-S)', `tt(-q)', `tt(-r)', and `tt(-R)' options from the
|
||||
tt(compadd) builtin.
|
||||
|
||||
Finally, the tt(_path_files) function supports one configuration key:
|
||||
tt(path_expand). If this is set to any 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.
|
||||
)
|
||||
item(tt(_parameters))(
|
||||
This should be used to complete parameter names if you need some of the
|
||||
extra options of tt(compadd). It first tries to complete only non-local
|
||||
parameters. All arguments are passed unchanged to the tt(compadd) builtin.
|
||||
)
|
||||
item(tt(_options))(
|
||||
This can be used to complete option names. The difference to the
|
||||
`tt(-o)' option of tt(compgen) is that this function uses a matching
|
||||
specification that ignores a leading `tt(no)', ignores underscores and
|
||||
allows the user to type upper-case letters, making them match their
|
||||
lower-case counterparts. All arguments passed to this function are
|
||||
propagated unchanged to the tt(compgen) builtin.
|
||||
)
|
||||
item(tt(_set_options) and tt(_unset_options))(
|
||||
These functions complete only set or unset options, with the same
|
||||
matching specification used in the tt(_options) function.
|
||||
|
||||
Note that you need to uncomment a few lines in the tt(_main_complete)
|
||||
function for these functions to work properly. The lines in question
|
||||
are used to store the option settings in effect before the completion
|
||||
widget locally sets the options it needs.
|
||||
)
|
||||
item(tt(_long_options))(
|
||||
This function resides in the tt(Base) subdirectory of the example
|
||||
completion system because it is not used by the core system.
|
||||
|
||||
This function is used to complete long options for commands that
|
||||
support the `tt(--help)' option as, for example, most of the GNU
|
||||
commands do. For this it invokes the command from the line with the
|
||||
`tt(--help)' option and then parses the output to find possible option
|
||||
names. Note that this means that you should be careful to make sure
|
||||
that this function is not called for a command that does not support
|
||||
this option.
|
||||
|
||||
For options that get an argument after a `tt(=)', the function also
|
||||
automatically tries to find out what should be completed as the argument.
|
||||
The possible completions for option-arguments can be described with
|
||||
the arguments to this function. This is done by giving pairs of
|
||||
patterns and actions as consecutive arguments. The actions specify
|
||||
what should be done to complete arguments of those options whose
|
||||
description match the pattern. The action may be a list of words in
|
||||
brackets or in parentheses, separated by spaces. A list in square brackets
|
||||
denotes possible values for an optional argument, a list in parentheses
|
||||
gives words to complete for mandatory arguments. If the action does
|
||||
not start with a square bracket or parenthesis, it should be the name of a
|
||||
command (probably with arguments) that should be invoked to complete
|
||||
after the equal sign. Example:
|
||||
|
||||
indent(
|
||||
nofill(tt(_long_options '*\*' '(yes no)' \))
|
||||
nofill(tt( '*=FILE*' '_files' \))
|
||||
nofill(tt( '*=DIR*' '_files -/'))
|
||||
)
|
||||
|
||||
Here, `tt(yes)' and `tt(no)' will be completed as the argument of
|
||||
options whose description ends in a star, file names for options that
|
||||
contain the substring `tt(=FILE)' in the description, and paths for
|
||||
options whose description contains `tt(=DIR)'. In fact, the last two
|
||||
patterns are not needed since this function always completes files
|
||||
for option descriptions containing `tt(=FILE)' and paths for option
|
||||
descriptions that contain `tt(=DIR)' or `tt(=PATH)'. These builtin
|
||||
patterns can be overridden by patterns given as arguments, however.
|
||||
|
||||
This function also accepts the `tt(-X)', `tt(-J)', and `tt(-V)'
|
||||
options which are passed unchanged to `tt(compadd)'. Finally, it
|
||||
accepts the option `tt(-t)'; if this is given, completion is only done
|
||||
on words starting with two hyphens.
|
||||
)
|
||||
enditem()
|
||||
|
|
@ -186,6 +186,18 @@ normally be shown only if there are at least two matches in the
|
|||
list. Setting tt(force_list) to an non-empty string makes the list be
|
||||
shown even if there is only one match.
|
||||
)
|
||||
item(tt(list_max))(
|
||||
Initially this is set to the value of the tt(LISTMAX) parameter.
|
||||
Completion widgets may set it to any other numeric value and the value
|
||||
stored at when the widget finishes will be used in the same way the
|
||||
value of tt(LISTMAX) is used.
|
||||
)
|
||||
item(tt(last_prompt))(
|
||||
If this is set to an non-empty string, the completion code will move
|
||||
the cursor back to the previous prompt after the list of completions
|
||||
has been displayed. Initially this is set depending on the setting of
|
||||
the tt(ALWAYS_LAST_PROMPT) option.
|
||||
)
|
||||
item(tt(insert))(
|
||||
This will be unset by the completon code if the contents of the
|
||||
command line will not be changed. It is set to tt(unambiguous),
|
||||
|
|
@ -193,6 +205,62 @@ tt(menu), or tt(automenu) if a common unambiguous string will be
|
|||
inserted or if the first match will be inserted and menu completion
|
||||
will be started (due to tt(MENU_COMPLETE) or tt(AUTO_MENU) being set),
|
||||
respectively.
|
||||
|
||||
On exit it may be set to any of the values above with the obvious
|
||||
result or to a number or a string of the form
|
||||
`var(group):var(match)'. If it is set to a number the match whose
|
||||
number is given will be inserted in the command line. A string like
|
||||
`tt(2:4)' specifies which match from which group should be
|
||||
inserted. In this example the fourth match of the second group is
|
||||
inserted. All groups and matches are number from one upwards. In the
|
||||
value of this key, negative numbers count backward from the last match
|
||||
or group (with `tt(-1)' selecting the last match or group) and values
|
||||
out of the range from one to the number of matches or groups are
|
||||
wrapped around (so that a value of zero selects the last match and a
|
||||
value equal to the number of matches or groups plus one selects the
|
||||
first one).
|
||||
)
|
||||
item(tt(to_end))(
|
||||
On entry to the completion widget this is set to tt(single) if the
|
||||
cursor would be moved to the end of the word only if completion
|
||||
generated only one match and that is inserted into the line. Depending
|
||||
on the original position of the cursor and the setting of the option
|
||||
tt(ALWAYS_TO_END) this may also be set to the string tt(match) if the
|
||||
cursor would be moved to the end if a whole match would be inserted
|
||||
(either if there is only one match or if menucompletion is used).
|
||||
|
||||
The value of this key after the completion widget exits will be used
|
||||
to determin when the cursor will be moved to the end of the string
|
||||
inserted into the line. If it is unset or set to the empty string, the
|
||||
cursor will never be moved to the end. If it is set to tt(single), it
|
||||
will be moved to the end only if completion generated only one
|
||||
match. A value of tt(always) says to move the cursor always to the end
|
||||
(even with normal completion when an unambiguous string is inserted),
|
||||
and any other value says to move the cursor to the end when a full
|
||||
match is inserted (a single match or the first match when using
|
||||
menucompletion).
|
||||
)
|
||||
item(tt(old_list))(
|
||||
This is set to tt(yes) if there is still a valid list of completions
|
||||
from a previous completion at the time the widget is invoked. Such a
|
||||
list exists if it was generated by the previous key press. If the list
|
||||
is also shown on the screen, the value of this key is tt(shown).
|
||||
|
||||
After the widget has exited the value of this key is only used if it
|
||||
was set to tt(keep). In this case, the completion code will continue
|
||||
to use this old list. If the widget generated new matches, they will
|
||||
not be used.
|
||||
)
|
||||
item(tt(old_insert))(
|
||||
On entry to the widget this will be set to the number of the match of
|
||||
an old list of completions that is currently inserted in the command
|
||||
line. If no match has been inserted, this is unset.
|
||||
|
||||
As with tt(old_list), the value of this key will only be used if it is
|
||||
the string tt(keep). If it was set to this value by the widget and
|
||||
there was an old match inserted in the line, this match will be kept
|
||||
and if the value of the tt(insert) key says that another match should
|
||||
be inserted, this will be inserted after the old one.
|
||||
)
|
||||
item(tt(exact))(
|
||||
This is set to tt(accept) if an exact match would be accepted by the
|
||||
|
|
@ -268,7 +336,8 @@ 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) ... ])(
|
||||
xitem([ tt(-M) var(match-spec) ] [ tt(-O) var(array) ] [ tt(-A) var(array) ])
|
||||
item([ tt(--) ] [ var(words) ... ])(
|
||||
|
||||
This builtin command can be used to add matches and directly control
|
||||
all the information the completion code stores with each possible
|
||||
|
|
@ -437,6 +506,23 @@ Note that with tt(compadd) this option does not automatically turn on
|
|||
menu completion if tt(AUTO_LIST) is set as the same options for the
|
||||
tt(compctl) and tt(compgen) builtin command do.
|
||||
)
|
||||
item(tt(-O) var(array))(
|
||||
If this option is given, the var(words) are em(not) added to the set of
|
||||
possible completions. Instead, matching is done as usual and all
|
||||
var(words) given as arguments that are matched will be stored in the
|
||||
array parameter whose name is given as var(array).
|
||||
)
|
||||
item(tt(-A) var(array))(
|
||||
Like the tt(-O) option this keeps the var(words) from being stored as
|
||||
possible completions. The matching words are instead stored in the array
|
||||
parameter given as var(array). In difference to the tt(-O) option this
|
||||
does not store the unchanged var(words) given as arguments, but instead
|
||||
the strings the completion code generated while matching. For example,
|
||||
with a matching specification of `tt(-M "L:|no=")', the string `tt(nof)'
|
||||
on the line and the string `tt(foo)' as one of the var(words), this option
|
||||
will make the string `tt(nofoo)' be stored in the array, whereas the tt(-O)
|
||||
option stores the `tt(foo)' originally given.
|
||||
)
|
||||
item(tt(-), tt(--))(
|
||||
This flag ends the list of flags and options. All arguments after it
|
||||
will be taken as the words to use as matches even if they begin with
|
||||
|
|
@ -596,3 +682,9 @@ tt(complete-history LPAR()RPAR() { compgen -H 0 '' })))
|
|||
|
||||
In this the function will complete words from the history matching the
|
||||
current word.
|
||||
|
||||
For a description of the example completion system from the
|
||||
distributions, see
|
||||
ifzman(zmanref(zshcompsys))\
|
||||
ifnzman(noderef(Completion System))\
|
||||
.
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ menu(Zsh Line Editor)
|
|||
menu(Programmable Completion)
|
||||
menu(Completion Widgets)
|
||||
menu(Zsh Modules)
|
||||
menu(Completion System)
|
||||
|
||||
--- Indices ---
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ list(em(zshzle) Zsh command line editing)
|
|||
list(em(zshcompctl) Zsh completion control)
|
||||
list(em(zshcompwid) Zsh completion widgets)
|
||||
list(em(zshmodules) Zsh loadable modules)
|
||||
list(em(zshcompsys) Zsh completion system)
|
||||
ifzshone(\
|
||||
list(em(zshall) Meta-man page containing all of the above)
|
||||
)\
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
texinode(Zsh Modules)()(Completion Widgets)(Top)
|
||||
texinode(Zsh Modules)(Completion System)(Completion Widgets)(Top)
|
||||
chapter(Zsh Modules)
|
||||
cindex(modules)
|
||||
sect(Description)
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ ifzshone(\
|
|||
zmanref(zshbuiltins),
|
||||
zmanref(zshcompctl),
|
||||
zmanref(zshcompwid),
|
||||
zmanref(zshcompsys),
|
||||
zmanref(zshexpn),
|
||||
zmanref(zshmisc),
|
||||
zmanref(zshmodules),
|
||||
|
|
|
|||
|
|
@ -139,6 +139,12 @@ The part of the buffer that lies to the right of the cursor position.
|
|||
If it is assigned to, only that part of the buffer is replaced, and the
|
||||
cursor remains between the old tt($LBUFFER) and the new tt($RBUFFER).
|
||||
)
|
||||
vindex(PREBUFFER)
|
||||
item(tt(PREBUFFER) (scalar))(
|
||||
In a multi-line input at the secondary prompt, this read-only parameter
|
||||
contains the contents of the lines before the one the cursor is
|
||||
currently in.
|
||||
)
|
||||
vindex(WIDGET)
|
||||
item(tt(WIDGET) (scalar))(
|
||||
The name of the widget currently being executed.
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ ifnzman(includefile(Zsh/zle.yo))
|
|||
ifnzman(includefile(Zsh/compctl.yo))
|
||||
ifnzman(includefile(Zsh/compwid.yo))
|
||||
ifnzman(includefile(Zsh/modules.yo))
|
||||
ifnzman(includefile(Zsh/compsys.yo))
|
||||
ifzshall(\
|
||||
def(source)(1)(NOTRANS(.so )man1/ARG1NOTRANS(.)1)\
|
||||
CMT()
|
||||
|
|
@ -78,6 +79,7 @@ source(zshzle)
|
|||
source(zshcompctl)
|
||||
source(zshcompwid)
|
||||
source(zshmodules)
|
||||
source(zshcompsys)
|
||||
manpage(ZSHALL)(1)(date())(zsh version())
|
||||
)\
|
||||
ifzman(includefile(Zsh/filelist.yo))
|
||||
|
|
|
|||
3
Doc/zshcompsys.yo
Normal file
3
Doc/zshcompsys.yo
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
manpage(ZSHCOMPSYS)(1)(date())(zsh version())
|
||||
manpagename(zshcompsys)(zsh completion system)
|
||||
includefile(Zsh/compsys.yo)
|
||||
|
|
@ -11,15 +11,15 @@
|
|||
# page.
|
||||
#
|
||||
#------------------------------------------------------------------------------
|
||||
hosts=("${${(s: :)${(s: :)${${(f)$(</etc/hosts)}%%\#*}#*[ ]*}}:#}")
|
||||
ports=( "${${${(f)$(</etc/services)}:#\#*}%%[ ]*}" )
|
||||
hosts=("${(@)${(@s: :)${(@s: :)${(@)${(@f)$(</etc/hosts)}%%\#*}#*[ ]*}}:#}")
|
||||
ports=( "${(@)${(@)${(@f)$(</etc/services)}:#\#*}%%[ ]*}" )
|
||||
|
||||
# groups=( $(cut -d: -f1 /etc/group) )
|
||||
# groups=( $(ypcat group.byname | cut -d: -f1) ) # if you use NIS
|
||||
|
||||
# It can be done without forking, but it used too much memory in old zsh's:
|
||||
groups=( "${${(f)$(</etc/group)}%%:*}" )
|
||||
#groups=( "${${(f)$(ypcat groups)}%%:*}" ) # if you use NIS
|
||||
groups=( "${(@)${(@f)$(</etc/group)}%%:*}" )
|
||||
#groups=( "${(@)${(@f)$(ypcat groups)}%%:*}" ) # if you use NIS
|
||||
|
||||
# Completion for zsh builtins.
|
||||
compctl -z -P '%' bg
|
||||
|
|
@ -251,7 +251,7 @@ compctl -k ftphosts ftp
|
|||
# Note that 'r[-exec,;]' must come first
|
||||
if [[ -r /proc/filesystems ]]; then
|
||||
# Linux
|
||||
filesystems='"${${(f)$(</proc/filesystems)}#* }"'
|
||||
filesystems='"${(@)${(@f)$(</proc/filesystems)}#* }"'
|
||||
else
|
||||
filesystems='ufs 4.2 4.3 nfs tmp mfs S51K S52K'
|
||||
fi
|
||||
|
|
@ -563,7 +563,7 @@ cvsprefix() {
|
|||
cvsentries() {
|
||||
setopt localoptions nullglob unset
|
||||
if [[ -f ${pref}CVS/Entries ]]; then
|
||||
reply=( "${pref}${^${${${(f@)$(<${pref}CVS/Entries)}:#D*}#/}%%/*}" )
|
||||
reply=( "${pref}${^${(@)${(@)${(f@)$(<${pref}CVS/Entries)}:#D*}#/}%%/*}" )
|
||||
fi
|
||||
}
|
||||
|
||||
|
|
@ -574,7 +574,7 @@ cvstargets() {
|
|||
}
|
||||
|
||||
cvsrevisions() {
|
||||
reply=( "${${${(M)${(f)$(cvs -q status -vl .)}:# *}##[ ]##}%%[ ]*}" )
|
||||
reply=( "${(@)${(@)${(@M)${(@f)$(cvs -q status -vl .)}:# *}##[ ]##}%%[ ]*}" )
|
||||
}
|
||||
|
||||
cvsrepositories() {
|
||||
|
|
@ -582,7 +582,7 @@ cvsrepositories() {
|
|||
[[ -f CVS/Root ]] && root=$(<CVS/Root)
|
||||
reply=(
|
||||
$root/^CVSROOT(:t)
|
||||
"${${(M)${(f)$(<$root/CVSROOT/modules)}:#[^#]*}%%[ ]*}"
|
||||
"${(@)${(@M)${(@f)$(<$root/CVSROOT/modules)}:#[^#]*}%%[ ]*}"
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -622,7 +622,7 @@ compctl -s '$(rpm -qa)' \
|
|||
'c[-1,--rcfile]' -f - \
|
||||
'p[1] s[-b]' -k '(p l c i b a)' - \
|
||||
'c[-1,--queryformat] N[-1,{]' \
|
||||
-s '"${${(f)$(rpm --querytags)}#RPMTAG_}"' -S '}' - \
|
||||
-s '"${(@)${(@f)$(rpm --querytags)}#RPMTAG_}"' -S '}' - \
|
||||
'W[1,-q*] C[-1,-([^-]*|)f*]' -f - \
|
||||
'W[1,-i*], W[1,-q*] C[-1,-([^-]*|)p*]' \
|
||||
-/g '*.rpm' + -f -- rpm
|
||||
|
|
@ -635,7 +635,7 @@ compctl -K talkmatch talk ytalk ytalk3
|
|||
function talkmatch {
|
||||
local u
|
||||
reply=($(users))
|
||||
for u in "${${(f)$(rwho 2>/dev/null)}%%:*}"; do
|
||||
for u in "${(@)${(@f)$(rwho 2>/dev/null)}%%:*}"; do
|
||||
reply=($reply ${u%% *}@${u##* })
|
||||
done
|
||||
}
|
||||
|
|
|
|||
|
|
@ -190,6 +190,7 @@ struct cmgroup {
|
|||
LinkList lmatches; /* list of matches */
|
||||
LinkList lfmatches; /* list of matches without fignore */
|
||||
LinkList lallccs; /* list of used compctls */
|
||||
int num; /* number of this group */
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -213,6 +214,8 @@ struct cmatch {
|
|||
int brsl; /* ...and the suffix */
|
||||
char *rems; /* when to remove the suffix */
|
||||
char *remf; /* shell function to call for suffix-removal */
|
||||
int rnum; /* group relative number */
|
||||
int gnum; /* global number */
|
||||
};
|
||||
|
||||
#define CMF_FILE 1 /* this is a file */
|
||||
|
|
@ -298,7 +301,12 @@ struct cpattern {
|
|||
#define CP_PATINSERT (1 << 23)
|
||||
#define CP_UNAMBIG (1 << 24)
|
||||
#define CP_UNAMBIGC (1 << 25)
|
||||
#define CP_LISTMAX (1 << 26)
|
||||
#define CP_LASTPROMPT (1 << 27)
|
||||
#define CP_TOEND (1 << 28)
|
||||
#define CP_OLDLIST (1 << 29)
|
||||
#define CP_OLDINS (1 << 30)
|
||||
|
||||
#define CP_NUM 26
|
||||
#define CP_NUM 31
|
||||
|
||||
#define CP_ALLMASK ((1 << CP_NUM) - 1)
|
||||
#define CP_ALLMASK ((int) ((((unsigned int) 1) << CP_NUM) - 1))
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ 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 *, 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 *, char **));
|
||||
|
||||
/**/
|
||||
char *(*comp_strptr) _((int *, int *, int));
|
||||
|
|
@ -103,7 +103,8 @@ int incompfunc;
|
|||
long compcurrent,
|
||||
compnmatches,
|
||||
compmatcher,
|
||||
compmatchertot;
|
||||
compmatchertot,
|
||||
complistmax;
|
||||
|
||||
/**/
|
||||
char **compwords,
|
||||
|
|
@ -124,7 +125,11 @@ char **compwords,
|
|||
*compexact,
|
||||
*compexactstr,
|
||||
*comppatmatch,
|
||||
*comppatinsert;
|
||||
*comppatinsert,
|
||||
*complastprompt,
|
||||
*comptoend,
|
||||
*compoldlist,
|
||||
*compoldins;
|
||||
|
||||
/**/
|
||||
Param *comppms;
|
||||
|
|
@ -439,7 +444,8 @@ setup_comp1(Module m)
|
|||
compcontext = compparameter = compredirect = compquote =
|
||||
compquoting = comprestore = complist = compinsert =
|
||||
compexact = compexactstr = comppatmatch = comppatinsert =
|
||||
compforcelist = NULL;
|
||||
compforcelist = complastprompt = comptoend =
|
||||
compoldlist = compoldins = NULL;
|
||||
makecompparamsptr = NULL;
|
||||
comp_setunsetptr = NULL;
|
||||
return 0;
|
||||
|
|
@ -487,6 +493,10 @@ finish_comp1(Module m)
|
|||
zsfree(compexactstr);
|
||||
zsfree(comppatmatch);
|
||||
zsfree(comppatinsert);
|
||||
zsfree(complastprompt);
|
||||
zsfree(comptoend);
|
||||
zsfree(compoldlist);
|
||||
zsfree(compoldins);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,11 +19,15 @@ compforcelist
|
|||
compinsert
|
||||
compiprefix
|
||||
compisuffix
|
||||
complastprompt
|
||||
complist
|
||||
complistmax
|
||||
compmatcher
|
||||
compmatcherstr
|
||||
compmatchertot
|
||||
compnmatches
|
||||
compoldlist
|
||||
compoldins
|
||||
compparameter
|
||||
comppatinsert
|
||||
comppatmatch
|
||||
|
|
@ -36,6 +40,7 @@ comprestore
|
|||
comp_setunsetptr
|
||||
comp_strptr
|
||||
compsuffix
|
||||
comptoend
|
||||
compwords
|
||||
freecmatcher
|
||||
freecmlist
|
||||
|
|
|
|||
|
|
@ -1694,7 +1694,7 @@ bin_compadd(char *name, char **argv, char *ops, int func)
|
|||
char *p, **sp, *e;
|
||||
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;
|
||||
char *ign = NULL, *rf = NULL, *expl = NULL, *apar = NULL, *opar = NULL;
|
||||
int f = 0, a = CAF_MATCH, dm;
|
||||
Cmatcher match = NULL;
|
||||
|
||||
|
|
@ -1791,6 +1791,14 @@ bin_compadd(char *name, char **argv, char *ops, int func)
|
|||
sp = &rf;
|
||||
e = "function name expected after -%c";
|
||||
break;
|
||||
case 'A':
|
||||
sp = &apar;
|
||||
e = "parameter name expected after -%c";
|
||||
break;
|
||||
case 'O':
|
||||
sp = ⦷
|
||||
e = "parameter name expected after -%c";
|
||||
break;
|
||||
case '-':
|
||||
argv++;
|
||||
goto ca_args;
|
||||
|
|
@ -1799,15 +1807,13 @@ bin_compadd(char *name, char **argv, char *ops, int func)
|
|||
return 1;
|
||||
}
|
||||
if (sp) {
|
||||
if (*sp) {
|
||||
zerrnam(name, "doubled option: -%c", NULL, *p);
|
||||
return 1;
|
||||
}
|
||||
if (p[1]) {
|
||||
*sp = p + 1;
|
||||
if (!*sp)
|
||||
*sp = p + 1;
|
||||
p = "" - 1;
|
||||
} else if (argv[1]) {
|
||||
*sp = *++argv;
|
||||
if (!*sp)
|
||||
*sp = *++argv;
|
||||
p = "" - 1;
|
||||
} else {
|
||||
zerrnam(name, e, NULL, *p);
|
||||
|
|
@ -1826,7 +1832,7 @@ bin_compadd(char *name, char **argv, char *ops, int func)
|
|||
|
||||
match = cpcmatcher(match);
|
||||
a = addmatchesptr(ipre, isuf, ppre, psuf, prpre, pre, suf, group,
|
||||
rs, rf, ign, f, a, match, expl, argv);
|
||||
rs, rf, ign, f, a, match, expl, apar, opar, argv);
|
||||
freecmatcher(match);
|
||||
|
||||
return a;
|
||||
|
|
@ -2152,7 +2158,13 @@ static struct compparam {
|
|||
{ "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) },
|
||||
{ "unambiguous_cursor", PM_INTEGER | PM_READONLY, NULL, NULL,
|
||||
VAL(get_unambig_curs) },
|
||||
{ "list_max", PM_INTEGER, VAL(complistmax), NULL, NULL },
|
||||
{ "last_prompt", PM_SCALAR, VAL(complastprompt), NULL, NULL },
|
||||
{ "to_end", PM_SCALAR, VAL(comptoend), NULL, NULL },
|
||||
{ "old_list", PM_SCALAR, VAL(compoldlist), NULL, NULL },
|
||||
{ "old_insert", PM_SCALAR, VAL(compoldins), NULL, NULL },
|
||||
{ NULL, 0, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -883,7 +883,7 @@ trashzle(void)
|
|||
moveto(nlnct, 0);
|
||||
if (clearflag && tccan(TCCLEAREOD)) {
|
||||
tcout(TCCLEAREOD);
|
||||
clearflag = 0;
|
||||
clearflag = listshown = 0;
|
||||
}
|
||||
if (postedit)
|
||||
fprintf(shout, "%s", postedit);
|
||||
|
|
@ -927,6 +927,7 @@ setup_zle(Module m)
|
|||
/* miscellaneous initialisations */
|
||||
stackhist = stackcs = -1;
|
||||
kungetbuf = (char *) zalloc(kungetsz = 32);
|
||||
hasperm = 0;
|
||||
|
||||
/* initialise the keymap system */
|
||||
init_keymaps();
|
||||
|
|
|
|||
|
|
@ -61,6 +61,8 @@ static struct zleparam {
|
|||
zleunsetfn, NULL },
|
||||
{ "RBUFFER", PM_SCALAR, FN(set_rbuffer), FN(get_rbuffer),
|
||||
zleunsetfn, NULL },
|
||||
{ "PREBUFFER", PM_SCALAR | PM_READONLY, NULL, FN(get_prebuffer),
|
||||
zleunsetfn, NULL },
|
||||
{ "WIDGET", PM_SCALAR | PM_READONLY, NULL, FN(get_widget),
|
||||
zleunsetfn, NULL },
|
||||
{ "LASTWIDGET", PM_SCALAR | PM_READONLY, NULL, FN(get_lwidget),
|
||||
|
|
@ -210,6 +212,16 @@ get_rbuffer(Param pm)
|
|||
return metafy((char *)line + cs, ll - cs, META_HEAPDUP);
|
||||
}
|
||||
|
||||
/**/
|
||||
static char *
|
||||
get_prebuffer(Param pm)
|
||||
{
|
||||
if (chline)
|
||||
return dupstrpfx(chline, hptr - chline);
|
||||
else
|
||||
return dupstring("");
|
||||
}
|
||||
|
||||
/**/
|
||||
static char *
|
||||
get_widget(Param pm)
|
||||
|
|
|
|||
|
|
@ -53,6 +53,11 @@ int nlnct;
|
|||
/**/
|
||||
int showinglist;
|
||||
|
||||
/* Non-zero if a completion list was displayed. */
|
||||
|
||||
/**/
|
||||
int listshown;
|
||||
|
||||
/* Non-zero if ALWAYS_LAST_PROMPT has been used, meaning that the *
|
||||
* screen below the buffer display should not be cleared by *
|
||||
* zrefresh(), but should be by trashzle(). */
|
||||
|
|
@ -253,13 +258,23 @@ zrefresh(void)
|
|||
if (inlist)
|
||||
return;
|
||||
|
||||
if (clearlist) {
|
||||
invalidatelist();
|
||||
moveto(0, 0);
|
||||
clearflag = 0;
|
||||
resetneeded = 1;
|
||||
clearlist = 0;
|
||||
if (clearlist && listshown) {
|
||||
if (tccan(TCCLEAREOD)) {
|
||||
int ovln = vln, ovcs = vcs;
|
||||
|
||||
moveto(nlnct, 0);
|
||||
tcout(TCCLEAREOD);
|
||||
moveto(ovln, ovcs);
|
||||
} else {
|
||||
invalidatelist();
|
||||
moveto(0, 0);
|
||||
clearflag = 0;
|
||||
resetneeded = 1;
|
||||
}
|
||||
listshown = 0;
|
||||
}
|
||||
clearlist = 0;
|
||||
|
||||
#ifdef HAVE_SELECT
|
||||
cost = 0; /* reset */
|
||||
#endif
|
||||
|
|
@ -287,6 +302,7 @@ zrefresh(void)
|
|||
moveto(0, 0);
|
||||
t0 = olnct; /* this is to clear extra lines even when */
|
||||
winchanged = 0; /* the terminal cannot TCCLEAREOD */
|
||||
listshown = 0;
|
||||
}
|
||||
#endif
|
||||
resetvideo();
|
||||
|
|
@ -303,6 +319,7 @@ zrefresh(void)
|
|||
tcout(TCCLEAREOD);
|
||||
else
|
||||
cleareol = 1; /* request: clear to end of line */
|
||||
listshown = 0;
|
||||
}
|
||||
if (t0 > -1)
|
||||
olnct = t0;
|
||||
|
|
|
|||
|
|
@ -72,12 +72,27 @@ static int wb, we;
|
|||
|
||||
static int offs;
|
||||
|
||||
/* These control the type of completion that will be done. They are *
|
||||
* affected by the choice of ZLE command and by relevant shell options. *
|
||||
* usemenu is set to 2 if we have to start automenu. */
|
||||
/* These control the type of completion that will be done. They are *
|
||||
* affected by the choice of ZLE command and by relevant shell options. *
|
||||
* usemenu is set to 2 if we have to start automenu and 3 if we have to *
|
||||
* insert a match as if for menucompletion but without really stating it. */
|
||||
|
||||
static int usemenu, useglob, useexact, useline, uselist;
|
||||
|
||||
/* Non-zero if we should keep an old list. */
|
||||
|
||||
static int oldlist, oldins;
|
||||
|
||||
/* The match and group number to insert when starting menucompletion. */
|
||||
|
||||
static int insmnum, insgnum, insgroup;
|
||||
|
||||
/* This is used to decide when the cursor should be moved to the end of *
|
||||
* the inserted word: 0 - never, 1 - only when a single match is inserted, *
|
||||
* 2 - when a full match is inserted (single or menu), 3 - always. */
|
||||
|
||||
static int movetoend;
|
||||
|
||||
/* != 0 if we are in the middle of a menu completion */
|
||||
|
||||
static int menucmp;
|
||||
|
|
@ -99,12 +114,12 @@ static int menupos, menulen, menuend, menuwe, menuinsc;
|
|||
|
||||
/* This is for completion inside a brace expansion. brbeg and brend hold *
|
||||
* strings that were temporarily removed from the string to complete. *
|
||||
* brpl and brsl, brbsl hold the offset of these strings. *
|
||||
* brpl and brsl, hold the offset of these strings. *
|
||||
* brpcs and brscs hold the positions of the re-inserted string in the *
|
||||
* line. */
|
||||
|
||||
static char *brbeg = NULL, *brend = NULL;
|
||||
static int brpl, brsl, brbsl, brpcs, brscs;
|
||||
static int brpl, brsl, brpcs, brscs, qbrpl, qbrsl, hasunqu;
|
||||
|
||||
/* The list of matches. fmatches contains the matches we first ignore *
|
||||
* because of fignore. */
|
||||
|
|
@ -114,7 +129,16 @@ static LinkList matches, fmatches;
|
|||
/* This holds the list of matches-groups. lmatches is a pointer to the *
|
||||
* last element in this list. */
|
||||
|
||||
static Cmgroup amatches, lmatches;
|
||||
static Cmgroup pmatches, amatches, lmatches;
|
||||
|
||||
/* Non-zero if we have permanently allocated matches. */
|
||||
|
||||
/**/
|
||||
int hasperm;
|
||||
|
||||
/* Number of permanently allocated matches and groups. */
|
||||
|
||||
static int permmnum, permgnum;
|
||||
|
||||
/* The total number of matches and the number of matches to be listed. */
|
||||
|
||||
|
|
@ -155,6 +179,7 @@ static char *ppre, *psuf, *lppre, *lpsuf, *prpre;
|
|||
static char *fpre, *fsuf;
|
||||
static char *ipre, *ripre;
|
||||
static char *isuf;
|
||||
static char *qfpre, *qfsuf, *qrpre, *qrsuf, *qlpre, *qlsuf;
|
||||
static int lpl, lsl, rpl, rsl, fpl, fsl, lppl, lpsl;
|
||||
static int noreal;
|
||||
|
||||
|
|
@ -485,14 +510,9 @@ reversemenucomplete(void)
|
|||
* with the next completions. This gives you a way to *
|
||||
* accept several selections from the list of matches. */
|
||||
|
||||
/**/
|
||||
void
|
||||
acceptandmenucomplete(void)
|
||||
static void
|
||||
acceptlast(void)
|
||||
{
|
||||
if (!menucmp) {
|
||||
feep();
|
||||
return;
|
||||
}
|
||||
if (brbeg && *brbeg) {
|
||||
int l;
|
||||
|
||||
|
|
@ -514,6 +534,17 @@ acceptandmenucomplete(void)
|
|||
menupos = cs;
|
||||
menuwe = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**/
|
||||
void
|
||||
acceptandmenucomplete(void)
|
||||
{
|
||||
if (!menucmp) {
|
||||
feep();
|
||||
return;
|
||||
}
|
||||
acceptlast();
|
||||
menucomplete();
|
||||
}
|
||||
|
||||
|
|
@ -650,7 +681,13 @@ check_param(char *s, int set)
|
|||
int n = 0, br = 1;
|
||||
|
||||
if (*b == Inbrace) {
|
||||
/* If this is a ${...}, ignore the possible (...) flags. */
|
||||
char *tb = b;
|
||||
|
||||
/* If this is a ${...}, see if we are before the '}'. */
|
||||
if (!skipparens(Inbrace, Outbrace, &tb))
|
||||
return NULL;
|
||||
|
||||
/* Ignore the possible (...) flags. */
|
||||
b++, br++;
|
||||
n = skipparens(Inpar, Outpar, &b);
|
||||
}
|
||||
|
|
@ -1494,11 +1531,13 @@ get_comp_string(void)
|
|||
|
||||
if (tt && tt < s + myoffs) {
|
||||
/* Braces are go: delete opening brace */
|
||||
char *com = NULL;
|
||||
char *com = NULL, *tmp;
|
||||
int pl, sl;
|
||||
|
||||
brbeg = dupstring(tt);
|
||||
brpl = tt - s;
|
||||
tmp = dupstrpfx(s, tt - s);
|
||||
qbrpl = strlen(quotename(tmp, NULL));
|
||||
pl = 1;
|
||||
sl = 0;
|
||||
chuck(tt);
|
||||
|
|
@ -1531,8 +1570,8 @@ get_comp_string(void)
|
|||
if (*p == Outbrace)
|
||||
chuck(p);
|
||||
brsl = strlen(s) - (p - s);
|
||||
brbsl = p - s;
|
||||
brend[sl] = '\0';
|
||||
qbrsl = strlen(quotename(p, NULL));
|
||||
}
|
||||
/* we are still waiting for an outbrace and maybe commas */
|
||||
if (brbeg)
|
||||
|
|
@ -2040,7 +2079,7 @@ static int
|
|||
match_str(char *l, char *w, int *bp, int *rwlp, int sfx, int test)
|
||||
{
|
||||
int ll = strlen(l), lw = strlen(w), oll = ll, olw = lw;
|
||||
int il = 0, iw = 0, t, ind, add, bc;
|
||||
int il = 0, iw = 0, t, ind, add, bc = (bp ? *bp : 0);
|
||||
VARARR(unsigned char, ea, ll + 1);
|
||||
char *ow;
|
||||
Cmlist ms;
|
||||
|
|
@ -2054,9 +2093,9 @@ match_str(char *l, char *w, int *bp, int *rwlp, int sfx, int test)
|
|||
|
||||
if (sfx) {
|
||||
l += ll; w += lw;
|
||||
ind = -1; add = -1; bc = brsl;
|
||||
ind = -1; add = -1;
|
||||
} else {
|
||||
ind = 0; add = 1; bc = brpl;
|
||||
ind = 0; add = 1;
|
||||
}
|
||||
/* ow will always point to the beginning (or end) of that sub-string
|
||||
* in w that wasn't put in the match-variables yet. */
|
||||
|
|
@ -2406,17 +2445,19 @@ comp_match(char *pfx, char *sfx, char *w, Comp cp,
|
|||
wl = strlen(w);
|
||||
*clp = bld_parts(w, wl, wl, NULL);
|
||||
*exact = 0;
|
||||
*bpl = (qu ? qbrpl : brpl);
|
||||
*bsl = (qu ? qbrsl : brsl);
|
||||
} else {
|
||||
Cline pli, plil;
|
||||
int mpl, rpl, wl;
|
||||
|
||||
if (qu)
|
||||
w = quotename(w, NULL);
|
||||
w = (qu ? quotename(w, NULL) : dupstring(w));
|
||||
|
||||
wl = strlen(w);
|
||||
|
||||
/* Always try to match the prefix. */
|
||||
|
||||
*bpl = (qu ? qbrpl : brpl);
|
||||
if ((mpl = match_str(pfx, w, bpl, &rpl, 0, 0)) < 0)
|
||||
return NULL;
|
||||
|
||||
|
|
@ -2441,6 +2482,7 @@ comp_match(char *pfx, char *sfx, char *w, Comp cp,
|
|||
plil = matchlastpart;
|
||||
|
||||
/* The try to match the suffix. */
|
||||
*bsl = (qu ? qbrsl : brsl);
|
||||
if ((msl = match_str(sfx, w + mpl, bsl, &rsl, 1, 0)) < 0) {
|
||||
free_cline(pli);
|
||||
|
||||
|
|
@ -2479,6 +2521,7 @@ comp_match(char *pfx, char *sfx, char *w, Comp cp,
|
|||
pli = matchparts;
|
||||
}
|
||||
r = dupstring(matchbuf);
|
||||
|
||||
*clp = pli;
|
||||
|
||||
/* Test if the string built is equal to the one from the line. */
|
||||
|
|
@ -2489,6 +2532,9 @@ comp_match(char *pfx, char *sfx, char *w, Comp cp,
|
|||
} else
|
||||
*exact = !strcmp(pfx, w);
|
||||
}
|
||||
if (!qu)
|
||||
hasunqu = 1;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
@ -3398,6 +3444,22 @@ add_match_data(int alt, char *str, Cline line,
|
|||
return cm;
|
||||
}
|
||||
|
||||
/* This stores the strings from the list in an array. */
|
||||
|
||||
static void
|
||||
set_param(char *name, LinkList l)
|
||||
{
|
||||
char **a, **p;
|
||||
LinkNode n;
|
||||
|
||||
a = (char **) zalloc((countlinknodes(l) + 1) * sizeof(char *));
|
||||
for (p = a, n = firstnode(l); n; incnode(n))
|
||||
*p++ = ztrdup((char *) getdata(n));
|
||||
*p = NULL;
|
||||
|
||||
setaparam(name, a);
|
||||
}
|
||||
|
||||
/* This is used by compadd to add a couple of matches. The arguments are
|
||||
* the strings given via options. The last argument is the array with
|
||||
* the matches. */
|
||||
|
|
@ -3407,22 +3469,29 @@ int
|
|||
addmatches(char *ipre, char *isuf,
|
||||
char *ppre, char *psuf, char *prpre, char *pre,
|
||||
char *suf, char *group, char *rems, char *remf, char *ign,
|
||||
int flags, int aflags, Cmatcher match, char *exp, char **argv)
|
||||
int flags, int aflags, Cmatcher match, char *exp,
|
||||
char *apar, char *opar, char **argv)
|
||||
{
|
||||
char *s, *ms, *lipre = NULL, *lisuf = NULL, *lpre = NULL, *lsuf = NULL;
|
||||
char **aign = NULL;
|
||||
int lpl, lsl, pl, sl, bpl, bsl, llpl = 0, llsl = 0, nm = mnum;
|
||||
int oisalt = 0, isalt, isexact;
|
||||
int oisalt = 0, isalt, isexact, doadd;
|
||||
Cline lc = NULL;
|
||||
Cmatch cm;
|
||||
struct cmlist mst;
|
||||
Cmlist oms = mstack;
|
||||
Comp cp = NULL;
|
||||
LinkList aparl = NULL, oparl = NULL;
|
||||
|
||||
/* Switch back to the heap that was used when the completion widget
|
||||
* was invoked. */
|
||||
SWITCHHEAPS(compheap) {
|
||||
HEAPALLOC {
|
||||
doadd = (!apar && !opar);
|
||||
if (apar)
|
||||
aparl = newlinklist();
|
||||
if (opar)
|
||||
oparl = newlinklist();
|
||||
if (exp) {
|
||||
expl = (Cexpl) zhalloc(sizeof(struct cexpl));
|
||||
expl->count = expl->fcount = 0;
|
||||
|
|
@ -3548,9 +3617,17 @@ addmatches(char *ipre, char *isuf,
|
|||
rems = NULL;
|
||||
} else if (rems)
|
||||
rems = dupstring(rems);
|
||||
|
||||
/* Probably quote the prefix and suffix for testing. */
|
||||
if (!cp && (aflags & CAF_MATCH) && !(aflags & CAF_QUOTE)) {
|
||||
lpre = quotename(lpre, NULL);
|
||||
lsuf = quotename(lsuf, NULL);
|
||||
llpl = strlen(lpre);
|
||||
llsl = strlen(lsuf);
|
||||
}
|
||||
}
|
||||
/* Walk through the matches given. */
|
||||
for (; (s = dupstring(*argv)); argv++) {
|
||||
for (; (s = *argv); argv++) {
|
||||
sl = strlen(s);
|
||||
bpl = brpl;
|
||||
bsl = brsl;
|
||||
|
|
@ -3565,25 +3642,40 @@ addmatches(char *ipre, char *isuf,
|
|||
if ((filell = strlen(*pt)) < sl
|
||||
&& !strcmp(*pt, s + sl - filell))
|
||||
isalt = 1;
|
||||
|
||||
if (isalt && !doadd)
|
||||
continue;
|
||||
}
|
||||
if (!(aflags & CAF_MATCH)) {
|
||||
ms = s;
|
||||
lc = bld_parts(s, sl, -1, NULL);
|
||||
ms = dupstring(s);
|
||||
lc = bld_parts(ms, sl, -1, NULL);
|
||||
isexact = 0;
|
||||
} else if (!(ms = comp_match(lpre, lsuf, s, cp, &lc,
|
||||
(aflags & CAF_QUOTE),
|
||||
!(aflags & CAF_QUOTE),
|
||||
&bpl, &bsl, &isexact)))
|
||||
continue;
|
||||
|
||||
cm = add_match_data(isalt, ms, lc, ipre, ipre, isuf, pre, prpre,
|
||||
ppre, psuf, suf, bpl, bsl,
|
||||
flags, isexact);
|
||||
cm->rems = rems;
|
||||
cm->remf = remf;
|
||||
if (doadd) {
|
||||
cm = add_match_data(isalt, ms, lc, ipre, ipre, isuf, pre,
|
||||
prpre, ppre, psuf, suf, bpl, bsl,
|
||||
flags, isexact);
|
||||
cm->rems = rems;
|
||||
cm->remf = remf;
|
||||
} else {
|
||||
if (apar)
|
||||
addlinknode(aparl, ms);
|
||||
if (opar)
|
||||
addlinknode(oparl, s);
|
||||
free_cline(lc);
|
||||
}
|
||||
}
|
||||
compnmatches = mnum;
|
||||
if (exp)
|
||||
addexpl();
|
||||
if (apar)
|
||||
set_param(apar, aparl);
|
||||
if (opar)
|
||||
set_param(opar, oparl);
|
||||
} LASTALLOC;
|
||||
} SWITCHBACKHEAPS;
|
||||
|
||||
|
|
@ -3629,9 +3721,6 @@ addmatch(char *s, char *t)
|
|||
hn = (HashNode) t;
|
||||
pm = (Param) t;
|
||||
|
||||
if (incompfunc)
|
||||
s = dupstring(s);
|
||||
|
||||
if (addwhat == -1 || addwhat == -5 || addwhat == -6 ||
|
||||
addwhat == CC_FILES || addwhat == -7 || addwhat == -8) {
|
||||
if ((addwhat == CC_FILES ||
|
||||
|
|
@ -3645,10 +3734,13 @@ addmatch(char *s, char *t)
|
|||
!strcmp(*pt, s + sl - filell))
|
||||
isalt = 1;
|
||||
}
|
||||
if (!(ms = comp_match(fpre, fsuf, s, filecomp, &lc,
|
||||
(addwhat == CC_FILES || addwhat == -6 ||
|
||||
addwhat == -5 || addwhat == -8),
|
||||
&bpl, &bsl, &isexact)))
|
||||
ms = ((addwhat == CC_FILES || addwhat == -6 ||
|
||||
addwhat == -5 || addwhat == -8) ?
|
||||
comp_match(qfpre, qfsuf, s, filecomp, &lc, 1,
|
||||
&bpl, &bsl, &isexact) :
|
||||
comp_match(fpre, fsuf, s, filecomp, &lc, 0,
|
||||
&bpl, &bsl, &isexact));
|
||||
if (!ms)
|
||||
return;
|
||||
|
||||
if (addwhat == -7 && !findcmd(s, 0))
|
||||
|
|
@ -3678,10 +3770,19 @@ addmatch(char *s, char *t)
|
|||
(((addwhat & CC_DISCMDS) && (hn->flags & DISABLED)) ||
|
||||
((addwhat & CC_EXCMDS) && !(hn->flags & DISABLED)))) ||
|
||||
((addwhat & CC_BINDINGS) && !(hn->flags & DISABLED))))) {
|
||||
if (!(ms = comp_match(rpre, rsuf, s, patcomp, &lc,
|
||||
char *p1, *s1, *p2, *s2;
|
||||
|
||||
if (addwhat == CC_QUOTEFLAG) {
|
||||
p1 = qrpre; s1 = qrsuf;
|
||||
p2 = rpre; s2 = rsuf;
|
||||
} else {
|
||||
p1 = qlpre; s1 = qlsuf;
|
||||
p2 = lpre; s2 = lsuf;
|
||||
}
|
||||
if (!(ms = comp_match(p1, s1, s, patcomp, &lc,
|
||||
(addwhat == CC_QUOTEFLAG),
|
||||
&bpl, &bsl, &isexact)) &&
|
||||
!(ms = comp_match(lpre, lsuf, s, NULL, &lc,
|
||||
!(ms = comp_match(p2, s2, s, NULL, &lc,
|
||||
(addwhat == CC_QUOTEFLAG),
|
||||
&bpl, &bsl, &isexact)))
|
||||
return;
|
||||
|
|
@ -4002,6 +4103,7 @@ docompletion(char *s, int lst, int incmd)
|
|||
ainfo = fainfo = NULL;
|
||||
matchers = newlinklist();
|
||||
|
||||
hasunqu = 0;
|
||||
useline = (lst != COMP_LIST_COMPLETE);
|
||||
useexact = (isset(RECEXACT) && usemenu != 1);
|
||||
uselist = (useline ?
|
||||
|
|
@ -4014,6 +4116,12 @@ docompletion(char *s, int lst, int incmd)
|
|||
zsfree(compforcelist);
|
||||
compforcelist = ztrdup("");
|
||||
haspattern = 0;
|
||||
complistmax = getiparam("LISTMAX");
|
||||
zsfree(complastprompt);
|
||||
complastprompt = ztrdup(((isset(ALWAYSLASTPROMPT) && zmult == 1) ||
|
||||
(unset(ALWAYSLASTPROMPT) && zmult != 1)) ?
|
||||
"yes" : "");
|
||||
movetoend = ((cs == we || isset(ALWAYSTOEND)) ? 2 : 1);
|
||||
|
||||
/* Make sure we have the completion list and compctl. */
|
||||
if (makecomplist(s, incmd, lst)) {
|
||||
|
|
@ -4031,7 +4139,7 @@ docompletion(char *s, int lst, int incmd)
|
|||
/* We have matches. */
|
||||
if (nmatches > 1)
|
||||
/* There is more than one match. */
|
||||
do_ambiguous();
|
||||
do_ambiguous();
|
||||
|
||||
else if (nmatches == 1) {
|
||||
/* Only one match. */
|
||||
|
|
@ -4039,6 +4147,7 @@ docompletion(char *s, int lst, int incmd)
|
|||
|
||||
while (!m->mcount)
|
||||
m = m->next;
|
||||
menucur = NULL;
|
||||
do_single(m->matches[0]);
|
||||
invalidatelist();
|
||||
}
|
||||
|
|
@ -4069,9 +4178,8 @@ docompletion(char *s, int lst, int incmd)
|
|||
g = g->next;
|
||||
}
|
||||
if (!tr) {
|
||||
clearflag = ((isset(USEZLE) && !termflags &&
|
||||
(isset(ALWAYSLASTPROMPT) && zmult == 1)) ||
|
||||
(unset(ALWAYSLASTPROMPT) && zmult != 1));
|
||||
clearflag = (isset(USEZLE) && !termflags &&
|
||||
complastprompt && *complastprompt);
|
||||
|
||||
if (clearflag && up + nlnct < lines)
|
||||
tcmultout(TCUP, TCMULTUP, up + nlnct);
|
||||
|
|
@ -4099,7 +4207,8 @@ callcompfunc(char *s, char *fn)
|
|||
{
|
||||
List list;
|
||||
int lv = lastval;
|
||||
|
||||
char buf[20];
|
||||
|
||||
if ((list = getshfunc(fn)) != &dummy_list) {
|
||||
char **p, *tmp;
|
||||
int set, aadd = 0, usea = 1, icf = incompfunc, osc = sfcontext;
|
||||
|
|
@ -4108,7 +4217,10 @@ callcompfunc(char *s, char *fn)
|
|||
comppms = (Param *) zalloc(CP_NUM * sizeof(Param));
|
||||
|
||||
set = -1 & ~(CP_PARAMETER | CP_REDIRECT | CP_QUOTE | CP_QUOTING |
|
||||
CP_EXACTSTR | CP_FORCELIST | (useglob ? 0 : CP_PATMATCH));
|
||||
CP_EXACTSTR | CP_FORCELIST | CP_OLDLIST | CP_OLDINS |
|
||||
(useglob ? 0 : CP_PATMATCH));
|
||||
if (!*complastprompt)
|
||||
set &= ~CP_LASTPROMPT;
|
||||
zsfree(compcontext);
|
||||
zsfree(compparameter);
|
||||
zsfree(compredirect);
|
||||
|
|
@ -4205,20 +4317,17 @@ callcompfunc(char *s, char *fn)
|
|||
zsfree(compprefix);
|
||||
zsfree(compsuffix);
|
||||
if (unset(COMPLETEINWORD)) {
|
||||
if (linwhat == IN_MATH)
|
||||
tmp = s;
|
||||
else
|
||||
tmp = quotename(s, NULL);
|
||||
/* Maybe we'll have to do quoting here some time. */
|
||||
tmp = dupstring(s);
|
||||
untokenize(tmp);
|
||||
compprefix = ztrdup(tmp);
|
||||
compsuffix = ztrdup("");
|
||||
} else {
|
||||
char *ss = s + offs, sav;
|
||||
char *ss, sav;
|
||||
|
||||
if (linwhat == IN_MATH)
|
||||
tmp = s;
|
||||
else
|
||||
tmp = quotename(s, &ss);
|
||||
tmp = dupstring(s);
|
||||
ss = tmp + offs;
|
||||
|
||||
sav = *ss;
|
||||
*ss = '\0';
|
||||
untokenize(tmp);
|
||||
|
|
@ -4260,6 +4369,30 @@ callcompfunc(char *s, char *fn)
|
|||
compexact = ztrdup("");
|
||||
set &= ~CP_EXACT;
|
||||
}
|
||||
zsfree(comptoend);
|
||||
if (movetoend == 1)
|
||||
comptoend = ztrdup("single");
|
||||
else
|
||||
comptoend = ztrdup("match");
|
||||
zsfree(compoldlist);
|
||||
zsfree(compoldins);
|
||||
if (hasperm && permmnum) {
|
||||
if (listshown)
|
||||
compoldlist = "shown";
|
||||
else
|
||||
compoldlist = "yes";
|
||||
set |= CP_OLDLIST;
|
||||
if (menucur) {
|
||||
sprintf(buf, "%d", (*menucur)->gnum);
|
||||
compoldins = buf;
|
||||
set |= CP_OLDINS;
|
||||
} else
|
||||
compoldins = "";
|
||||
} else
|
||||
compoldlist = compoldins = "";
|
||||
compoldlist = ztrdup(compoldlist);
|
||||
compoldins = ztrdup(compoldins);
|
||||
|
||||
incompfunc = 1;
|
||||
startparamscope();
|
||||
makecompparamsptr();
|
||||
|
|
@ -4294,10 +4427,32 @@ callcompfunc(char *s, char *fn)
|
|||
else if (!strcmp(compinsert, "auto") ||
|
||||
!strcmp(compinsert, "automenu"))
|
||||
useline = 1, usemenu = 2;
|
||||
else
|
||||
else if (idigit(*compinsert)) {
|
||||
char *m;
|
||||
|
||||
useline = 1; usemenu = 3;
|
||||
insmnum = atoi(compinsert);
|
||||
if ((m = strchr(compinsert, ':'))) {
|
||||
insgroup = 1;
|
||||
insgnum = atoi(m + 1);
|
||||
}
|
||||
} else
|
||||
useline = usemenu = 0;
|
||||
useexact = (compexact && !strcmp(compexact, "accept"));
|
||||
|
||||
if (!comptoend || !*comptoend)
|
||||
movetoend = 0;
|
||||
else if (!strcmp(comptoend, "single"))
|
||||
movetoend = 1;
|
||||
else if (!strcmp(comptoend, "always"))
|
||||
movetoend = 3;
|
||||
else
|
||||
movetoend = 2;
|
||||
|
||||
oldlist = (hasperm && compoldlist && !strcmp(compoldlist, "keep"));
|
||||
oldins = (hasperm && menucur &&
|
||||
compoldins && !strcmp(compoldins, "keep"));
|
||||
|
||||
zfree(comppms, CP_NUM * sizeof(Param));
|
||||
comppms = ocpms;
|
||||
}
|
||||
|
|
@ -4327,6 +4482,7 @@ makecomplist(char *s, int incmd, int lst)
|
|||
struct cmlist ms;
|
||||
Cmlist m;
|
||||
char *p, *os = s;
|
||||
int onm = nmatches;
|
||||
|
||||
/* Inside $... ? */
|
||||
if (compfunc && (p = check_param(s, 0)))
|
||||
|
|
@ -4382,10 +4538,12 @@ makecomplist(char *s, int incmd, int lst)
|
|||
|
||||
if (!validlist)
|
||||
lastambig = 0;
|
||||
amatches = 0;
|
||||
amatches = NULL;
|
||||
mnum = 0;
|
||||
unambig_mnum = -1;
|
||||
isuf = NULL;
|
||||
insmnum = insgnum = 1;
|
||||
insgroup = oldlist = oldins = 0;
|
||||
begcmgroup("default", 0);
|
||||
|
||||
ccused = newlinklist();
|
||||
|
|
@ -4399,7 +4557,7 @@ makecomplist(char *s, int incmd, int lst)
|
|||
|
||||
endcmgroup(NULL);
|
||||
|
||||
if (amatches)
|
||||
if (amatches && !oldlist)
|
||||
amatches->ccs = (Compctl *) makearray(ccused, 0,
|
||||
&(amatches->ccount), NULL);
|
||||
else {
|
||||
|
|
@ -4408,7 +4566,13 @@ makecomplist(char *s, int incmd, int lst)
|
|||
for (n = firstnode(ccused); n; incnode(n))
|
||||
freecompctl((Compctl) getdata(n));
|
||||
}
|
||||
if (oldlist) {
|
||||
nmatches = onm;
|
||||
validlist = 1;
|
||||
amatches = pmatches;
|
||||
|
||||
return 0;
|
||||
}
|
||||
PERMALLOC {
|
||||
permmatches();
|
||||
} LASTALLOC;
|
||||
|
|
@ -4996,9 +5160,9 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
|
|||
delit = ispattern = 0;
|
||||
usemenu = um;
|
||||
patcomp = filecomp = NULL;
|
||||
menucur = NULL;
|
||||
rpre = rsuf = lpre = lsuf = ppre = psuf = lppre = lpsuf = prpre =
|
||||
fpre = fsuf = ipre = ripre = prpre = NULL;
|
||||
rpre = rsuf = lpre = lsuf = ppre = psuf = lppre = lpsuf =
|
||||
fpre = fsuf = ipre = ripre = prpre =
|
||||
qfpre = qfsuf = qrpre = qrsuf = qlpre = qlsuf = NULL;
|
||||
|
||||
curcc = cc;
|
||||
|
||||
|
|
@ -5106,8 +5270,10 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
|
|||
lpre = zhalloc(lpl + 1);
|
||||
memcpy(lpre, s, lpl);
|
||||
lpre[lpl] = '\0';
|
||||
qlpre = quotename(lpre, NULL);
|
||||
lsuf = dupstring(s + offs);
|
||||
lsl = strlen(lsuf);
|
||||
qlsuf = quotename(lsuf, NULL);
|
||||
|
||||
/* First check for ~.../... */
|
||||
if (ic == Tilde) {
|
||||
|
|
@ -5126,9 +5292,11 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
|
|||
rpre = (*p || *lpre == Tilde || *lpre == Equals) ?
|
||||
(noreal = 0, getreal(tt)) :
|
||||
dupstring(tt);
|
||||
qrpre = quotename(rpre, NULL);
|
||||
|
||||
for (p = lsuf; *p && *p != String && *p != Tick; p++);
|
||||
rsuf = *p ? (noreal = 0, getreal(lsuf)) : dupstring(lsuf);
|
||||
qrsuf = quotename(rsuf, NULL);
|
||||
|
||||
/* Check if word is a pattern. */
|
||||
|
||||
|
|
@ -5204,7 +5372,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
|
|||
lppre = dupstring((char *) (line + wb));
|
||||
line[cs] = save;
|
||||
if (brbeg && *brbeg)
|
||||
strcpy(lppre + brpl, lppre + brpl + strlen(brbeg));
|
||||
strcpy(lppre + qbrpl, lppre + qbrpl + strlen(brbeg));
|
||||
if ((p = strrchr(lppre, '/'))) {
|
||||
p[1] = '\0';
|
||||
lppl = strlen(lppre);
|
||||
|
|
@ -5226,7 +5394,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
|
|||
lpsuf = dupstring((char *) (line + cs));
|
||||
line[we] = save;
|
||||
if (brend && *brend) {
|
||||
char *p = lpsuf + brsl - (cs - wb);
|
||||
char *p = lpsuf + qbrsl - (cs - wb);
|
||||
|
||||
strcpy(p, p + strlen(brend));
|
||||
}
|
||||
|
|
@ -5241,8 +5409,10 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
|
|||
/* And get the file prefix. */
|
||||
fpre = dupstring(((s1 == s || s1 == rpre || ic) &&
|
||||
(*s != '/' || cs == wb)) ? s1 : s1 + 1);
|
||||
qfpre = quotename(fpre, NULL);
|
||||
/* And the suffix. */
|
||||
fsuf = dupstrpfx(rsuf, s2 - rsuf);
|
||||
qfsuf = quotename(fsuf, NULL);
|
||||
|
||||
if (comppatmatch && *comppatmatch && (ispattern & 2)) {
|
||||
int t2;
|
||||
|
|
@ -5506,6 +5676,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
|
|||
* that things starting with these characters will be added. */
|
||||
rpre = dyncat((ic == Tilde) ? "~" : "=", rpre);
|
||||
rpl++;
|
||||
qrpre = dyncat((ic == Tilde) ? "~" : "=", qrpre);
|
||||
}
|
||||
if (!ic && (cc->mask & CC_COMMPATH) && !*ppre && !*psuf) {
|
||||
/* If we have to complete commands, add alias names, *
|
||||
|
|
@ -6137,7 +6308,10 @@ permmatches(void)
|
|||
Cmatch *p, *q;
|
||||
Cexpl *ep, *eq, e, o;
|
||||
Compctl *cp, *cq;
|
||||
int nn, nl, fi = 0;
|
||||
int nn, nl, fi = 0, gn = 1, mn = 1, rn;
|
||||
|
||||
if (hasperm)
|
||||
freematches();
|
||||
|
||||
amatches = lmatches = NULL;
|
||||
nmatches = smatches = 0;
|
||||
|
|
@ -6179,13 +6353,17 @@ permmatches(void)
|
|||
n->next = amatches;
|
||||
amatches = n;
|
||||
n->prev = 0;
|
||||
n->num = gn++;
|
||||
|
||||
n->flags = g->flags;
|
||||
n->mcount = g->mcount;
|
||||
n->matches = p = (Cmatch *) ncalloc((n->mcount + 1) *
|
||||
sizeof(Cmatch));
|
||||
for (q = g->matches; *q; q++, p++)
|
||||
for (rn = 1, q = g->matches; *q; q++, p++, rn) {
|
||||
*p = dupmatch(*q);
|
||||
(*p)->rnum = rn++;
|
||||
(*p)->gnum = mn++;
|
||||
}
|
||||
*p = NULL;
|
||||
|
||||
n->lcount = g->lcount;
|
||||
|
|
@ -6216,6 +6394,10 @@ permmatches(void)
|
|||
n->ccs = NULL;
|
||||
g = g->next;
|
||||
}
|
||||
pmatches = amatches;
|
||||
hasperm = 1;
|
||||
permmnum = mn - 1;
|
||||
permgnum = gn - 1;
|
||||
}
|
||||
|
||||
/* This frees one match. */
|
||||
|
|
@ -6247,7 +6429,7 @@ freematch(Cmatch m)
|
|||
static void
|
||||
freematches(void)
|
||||
{
|
||||
Cmgroup g = amatches, n;
|
||||
Cmgroup g = pmatches, n;
|
||||
Cmatch *m;
|
||||
Cexpl *e;
|
||||
Compctl *c;
|
||||
|
|
@ -6281,24 +6463,27 @@ freematches(void)
|
|||
|
||||
g = n;
|
||||
}
|
||||
hasperm = 0;
|
||||
}
|
||||
|
||||
/* Insert the given string into the command line. If move is non-zero, *
|
||||
* the cursor position is changed and len is the length of the string *
|
||||
* to insert (if it is -1, the length is calculated here). */
|
||||
* to insert (if it is -1, the length is calculated here). *
|
||||
* The last argument says if we should quote the string. */
|
||||
|
||||
/**/
|
||||
static void
|
||||
static int
|
||||
inststrlen(char *str, int move, int len)
|
||||
{
|
||||
if (!len || !str)
|
||||
return;
|
||||
return 0;
|
||||
if (len == -1)
|
||||
len = strlen(str);
|
||||
spaceinline(len);
|
||||
strncpy((char *)(line + cs), str, len);
|
||||
if (move)
|
||||
cs += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
/* This builds the unambiguous string. If ins is non-zero, it is
|
||||
|
|
@ -6319,10 +6504,11 @@ cline_str(Cline l, int ins, int *csp)
|
|||
* to re-insert. */
|
||||
if (ins) {
|
||||
if ((hasp = (brbeg && *brbeg))) {
|
||||
plen = strlen(brbeg); pl = brpl;
|
||||
plen = strlen(brbeg); pl = (hasunqu ? brpl : qbrpl);
|
||||
}
|
||||
if ((hass = (brend && *brend))) {
|
||||
slen = strlen(brend); sl = we - wb - brsl - plen - slen + 1;
|
||||
slen = strlen(brend);
|
||||
sl = we - wb - (hasunqu ? brsl : qbrsl) - plen - slen + 1;
|
||||
}
|
||||
if (!pl) {
|
||||
inststrlen(brbeg, 1, -1);
|
||||
|
|
@ -6606,6 +6792,7 @@ do_ambiguous(void)
|
|||
* how REC_EXACT takes effect. We effectively turn the ambiguous *
|
||||
* completion into an unambiguous one. */
|
||||
if (ainfo && ainfo->exact == 1 && useexact && !(fromcomp & FC_LINE)) {
|
||||
menucur = NULL;
|
||||
do_single(ainfo->exactm);
|
||||
invalidatelist();
|
||||
return;
|
||||
|
|
@ -6628,6 +6815,8 @@ do_ambiguous(void)
|
|||
int atend = (cs == we), oll = ll, la;
|
||||
VARARR(char, oline, ll);
|
||||
|
||||
menucur = NULL;
|
||||
|
||||
/* Copy the line buffer to be able to easily test if it changed. */
|
||||
memcpy(oline, line, ll);
|
||||
|
||||
|
|
@ -6653,6 +6842,10 @@ do_ambiguous(void)
|
|||
fromcomp = ((isset(AUTOMENU) ? FC_LINE : 0) |
|
||||
((atend && cs != lastend) ? FC_INWORD : 0));
|
||||
|
||||
/* Probably move the cursor to then end. */
|
||||
if (movetoend == 3)
|
||||
cs = lastend;
|
||||
|
||||
/* If the LIST_AMBIGUOUS option (meaning roughly `show a list only *
|
||||
* if the completion is completely ambiguous') is set, and some *
|
||||
* prefix was inserted, return now, bypassing the list-displaying *
|
||||
|
|
@ -6674,7 +6867,8 @@ do_ambiguous(void)
|
|||
* if it is needed. */
|
||||
if (isset(LISTBEEP))
|
||||
feep();
|
||||
if (uselist && usemenu != 2 && !showinglist &&
|
||||
if (uselist && usemenu != 2 &&
|
||||
(!showinglist || (usemenu == 3 && !oldlist)) &&
|
||||
(smatches >= 2 || (compforcelist && *compforcelist)))
|
||||
showinglist = -2;
|
||||
}
|
||||
|
|
@ -6721,7 +6915,7 @@ do_single(Cmatch m)
|
|||
/* We are currently not in a menu-completion, *
|
||||
* so set the position variables. */
|
||||
menupos = wb;
|
||||
menuwe = (cs == we) || isset(ALWAYSTOEND);
|
||||
menuwe = (movetoend >= 2 || (movetoend == 1 && !menucmp));
|
||||
menuend = we;
|
||||
}
|
||||
/* If we are already in a menu-completion or if we have done a *
|
||||
|
|
@ -6770,14 +6964,20 @@ do_single(Cmatch m)
|
|||
* If it is, we append a slash. */
|
||||
struct stat buf;
|
||||
char *p;
|
||||
int t = 0;
|
||||
|
||||
/* Build the path name. */
|
||||
p = (char *) zhalloc(strlen(prpre) + strlen(str) +
|
||||
if (m->ipre && m->ipre[0] == '~' && !m->ipre[1])
|
||||
t = 1;
|
||||
else {
|
||||
/* Build the path name. */
|
||||
p = (char *) zhalloc(strlen(prpre) + strlen(str) +
|
||||
strlen(psuf) + 3);
|
||||
sprintf(p, "%s%s%s", (prpre && *prpre) ? prpre : "./", str, psuf);
|
||||
sprintf(p, "%s%s%s", (prpre && *prpre) ? prpre : "./", str, psuf);
|
||||
|
||||
/* And do the stat. */
|
||||
if (!(sr = ztat(p, &buf, 0)) && S_ISDIR(buf.st_mode)) {
|
||||
/* And do the stat. */
|
||||
t = (!(sr = ztat(p, &buf, 0)) && S_ISDIR(buf.st_mode));
|
||||
}
|
||||
if (t) {
|
||||
/* It is a directory, so add the slash. */
|
||||
havesuff = 1;
|
||||
inststrlen("/", 1, 1);
|
||||
|
|
@ -6822,23 +7022,71 @@ do_single(Cmatch m)
|
|||
if (menuwe && m->ripre && isset(AUTOPARAMKEYS))
|
||||
makeparamsuffix(((m->flags & CMF_PARBR) ? 1 : 0), menuinsc);
|
||||
|
||||
if (menucmp && !menuwe)
|
||||
if ((menucmp && !menuwe) || !movetoend)
|
||||
cs = menuend;
|
||||
}
|
||||
|
||||
/* This maps the value in v into the range [0,m-1], decrementing v
|
||||
* if it is non-negative and making negative values cound backwards. */
|
||||
|
||||
static int
|
||||
comp_mod(int v, int m)
|
||||
{
|
||||
if (v >= 0)
|
||||
v--;
|
||||
if (v >= 0)
|
||||
return v % m;
|
||||
else {
|
||||
while (v < 0)
|
||||
v += m;
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
/* This handles the beginning of menu-completion. */
|
||||
|
||||
/**/
|
||||
static void
|
||||
do_ambig_menu(void)
|
||||
{
|
||||
menucmp = 1;
|
||||
menucur = NULL;
|
||||
menugrp = amatches;
|
||||
while (!menugrp->mcount)
|
||||
menugrp = menugrp->next;
|
||||
do_single(menugrp->matches[0]);
|
||||
menucur = menugrp->matches;
|
||||
Cmatch *mc;
|
||||
|
||||
if (usemenu != 3) {
|
||||
menucmp = 1;
|
||||
menucur = NULL;
|
||||
} else {
|
||||
if (oldlist) {
|
||||
if (oldins)
|
||||
acceptlast();
|
||||
} else
|
||||
menucur = NULL;
|
||||
}
|
||||
if (insgroup) {
|
||||
insgnum = comp_mod(insgnum, permgnum);
|
||||
for (menugrp = amatches;
|
||||
menugrp && menugrp->num != insgnum + 1;
|
||||
menugrp = menugrp->next);
|
||||
if (!menugrp || !menugrp->mcount) {
|
||||
menucur = NULL;
|
||||
return;
|
||||
}
|
||||
insmnum = comp_mod(insmnum, menugrp->mcount);
|
||||
} else {
|
||||
int c = 0;
|
||||
|
||||
insmnum = comp_mod(insmnum, permmnum);
|
||||
for (menugrp = amatches;
|
||||
menugrp && (c += menugrp->mcount) <= insmnum;
|
||||
menugrp = menugrp->next)
|
||||
insmnum -= menugrp->mcount;
|
||||
if (!menugrp) {
|
||||
menucur = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
mc = menugrp->matches + insmnum;
|
||||
do_single(*mc);
|
||||
menucur = mc;
|
||||
}
|
||||
|
||||
/* Return the length of the common prefix of s and t. */
|
||||
|
|
@ -6924,6 +7172,15 @@ printfmt(char *fmt, int n, int dopr)
|
|||
u = 0; m = 1;
|
||||
tcout(TCUNDERLINEEND);
|
||||
break;
|
||||
case '{':
|
||||
for (p++; *p && (*p != '%' || p[1] != '}'); p++, cc++)
|
||||
if (dopr)
|
||||
putc(*p, shout);
|
||||
if (*p)
|
||||
p++;
|
||||
else
|
||||
p--;
|
||||
break;
|
||||
}
|
||||
if (m) {
|
||||
if (b)
|
||||
|
|
@ -6971,7 +7228,6 @@ listmatches(void)
|
|||
Cexpl *e;
|
||||
int nlines = 0, ncols, nlist = 0, longest = 1, pnl = 0;
|
||||
int of = isset(LISTTYPES), opl = 0;
|
||||
int listmax = getiparam("LISTMAX");
|
||||
|
||||
#ifdef DEBUG
|
||||
/* Sanity check */
|
||||
|
|
@ -6983,11 +7239,10 @@ listmatches(void)
|
|||
|
||||
/* Set the cursor below the prompt. */
|
||||
trashzle();
|
||||
showinglist = 0;
|
||||
showinglist = listshown = 0;
|
||||
|
||||
clearflag = (isset(USEZLE) && !termflags &&
|
||||
(isset(ALWAYSLASTPROMPT) && zmult == 1)) ||
|
||||
(unset(ALWAYSLASTPROMPT) && zmult != 1);
|
||||
complastprompt && *complastprompt);
|
||||
|
||||
for (g = amatches; g; g = g->next) {
|
||||
char **pp = g->ylist;
|
||||
|
|
@ -7066,7 +7321,8 @@ listmatches(void)
|
|||
}
|
||||
|
||||
/* Maybe we have to ask if the user wants to see the list. */
|
||||
if ((listmax && nlist > listmax) || (!listmax && nlines >= lines)) {
|
||||
if ((complistmax && nlist > complistmax) ||
|
||||
(!complistmax && nlines >= lines)) {
|
||||
int qup;
|
||||
zsetterm();
|
||||
qup = printfmt("zsh: do you wish to see all %n possibilities? ", nlist, 1);
|
||||
|
|
@ -7204,6 +7460,7 @@ listmatches(void)
|
|||
if ((nlines += nlnct - 1) < lines) {
|
||||
tcmultout(TCUP, TCMULTUP, nlines);
|
||||
showinglist = -1;
|
||||
listshown = 1;
|
||||
} else
|
||||
clearflag = 0, putc('\n', shout);
|
||||
} else
|
||||
|
|
|
|||
51
Src/glob.c
51
Src/glob.c
|
|
@ -397,6 +397,7 @@ scanner(Complist q)
|
|||
int pbcwdsav = pathbufcwd;
|
||||
int errssofar = errsfound;
|
||||
struct dirsav ds;
|
||||
char *str;
|
||||
|
||||
ds.ino = ds.dev = 0;
|
||||
ds.dirname = NULL;
|
||||
|
|
@ -412,17 +413,18 @@ scanner(Complist q)
|
|||
scanner(q->next);
|
||||
}
|
||||
c = q->comp;
|
||||
str = c->str;
|
||||
/* Now the actual matching for the current path section. */
|
||||
if (!(c->next || c->left) && !haswilds(c->str)
|
||||
if (!(c->next || c->left) && !haswilds(str)
|
||||
&& (!((c->stat & (C_LCMATCHUC|C_IGNCASE)) || c->errsmax)
|
||||
|| !strcmp(".", c->str) || !strcmp("..", c->str))) {
|
||||
|| !*str || !strcmp(".", str) || !strcmp("..", str))) {
|
||||
/*
|
||||
* We always need to match . and .. explicitly, even if we're
|
||||
* checking other strings for case-insensitive matches.
|
||||
*
|
||||
* It's a straight string to the end of the path section.
|
||||
*/
|
||||
int l = strlen(c->str);
|
||||
int l = strlen(str);
|
||||
|
||||
if (l + !l + pathpos - pathbufcwd >= PATH_MAX) {
|
||||
int err;
|
||||
|
|
@ -442,14 +444,14 @@ scanner(Complist q)
|
|||
/* Not the last path section. Just add it to the path. */
|
||||
int oppos = pathpos;
|
||||
|
||||
if (!errflag && !(q->closure && !strcmp(c->str, "."))) {
|
||||
addpath(c->str);
|
||||
if (!errflag && !(q->closure && !strcmp(str, "."))) {
|
||||
addpath(str);
|
||||
if (!closure || statfullpath("", NULL, 1))
|
||||
scanner((q->closure) ? q : q->next);
|
||||
pathbuf[pathpos = oppos] = '\0';
|
||||
}
|
||||
} else
|
||||
insert(c->str, 0);
|
||||
insert(str, 0);
|
||||
} else {
|
||||
/* Do pattern matching on current path section. */
|
||||
char *fn = pathbuf[pathbufcwd] ? unmeta(pathbuf + pathbufcwd) : ".";
|
||||
|
|
@ -2282,16 +2284,45 @@ int
|
|||
getmatch(char **sp, char *pat, int fl, int n, char *replstr)
|
||||
{
|
||||
Comp c;
|
||||
char *s = *sp, *t, *start, sav;
|
||||
int i, l = strlen(*sp), matched;
|
||||
|
||||
MUSTUSEHEAP("getmatch"); /* presumably covered by prefork() test */
|
||||
repllist = NULL;
|
||||
c = parsereg(pat);
|
||||
if (!c) {
|
||||
zerr("bad pattern: %s", pat, 0);
|
||||
return 1;
|
||||
}
|
||||
return igetmatch(sp, c, fl, n, replstr);
|
||||
}
|
||||
|
||||
/**/
|
||||
void
|
||||
getmatcharr(char ***ap, char *pat, int fl, int n, char *replstr)
|
||||
{
|
||||
char **arr = *ap, **pp;
|
||||
Comp c;
|
||||
|
||||
MUSTUSEHEAP("getmatch"); /* presumably covered by prefork() test */
|
||||
|
||||
c = parsereg(pat);
|
||||
if (!c) {
|
||||
zerr("bad pattern: %s", pat, 0);
|
||||
return 1;
|
||||
return;
|
||||
}
|
||||
*ap = pp = ncalloc(sizeof(char *) * (arrlen(arr) + 1));
|
||||
while ((*pp = *arr++))
|
||||
if (igetmatch(pp, c, fl, n, replstr))
|
||||
pp++;
|
||||
}
|
||||
|
||||
/**/
|
||||
static int
|
||||
igetmatch(char **sp, Comp c, int fl, int n, char *replstr)
|
||||
{
|
||||
char *s = *sp, *t, *start, sav;
|
||||
int i, l = strlen(*sp), matched;
|
||||
|
||||
repllist = NULL;
|
||||
|
||||
if (fl & SUB_ALL) {
|
||||
i = domatch(s, c, 0);
|
||||
*sp = get_match_ret(*sp, 0, i ? l : 0, fl, i ? replstr : 0);
|
||||
|
|
|
|||
24
Src/subst.c
24
Src/subst.c
|
|
@ -1361,16 +1361,24 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
NULL, s[-1]);
|
||||
return NULL;
|
||||
}
|
||||
singsub(&s);
|
||||
{
|
||||
char t = s[-1];
|
||||
|
||||
singsub(&s);
|
||||
if (t == '/' && (flags & SUB_SUBSTR)) {
|
||||
if (*s == '#' || *s == '%') {
|
||||
flags &= ~SUB_SUBSTR;
|
||||
if (*s == '%')
|
||||
flags |= SUB_END;
|
||||
s++;
|
||||
} else if (*s == '\\') {
|
||||
s++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!vunset && isarr) {
|
||||
char **ap = aval;
|
||||
char **pp = aval = (char **)ncalloc(sizeof(char *) * (arrlen(aval) + 1));
|
||||
|
||||
while ((*pp = *ap++)) {
|
||||
if (getmatch(pp, s, flags, flnum, replstr))
|
||||
pp++;
|
||||
}
|
||||
getmatcharr(&aval, s, flags, flnum, replstr);
|
||||
copied = 1;
|
||||
} else {
|
||||
if (vunset)
|
||||
|
|
|
|||
|
|
@ -3177,10 +3177,7 @@ bslashquote(const char *s, char **e, int instring)
|
|||
*v++ = *u;
|
||||
}
|
||||
*v = '\0';
|
||||
if (strcmp(buf, s))
|
||||
tt = dupstring(buf);
|
||||
else
|
||||
tt = s;
|
||||
tt = dupstring(buf);
|
||||
v += tt - buf;
|
||||
if (e && (sf & 1))
|
||||
*e += tt - buf;
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue