1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-06-16 20:58:05 +02:00

zsh-3.1.5-pws-10

This commit is contained in:
Tanaka Akira 1999-04-15 18:17:36 +00:00
parent b4a5b9db8b
commit 904b939cbd
97 changed files with 2943 additions and 541 deletions

View file

@ -0,0 +1,3 @@
#defcomp -command-
complist -c

View file

@ -0,0 +1,10 @@
#defcomp -condition-
if [[ -current -1 -o ]]; then
complist -o -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}'
elif [[ -current -1 -nt || -current -1 -ot || -current -1 -ef ]]; then
_files
else
_files
complist -v
fi

13
Completion/Base/_default Normal file
View file

@ -0,0 +1,13 @@
#defcomp -default-
# We first try the `compctl's. This is without first (-T) and default (-D)
# completion. If you want them add `-T' and/or `-D' to this command.
# If there is a `compctl' for the command we are working on, we return
# immediatly. If you want to use new style completion anyway, remove the
# `|| return'. Also, you may want to use new style completion if the
# `compctl' didn't produce any matches. In that case remove the `|| return'
# and at the line `[[ -nmatches 0 ]] || return' after `compcall'.
compcall || return
_files

View file

@ -0,0 +1,31 @@
#autoload
# This function is called from functions that do matching whenever they
# need to build a pattern that is used to match possible completions.
# It gets the name of the calling function and two names of parameters
# as arguments. The first one is used in the calling function to build
# the pattern used for matching possible completions. The content of this
# parameter on entry to this function is the string taken from the line.
# Here it parameter should be changed to a pattern that matches words as
# the match specs currently in use do.
# In the calling function this pattern may be changed again or used only
# in parts. The second parameter whose name is given as the third argument
# allows to give pattern flags liek `(#l)' that are to be used whenever
# matching is done.
#
# As an example, if you have global match specifications like:
#
# compctl -M 'm:{a-z}={A-Z}' 'm:{a-z}={A-Z} r:|[.-]=* r:|=*'
#
# This function would look like:
#
# eval "${3}='(#l)'"
# [[ MATCHER -eq 2 ]] && eval "$1='${(P)2:gs/./*./:gs/-/*-/}'"
#
# The first line makes sure that matching is done case-insensitive as
# specified by `m:{a-z}={A-Z}'. The second line replaces dots and hyphens
# in the given string by patterns matching any characters before them,
# like the `r:|[.-]=* r:|=*'. To make this work, the function `_match_test'
# would have to be changed to `(( MATCHERS <= 2 ))'
#
# The default implementation of this function is empty.

View file

@ -0,0 +1,15 @@
#autoload
# This function is called at the beginning of functions that do matching in
# shell code. It should test the value of the `MATCHER' special parameter
# and return non-zero if the calling function should try to generate matches
# for the global match specification in use.
#
# This function gets one argument, the name of the function calling it.
#
# If you have a global match specification with more than one set of patterns
# you may want to modify this function to return non-zero for all of your
# match specifications and modify the function `_match_pattern' to build the
# pattern to use in the calling function.
(( MATCHER == 1 ))

View file

@ -0,0 +1,5 @@
#defcomp - nohup nice eval time rusage noglob nocorrect exec
[[ -position 1 -1 ]]
_normal "$@"

View file

@ -0,0 +1,3 @@
#defcomp -redirect-
_files

View file

@ -0,0 +1,4 @@
#defcomp -subscript-
_compalso -math- "$@"
[[ ${(Pt)${COMMAND}} = assoc* ]] && complist -k "( ${(kP)${COMMAND}} )"

3
Completion/Base/_vars Normal file
View file

@ -0,0 +1,3 @@
#defcomp -math- getopts read unset vared
complist -v

View file

@ -0,0 +1,3 @@
#defcomp unalias
complist -a

View file

@ -0,0 +1,3 @@
#defcomp shift
complist -A

View file

@ -0,0 +1,3 @@
#defcomp autoload
complist -s '${^fpath}/*(N:t)'

View file

@ -0,0 +1,3 @@
#defcomp bg
complist -z -P '%'

View file

@ -0,0 +1,7 @@
#defcomp bindkey
if [[ -mword 1 -*[DAN]* || -mcurrent -1 -*M ]]; then
complist -s '$(bindkey -l)'
else
complist -b
fi

View file

@ -0,0 +1,7 @@
#defcomp builtin
if [[ -position 2 -1 ]]; then
_normal "$@"
else
complist -eB
fi

3
Completion/Builtins/_cd Normal file
View file

@ -0,0 +1,3 @@
#defcomp cd
_files -W cdpath -g '*(-/)'

View file

@ -0,0 +1,7 @@
#defcomp command
if [[ -position 2 -1 ]]; then
_normal "$@"
else
complist -em
fi

View file

@ -0,0 +1,3 @@
#defcomp rmdir df du dircmp
_files -/

View file

@ -0,0 +1,6 @@
#defcomp disable
[[ -mcurrent -1 -*a* ]] && complist -ea
[[ -mcurrent -1 -*f* ]] && complist -eF
[[ -mcurrent -1 -*r* ]] && complist -ew
[[ ! -mcurrent -1 -* ]] && complist -eB

View file

@ -0,0 +1,3 @@
#defcomp echotc
complist -k '(al dc dl do le up al bl cd ce cl cr dc dl do ho is le ma nd nl se so up)'

View file

@ -0,0 +1,6 @@
#defcomp enable
[[ -mcurrent -1 -*a* ]] && complist -da
[[ -mcurrent -1 -*f* ]] && complist -dF
[[ -mcurrent -1 -*r* ]] && complist -dw
[[ ! -mcurrent -1 -* ]] && complist -dB

7
Completion/Builtins/_fc Normal file
View file

@ -0,0 +1,7 @@
#defcomp fc
if [[ -mcurrent -1 -*e ]]; then
complist -c
elif [[ -mcurrent -1 -[ARWI]## ]]; then
_files
fi

View file

@ -0,0 +1,3 @@
#defcomp unfunction
complist -F

13
Completion/Builtins/_hash Normal file
View file

@ -0,0 +1,13 @@
#defcomp hash
if [[ -mword 1 -*d* ]]; then
if [[ -string 1 '=' ]]; then
_path_files -g '*(-/)'
else
complist -n -q -S '='
fi
elif [[ -string 1 '=' ]]; then
_files -/g '*(*)'
else
complist -m -q -S '='
fi

View file

@ -0,0 +1,3 @@
#defcomp fg jobs
complist -j -P '%'

11
Completion/Builtins/_kill Normal file
View file

@ -0,0 +1,11 @@
#defcomp kill
local list
if [[ -iprefix '-' ]]; then
complist -k "($signals[1,-3])"
else
complist -P '%' -j
list=("$(ps 2>/dev/null)")
complist -y '$list' -s '`ps 2>/dev/null | tail +2 | cut -c1-5`'
fi

View file

@ -0,0 +1,3 @@
#defcomp limit unlimit
complist -k "(${(j: :)${(f)$(limit)}%% *})"

View file

@ -0,0 +1,3 @@
#defcomp sched
[[ -position 2 -1 ]] && _normal "$@"

7
Completion/Builtins/_set Normal file
View file

@ -0,0 +1,7 @@
#defcomp set
if [[ -mcurrent -1 [-+]o ]]; then
complist -o
elif [[ -current -1 -A ]]; then
complist -A
fi

View file

@ -0,0 +1,7 @@
#defcomp setopt
local nm=$NMATCHES
complist -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' \
-s '$({ unsetopt kshoptionprint; unsetopt } 2>/dev/null)'
[[ -nmatches nm ]] && complist -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' -o

View file

@ -0,0 +1,7 @@
#defcomp source
if [[ -position 2 -1 ]]; then
_normal "$@"
else
_files
fi

View file

@ -0,0 +1,7 @@
#defcomp trap
if [[ -position 1 ]]; then
complist -c
else
complist -k signals
fi

View file

@ -0,0 +1,6 @@
#defcomp unhash
[[ -mword 1 -*d* ]] && complist -n
[[ -mword 1 -*a* ]] && complist -a
[[ -mword 1 -*f* ]] && complist -F
[[ ! -mword 1 -* ]] && complist -m

View file

@ -0,0 +1,7 @@
#defcomp unsetopt
local nm=$NMATCHES
complist -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' \
-s '$({ unsetopt kshoptionprint; setopt } 2>/dev/null)'
[[ -nmatches nm ]] && complist -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' -o

View file

@ -0,0 +1,3 @@
#defcomp declare export integer local readonly typeset
complist -v -q -S '='

View file

@ -0,0 +1,7 @@
#defcomp wait
local list
complist -P '%' -j
list=("$(ps 2>/dev/null)")
complist -y '$list' -s '`ps 2>/dev/null | tail +2 | cut -c1-5`'

View file

@ -0,0 +1,3 @@
#defcomp which whence where type
complist -caF

50
Completion/Builtins/_zftp Normal file
View file

@ -0,0 +1,50 @@
#defpatcomp zf*
# Don't try any more completion after this.
_compskip=1
# Completion for zftp builtin and zf* functions. The functions
# zfcd_match and zfget_match (used for old-style completion)
# need to be installed for remote file and directory completion to work.
local subcom
if [[ $COMMAND = zftp ]]; then
if [[ $CURRENT -eq 1 ]]; then
compadd -m open params user login type ascii binary mode put \
putat get getat append appendat ls dir local remote mkdir rmdir
return
fi
subcom=$1
else
subcom=$COMMAND
fi
case $subcom in
*(cd|ls|dir))
# complete remote directories; we could be smarter about hiding prefixes
zfcd_match $PREFIX $SUFFIX
(( $#reply )) && compadd -m -S/ -q $reply
;;
*(get(|at)|gcp|delete|remote))
# complete remote files
zfget_match $PREFIX $SUFFIX
(( $#reply )) && compadd -F fignore -m $reply
;;
*(put(|at)|pcp))
# complete local files
_files
;;
*(open|anon|params))
# complete hosts: should do cleverer stuff with user names
complist -k hosts
;;
*)
# dunno... try ordinary completion after all.
unset _compskip
;;
esac

7
Completion/Builtins/_zle Normal file
View file

@ -0,0 +1,7 @@
#defcomp zle
if [[ -word 1 -N && -position 3 ]]; then
complist -F
else
complist -b
fi

View file

@ -0,0 +1,9 @@
#defcomp zmodload
if [[ -mword 1 -*(a*u|u*a)* || -mword 1 -*a* && -position 3 -1 ]]; then
complist -B
elif [[ -mword 1 -*u* ]]; then
complist -s '$(zmodload)'
else
complist -s '${^module_path}/*(N:t:r)'
fi

View file

@ -0,0 +1,37 @@
#defkeycomp 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
# corrected filename to standard output.
#
# You can adapt max_approx to the maximum number of mistakes
# which are allowed in total.
emulate -LR zsh
setopt extendedglob
local file="$PREFIX$SUFFIX" trylist
integer approx max_approx=6
[[ -z $WIDGET ]] && file=$1
if [[ -e "$file" ]]; then
if [[ -n $WIDGET ]]; then
compadd "$file"
else
print "$file"
fi
return
fi
for (( approx = 1; approx <= max_approx; approx++ )); do
trylist=( (#a$approx)"$file"(N) )
(( $#trylist )) && break
done
(( $#trylist )) || return 1
if [[ -n $WIDGET ]]; then
compadd -U "${trylist[@]}"
else
print "${trylist[@]}"
fi

View file

@ -0,0 +1,4 @@
#defkeycomp complete-word \C-xm
local file
file=($~PREFIX*$~SUFFIX(om[1]N))
(( $#file )) && compadd -f $file

147
Completion/Core/_comp_parts Normal file
View file

@ -0,0 +1,147 @@
#autoload
# This function can be used to separately complete parts of strings
# where each part may be one of a set of matches and different parts
# have different sets.
# Arguments are alternatingly arrays and separator strings. Arrays may
# be given by name or literally as words separated by white space in
# parentheses, e.g.:
#
# _comp_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 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
# Test if we should use this function for the global matcher in use.
_match_test _comp_parts || return
# Get the options.
group=()
expl=()
while getopts "J:V:X:" opt; do
case "$opt" in
[JV]) group=("-$opt" "$OPTARG");;
X) expl=(-X "$OPTARG");;
esac
done
shift OPTIND-1
# Get the string from the line.
str="$PREFIX$SUFFIX"
prefix=""
# Walk through the arguments to find the longest unambiguous prefix.
while [[ $# -gt 1 ]]; do
# Get the next array and separator.
arr="$1"
sep="$2"
if [[ "$arr[1]" == '(' ]]; then
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.
test="${str%%${sep}*}"
matchflags=""
_match_pattern _comp_parts test matchflags
test="${matchflags}${test}"
testarr=( "${(@M)${(@P)arr}:#${~test}*}" )
# If there are no matches we give up. If there is more than one
# match, this is the part we will complete.
(( $#testarr )) || return
[[ $#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.
matchflags=""
test="$str"
_match_pattern _comp_parts test matchflags
test="${matchflags}${test}"
testarr=( "${(@M)${(@P)arr}:#${~test}*}" )
fi
[[ $#testarr -eq 0 || ${#testarr[1]} -eq 0 ]] && return
# Now we build the suffixes to give to the completion code.
shift
matchers=()
suffixes=("")
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}*}"
else
test="$str"
fi
matchflags=""
_match_pattern _comp_parts test matchflags
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.
arr="$2"
if [[ "$arr[1]" == '(' ]]; then
tmparr=( ${=arr[2,-2]} )
arr=tmparr
fi
suffixes=("${^suffixes[@]}${1}${(@M)^${(@P)arr}:#${~test}*}")
# 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}=*")
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 "$group[@]" "$expl[@]" "$matchers[@]" "$autosuffix[@]" -p "$prefix" -s "$i" - "$testarr[@]"
done

13
Completion/Core/_compalso Normal file
View file

@ -0,0 +1,13 @@
#autoload
# This searches $1 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
tmp="$_comps[$1]"
[[ -z "$tmp" ]] || "$tmp" "$@"

26
Completion/Core/_files Normal file
View file

@ -0,0 +1,26 @@
#autoload
# Utility function for completing files of a given type or any file.
# In many cases you will want to call this one instead of _path_files().
local nm=$NMATCHES
_path_files "$@"
if [[ $# -ne 0 && -nmatches nm ]]; then
local opt opts
# We didn't get any matches for those types of files described by
# the `-g' or `-/' option. Now we try it again accepting all files.
# First we get those options that we have to use even if then. If
# we find out that the `-f' option was given, we already accepted
# all files and give up immediatly.
opts=()
while getopts "P:S:W:F:J:V:X:f/g:" opt; do
[[ "$opt" = f ]] && return
[[ "$opt" = [PSWFJVX] ]] && opts=("$opts[@]" "-$opt" "$OPTARG")
done
_path_files "$opts[@]"
fi

View file

@ -0,0 +1,48 @@
#autoload
# The main loop of the completion code. This is what is called when
# completion is attempted from the command line.
# The completion code gives us the special variables and the arguments
# from the command line are given as positional parameters.
local comp name
setopt localoptions nullglob rcexpandparam globdots
unsetopt markdirs globsubst shwordsplit nounset
# An entry for `-first-' is the replacement for `compctl -T'
# Completion functions may set `_compskip' to any value to make the
# main loops stop calling other completion functions.
comp="$_comps[-first-]"
if [[ ! -z "$comp" ]]; then
"$comp" "$@"
if (( $+_compskip )); then
unset _compskip
return
fi
fi
# For arguments we use the `_normal function.
if [[ $CONTEXT == argument || $CONTEXT == command ]]; then
_normal "$@"
else
# Let's see if we have a special completion definition for the other
# possible contexts.
comp=''
case $CONTEXT in
redirect) comp="$_comps[-redirect-]";;
math) comp="$_comps[-math-]";;
subscript) comp="$_comps[-subscript-]";;
value) comp="$_comps[-value-]";;
condition) comp="$_comps[-condition-]";;
esac
# If not, we use default completion, if any.
[[ -z "$comp" ]] && comp="$_comps[-default-]"
[[ -z "$comp" ]] || "$comp" "$@"
fi

54
Completion/Core/_normal Normal file
View file

@ -0,0 +1,54 @@
#autoload
local comp cmd1 cmd2 pat val name
# Completing in command position? If not we set up `cmd1' and `cmd2' as
# two strings we have search in the completion definition arrays (e.g.
# a path and the last path name component).
if [[ $CONTEXT == command ]]; then
comp="$_comps[-command-]"
[[ -z "$comp" ]] || "$comp" "$@"
return
elif [[ "$COMMAND[1]" == '=' ]]; then
eval cmd1\=$COMMAND
cmd2="$COMMAND[2,-1]"
elif [[ "$COMMAND" == */* ]]; then
cmd1="$COMMAND"
cmd2="${COMMAND:t}"
else
cmd1="$COMMAND"
eval cmd2=$(whence -p $COMMAND)
fi
# See if there are any matching pattern completions.
for i in "$_patcomps[@]"; do
pat="${i% *}"
val="${i#* }"
if [[ "$cmd1" == $~pat || "$cmd2" == $~pat ]]; then
"$val" "$@"
if (( $+_compskip )); then
unset _compskip
return
fi
fi
done
# Now look up the two names in the normal completion array.
name="$cmd1"
comp="$_comps[$cmd1]"
if [[ -z "$comp" ]]; then
name="$cmd2"
comp="$_comps[$cmd2]"
fi
# And generate the matches, probably using default completion.
if [[ -z "$comp" ]]; then
name=-default-
comp="$_comps[-default-]"
fi
[[ -z "$comp" ]] || "$comp" "$@"

311
Completion/Core/_path_files Normal file
View file

@ -0,0 +1,311 @@
#autoload
# Utility function for in-path completion.
# Supported arguments are: `-f', `-/', `-g <patterns>', `-J <group>',
# `-V <group>', `-W paths', `-X explanation', and `-F <ignore>'. All but
# the last have the same syntax and meaning as for `complist'. The
# `-F <ignore>' option may be used to give a list of suffixes either by
# giving the name of an array or literally by giving them in a string
# surrounded by parentheses. Files with one of the suffixes thus given
# are treated like files with one of the suffixes in the `fignore' array
# in normal completion.
#
# This function uses the helper functions `_match_test' and `_match_pattern'.
# First see if we should generate matches for the global matcher in use.
_match_test _path_files || return
# Yes, so...
local nm prepaths str linepath realpath donepath patstr prepath testpath rest
local tmp1 collect tmp2 suffixes i ignore matchflags opt group sopt pats gopt
local addpfx addsfx expl
setopt localoptions nullglob rcexpandparam globdots extendedglob
unsetopt markdirs globsubst shwordsplit nounset
prepaths=('')
ignore=()
group=()
sopt='-'
gopt=''
pats=()
addpfx=()
addsfx=()
expl=()
# Get the options.
while getopts "P:S:W:F:J:V:X:f/g:" opt; do
case "$opt" in
P) addpfx=(-P "$OPTARG")
;;
S) addsfx=(-S "$OPTARG")
;;
W) tmp1="$OPTARG"
if [[ "$tmp1[1]" = '(' ]]; then
prepaths=( ${^=tmp1[2,-2]}/ )
else
prepaths=( ${(P)=${tmp1}} )
(( ! $#prepaths )) && prepaths=( ${tmp1}/ )
fi
(( ! $#prepaths )) && prepaths=( '' )
;;
F) tmp1="$OPTARG"
if [[ "$tmp1[1]" = '(' ]]; then
ignore=( ${^=tmp1[2,-2]}/ )
else
ignore=( ${(P)${tmp1}} )
fi
(( $#ignore )) && ignore=(-F "( $ignore )")
;;
[JV]) group=("-$opt" "$OPTARG")
;;
X) expl=(-X "$OPTARG")
;;
f) sopt="${sopt}f"
pats=("$pats[@]" '*')
;;
/) sopt="${sopt}/"
pats=("$pats[@]" '*(-/)')
;;
g) gopt='-g'
pats=("$pats[@]" ${=OPTARG})
;;
esac
done
# If we were given no file selection option, we behave as if we were given
# a `-f'.
if [[ "$sopt" = - ]]; then
if [[ -z "$gopt" ]]; then
sopt='-f'
pats=('*')
else
unset sopt
fi
fi
# str holds the whole string from the command line with a `*' between
# the prefix and the suffix.
str="${PREFIX:q}*${SUFFIX:q}"
# If the string began with a `~', the quoting turned this into `\~',
# remove the slash.
[[ "$str" = \\\~* ]] && str="$str[2,-1]"
# We will first try normal completion called with `complist', but only if we
# weren't given a `-F' option.
if (( ! $#ignore )); then
# First build an array containing the `-W' option, if there is any and we
# want to use it. We don't want to use it if the string from the command line
# is a absolute path or relative to the current directory.
if [[ -z "$tmp1[1]" || "$str[1]" = [~/] || "$str" = (.|..)/* ]]; then
tmp1=()
else
tmp1=(-W "( $prepaths )")
fi
# Now call complist.
nm=$NMATCHES
if [[ -z "$gopt" ]]; then
complist "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" "$tmp1[@]" $sopt
else
complist "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" "$tmp1[@]" $sopt -g "$pats"
fi
# If this generated any matches, we don't want to do in-path completion.
[[ -nmatches nm ]] || return
# No `-F' option, so we want to use `fignore'.
ignore=(-F fignore)
fi
# Now let's have a closer look at the string to complete.
if [[ "$str[1]" = \~ ]]; then
# It begins with `~', so remember anything before the first slash to be able
# to report it to the completion code. Also get an expanded version of it
# (in `realpath'), so that we can generate the matches. Then remove that
# prefix from the string to complete, set `donepath' to build the correct
# paths and make sure that the loop below is run only once with an empty
# prefix path by setting `prepaths'.
linepath="${str%%/*}/"
eval realpath\=$linepath
str="${str#*/}"
donepath=''
prepaths=( '' )
else
# If the string does not start with a `~' we don't remove a prefix from the
# string.
liniepath=''
realpath=''
if [[ "$str[1]" = / ]]; then
# If it is a absolut path name, we remove the first slash and put it in
# `donepath' meaning that we treat it as the path that was already handled.
# Also, we don't use the paths from `-W'.
str="$str[2,-1]"
donepath='/'
prepaths=( '' )
else
# The common case, we just use the string as it is, unless it begins with
# `./' or `../' in which case we don't use the paths from `-W'.
[[ "$str" = (.|..)/* ]] && prepaths=( '' )
donepath=''
fi
fi
# First we skip over all pathname components in `str' which really exist in
# the file-system, so that `/usr/lib/l<TAB>' doesn't offer you `lib' and
# `lib5'. Pathname components skipped this way are taken from `str' and added
# to `donepath'.
while [[ "$str" = */* ]] do
[[ -e "$realpath$donepath${str%%/*}" ]] || break
donepath="$donepath${str%%/*}/"
str="${str#*/}"
done
# Now build the glob pattern by calling `_match_pattern'.
patstr="$str"
matchflags=""
_match_pattern _path_files patstr matchflags
# We almost expect the pattern to have changed `..' into `*.*.', `/.' into
# `/*.', and probably to contain two or more consecutive `*'s. Since these
# have special meaning for globbing, we remove them. But before that, we
# add the pattern for matching any characters before a slash.
patstr="$patstr:gs-/-*/-:gs/*.*.//:gs-/*.-/.-:gs/**/*/"
# Finally, generate the matches. First we loop over all the paths from `-W'.
# Note that in this loop `str' is used as a modifyable version of `patstr'
# and `testpath' is a modifyable version of `donepath'.
for prepath in "$prepaths[@]"; do
str="$patstr"
testpath="$donepath"
# The second loop tests the components of the path in `str' to get the
# possible matches.
while [[ "$str" = */* ]] do
# `rest' is the pathname after the first slash that is left. In `tmp1'
# we get the globbing matches for the pathname component currently
# handled.
rest="${str#*/}"
tmp1="${prepath}${realpath}${testpath}${~matchflags}${str%%/*}(-/)"
tmp1=( $~tmp1 )
if [[ $#tmp1 -eq 0 ]]; then
# If this didn't produce any matches, we don't need to test this path
# any further, so continue with the next `-W' path, if any.
continue 2
elif [[ $#tmp1 -gt 1 ]]; then
# If it produced more than one match, we want to remove those which
# don't have possible following pathname components matching the
# rest of the string we are completing. (The case with only one
# match is handled below.)
# In `collect' we will collect those of the produced pathnames that
# have a matching possible path-suffix. In `suffixes' we build an
# array containing strings build from the rest of the string to
# complete and the glob patterns we were given as arguments.
collect=()
suffixes=( $rest$^pats )
suffixes=( "${(@)suffixes:gs.**.*.}" )
# In the loop the prefixes from the `tmp1' array produced above and
# the suffixes we just built are used to produce possible matches
# via globbing.
for i in $tmp1; do
tmp2=( ${~i}/${~matchflags}${~suffixes} )
[[ $#tmp2 -ne 0 ]] && collect=( $collect $i )
done
# If this test showed that none of the matches from the glob in `tmp1'
# has a possible sub-path matching what's on the line, we give up and
# continue with the next `-W' path.
if [[ $#collect -eq 0 ]]; then
continue 2
elif [[ $#collect -ne 1 ]]; then
# If we have more than one possible match, this means that the
# pathname component currently handled is ambiguous, so we give
# it to the completion code.
# First we build the full path prefix in `tmp1'.
tmp1="$prepath$realpath$testpath"
# Now produce all matching pathnames in `collect'.
collect=( ${~collect}/${~matchflags}${~suffixes} )
# And then remove the common path prefix from all these matches.
collect=( ${collect#$tmp1} )
# Finally, we add all these matches with the common (unexpanded)
# pathprefix (the `-p' option), the path-prefix (the `-W' option)
# to allow the completion code to test file type, and the path-
# suffix (the `-s' option). We also tell the completion code that
# these are file names and that `fignore' should be used as usual
# (the `-f' and `-F' options).
for i in $collect; do
compadd "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" -p "$linepath$testpath" -W "$tmp1" -s "/${i#*/}" -f "$ignore[@]" - "${i%%/*}"
done
# We have just finished handling all the matches from above, so we
# can continue with the next `-W' path.
continue 2
fi
# We reach this point if only one of the path prefixes in `tmp1'
# has a existing path-suffix matching the string from the line.
# In this case we accept this match and continue with the next
# path-name component.
tmp1=( "$collect[1]" )
fi
# This is also reached if the first globbing produced only one match
# in this case we just continue with the next pathname component, too.
tmp1="$tmp1[1]"
testpath="$testpath${tmp1##*/}/"
str="$rest"
done
# We are here if all pathname components except the last one (which is still
# not tested) are unambiguous. So we add matches with the full path prefix,
# no path suffix, the `-W' we are currently handling, all the matches we
# can produce in this directory, if any.
tmp1="$prepath$realpath$testpath"
suffixes=( $str$^pats )
suffixes=( "${(@)suffixes:gs.**.*.}" )
tmp2=( ${~tmp1}${~matchflags}${~suffixes} )
if [[ $#tmp2 -eq 0 && "$sopt" = */* ]]; then
[[ "$testpath[-1]" = / ]] && testpath="$testpath[1,-2]"
compadd "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" -f - "$linepath$testpath"
else
compadd "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" -p "$linepath$testpath" -W "$prepath$realpath$testpath" -f "$ignore[@]" - ${(@)tmp2#$tmp1}
fi
done

89
Completion/Core/compdump Normal file
View file

@ -0,0 +1,89 @@
# This is a file to be sourced to dump the definitions for new-style
# completion defined by 'compinit' in the same directory. The output
# should be directed into the "compinit.dump" in the same directory as
# compinit. If you rename init, just stick .dump onto the end of whatever
# you have called it and put it in the same directory. This is handled
# automatically if you invoke compinit with the option -d.
#
# You will need to update the dump every time you add a new completion.
# To do this, simply remove the .dump file, start a new shell, and
# create the .dump file as before. Again, compinit -d handles this
# automatically.
#
# It relies on KSH_ARRAYS not being set.
# Print the number of files used for completion. This is used in compinit
# to see if auto-dump should re-dump the dump-file.
_d_file=${COMPDUMP-${0:h}/compinit.dump}
typeset -U _d_files
_d_files=( ${^~fpath}/_*~*~(N:t) )
print "#files: $#_d_files" > $_d_file
unset _d_files
# First dump the arrays _comps and _patcomps. The quoting hieroglyphyics
# ensure that a single quote inside a variable is itself correctly quoted.
print "_comps=(" >> $_d_file
for _d_f in ${(ok)_comps}; do
print -r - "'${_d_f//\'/'\\''}'" "'${_comps[$_d_f]//\'/'\\''}'"
done >> $_d_file
print ")" >> $_d_file
print "\n_patcomps=(" >> $_d_file
for _d_f in "$_patcomps[@]"; do
print -r - "'${_d_f//\'/'\\''}'"
done >> $_d_file
print ")" >> $_d_file
print >> $_d_file
# Now dump the key bindings. We dump all bindings for zle widgets
# whose names start with a underscore.
# We need both the zle -C's and the bindkey's to recreate.
_d_bks=()
zle -lL |
while read -rA _d_line; do
if [[ ${_d_line[5]} = _* ]]; then
print -r - ${_d_line}
_d_bks=($_d_bks ${_d_line[3]})
fi
done >> $_d_file
bindkey |
while read -rA _d_line; do
if [[ ${_d_line[2]} = (${(j.|.)~_d_bks}) ]]; then
print -r "bindkey '${_d_line[1][2,-2]}' ${_d_line[2]}"
fi
done >> $_d_file
print >> $_d_file
# Autoloads: whence -w produces "_d_foo: function", so look for
# all functions beginning with `_'.
_d_als=($(whence -wm '_*' | sort |
while read -rA _d_line; do
[[ ${_d_line[2]} = function ]] && print -r - ${_d_line[1]%:}
done))
# print them out: about five to a line looks neat
while (( $#_d_als )); do
print -n autoload
for (( _i = 0; _i < 5; _i++ )); do
if (( $#_d_als )); then
print -n " $_d_als[1]"
shift _d_als
fi
done
print
done >> $_d_file
print >> $_d_file
unset _d_line _d_zle _d_bks _d_als _d_f _f_file

269
Completion/Core/compinit Normal file
View file

@ -0,0 +1,269 @@
# 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).
# The names of the files that will be considered for autoloading have to
# start with a underscores (like `_setopt).
# The first line of these files will be read and has to say what should be
# done with its contents:
#
# `#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
#
# `#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
#
# `#defkeycomp <style> [ <key-sequence> ... ]
# this is used to bind special completions to all the given
# <key-sequence>(s). The <style> is the name of one of the built-in
# completion widgets (complete-word, delete-char-or-list,
# expand-or-complete, expand-or-complete-prefix, list-choices,
# menu-complete, menu-expand-or-complete, or reverse-menu-complete).
# This creates a widget behaving like <style> so that the
# completions are chosen as given in the the rest of the file,
# rather than by the context. The widget has the same name as
# the autoload file and can be bound using bindkey in the normal way.
#
# `#autoload'
# this is for helper functions that are not used to
# generate matches, but should automatically be loaded
# when they are called
#
# Note that no white space is allowed between the `#' and the rest of
# the string.
#
# See the file `compdump' for how to speed up initialiation.
#
# 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).
if [[ "$1" = -d ]]; then
_i_autodump=1
else
_i_autodump=0
fi
# The associative array containing the definitions for the commands.
# Definitions for patterns will be stored in the normal array `_patcomps'.
typeset -A _comps
_patcomps=()
# This function is used to register or delete completion functions. For
# registering completion functions, it is invoked with the name of the
# function as it's first argument (after the options). The other
# arguments depend on what type of completion function is defined. If
# none of the `-p' and `-k' options is given a function for a command is
# defined. The arguments after the function name are then interpreted as
# the names of the command for which the function generates matches.
# With the `-p' option a function for a name pattern is defined. This
# function will be invoked when completing for a command whose name
# matches the pattern given as argument after the function name (in this
# case only one argument is accepted).
# With the `-k' option a function for a special completion keys is
# defined and immediatly bound to those keys. Here, the extra arguments
# are the name of one of the builtin completion widgets and any number
# of key specifications as accepted by the `bindkey' builtin.
# In any case the `-a' option may be given which makes the function
# whose name is given as the first argument be autoloaded. When defining
# a function for command names the `-n' option may be given and keeps
# the definitions from overriding any previous definitions for the
# commands.
# For deleting definitions, the `-d' option must be given. Without the
# `-p' option, this deletes definitions for functions for the commands
# whose names are given as arguments. If combined with the `-p' option
# it deletes the definitions for the patterns given as argument.
# The `-d' option may not be combined with the `-k' option, i.e.
# definitions for key function can not be removed.
#
# Examples:
#
# compdef -a foo bar baz
# make the completion for the commands `bar' and `baz' use the
# function `foo' and make this function be autoloaded
#
# compdef -p foo 'c*'
# make completion for all command whose name begins with a `c'
# generate matches by calling the function `foo' before generating
# matches defined for the command itself
#
# compdef -k foo list-choices '^X^M' '\C-xm'
# make the function `foo' be invoked when typing `Control-X Control-M'
# or `Control-X m'; the function should generate matches and will
# behave like the `list-choices' builtin widget
#
# compdef -d bar baz
# delete the definitions for the command names `bar' and `baz'
compdef() {
local opt autol type func delete new i
# Get the options.
while getopts "anpkd" opt; do
case "$opt" in
a) autol=yes;;
n) new=yes;;
[pk]) if [[ -n "$type" ]]; then
# Error if both `-p' and `-k' are given (or one of them
# twice).
echo "$0: type already set to $type"
return 1
fi
if [[ "$opt" = p ]]; then
type=pattern
else
type=key
fi
;;
d) delete=yes;;
esac
done
shift OPTIND-1
if [[ -z "$delete" ]]; then
# Adding definitions, first get the name of the function name
# and probably do autoloading.
func="$1"
[[ -n "$autol" ]] && autoload "$func"
shift
case "$type" in
pattern)
if [[ $# -gt 1 ]]; then
echo "$0: only one pattern allowed"
return 1
fi
# Patterns are stored in strings like `c* foo', with a space
# between the pattern and the function name.
_patcomps=("$_patcomps[@]" "$1 $func")
;;
key)
if [[ $# -lt 2 ]]; then
echo "$0: missing keys"
return 1
fi
# Define the widget.
zle -C "$func" "$1" "$func"
shift
# And bind the keys...
for i; do
bindkey "$i" "$func"
done
;;
*)
# For commands store the function name in the `_comps'
# associative array, command names as keys.
for i; do
[[ -z "$new" || "${+_comps[$i]}" -eq 0 ]] && _comps[$i]="$func"
done
;;
esac
else
# Handle the `-d' option, deleting.
case "$type" in
pattern)
# Note the space.
for i; do
_patcomps=("${(@)patcomps:#$i *}")
done
;;
key)
# Oops, cannot do that yet.
echo "$0: cannot restore key bindings"
return 1
;;
*)
# Deleting definitons for command is even simpler.
for i; do
unset "_comps[$i]"
done
esac
fi
}
# Now we automatically make the definition files autoloaded.
# First we get the name of a dump file if this will be used.
: ${COMPDUMP:=$0.dump}
if [[ ! -o extendedglob ]]; then
_i_noextglob=yes
setopt extendedglob
fi
typeset -U _i_files
_i_files=( ${^~fpath}/_*~*~(N:t) )
_i_initname=$0
_i_done=''
# If we have a dump file, load it.
if [[ -f "$COMPDUMP" ]]; then
read -rA _i_line < "$COMPDUMP"
if [[ _i_autodump -eq 1 && $_i_line[2] -eq $#_i_files ]]; then
builtin . "$COMPDUMP"
_i_done=yes
fi
unset _i_line
fi
if [[ -z "$_i_done" ]]; then
for _i_dir in $fpath; do
[[ $_i_dir = . ]] && continue
for _i_file in $_i_dir/_*~*~(N); do
read -rA _i_line < $_i_file
_i_tag=$_i_line[1]
shift _i_line
if [[ $_i_tag = '#defcomp' ]]; then
compdef -na "${_i_file:t}" "${_i_line[@]}"
elif [[ $_i_tag = '#defpatcomp' ]]; then
compdef -pa "${_i_file:t}" "${_i_line[@]}"
elif [[ $_i_tag = '#defkeycomp' ]]; then
compdef -ka "${_i_file:t}" "${_i_line[@]}"
elif [[ $_i_tag = '#autoload' ]]; then
autoload ${_i_file:t}
fi
done
done
bindkey |
while read -rA _i_line; do
if [[ "$_i_line[2]" = complete-word ||
"$_i_line[2]" = delete-char-or-list ||
"$_i_line[2]" = expand-or-complete ||
"$_i_line[2]" = expand-or-complete-prefix ||
"$_i_line[2]" = list-choices ||
"$_i_line[2]" = menu-complete ||
"$_i_line[2]" = menu-expand-or-complete ||
"$_i_line[2]" = reverse-menu-complete ]]; then
zle -C _complete_$_i_line[2] $_i_line[2] _main_complete
bindkey "${_i_line[1][2,-2]}" _complete_$_i_line[2]
fi
done
unset _i_dir _i_line _i_file _i_tag
# If autodumping was requested, do it now.
(( _i_autodump )) && builtin . ${_i_initname:h}/compdump
fi
[[ -z "$_i_noextglob" ]] || unsetopt extendedglob
unset _i_files _i_initname _i_done _i_autodump _i_noextglob

107
Completion/README Normal file
View file

@ -0,0 +1,107 @@
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
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 .
The subdirectories contain:
Core:
The basic functions and files to be sourced. You will certainly need
these, and will most likely not feel like altering them (or, in some
cases, even reading them, unless you are a shell wizard). 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.
_comp_parts
Utility used for completing words with multiple separate parts, such as
`<user>@<host>'
_compalso
Utility for calling a function to add additional completions to an
already existing set.
_files
A frontend to _path_files which will default to any old file if the
specified file was not found.
_main_complete
The main entry point called by the key bindings which compinit sets
up (the main `completion widget' in zsh jargon).
_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.)
_path_files
The function usually called to complete filenames and directories. It
replaces the standard -f 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
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.
_match_pattern
_match_test
These are used by Base/_path_files (and hence also Base/_files) 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 ((...)).
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.

22
Completion/User/_a2ps Normal file
View file

@ -0,0 +1,22 @@
#defcomp a2ps
if [[ -prefix -- ]]; then
_comp_parts '(--borders --compact --truncate-lines --interpret
--print-anyway --delegate)' '=' '(yes no)'
_comp_parts '(--major)' '=' '(rows columns)'
_comp_parts '(--end-of-line)' '=' '(r n nr rn any)'
complist -S= -k '(--medium --columns --rows --line-numbers
--font-size --lines-per-page --chars-per-line
--tabsize --non-printable-format --encoding
--title --stdin --prologue --highlight-level
--strip-level --output --version-control --suffix
--printer --copies --sides --page-prefeed
--no-page-prefeed)'
complist -qS= -k '(--margin --header --underlay --left-title
--right-title --left-footer --footer --right-footer
--pages --pretty-print)'
complist -k '(--landscape --portrait --catman --no-header)'
else
_files -F fignore -g "*~*.ps"
fi

View file

@ -0,0 +1,3 @@
#defcomp compress
_files -g '*~*.Z'

View file

@ -0,0 +1,12 @@
#defcomp configure
if [[ $PREFIX = *=* ]]; then
# Complete filenames after e.g. --prefix=
IPREFIX=${PREFIX%%=*}=
PREFIX=${PREFIX#*=}
complist -f
else
# Generate a list of options from configure --help
complist -s '$($COMMAND --help |
sed -n -e '\''s/^ *\(--[-a-z0-9]*\)[ =,].*$/\1/p'\'')'
fi

13
Completion/User/_dd Normal file
View file

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

3
Completion/User/_dvi Normal file
View file

@ -0,0 +1,3 @@
#defcomp xdvi dvips dvibook dviconcat dvicopy dvidvi dviselect dvitodvi dvitype
_files -g '*.(dvi|DVI)'

21
Completion/User/_find Normal file
View file

@ -0,0 +1,21 @@
#defcomp find
if [[ -mbetween -(ok|exec) \\\; ]]; then
_normal "$@"
elif [[ -iprefix - ]]; then
complist -s 'daystart {max,min,}depth follow noleaf version xdev \
{a,c,}newer {a,c,m}{min,time} empty false {fs,x,}type gid inum links \
{i,}{l,}name {no,}{user,group} path perm regex size true uid used \
exec {f,}print{f,0,} ok prune ls'
elif [[ -position 1 ]]; then
complist -g '. ..'
_files -g '(-/)'
elif [[ -mcurrent -1 -((a|c|)newer|fprint(|0|f)) ]]; then
_files
elif [[ -current -1 -fstype ]]; then
complist -k '(ufs 4.2 4.3 nfs tmp mfs S51K S52K)'
elif [[ -current -1 -group ]]; then
complist -k groups
elif [[ -current -1 -user ]]; then
complist -u
fi

3
Completion/User/_gunzip Normal file
View file

@ -0,0 +1,3 @@
#defcomp gunzip zcat
_files -g '*.[gG][z]'

3
Completion/User/_gzip Normal file
View file

@ -0,0 +1,3 @@
#defcomp gzip
_files -g '*~*.[gG][zZ]'

3
Completion/User/_hosts Normal file
View file

@ -0,0 +1,3 @@
#defcomp ftp ncftp ping rwho rup xping traceroute nslookup
complist -k hosts

3
Completion/User/_make Normal file
View file

@ -0,0 +1,3 @@
#defcomp make gmake pmake
complist -s "\$(awk '/^[a-zA-Z0-9][^/ ]+:/ {print \$1}' FS=: [mM]akefile)"

11
Completion/User/_man Normal file
View file

@ -0,0 +1,11 @@
#defcomp man
setopt localoptions rcexpandparam
local rep
if [[ $2 = (<->*|ln) ]]; then
rep=( $manpath/(man|cat)$2/$PREFIX*$SUFFIX.<->*(N:t:r) )
else
rep=( $manpath/(man|cat)*/$PREFIX*$SUFFIX.<->*(N:t:r) )
fi
(( $#rep )) && compadd -m $rep

70
Completion/User/_mh Normal file
View file

@ -0,0 +1,70 @@
#defcomp folder comp inc mark refile repl scan show next prev rmm pick whom mhn mhpath mhpatch
# Completion for all possible MH commands.
# Alter the following two to your own mh directory and the directory
# where standard mh library files live. (It works anyway, but this
# will save a little time.)
local mymhdir=~/Mail
local mhlib=/usr/lib/mh
# To be on the safe side, check this exists and if not, get it anyway.
[[ -d $mymhdir ]] || mymhdir=$(mhpath +)
if [[ -iprefix - ]]; then
# get list of options, which MH commands can generate themselves
# awk is just too icky to use for this, sorry. send me one if
# you come up with it.
compadd -m $($COMMAND -help | perl -ne 'if (/^\s*-\(?(\S+)/) {
$n = $1;
$n =~ s/\)//g;
print $n =~ s/^\[([a-z]+)\]// ? "$n\n$1$n\n" : "$n\n";
}')
return
elif [[ -iprefix '+' || -iprefix '@' || -current -1 -draftfolder ]]; then
# Complete folder names.
local mhpath
if [[ $IPREFIX != '@' ]]; then
[[ $IPREFIX = '+' ]] || IPREFIX=+
mhpath=$mymhdir
else
mhpath=$(mhpath)
fi
# painless, or what?
complist -W mhpath -/
elif [[ -mcurrent -1 -(editor|(whatnow|rmm|show|more)proc) ]]; then
complist -c
elif [[ -current -1 -file ]]; then
complist -f
elif [[ -mcurrent -1 -(form|audit|filter) ]]; then
# Need some MH template file, which may be in our own MH directory
# or with the standard library.
local mhfpath
# This is the only place we need mhlib, so leave the test till here.
[[ -d $mhlib ]] || { mhlib=$(mhparam mhlproc); mhlib=$mhlib:h; }
mhfpath=($mymhdir $mhlib)
complist -W mhfpath -g '*(.)'
elif [[ -mcurrent -1 -(no|)cc ]]; then
compadd -m all to cc me
elif [[ -mcurrent -1 -[rw]cache ]]; then
compadd -m public private never ask
else
# Generate sequences.
local foldnam folddir f
for f in $argv; do
[[ $f = [@+]* ]] && foldnam=$f
done
if [[ $foldnam = '+'* ]]; then
folddir=$mymhdir/${foldnam#+}
elif [[ $foldnam = '@'* ]]; then
folddir=$(mhpath)/${foldnam#@}
else
folddir=$(mhpath)
# leaving foldnam empty works here
fi
complist -s '$(mark $foldnam | awk -F: '\''{ print $1 }'\'')'
compadd -m reply next cur prev first last all unseen
complist -W folddir -g '<->'
fi

3
Completion/User/_pdf Normal file
View file

@ -0,0 +1,3 @@
function acroread
_files -g '*.(pdf|PDF)'

3
Completion/User/_ps Normal file
View file

@ -0,0 +1,3 @@
#defcomp gs ghostview gview psnup psselect pswrap pstops pstruct lpr
_files -g '*([pP][sS]|eps)'

9
Completion/User/_rcs Normal file
View file

@ -0,0 +1,9 @@
#defcomp co ci rcs
[[ $COMMAND = ci || $COMMAND = rcs ]] && _files
if [[ $NMATCHES -eq 0 && -d RCS && $COMMAND != ci ]]; then
local rep
rep=(RCS/$PREFIX*$SUFFIX,v(:t:s/\,v//))
(( $#rep )) && compadd -m $rep
fi

9
Completion/User/_rlogin Normal file
View file

@ -0,0 +1,9 @@
#defcomp rlogin rsh ssh
if [[ -position 1 ]]; then
complist -k hosts
elif [[ -position 2 ]]; then
complist -k '(-l)'
else
complist -u
fi

2
Completion/User/_strip Normal file
View file

@ -0,0 +1,2 @@
#defcomp strip
_files -g '*(*)'

16
Completion/User/_stty Normal file
View file

@ -0,0 +1,16 @@
#defcomp stty
if [[ -mcurrent -1 \
(*erase|discard|status|dsusp|intr|kill|lnext|quit|reprint|start|s*p) ]]
then
compadd -m -Q '^-' '^h' '^?' '^c' '^u'
else
[[ -string '-' || -string '+' ]]
compadd -m rows columns intr quit erase kill eof eol \
eol2 start stop susp dsusp reprint discard werase lnext \
parenb parodd cs8 cstopb hupcl cread clocal parext \
ignbrk brkint ignpar parmrk inpck istrip inlcr igncr icrnl iuclc \
ixon ixany ixoff imaxbel isig icanon xcase echo echoe echok \
echonl noflsh tostop echoctl echoprt echoke flusho pending iexten \
opost olcuc onlcr ocrnl onocr onlret ofill ofdel
fi

11
Completion/User/_tar Normal file
View file

@ -0,0 +1,11 @@
#defcomp tar
local nm=$NMATCHES tf="$2"
if [[ ( -mword 1 *t*f* || -mword 1 *x*f* ) && -position 3 100000 ]]; then
complist -k "( $(tar tf $tf) )"
elif [[ -mword 1 *c*f* && -position 3 100000 ]]; then
_files
elif [[ -mcurrent -1 *f* && -position 2 ]]; then
_files -g '*.(tar|TAR)'
fi

3
Completion/User/_tex Normal file
View file

@ -0,0 +1,3 @@
#defcomp tex latex slitex
_files -g '*.(tex|TEX|texinfo|texi)'

View file

@ -0,0 +1,3 @@
#defcomp uncompress zmore
_files -g '*.Z'

View file

@ -0,0 +1,5 @@
#defpatcomp */X11/*
# A simple pattern completion, just as an example.
complist -J options -k '(-display -name -xrm)'

3
Completion/User/_xfig Normal file
View file

@ -0,0 +1,3 @@
#defcomp xfig
_files -g '*.fig'

View file

@ -27,5 +27,5 @@
# This must also serve as a shell script, so do not add spaces around the
# `=' signs.
VERSION=3.1.5-pws-9
VERSION_DATE='February 18, 1999'
VERSION=3.1.5-pws-10
VERSION_DATE='February 26, 1999'

View file

@ -162,7 +162,7 @@ xitem(tt(compadd) [ tt(-qQfnUam) ] [ tt(-F) var(array) ])
xitem([ tt(-P) var(prefix) ] [ tt(-S) var(suffix) ])
xitem([ tt(-p) var(hidden-prefix) ] [ tt(-s) var(hidden-suffix) ])
xitem([ tt(-i) var(ignored-prefix) ] [ tt(-W) var(file-prefix) ])
xitem([ tt(-J) var(name) ] [ tt(-V) var(name) ])
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) ... ])(
@ -182,14 +182,17 @@ item(tt(-S) var(suffix))(
Like tt(-P) but gives a string that has to be inserted after the match.
)
item(tt(-p) var(hidden-prefix))(
This gives a string that should be
...
This gives a string that should be inserted in the line before the
match but that should not appear in the list of matches.
)
item(tt(-s) var(hidden-suffix))(
...
Like `tt(-p)', but gives a string to insert after the match.
)
item(tt(-i) var(ignored-prefix))(
...
This gives a string to insert into the command line just before any
string given with the `tt(-P)' option. Without `tt(-P)' the string is
inserted before the string given with `tt(-p)' or directly before the
match.
)
item(tt(-J) var(name))(
As for tt(compctl) and tt(complist) this gives the name of the group
@ -198,6 +201,10 @@ of matches the words should be stored in.
item(tt(-V) var(name))(
Like tt(-J) but naming a unsorted group.
)
item(tt(-X) var(explanation))(
The var(explanation) string will be printed with the list of matches,
as for tt(compctl -X).
)
item(tt(-q))(
This flag has the same meaning as for tt(compctl) and tt(complist),
too. It makes the suffix given with tt(-S) be automatically removed if
@ -382,15 +389,19 @@ given, it is true if the number of words is equal to or greater than
var(min) and equal to or less than var(max)
)
item(tt(-after) var(string))(
true if the cursor is after a word that is equal to var(string)
true if the cursor is after a word that is equal to var(string); this
removes all words up to and including the matched word from the
positional parameters
)
item(tt(-mafter) var(pattern))(
like tt(-after) but using pattern matching
)
item(tt(-between) var(string1) var(string2))(
true if the cursor is after a word that is equal to var(string1), if
there is also a word that is equal to va(string2), this is true only
if the cursor is before it
there is also a word that is equal to var(string2), this is true only
if the cursor is before it; as a side effect, all words before
var(string1) and after var(string2) (both inclusive) are removed from
the positional parameters
)
item(tt(-mbetween) var(pattern1) var(pattern2))(
like tt(-between) but using pattern matching

View file

@ -869,7 +869,7 @@ can be specified by separating two characters by a `tt(-)'.
A `tt(-)' or `tt(])' may be matched by including it as the
first character in the list.
There are also several named classes of characters, in the form
`tt([:)var(name)(tt:])' with the following meanings: `tt([:alnum:])'
`tt([:)var(name)tt(:])' with the following meanings: `tt([:alnum:])'
alphanumeric, `tt([:alpha:])' alphabetic,
`tt([:blank:])' space or tab,
`tt([:cntrl:])' control character, `tt([:digit:])' decimal
@ -988,12 +988,18 @@ item(I)(
Case sensitive: locally negates the effect of tt(i) or tt(l) from
that point on.
)
item(tt(a)var(num))(
Approximate matching: var(num) errors are allowed in the string matched by
the pattern. The rules for this are described in the next subsection.
)
enditem()
For example, the test string tt(fooxx) can be matched by the pattern
tt(LPAR()#i)tt(RPAR()FOOXX), but not by tt(LPAR()#l)tt(RPAR()FOOXX),
tt(LPAR()#i)tt(RPAR()FOO)tt(LPAR()#I)tt(RPAR()XX) or
tt(LPAR()LPAR()#i)tt(RPAR()FOOX)tt(RPAR()X).
tt(LPAR()LPAR()#i)tt(RPAR()FOOX)tt(RPAR()X). The string
tt(LPAR()#ia2)tt(RPAR()readme) specifies case-insensitive matching of
tt(readme) with up to two errors.
When using the ksh syntax for grouping both tt(KSH_GLOB) and
tt(EXTENDED_GLOB) must be set and the left parenthesis should be
@ -1004,6 +1010,61 @@ examining whole paths case-insensitively every directory must be
searched for all files which match, so that a pattern of the form
tt(LPAR()#i)tt(RPAR()/foo/bar/...) is potentially slow.
subsect(Approximate Matching)
When matching approximately, the shell keeps a count of the errors found,
which cannot exceed the number specified in the
tt(LPAR()#a)var(num)tt(RPAR()) flags. Four types of error are recognised:
startitem()
item(1.)(
Different characters, as in tt(fooxbar) and tt(fooybar).
)
item(2.)(
Transposition of characters, as in tt(banana) and tt(abnana).
)
item(3.)(
A character missing in the target string, as with the pattern tt(road) and
target string tt(rod).
)
item(4.)(
An extra character appearing in the target string, as with tt(stove)
and tt(strove).
)
enditem()
Thus, the pattern tt(LPAR()#a3)tt(RPAR()abcd) matches tt(dcba), with the
errors occurring by using the first rule twice and the second once,
grouping the string as tt([d][cb][a]) and tt([a][bc][d]).
Non-literal parts of the pattern must match exactly, including characters
in character ranges: hence tt(LPAR()#a1)tt(RPAR()???) matches strings of
length four, by applying rule 4 to an empty part of the pattern, but not
strings of length three, since all the tt(?) must match. Other characters
which must match exactly are initial dots in filenames (unless the
tt(GLOB_DOTS) option is set), and all slashes in file names, so that
tt(a/bc) is two errors from tt(ab/c) (the slash cannot be transposed with
another character). Similarly, errors are counted separately for
non-contiguous strings in the pattern, so that tt(LPAR()ab|cd)tt(RPAR()ef)
is two errors from tt(aebf).
When using exclusion via the tt(~) operator, approximate matching is
treated entirely separately for the excluded part and must be activated
separately. Thus, tt(LPAR()#a1)tt(RPAR()README~READ_ME) matches
tt(READ.ME) but not tt(READ_ME), as the trailing tt(READ_ME) is matched
without approximation. However,
tt(LPAR()#a1)tt(RPAR()README~LPAR()#a1)tt(RPAR()READ_ME)
does not match any pattern of the form tt(READ)var(?)tt(ME) as all
such forms are now excluded.
Apart from exclusions, there is only one overall error count; however, the
maximum errors allowed may be altered locally, and this can be delimited by
grouping. For example,
tt(LPAR()#a1)tt(RPAR()cat)tt(LPAR()LPAR()#a0)tt(RPAR()dog)tt(RPAR()fox)
allows one error in total, which may not occur in the tt(dog) section, and
the pattern
tt(LPAR()#a1)tt(RPAR()cat)tt(LPAR()#a0)tt(RPAR()dog)tt(LPAR()#a1)tt(RPAR()fox)
is equivalent.
subsect(Recursive Globbing)
A pathname component of the form `tt(LPAR())var(foo)tt(/RPAR()#)'
matches a path consisting of zero or more directories

View file

@ -144,8 +144,8 @@ then be processed with bf(dvips) and optionally bf(gs) (Ghostscript) to
produce a nicely formatted printed guide.
)
item(The HTML guide)(
Mark Borges, tt(<mdb@cdc.noaa.gov), maintains an HTML version of this
guide at tt(http://www.peak.org/zsh/Doc/zsh_toc.html).
An HTML version of this guide is available at the Zsh web site via
tt(http://sunsite.auc.dk/zsh/Doc/index.html).
(The HTML version is produced with bf(texi2html), which may be obtained
from tt(http://wwwcn.cern.ch/dci/texi2html/). The command is
`tt(texi2html -split_chapter -expandinfo zsh.texi)'.)

View file

@ -103,6 +103,7 @@ t :] [:]]#
t [ [[]
t ] []]
t [] [^]]]
# Case insensitive matching
t fooxx (#i)FOOXX
f fooxx (#l)FOOXX
t FOOXX (#l)fooxx
@ -113,5 +114,36 @@ f fooxx ((#i)FOOX)X
f BAR (bar|(#i)foo)
t FOO (bar|(#i)foo)
t Modules (#i)*m*
# Approximate matching
t READ.ME (#ia1)readme
f READ..ME (#ia1)readme
t README (#ia1)readm
t READM (#ia1)readme
t README (#ia1)eadme
t EADME (#ia1)readme
t READEM (#ia1)readme
f ADME (#ia1)readme
f README (#ia1)read
t bob (#a1)[b][b]
f bob (#a1)[b][b]a
t bob (#a1)[b]o[b]a
f bob (#a1)[c]o[b]
t abcd (#a2)XbcX
t abcd (#a2)ad
t ad (#a2)abcd
t abcd (#a2)bd
t bd (#a2)abcd
t badc (#a2)abcd
# This next one is a little tricky: a[d]bc[] = a[]bc[d]
t adbc (#a2)abcd
f dcba (#a2)abcd
# the next one is [d][cb][a] = [a][bc][d] with a transposition
t dcba (#a3)abcd
t aabaXaaabY (#a1)(a#b)#Y
t aabaXaaabY (#a1)(a#b)(a#b)Y
t aaXaaaaabY (#a1)(a#b)(a#b)Y
f read.me (#ia1)README~READ.ME
t read.me (#ia1)README~READ_ME
f read.me (#ia1)README~(#a1)READ_ME
EOT
print "$failed tests failed."

View file

@ -19,6 +19,7 @@ zsh
libzsh.so*
sigcount.h
signames.c
version.h
zshpaths.h
zshxmods.h
bltinmods.list

View file

@ -37,7 +37,7 @@
# include "rlimits.h"
# if defined(RLIM_T_IS_QUAD_T) || defined(RLIM_T_IS_UNSIGNED)
# if defined(RLIM_T_IS_QUAD_T) || defined(RLIM_T_IS_LONG_LONG) || defined(RLIM_T_IS_UNSIGNED)
static rlim_t
zstrtorlimt(const char *s, char **t, int base)
{
@ -62,9 +62,9 @@ zstrtorlimt(const char *s, char **t, int base)
*t = (char *)s;
return ret;
}
# else /* !RLIM_T_IS_QUAD_T && !RLIM_T_IS_UNSIGNED */
# else /* !RLIM_T_IS_QUAD_T && !RLIM_T_IS_LONG_LONG && !RLIM_T_IS_UNSIGNED */
# define zstrtorlimt(a, b, c) zstrtol((a), (b), (c))
# endif /* !RLIM_T_IS_QUAD_T && !RLIM_T_IS_UNSIGNED */
# endif /* !RLIM_T_IS_QUAD_T && !RLIM_T_IS_LONG_LONG && !RLIM_T_IS_UNSIGNED */
/* Display resource limits. hard indicates whether `hard' or `soft' *
* limits should be displayed. lim specifies the limit, or may be -1 *
@ -107,9 +107,15 @@ showlimits(int hard, int lim)
else
printf("%qdkB\n", val / 1024L);
# else
# ifdef RLIM_T_IS_LONG_LONG
printf("%lldMB\n", val / (1024L * 1024L));
else
printf("%lldkB\n", val / 1024L);
# else
printf("%ldMB\n", val / (1024L * 1024L));
else
printf("%ldkB\n", val / 1024L);
# endif /* RLIM_T_IS_LONG_LONG */
# endif /* RLIM_T_IS_QUAD_T */
}
}

View file

@ -271,9 +271,10 @@ struct cline {
#define CLF_MISS 4
#define CLF_DIFF 8
#define CLF_SUF 16
#define CLF_NEW 32
#define CLF_VAR 64
#define CLF_JOIN 128
#define CLF_PNEW 32
#define CLF_SNEW 64
#define CLF_VAR 128
#define CLF_JOIN 256
/* Flags for makecomplist*(). Things not to do. */

View file

@ -49,10 +49,10 @@ void (*makecompparamsptr) _((void));
/* pointers to functions required by compctl and defined by zle */
/**/
void (*addmatchesptr) _((char *, char *, char *, char *, char *, char *, char *, char *, char *, char *, int, int, Cmatcher, char **));
void (*addmatchesptr) _((char *, char *, char *, char *, char *, char *, char *, char *, char *, char *, int, int, Cmatcher, char *, char **));
/**/
char *(*comp_strptr) _((int*,int*));
char *(*comp_strptr) _((int*, int*, int));
/**/
int (*getcpatptr) _((char *, int, char *, int));
@ -410,6 +410,7 @@ setup_comp1(Module m)
cc_first.mask2 = CC_CCCONT;
compcontext = compcommand = compprefix = compsuffix =
compiprefix = NULL;
makecompparamsptr = NULL;
return 0;
}

View file

@ -1676,7 +1676,7 @@ bin_compadd(char *name, char **argv, char *ops, int func)
char *p, **sp, *e;
char *ipre = NULL, *ppre = NULL, *psuf = NULL, *prpre = NULL;
char *pre = NULL, *suf = NULL, *group = NULL, *m = NULL, *rs = NULL;
char *ign = NULL, *rf = NULL;
char *ign = NULL, *rf = NULL, *expl = NULL;
int f = 0, a = 0, dm;
Cmatcher match = NULL;
@ -1757,6 +1757,10 @@ bin_compadd(char *name, char **argv, char *ops, int func)
e = "matching specification expected after -%c";
dm = 1;
break;
case 'X':
sp = &expl;
e = "string expected after -%c";
break;
case 'r':
f |= CMF_REMOVE;
sp = &rs;
@ -1802,7 +1806,7 @@ bin_compadd(char *name, char **argv, char *ops, int func)
match = cpcmatcher(match);
addmatchesptr(ipre, ppre, psuf, prpre, pre, suf, group,
rs, rf, ign, f, a, match, argv);
rs, rf, ign, f, a, match, expl, argv);
freecmatcher(match);
return 0;
@ -2049,8 +2053,8 @@ cond_strcl(char **a, int id)
zerr("zle not loaded, zle condition not available", NULL, 0);
return 1;
}
i = getcpatptr(comp_strptr(&ipl, NULL), i, s, id);
if (i != -1) {
i = getcpatptr(comp_strptr(&ipl, NULL, 1), i, s, id);
if (i != -1 && i >= ipl) {
ignore_prefix(i - ipl);
return 1;
}

View file

@ -478,6 +478,17 @@ bin_zle_complete(char *name, char **args, char *ops, char func)
Thingy t;
Widget w, cw;
#ifdef DYNAMIC
if (!require_module(name, "compctl", 0, 0)) {
zerrnam(name, "can't load compctl module", NULL, 0);
return 1;
}
#else
if (!makecompparamsptr) {
zerrnam(name, "compctl module not available", NULL, 0);
return 1;
}
#endif
t = rthingy(args[1]);
cw = t->widget;
unrefthingy(t);

File diff suppressed because it is too large Load diff

View file

@ -2558,7 +2558,7 @@ execarith(Cmd cmd)
val = matheval(e);
}
if (isset(XTRACE)) {
fprintf(stderr, " ))\n", stderr);
fprintf(stderr, " ))\n");
fflush(stderr);
}
errflag = 0;

View file

@ -71,6 +71,7 @@ struct gmatch {
int badcshglob;
static int mode; /* != 0 if we are parsing glob patterns */
static int scanning; /* != 0 if we are scanning file paths */
static int pathpos; /* position in pathbuf */
static int matchsz; /* size of matchbuf */
static int matchct; /* number of matches found */
@ -134,7 +135,7 @@ struct complist {
struct comp {
Comp left, right, next, exclude;
char *str;
int stat;
int stat, errsmax;
};
/* Type of Comp: a closure with one or two #'s, the end of a *
@ -162,6 +163,18 @@ struct comp {
#define GF_PATHADD 1 /* file glob, adding path components */
#define GF_TOPLEV 2 /* outside (), so ~ ends main match */
/* Next character after one which may be a Meta (x is any char *) */
#define METANEXT(x) (*(x) == Meta ? (x)+2 : (x)+1)
/*
* Increment pointer which may be on a Meta (x is a pointer variable),
* returning the incremented value (i.e. like pre-increment).
*/
#define METAINC(x) ((x) += (*(x) == Meta) ? 2 : 1)
/*
* Return unmetafied char from string (x is any char *)
*/
#define UNMETA(x) (*(x) == Meta ? (x)[1] ^ 32 : *(x))
static char *pptr; /* current place in string being matched */
static Comp tail;
static int first; /* are leading dots special? */
@ -352,6 +365,25 @@ haswilds(char *str)
return 0;
}
/* Flags to apply to current level of grouping */
static int addflags;
/*
* Approximate matching.
*
* errsmax is used while parsing to store the current number
* of errors allowed. While executing it is usually set to -1,
* but can be set to something else to fix a different maximum
* no. of errors which acts as a limit on the local value: see
* scanner() for why this is necessary.
*
* errsfound is used while executing a pattern to record the
* number of errors found so far.
*/
static int errsmax, errsfound;
/* Do the globbing: scanner is called recursively *
* with successive bits of the path until we've *
* tried all of it. */
@ -363,6 +395,7 @@ scanner(Complist q)
Comp c;
int closure;
int pbcwdsav = pathbufcwd;
int errssofar = errsfound;
struct dirsav ds;
ds.ino = ds.dev = 0;
@ -381,7 +414,7 @@ scanner(Complist q)
c = q->comp;
/* Now the actual matching for the current path section. */
if (!(c->next || c->left) && !haswilds(c->str)
&& (!(c->stat & (C_LCMATCHUC|C_IGNCASE))
&& (!((c->stat & (C_LCMATCHUC|C_IGNCASE)) || c->errsmax)
|| !strcmp(".", c->str) || !strcmp("..", c->str))) {
/*
* We always need to match . and .. explicitly, even if we're
@ -433,6 +466,7 @@ scanner(Complist q)
((glob_pre && !strpfx(glob_pre, fn))
|| (glob_suf && !strsfx(glob_suf, fn))))
continue;
errsfound = errssofar;
if (domatch(fn, c, gf_noglobdots)) {
/* if this name matchs the pattern... */
if (pbcwdsav == pathbufcwd &&
@ -453,7 +487,34 @@ scanner(Complist q)
if (dirs) {
int l;
/* if not the last component in the path */
/*
* If not the last component in the path:
*
* If we made an approximation in the new path segment,
* and the pattern includes closures other than a
* trailing * (we only test if it is not a string),
* then it is possible we made too many errors. For
* example, (ab)#(cb)# will match the directory abcb
* with one error if allowed to, even though it can
* match with none. This will stop later parts of the
* path matching, so we need to check by reducing the
* maximum number of errors and seeing if the directory
* still matches. Luckily, this is not a terribly
* common case, since complex patterns typically occur
* in the last part of the path which is not affected
* by this problem.
*/
if (errsfound > errssofar && (c->next || c->left)) {
errsmax = errsfound - 1;
while (errsmax >= errssofar) {
errsfound = errssofar;
if (!domatch(fn, c, gf_noglobdots))
break;
errsmax = errsfound - 1;
}
errsfound = errsmax + 1;
errsmax = -1;
}
if (closure) {
/* if matching multiple directories */
struct stat buf;
@ -470,9 +531,14 @@ scanner(Complist q)
continue;
}
l = strlen(fn) + 1;
subdirs = hrealloc(subdirs, subdirlen, subdirlen + l);
subdirs = hrealloc(subdirs, subdirlen, subdirlen + l
+ sizeof(int));
strcpy(subdirs + subdirlen, fn);
subdirlen += l;
/* store the count of errors made so far, too */
memcpy(subdirs + subdirlen, (char *)&errsfound,
sizeof(int));
subdirlen += sizeof(int);
} else
/* if the last filename component, just add it */
insert(fn, 1);
@ -482,8 +548,11 @@ scanner(Complist q)
if (subdirs) {
int oppos = pathpos;
for (fn = subdirs; fn < subdirs+subdirlen; fn += strlen(fn) + 1) {
for (fn = subdirs; fn < subdirs+subdirlen; ) {
addpath(fn);
fn += strlen(fn) + 1;
memcpy((char *)&errsfound, fn, sizeof(int));
fn += sizeof(int);
scanner((q->closure) ? q : q->next); /* scan next level */
pathbuf[pathpos = oppos] = '\0';
}
@ -502,16 +571,13 @@ scanner(Complist q)
/* Parse a series of path components pointed to by pptr */
/* Flags to apply to current level of grourping */
static int addflags;
/**/
static Comp
compalloc(void)
{
Comp c = (Comp) alloc(sizeof *c);
c->stat |= addflags;
c->errsmax = errsmax;
return c;
}
@ -519,10 +585,19 @@ compalloc(void)
static int
getglobflags()
{
char *nptr;
/* (#X): assumes we are still positioned on the initial '(' */
pptr++;
while (*++pptr && *pptr != Outpar) {
switch (*pptr) {
case 'a':
/* Approximate matching, max no. of errors follows */
errsmax = zstrtol(++pptr, &nptr, 10);
if (pptr == nptr)
return 1;
pptr = nptr-1;
break;
case 'l':
/* Lowercase in pattern matches lower or upper in target */
addflags |= C_LCMATCHUC;
@ -635,6 +710,7 @@ parsecomp(int gflag)
if (eptr == cstr) {
/* if no string yet, carry on and get one. */
c->stat = addflags;
c->errsmax = errsmax;
cstr = pptr;
continue;
}
@ -817,6 +893,7 @@ parsecompsw(int gflag)
{
Comp c1, c2, c3, excl = NULL, stail = tail;
int oaddflags = addflags;
int oerrsmax = errsmax;
char *sptr;
/*
@ -845,12 +922,14 @@ parsecompsw(int gflag)
return NULL;
if (isset(EXTENDEDGLOB) && *pptr == Tilde) {
/* Matching remainder of pattern excludes the pattern from matching */
int oldmode = mode;
int oldmode = mode, olderrsmax = errsmax;
mode = 1;
errsmax = 0;
pptr++;
excl = parsecomp(gflag);
mode = oldmode;
errsmax = olderrsmax;
if (!excl)
return NULL;
}
@ -878,8 +957,10 @@ parsecompsw(int gflag)
c2->stat |= C_PATHADD;
c1 = c2;
}
if (!(gflag & GF_TOPLEV))
if (!(gflag & GF_TOPLEV)) {
addflags = oaddflags;
errsmax = oerrsmax;
}
return c1;
}
@ -965,6 +1046,7 @@ parsepat(char *str)
{
mode = 0; /* path components present */
addflags = 0;
errsmax = 0;
pptr = str;
tail = NULL;
/*
@ -1102,7 +1184,7 @@ static int
gmatchcmp(Gmatch a, Gmatch b)
{
int i, *s;
long r;
long r = 0L;
for (i = gf_nsorts, s = gf_sortlist; i; i--, s++) {
switch (*s & ~GS_DESC) {
@ -1594,10 +1676,14 @@ glob(LinkList list, LinkNode np)
matchptr = matchbuf = (Gmatch)zalloc((matchsz = 16) *
sizeof(struct gmatch));
matchct = 0;
errsfound = 0;
errsmax = -1;
/* The actual processing takes place here: matches go into *
* matchbuf. This is the only top-level call to scanner(). */
scanning = 1;
scanner(q);
scanning = 0;
/* Deal with failures to match depending on options */
if (matchct)
@ -2427,6 +2513,14 @@ domatch(char *str, Comp c, int fist)
int ret;
pptr = str;
first = fist;
/*
* If scanning paths, keep the error count over the whole
* filename
*/
if (!scanning) {
errsfound = 0;
errsmax = -1;
}
if (*pptr == Nularg)
pptr++;
PERMALLOC {
@ -2444,15 +2538,17 @@ static int
excluded(Comp c, char *eptr)
{
char *saves = pptr;
int savei = first, savel = longest, ret;
int savei = first, savel = longest, savee = errsfound, ret;
first = 0;
/*
* Even if we've been told always to match the longest string,
* i.e. not anchored to the end, we want to match the full string
* we've already matched when we're trying to exclude it.
* Likewise, approximate matching here is treated separately.
*/
longest = 0;
errsfound = 0;
if (PATHADDP(c) && pathpos) {
VARARR(char, buf, pathpos + strlen(eptr) + 1);
@ -2470,13 +2566,18 @@ excluded(Comp c, char *eptr)
pptr = saves;
first = savei;
longest = savel;
errsfound = savee;
return ret;
}
/*
* Structure for storing instances of a pattern in a closured.
*/
struct gclose {
char *start;
char *end;
char *start; /* Start of this instance */
char *end; /* End of this instance */
int errsfound; /* Errors found up to start of instance */
};
typedef struct gclose *Gclose;
@ -2488,34 +2589,48 @@ typedef struct gclose *Gclose;
* also not bother going any further, since the first time we got to
* that position (when it was marked), we must already have failed on
* and backtracked over any further closure matches beyond that point.
* If we are using approximation, the number in the string is incremented
* by the current error count; if we come back to that point with a
* lower error count, it is worth trying from that point again, but
* we must now mark that point in trystring with the new error.
*/
/**/
static void
addclosures(Comp c, LinkList closlist, int *pdone, char *trystring)
addclosures(Comp c, LinkList closlist, int *pdone, unsigned char *trystring)
{
Gclose gcnode;
char *opptr = pptr;
unsigned char *tpos;
while (*pptr) {
if (STARP(c)) {
if (trystring[(pptr+1)-opptr])
break;
if (*(tpos = trystring + ((pptr+1) - opptr))) {
if ((unsigned)(errsfound+1) >= *tpos)
break;
*tpos = (unsigned)(errsfound+1);
}
gcnode = (Gclose)zalloc(sizeof(struct gclose));
gcnode->start = pptr;
gcnode->end = ++pptr;
gcnode->end = METAINC(pptr);
gcnode->errsfound = errsfound;
} else {
char *saves = pptr;
int savee = errsfound;
if (OPTIONALP(c) && *pdone >= 1)
return;
if (!matchonce(c) || saves == pptr ||
trystring[pptr-opptr]) {
(*(tpos = trystring + (pptr-opptr)) &&
(unsigned)(errsfound+1) >= *tpos)) {
pptr = saves;
break;
}
if (*tpos)
*tpos = (unsigned)(errsfound+1);
gcnode = (Gclose)zalloc(sizeof(struct gclose));
gcnode->start = saves;
gcnode->end = pptr;
gcnode->errsfound = savee;
}
pushnode(closlist, gcnode);
(*pdone)++;
@ -2523,13 +2638,29 @@ addclosures(Comp c, LinkList closlist, int *pdone, char *trystring)
}
/*
* Match characters with case-insensitivity.
* Note CHARMATCH(x,y) != CHARMATCH(y,x)
* Match characters with case-insensitivity. Note charmatch(x,y) !=
* charmatch(y,x): the first argument comes from the target string, the
* second from the pattern. This used to be a macro, and in principle
* could be turned back into one.
*/
#define CHARMATCH(x, y) \
(x == y || (((c->stat & C_IGNCASE) ? (tulower(x) == tulower(y)) : \
(c->stat & C_LCMATCHUC) ? (islower(y) && tuupper(y) == x) : 0)))
/**/
static int
charmatch(Comp c, char *x, char *y)
{
/*
* This takes care of matching two characters which may be a
* two byte sequence, Meta followed by something else.
* Here we bypass tulower() and tuupper() for speed.
*/
int xi = (STOUC(UNMETA(x)) & 0xff), yi = (STOUC(UNMETA(y)) & 0xff);
return xi == yi ||
(((c->stat & C_IGNCASE) ?
((isupper(xi) ? tolower(xi) : xi) ==
(isupper(yi) ? tolower(yi) : yi)) :
(c->stat & C_LCMATCHUC) ?
(islower(yi) && toupper(yi) == xi) : 0));
}
/* see if current string in pptr matches c */
@ -2539,14 +2670,16 @@ doesmatch(Comp c)
{
if (CLOSUREP(c)) {
int done, retflag = 0;
char *saves, *trystring, *opptr;
char *saves, *opptr;
unsigned char *trystring, *tpos;
int savee;
LinkList closlist;
Gclose gcnode;
if (first && *pptr == '.')
return 0;
if (!inclosure && !c->left) {
if (!inclosure && !c->left && !c->errsmax) {
/* We are not inside another closure, and the current
* pattern is a simple string. We handle this very common
* case specially: otherwise, matches like *foo* are
@ -2561,26 +2694,30 @@ doesmatch(Comp c)
!itok(looka)) {
/* Another simple optimisation for a very common case:
* we are processing a * and there is
* an ordinary character match next. We look ahead for
* that character, taking care of Meta bytes.
* an ordinary character match (which may not be a Metafied
* character, just to make it easier) next. We look ahead
* for that character, taking care of Meta bytes.
*/
while (*pptr) {
for (; *pptr; pptr++) {
if (*pptr == Meta)
pptr++;
else if (CHARMATCH(STOUC(*pptr), STOUC(looka)))
else if (charmatch(c, pptr, &looka))
break;
}
if (!*(saves = pptr))
break;
savee = errsfound;
if (doesmatch(c->next))
return 1;
pptr = saves+1;
errsfound = savee;
}
} else {
/* Standard track-forward code */
for (done = 0; ; done++) {
saves = pptr;
savee = errsfound;
if ((done || ONEHASHP(c) || OPTIONALP(c)) &&
((!c->next && (!LASTP(c) || !*pptr || longest)) ||
(c->next && doesmatch(c->next))))
@ -2588,6 +2725,7 @@ doesmatch(Comp c)
if (done && OPTIONALP(c))
return 0;
pptr = saves;
errsfound = savee;
first = 0;
if (STARP(c)) {
if (!*pptr)
@ -2602,7 +2740,7 @@ doesmatch(Comp c)
/* The full, gory backtracking code is now necessary. */
inclosure++;
closlist = newlinklist();
trystring = zcalloc(strlen(pptr)+1);
trystring = (unsigned char *)zcalloc(strlen(pptr)+1);
opptr = pptr;
/* Start by making a list where each match is as long
@ -2621,7 +2759,7 @@ doesmatch(Comp c)
retflag = 1;
break;
}
trystring[saves-opptr] = 1;
trystring[saves-opptr] = (unsigned)(errsfound + 1);
/*
* If we failed, the first thing to try is whether we can
* shorten the match using the last pattern in the closure.
@ -2633,14 +2771,18 @@ doesmatch(Comp c)
char savec = *gcnode->end;
*gcnode->end = '\0';
pptr = gcnode->start;
errsfound = gcnode->errsfound;
if (matchonce(c) && pptr != gcnode->start
&& !trystring[pptr-opptr]) {
&& (!*(tpos = trystring + (pptr-opptr)) ||
*tpos > (unsigned)(errsfound+1))) {
if (*tpos)
*tpos = (unsigned)(errsfound+1);
*gcnode->end = savec;
gcnode->end = pptr;
/* Try again to construct a list based on
* this new position
*/
addclosures(c, closlist, &done, trystring+(pptr-opptr));
addclosures(c, closlist, &done, tpos);
continue;
}
*gcnode->end = savec;
@ -2650,6 +2792,7 @@ doesmatch(Comp c)
*/
if ((gcnode = (Gclose)getlinknode(closlist))) {
pptr = gcnode->start;
errsfound = gcnode->errsfound;
zfree(gcnode, sizeof(struct gclose));
done--;
} else
@ -2723,8 +2866,7 @@ rangematch(char **patptr, int ch, int rchar)
#define PAT(X) (pat[X] == Meta ? pat[(X)+1] ^ 32 : untok(pat[X]))
#define PPAT(X) (pat[(X)-1] == Meta ? pat[X] ^ 32 : untok(pat[X]))
for (pat++; *pat != Outbrack && *pat;
*pat == Meta ? pat += 2 : pat++) {
for (pat++; *pat != Outbrack && *pat; METAINC(pat)) {
if (*pat == Inbrack) {
/* Inbrack can only occur inside a range if we found [:...:]. */
pat += 2;
@ -2748,6 +2890,22 @@ rangematch(char **patptr, int ch, int rchar)
*patptr = pat;
}
/*
* matchonce() is the core of the pattern matching, handling individual
* strings and instances of a pattern in a closure.
*
* Note on approximate matching: The rule is supposed to be
* (1) Take the longest possible match without approximation.
* (2) At any failure, make the single approximation that results
* in the longest match for the remaining part (which may
* include further approximations).
* (3) If we match the same distance, take the one with fewer
* approximations.
* If this is wrong, I haven't yet discovered a counterexample. Email
* lines are now open.
* pws 1999/02/23
*/
/**/
static int
matchonce(Comp c)
@ -2758,7 +2916,7 @@ matchonce(Comp c)
if (!pat || !*pat) {
/* No current pattern (c->str). */
char *saves;
int savei;
int savee, savei;
if (errflag)
return 0;
@ -2766,6 +2924,7 @@ matchonce(Comp c)
* check for exclusion of pattern or alternatives. */
saves = pptr;
savei = first;
savee = errsfound;
/* Loop over alternatives with exclusions: (foo~bar|...). *
* Exclusions apply to the pattern in c->left. */
if (c->left || c->right) {
@ -2812,6 +2971,7 @@ matchonce(Comp c)
*/
exclend--;
pptr = saves;
errsfound = savee;
}
inclosure--;
if (ret)
@ -2822,19 +2982,43 @@ matchonce(Comp c)
if (c->right && (!ret || inclosure)) {
/* If in a closure, we always want the longest match. */
char *newpptr = pptr;
int newerrsfound = errsfound;
pptr = saves;
first = savei;
errsfound = savee;
ret2 = doesmatch(c->right);
if (ret && (!ret2 || pptr < newpptr))
if (ret && (!ret2 || pptr < newpptr)) {
pptr = newpptr;
errsfound = newerrsfound;
}
}
if (!ret && !ret2) {
pptr = saves;
first = savei;
errsfound = savee;
break;
}
if (!ret && !ret2)
return 0;
}
if (CLOSUREP(c))
return 1;
if (!c->next) /* no more patterns left */
return (!LASTP(c) || !*pptr || longest);
if (!c->next) {
/*
* No more patterns left, but we may still be in the middle
* of a match, in which case alles in Ordnung...
*/
if (!LASTP(c))
return 1;
/*
* ...else we're at the last pattern, so this is our last
* ditch attempt at an approximate match: try to omit the
* last few characters.
*/
for (; *pptr && errsfound < c->errsmax &&
(errsmax == -1 || errsfound < errsmax);
METAINC(pptr))
errsfound++;
return !*pptr || longest;
}
/* optimisation when next pattern is not a closure */
if (!CLOSUREP(c->next)) {
c = c->next;
@ -2843,7 +3027,10 @@ matchonce(Comp c)
}
return doesmatch(c->next);
}
/* Don't match leading dot if first is set */
/*
* Don't match leading dot if first is set
* (don't even try for an approximate match)
*/
if (first && *pptr == '.' && *pat != '.')
return 0;
if (*pat == Star) { /* final * is not expanded to ?#; returns success */
@ -2852,39 +3039,47 @@ matchonce(Comp c)
return 1;
}
first = 0; /* finished checking start of pattern */
if (*pat == Quest && *pptr) {
if (*pat == Quest) {
/* match exactly one character */
if (*pptr == Meta)
pptr++;
pptr++;
if (!*pptr)
break;
METAINC(pptr);
pat++;
continue;
}
if (*pat == Inbrack) {
/* Match groups of characters */
char ch;
char *saves, *savep;
if (!*pptr)
break;
ch = *pptr == Meta ? pptr[1] ^ 32 : *pptr;
saves = pptr;
savep = pat;
ch = UNMETA(pptr);
if (pat[1] == Hat || pat[1] == '^' || pat[1] == '!') {
/* group is negated */
*++pat = Hat;
rangematch(&pat, ch, Hat);
DPUTS(!*pat, "BUG: something is very wrong in doesmatch()");
if (*pat != Outbrack)
if (*pat != Outbrack) {
pptr = saves;
pat = savep;
break;
}
pat++;
*pptr == Meta ? pptr += 2 : pptr++;
METAINC(pptr);
continue;
} else {
/* pattern is not negated (affirmed? asserted?) */
rangematch(&pat, ch, Inbrack);
DPUTS(!pat || !*pat, "BUG: something is very wrong in doesmatch()");
if (*pat == Outbrack)
if (*pat == Outbrack) {
pptr = saves;
pat = savep;
break;
for (*pptr == Meta ? pptr += 2 : pptr++;
*pat != Outbrack; pat++);
}
for (METAINC(pptr); *pat != Outbrack; pat++);
pat++;
continue;
}
@ -2892,7 +3087,7 @@ matchonce(Comp c)
if (*pat == Inang) {
/* Numeric globbing. */
unsigned long t1, t2, t3;
char *ptr;
char *ptr, *saves = pptr, *savep = pat;
if (!idigit(*pptr))
break;
@ -2933,19 +3128,146 @@ matchonce(Comp c)
pptr--;
t1 /= 10;
}
if (t1 < t2 || (!not3 && t1 > t3))
if (t1 < t2 || (!not3 && t1 > t3)) {
pptr = saves;
pat = savep;
break;
}
}
continue;
}
if (CHARMATCH(STOUC(*pptr), STOUC(*pat))) {
/* just plain old characters */
pptr++;
pat++;
/* itok(Meta) is zero */
DPUTS(itok(*pat), "BUG: matching tokenized character");
if (charmatch(c, pptr, pat)) {
/* just plain old characters (or maybe unplain new characters) */
METAINC(pptr);
METAINC(pat);
continue;
}
if (errsfound < c->errsmax &&
(errsmax == -1 || errsfound < errsmax)) {
/*
* We tried to match literal characters and failed. Now it's
* time to match approximately. Note this doesn't handle the
* case where we *didn't* try to match literal characters,
* including the case where we were already at the end of the
* pattern, because then we never get here. In that case the
* pattern has to be matched exactly, but we could maybe
* advance up the target string before trying it, so we have to
* handle that case elsewhere.
*/
char *saves = pptr, *savep = c->str;
char *maxpptr = pptr, *patnext = METANEXT(pat);
int savee, maxerrs = -1;
/* First try to advance up the pattern. */
c->str = patnext;
savee = ++errsfound;
if (matchonce(c)) {
maxpptr = pptr;
maxerrs = errsfound;
}
errsfound = savee;
if (*saves) {
/*
* If we have characters on both strings, we have more
* choice.
*
* Try to edge up the target string.
*/
char *strnext = METANEXT(saves);
pptr = strnext;
c->str = pat;
if (matchonce(c) &&
(maxerrs == -1 || pptr > maxpptr ||
(pptr == maxpptr && errsfound <= maxerrs))) {
maxpptr = pptr;
maxerrs = errsfound;
}
errsfound = savee;
/*
* Try edging up both of them at once.
* Note this takes precedence in the case of equal
* length as we get further up the pattern.
*/
c->str = patnext;
pptr = strnext;
if (matchonce(c) &&
(maxerrs == -1 || pptr > maxpptr ||
(pptr == maxpptr && errsfound <= maxerrs))) {
maxpptr = pptr;
maxerrs = errsfound;
}
errsfound = savee;
/*
* See if we can transpose: that counts as just one error.
*
* Note, however, `abanana' and `banana': transposing
* is wrong here, as it gets us two errors,
* [ab][a]nana vs [ba][]nana, instead of the correct
* [a]banana vs []banana, so we still need to try
* the other possibilities.
*/
if (strnext && patnext && !itok(*patnext) &&
charmatch(c, strnext, pat) &&
charmatch(c, saves, patnext)) {
c->str = patnext;
METAINC(c->str);
pptr = strnext;
METAINC(pptr);
if (matchonce(c) &&
(maxerrs == -1 || pptr > maxpptr ||
(pptr == maxpptr && errsfound <= maxerrs))) {
maxpptr = pptr;
maxerrs = errsfound;
}
}
}
/*
* We don't usually restore state on failure, but we need
* to fix up the Comp structure which we altered to
* look at the tail of the pattern.
*/
c->str = savep;
/*
* If that failed, game over: we don't want to break
* and try the other approximate test, because we just did
* that.
*/
if (maxerrs == -1)
return 0;
pptr = maxpptr;
errsfound = maxerrs;
return 1;
}
break;
}
if (*pptr && errsfound < c->errsmax &&
(errsmax == -1 || errsfound < errsmax)) {
/*
* The pattern failed, but we can try edging up the target string
* and rematching with an error. Note we do this from wherever we
* got to in the pattern string c->str, not the start. hence the
* need to modify c->str.
*
* At this point, we don't have a literal character in the pattern
* (handled above), so we don't try any funny business on the
* pattern itself.
*/
int ret;
char *savep = c->str;
errsfound++;
METAINC(pptr);
c->str = pat;
ret = matchonce(c);
c->str = savep;
return ret;
}
return 0;
}
@ -2958,6 +3280,7 @@ parsereg(char *str)
remnulargs(str);
mode = 1; /* no path components */
addflags = 0;
errsmax = 0;
pptr = str;
tail = NULL;
return parsecompsw(GF_TOPLEV);

View file

@ -607,6 +607,9 @@ hashdir(char **dirp)
Cmdnam cn;
DIR *dir;
char *fn;
#ifdef _WIN32
char *exe;
#endif
if (isrelative(*dirp) || !(dir = opendir(unmeta(*dirp))))
return;
@ -618,6 +621,23 @@ hashdir(char **dirp)
cn->u.name = dirp;
cmdnamtab->addnode(cmdnamtab, ztrdup(fn), cn);
}
#ifdef _WIN32
/* Hash foo.exe as foo, since when no real foo exists, foo.exe
will get executed by DOS automatically. This quiets
spurious corrections when CORRECT or CORRECT_ALL is set. */
if ((exe = strrchr(fn, '.')) &&
(exe[1] == 'E' || exe[1] == 'e') &&
(exe[2] == 'X' || exe[2] == 'x') &&
(exe[3] == 'E' || exe[3] == 'e') && exe[4] == 0) {
*exe = 0;
if (!cmdnamtab->getnode(cmdnamtab, fn)) {
cn = (Cmdnam) zcalloc(sizeof *cn);
cn->flags = 0;
cn->u.name = dirp;
cmdnamtab->addnode(cmdnamtab, ztrdup(fn), cn);
}
}
#endif /* _WIN32 */
}
closedir(dir);
}

View file

@ -567,6 +567,37 @@ load_module(char const *name)
return m;
}
/* This ensures that the module with the name given as the second argument
* is loaded.
* The third argument should be non-zero if the function should complain
* about trying to load a module with a full path name in restricted mode.
* The last argument should be non-zero if this function should signal an
* error if the module is already loaded.
* The return value is the module of NULL if the module couldn't be loaded. */
/**/
Module
require_module(char *nam, char *module, int res, int test)
{
Module m = NULL;
LinkNode node;
node = find_module(module);
if (node && (m = ((Module) getdata(node)))->handle &&
!(m->flags & MOD_UNLOAD)) {
if (test) {
zwarnnam(nam, "module %s already loaded.", module, 0);
return NULL;
}
} else if (res && isset(RESTRICTED) && strchr(module, '/')) {
zwarnnam(nam, "%s: restricted", module, 0);
return NULL;
} else
return load_module(module);
return m;
}
/**/
void
add_dep(char *name, char *from)
@ -963,22 +994,10 @@ bin_zmodload_load(char *nam, char **args, char *ops)
return 0;
} else {
/* load modules */
for (; *args; args++) {
Module m;
for (; *args; args++)
if (!require_module(nam, *args, 1, (!ops['i'])))
ret = 1;
node = find_module(*args);
if (node && (m = ((Module) getdata(node)))->handle &&
!(m->flags & MOD_UNLOAD)) {
if (!ops['i']) {
zwarnnam(nam, "module %s already loaded.", *args, 0);
ret = 1;
}
} else if (isset(RESTRICTED) && strchr(*args, '/')) {
zwarnnam(nam, "%s: restricted", *args, 0);
ret = 1;
} else if (!load_module(*args))
ret = 1;
}
return ret;
}
}

View file

@ -679,11 +679,13 @@ static char **garr;
static long
getarg(char **str, int *inv, Value v, int a2, long *w)
{
int num = 1, word = 0, rev = 0, ind = 0, down = 0, l, i;
int num = 1, word = 0, rev = 0, ind = 0, down = 0, l, i, ishash;
char *s = *str, *sep = NULL, *t, sav, *d, **ta, **p, *tt;
long r = 0;
Comp c;
ishash = (v->pm && PM_TYPE(v->pm->flags) == PM_HASHED);
/* first parse any subscription flags */
if (v->pm && (*s == '(' || *s == Inpar)) {
int escapes = 0;
@ -771,12 +773,13 @@ getarg(char **str, int *inv, Value v, int a2, long *w)
} else if (rev) {
v->isarr |= SCANPM_WANTVALS;
}
if (!down && v->pm && PM_TYPE(v->pm->flags) == PM_HASHED)
if (!down && ishash)
v->isarr &= ~SCANPM_MATCHMANY;
*inv = ind;
}
for (t=s, i=0; *t && ((*t != ']' && *t != Outbrack && *t != ',') || i); t++)
for (t=s, i=0;
*t && ((*t != ']' && *t != Outbrack && (ishash || *t != ',')) || i); t++)
if (*t == '[' || *t == Inbrack)
i++;
else if (*t == ']' || *t == Outbrack)
@ -791,7 +794,7 @@ getarg(char **str, int *inv, Value v, int a2, long *w)
singsub(&s);
if (!rev) {
if (v->pm && PM_TYPE(v->pm->flags) == PM_HASHED) {
if (ishash) {
HashTable ht = v->pm->gets.hfn(v->pm);
if (!ht) {
ht = newparamtable(17, v->pm->nam);
@ -867,7 +870,7 @@ getarg(char **str, int *inv, Value v, int a2, long *w)
if ((c = parsereg(s))) {
if (v->isarr) {
if (PM_TYPE(v->pm->flags) == PM_HASHED) {
if (ishash) {
scancomp = c;
if (ind)
v->isarr |= SCANPM_MATCHKEY;

View file

@ -999,11 +999,12 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
if (!(v = fetchvalue((subexp ? &ov : &s), (wantt ? -1 :
((unset(KSHARRAYS) || inbrace) ? 1 : -1)),
hkeys|hvals)))
hkeys|hvals)) ||
(v->pm && (v->pm->flags & PM_UNSET)))
vunset = 1;
if (wantt) {
if (v) {
if (v && v->pm && !(v->pm->flags & PM_UNSET)) {
int f = v->pm->flags;
switch (PM_TYPE(f)) {

View file

@ -70,8 +70,15 @@ char *alloca _((size_t));
# endif
#endif
#ifdef HAVE_LIBC_H /* NeXT */
# include <libc.h>
/*
* libc.h in an optional package for Debian Linux is broken (it
* defines dup() as a synonym for dup2(), which has a different
* number of arguments), so just include it for next.
*/
#ifdef __NeXT__
# ifdef HAVE_LIBC_H
# include <libc.h>
# endif
#endif
#ifdef HAVE_SYS_TYPES_H

View file

@ -173,6 +173,7 @@ refreshptr
remlpaths
remnulargs
removehashnode
require_module
resetneeded
restoredir
reswdtab

View file

@ -196,10 +196,13 @@
/* Define to 1 if system has working FIFO's */
#undef HAVE_FIFOS
/* Define to 1 if struct rlimit use quad_t */
/* Define to 1 if struct rlimit uses quad_t */
#undef RLIM_T_IS_QUAD_T
/* Define to 1 if rlimit use unsigned */
/* Define to 1 if struct rlimit uses long long */
#undef RLIM_T_IS_LONG_LONG
/* Define to 1 if rlimit uses unsigned */
#undef RLIM_T_IS_UNSIGNED
/* Define to the type used in struct rlimit */

View file

@ -673,7 +673,8 @@ dnl The backslash substitution is to persuade cygwin to cough up
dnl slashes rather than doubled backslashes in the path.
echo "#include <signal.h>" > nametmp.c
sigfile_list="`$CPP nametmp.c |
sed -n -e 's/^#[ ].*\"\(.*\)\"/\1/p' -e 's/\\\\\\\\/\//g' |
sed -n 's/^#[ ].*\"\(.*\)\"/\1/p' |
sed 's/\\\\\\\\/\//g' |
$AWK '{ if (\$1 ~ \"sig\") files[[\$1]] = \$1 }
END { for (var in files) print var }'`"
rm -f nametmp.c
@ -681,6 +682,7 @@ if test -z "$sigfile_list"; then
dnl In case we don't get the stuff from the preprocesor, use the old
dnl list of standard places.
sigfile_list="/usr/include/bsd/sys/signal.h
/usr/include/signum.h
/usr/include/asm/signum.h
/usr/include/asm/signal.h
/usr/include/linux/signal.h
@ -689,9 +691,13 @@ if test -z "$sigfile_list"; then
fi
for SIGNAL_H in $sigfile_list
do
test -f $SIGNAL_H && \
grep '#[ ]*define[ ][ ]*SIG[0-9A-Z]*[ ]*[0-9][0-9]*' $SIGNAL_H > /dev/null && \
break
dnl Try to make sure it doesn't get confused by files that don't
dnl have real signal definitions in, but do #define SIG* by counting
dnl the number of signals. Maybe we could even check for e.g. SIGHUP?
nsigs=`test -f $SIGNAL_H && \
grep '#[ ]*define[ ][ ]*SIG[0-9A-Z]*[ ]*[0-9][0-9]*' $SIGNAL_H | \
wc -l | sed 's/[ ]//g'`
test "x$nsigs" != x && test "$nsigs" -ge 7 && break
done
zsh_cv_path_signal_h=$SIGNAL_H
])
@ -729,20 +735,43 @@ dnl ------------------
dnl rlimit type checks
dnl ------------------
DEFAULT_RLIM_T=long
AC_CACHE_CHECK(if rlim_t is quad_t,
zsh_cv_rlim_t_is_quad_t,
AC_CACHE_CHECK(if rlim_t is longer than a long,
zsh_cv_rlim_t_is_longer,
[AC_TRY_RUN([
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#include <sys/resource.h>
main(){struct rlimit r;exit(sizeof(r.rlim_cur) <= sizeof(long));}],
zsh_cv_rlim_t_is_quad_t=yes,
zsh_cv_rlim_t_is_quad_t=no,
zsh_cv_rlim_t_is_quad_t=yes)])
if test $zsh_cv_rlim_t_is_quad_t = yes; then
AC_DEFINE(RLIM_T_IS_QUAD_T)
DEFAULT_RLIM_T=quad_t
zsh_cv_rlim_t_is_longer=yes,
zsh_cv_rlim_t_is_longer=no,
zsh_cv_rlim_t_is_longer=yes)])
if test $zsh_cv_rlim_t_is_longer = yes; then
AC_CACHE_CHECK(if rlim_t is a quad,
zsh_cv_rlim_t_is_quad_t,
[AC_TRY_RUN([
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#include <stdio.h>
#include <sys/resource.h>
main() {
struct rlimit r;
char buf[[20]];
r.rlim_cur = 0;
sprintf(buf, "%qd", r.rlim_cur);
exit(strcmp(buf, "0"));
}],
zsh_cv_rlim_t_is_quad_t=yes,
zsh_cv_rlim_t_is_quad_t=no,
zsh_cv_rlim_t_is_quad_t=no)])
if test $zsh_cv_tlim_t_is_quad_t = yes; then
AC_DEFINE(RLIM_T_IS_QUAD_T)
DEFAULT_RLIM_T=quad_t
else
AC_DEFINE(RLIM_T_IS_LONG_LONG)
DEFAULT_RLIM_T='long long'
fi
else
AC_CACHE_CHECK(if the rlim_t is unsigned,
zsh_cv_type_rlim_t_is_unsigned,
@ -1113,7 +1142,6 @@ main()
elif test "x$zsh_cv_func_dlsym_needs_underscore" != xno; then
dnl Do not cache failed value
unset zsh_cv_func_dlsym_needs_underscore
dynamic=no
fi
fi

View file

@ -299,7 +299,7 @@ Phil: zless, 5032, simplified by Bart, 5037, also added a `setopt
localoptions' after spending an hour wondering why nothing worked any
more.
Me: `make install' does not do `make install.info', 5047
pws: `make install' does not do `make install.info', 5047
Sven: compcall tries old-style completion from new-style function,
compctl -K ' func' handles newstyle completion, 5059; avoid recursion,
@ -309,7 +309,7 @@ Sven: inserting completion inside brace expansion, 5060
Sven: extra completion context, 5092
Me: typeset -T MYPATH mypath, 5094, plus fix for MYPATH=(foo),
pws: typeset -T MYPATH mypath, 5094, plus fix for MYPATH=(foo),
mypath=foo (and also existing PATH=(foo) bug), 5120
Sven: doc fix for glob qualifiers, 5102
@ -320,18 +320,18 @@ Drazen Kacar, modified by me: workaround for terminal bug on Solaris,
Sven: zle and widget information via variables in new completion
functions, 5104
Me: remove old zle -C, zle -C now does new completion, 5105
pws: remove old zle -C, zle -C now does new completion, 5105
Sven: glob qualifier o for modes, 5107
Me: fix for unsetting special zle variables, 5111
pws: fix for unsetting special zle variables, 5111
Drazen Kacar, modified by me: unlock terminal device on Solaris, 5118
(5117 was wrong)
pws-7
Me: patch for zls, 5054 (appeared in pws-6 but not in corresponding
pws: patch for zls, 5054 (appeared in pws-6 but not in corresponding
patchlist).
Bart: finally added missing hunk from 4965 which allowed unsetting an
@ -355,7 +355,7 @@ Sven: fix for command completion and pattern completions, 5178
Sven: ${(P)...} 5183, 5199, 5200
Me: compctl documentation tidy-up, 5185, 5198
pws: compctl documentation tidy-up, 5185, 5198
Sven: zle commands which use the minibuffer erase completion listings,
5201
@ -370,13 +370,13 @@ Sven: ${foo:q}, 5208, preliminary
Sven: use ${foo:q} for quoting prefix and suffix in new completion, 5120
Me: bashautolist option, 5229; Sven's addition, 5234, and doc 5235; 5269
pws: bashautolist option, 5229; Sven's addition, 5234, and doc 5235; 5269
Me: .zlogout doc, 5233
pws: .zlogout doc, 5233
Me: added note on Linux Alpha with egcs to Etc/MACHINES, not posted
pws: added note on Linux Alpha with egcs to Etc/MACHINES, not posted
Me: typeset -T fix, 5247
pws: typeset -T fix, 5247
Bart: parameter scoping docs, 5258
@ -390,7 +390,7 @@ Sven: rewrite of $foo:q, 5265, +doc, 5284
Sven: get matcher number in new completion function, 5266
Me: interrupts in getquery() weren't gracefully handled, 5281
pws: interrupts in getquery() weren't gracefully handled, 5281
pws-8
@ -409,14 +409,14 @@ Sven: compctl matcher to use reference counts, 5316
Sven: keys available in zle widget functions, 5320
Me: compctl -LM, 5321
pws: compctl -LM, 5321
Me: revamped signames.c generation, 5326, 5329, plus Matt fix, 5330
pws: revamped signames.c generation, 5326, 5329, plus Matt fix, 5330
Sweth, Bart, Me: Functions/allopt, basically as in 2121 with the odd
emulate and local.
Me: emulate -L, 5332
pws: emulate -L, 5332
Sven: printing of zle condition codes, 5335
@ -425,9 +425,9 @@ Sven: Modularisation of new completion shell code, 5341
Sven: ignoring ignored prefix in new conditions, 5342; related fixes,
5343
Me: patch for completion init and __normal, 5344; Sven fix, 5351
pws: patch for completion init and __normal, 5344; Sven fix, 5351
Me: "$foo[@]" didn't remove the argument if $foo wasn't set, 5349;
pws: "$foo[@]" didn't remove the argument if $foo wasn't set, 5349;
Bart's fix so this works on OSes other than AIX, 5361
Sven: change fignore handling, 5352
@ -437,14 +437,14 @@ failed, 5354
Sven: compadd -R function for suffix removal, 5355
Me: #key-* completions now allow 0 or more key bindings, 5362
pws: #key-* completions now allow 0 or more key bindings, 5362
Me: Moved Misc/Completion to Functions/Completion; added some of my own
pws: Moved Misc/Completion to Functions/Completion; added some of my own
new-style completions: not posted
Me: 5281 now works, 5364
pws: 5281 now works, 5364
Me: make dependencies for main.o, Makemod, zshpaths.h, 5365
pws: make dependencies for main.o, Makemod, zshpaths.h, 5365
pws-9
@ -458,9 +458,9 @@ Andrej: Reliant UNIX configuration, 5377
Sven: Manual for new completion (so far), 5384, 5397
Me: dump new completion status for fast initialisation, 5393
pws: dump new completion status for fast initialisation, 5393
Me: bug fixlet for __path_files, 5398
pws: bug fixlet for __path_files, 5398
Sven: overhaul of do_ambiguous with some bug-fixage, 5399, 5407
@ -469,11 +469,11 @@ $COMPDUMP file, 5402
Sven: files -> __files, 5401
Me: magicequalsubst now affects all arguments ...=~...:~..., 5403
pws: magicequalsubst now affects all arguments ...=~...:~..., 5403
Me: set -x output for [[ ... ]], 5408
pws: set -x output for [[ ... ]], 5408
Me: IRIX 6.5 problems in Etc/MACHINES (see 5410 from Helmut Jarausch).
pws: IRIX 6.5 problems in Etc/MACHINES (see 5410 from Helmut Jarausch).
Sven: 5412: better matcher control.
@ -483,7 +483,7 @@ Sven: 5417: multiple subscripts with undefined array
Sven: 5418: small addmatches fixes
Me: 5421: setting same element of assoc array in full array assignment crashed
pws: 5421: setting same element of assoc array in full array assignment crashed
Sven: 5422: braces in completions were not tokenized; array parameters were
used uncopied
@ -492,14 +492,73 @@ Sven: 5423: compadd accepts either - or -- to end options
Sven: 5424: addmatches fix when not doing matching
Me: 5425: fix pattern matching for new completion
pws: 5425: fix pattern matching for new completion
Sven: 5429: $CONTEXT strings
Sven: 5430: rewrite Functions/Completions with simplified syntax (no #array
type completions).
Me: 5436: set -x for function calls and ((...)).
pws: 5436: set -x for function calls and ((...)).
Me: unposted (but see 5440): zftp changes: more return 6's, functions now
pws: unposted (but see 5440): zftp changes: more return 6's, functions now
do auto-open and avoid subshells.
pws-10
Martin Buchholz: 5448: libc.h can't be included on Debian Linux, so only
include it on NeXT where it's necessary.
Matt: 5330: I've put this back the way it original was. I hate sed almost
as much as awk.
Sven: 5455: keep track of which matcher specification to use
Sven: 5466: compwid manual for -after and -between
Sven: 5467: expn manual typo
Sven: 5469: init fix and Functions/Completion/_comp_parts
Sven: 5470: new completion conditions didn't handle untokenization
consistently.
Sven: 5471: range code knows not to handle associative arrays
Sven: 5476: quoting of tildes in Functions/Completion/_path_files
Sven: 5483: completeinword fixes
Sven: 5489: control for matching in _path_files and _comp_parts
Sven: 5490: unset test for AA elements when substituting
pws: unposted, see 5503: remove dynamic=no from configure.in when
underscore is needed.
pws: 5508: init and dump, globbing and printing.
Sven: 5511: make sure compctl is available for new completion
Sven: 5512, 5525: globcomplete fix for new completion
Sven: 5521: improved option handling for _path_files
Sven: 5529: cleanup for Functions/Completion
pws: 5531: small init fix
pws: 5538: approximate pattern matching, (#a1)readme etc.
Sven: 5543: compadd -X, zshcompwid manual
Sven: 5544: another completion cleanup
pws: 5545: silly set -x mistake
Sven: 5548: _path_files, _comp_parts
Matt: 5553: under _WIN32, .exe suffix is optional for commands
pws: unposted: Functions/Completion moved to Completion; subdirectories
Core, Base, Builtins, User, Commands created; Completion/README created.