mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-06-21 10:28:05 +02:00
zsh-3.1.5-pws-10
This commit is contained in:
parent
b4a5b9db8b
commit
904b939cbd
97 changed files with 2943 additions and 541 deletions
Completion
Base
Builtins
_aliases_arrays_autoload_bg_jobs_bindkey_builtin_cd_command_dirs_disable_echotc_enable_fc_functions_hash_jobs_kill_limits_sched_set_setopt_source_trap_unhash_unsetopt_vars_eq_wait_which_zftp_zle_zmodload
Commands
Core
READMEUser
Config
Doc/Zsh
Misc
Src
acconfig.hconfigure.inpatchlist.txt
3
Completion/Base/_command_names
Normal file
3
Completion/Base/_command_names
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#defcomp -command-
|
||||||
|
|
||||||
|
complist -c
|
10
Completion/Base/_condition
Normal file
10
Completion/Base/_condition
Normal 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
13
Completion/Base/_default
Normal 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
|
31
Completion/Base/_match_pattern
Normal file
31
Completion/Base/_match_pattern
Normal 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.
|
15
Completion/Base/_match_test
Normal file
15
Completion/Base/_match_test
Normal 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 ))
|
5
Completion/Base/_precommand
Normal file
5
Completion/Base/_precommand
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
#defcomp - nohup nice eval time rusage noglob nocorrect exec
|
||||||
|
|
||||||
|
[[ -position 1 -1 ]]
|
||||||
|
|
||||||
|
_normal "$@"
|
3
Completion/Base/_redirect
Normal file
3
Completion/Base/_redirect
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#defcomp -redirect-
|
||||||
|
|
||||||
|
_files
|
4
Completion/Base/_subscript
Normal file
4
Completion/Base/_subscript
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
#defcomp -subscript-
|
||||||
|
|
||||||
|
_compalso -math- "$@"
|
||||||
|
[[ ${(Pt)${COMMAND}} = assoc* ]] && complist -k "( ${(kP)${COMMAND}} )"
|
3
Completion/Base/_vars
Normal file
3
Completion/Base/_vars
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#defcomp -math- getopts read unset vared
|
||||||
|
|
||||||
|
complist -v
|
3
Completion/Builtins/_aliases
Normal file
3
Completion/Builtins/_aliases
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#defcomp unalias
|
||||||
|
|
||||||
|
complist -a
|
3
Completion/Builtins/_arrays
Normal file
3
Completion/Builtins/_arrays
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#defcomp shift
|
||||||
|
|
||||||
|
complist -A
|
3
Completion/Builtins/_autoload
Normal file
3
Completion/Builtins/_autoload
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#defcomp autoload
|
||||||
|
|
||||||
|
complist -s '${^fpath}/*(N:t)'
|
3
Completion/Builtins/_bg_jobs
Normal file
3
Completion/Builtins/_bg_jobs
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#defcomp bg
|
||||||
|
|
||||||
|
complist -z -P '%'
|
7
Completion/Builtins/_bindkey
Normal file
7
Completion/Builtins/_bindkey
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
#defcomp bindkey
|
||||||
|
|
||||||
|
if [[ -mword 1 -*[DAN]* || -mcurrent -1 -*M ]]; then
|
||||||
|
complist -s '$(bindkey -l)'
|
||||||
|
else
|
||||||
|
complist -b
|
||||||
|
fi
|
7
Completion/Builtins/_builtin
Normal file
7
Completion/Builtins/_builtin
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
#defcomp builtin
|
||||||
|
|
||||||
|
if [[ -position 2 -1 ]]; then
|
||||||
|
_normal "$@"
|
||||||
|
else
|
||||||
|
complist -eB
|
||||||
|
fi
|
3
Completion/Builtins/_cd
Normal file
3
Completion/Builtins/_cd
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#defcomp cd
|
||||||
|
|
||||||
|
_files -W cdpath -g '*(-/)'
|
7
Completion/Builtins/_command
Normal file
7
Completion/Builtins/_command
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
#defcomp command
|
||||||
|
|
||||||
|
if [[ -position 2 -1 ]]; then
|
||||||
|
_normal "$@"
|
||||||
|
else
|
||||||
|
complist -em
|
||||||
|
fi
|
3
Completion/Builtins/_dirs
Normal file
3
Completion/Builtins/_dirs
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#defcomp rmdir df du dircmp
|
||||||
|
|
||||||
|
_files -/
|
6
Completion/Builtins/_disable
Normal file
6
Completion/Builtins/_disable
Normal 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
|
3
Completion/Builtins/_echotc
Normal file
3
Completion/Builtins/_echotc
Normal 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)'
|
6
Completion/Builtins/_enable
Normal file
6
Completion/Builtins/_enable
Normal 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
7
Completion/Builtins/_fc
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
#defcomp fc
|
||||||
|
|
||||||
|
if [[ -mcurrent -1 -*e ]]; then
|
||||||
|
complist -c
|
||||||
|
elif [[ -mcurrent -1 -[ARWI]## ]]; then
|
||||||
|
_files
|
||||||
|
fi
|
3
Completion/Builtins/_functions
Normal file
3
Completion/Builtins/_functions
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#defcomp unfunction
|
||||||
|
|
||||||
|
complist -F
|
13
Completion/Builtins/_hash
Normal file
13
Completion/Builtins/_hash
Normal 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
|
3
Completion/Builtins/_jobs
Normal file
3
Completion/Builtins/_jobs
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#defcomp fg jobs
|
||||||
|
|
||||||
|
complist -j -P '%'
|
11
Completion/Builtins/_kill
Normal file
11
Completion/Builtins/_kill
Normal 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
|
3
Completion/Builtins/_limits
Normal file
3
Completion/Builtins/_limits
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#defcomp limit unlimit
|
||||||
|
|
||||||
|
complist -k "(${(j: :)${(f)$(limit)}%% *})"
|
3
Completion/Builtins/_sched
Normal file
3
Completion/Builtins/_sched
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#defcomp sched
|
||||||
|
|
||||||
|
[[ -position 2 -1 ]] && _normal "$@"
|
7
Completion/Builtins/_set
Normal file
7
Completion/Builtins/_set
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
#defcomp set
|
||||||
|
|
||||||
|
if [[ -mcurrent -1 [-+]o ]]; then
|
||||||
|
complist -o
|
||||||
|
elif [[ -current -1 -A ]]; then
|
||||||
|
complist -A
|
||||||
|
fi
|
7
Completion/Builtins/_setopt
Normal file
7
Completion/Builtins/_setopt
Normal 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
|
7
Completion/Builtins/_source
Normal file
7
Completion/Builtins/_source
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
#defcomp source
|
||||||
|
|
||||||
|
if [[ -position 2 -1 ]]; then
|
||||||
|
_normal "$@"
|
||||||
|
else
|
||||||
|
_files
|
||||||
|
fi
|
7
Completion/Builtins/_trap
Normal file
7
Completion/Builtins/_trap
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
#defcomp trap
|
||||||
|
|
||||||
|
if [[ -position 1 ]]; then
|
||||||
|
complist -c
|
||||||
|
else
|
||||||
|
complist -k signals
|
||||||
|
fi
|
6
Completion/Builtins/_unhash
Normal file
6
Completion/Builtins/_unhash
Normal 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
|
7
Completion/Builtins/_unsetopt
Normal file
7
Completion/Builtins/_unsetopt
Normal 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
|
3
Completion/Builtins/_vars_eq
Normal file
3
Completion/Builtins/_vars_eq
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#defcomp declare export integer local readonly typeset
|
||||||
|
|
||||||
|
complist -v -q -S '='
|
7
Completion/Builtins/_wait
Normal file
7
Completion/Builtins/_wait
Normal 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`'
|
3
Completion/Builtins/_which
Normal file
3
Completion/Builtins/_which
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#defcomp which whence where type
|
||||||
|
|
||||||
|
complist -caF
|
50
Completion/Builtins/_zftp
Normal file
50
Completion/Builtins/_zftp
Normal 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
7
Completion/Builtins/_zle
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
#defcomp zle
|
||||||
|
|
||||||
|
if [[ -word 1 -N && -position 3 ]]; then
|
||||||
|
complist -F
|
||||||
|
else
|
||||||
|
complist -b
|
||||||
|
fi
|
9
Completion/Builtins/_zmodload
Normal file
9
Completion/Builtins/_zmodload
Normal 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
|
37
Completion/Commands/_correct_filename
Normal file
37
Completion/Commands/_correct_filename
Normal 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
|
4
Completion/Commands/_most_recent_file
Normal file
4
Completion/Commands/_most_recent_file
Normal 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
147
Completion/Core/_comp_parts
Normal 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
13
Completion/Core/_compalso
Normal 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
26
Completion/Core/_files
Normal 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
|
48
Completion/Core/_main_complete
Normal file
48
Completion/Core/_main_complete
Normal 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
54
Completion/Core/_normal
Normal 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
311
Completion/Core/_path_files
Normal 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
89
Completion/Core/compdump
Normal 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
269
Completion/Core/compinit
Normal 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
107
Completion/README
Normal 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
22
Completion/User/_a2ps
Normal 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
|
3
Completion/User/_compress
Normal file
3
Completion/User/_compress
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#defcomp compress
|
||||||
|
|
||||||
|
_files -g '*~*.Z'
|
12
Completion/User/_configure
Normal file
12
Completion/User/_configure
Normal 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
13
Completion/User/_dd
Normal 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
3
Completion/User/_dvi
Normal 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
21
Completion/User/_find
Normal 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
3
Completion/User/_gunzip
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#defcomp gunzip zcat
|
||||||
|
|
||||||
|
_files -g '*.[gG][z]'
|
3
Completion/User/_gzip
Normal file
3
Completion/User/_gzip
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#defcomp gzip
|
||||||
|
|
||||||
|
_files -g '*~*.[gG][zZ]'
|
3
Completion/User/_hosts
Normal file
3
Completion/User/_hosts
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#defcomp ftp ncftp ping rwho rup xping traceroute nslookup
|
||||||
|
|
||||||
|
complist -k hosts
|
3
Completion/User/_make
Normal file
3
Completion/User/_make
Normal 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
11
Completion/User/_man
Normal 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
70
Completion/User/_mh
Normal 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
3
Completion/User/_pdf
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
function acroread
|
||||||
|
|
||||||
|
_files -g '*.(pdf|PDF)'
|
3
Completion/User/_ps
Normal file
3
Completion/User/_ps
Normal 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
9
Completion/User/_rcs
Normal 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
9
Completion/User/_rlogin
Normal 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
2
Completion/User/_strip
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
#defcomp strip
|
||||||
|
_files -g '*(*)'
|
16
Completion/User/_stty
Normal file
16
Completion/User/_stty
Normal 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
11
Completion/User/_tar
Normal 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
3
Completion/User/_tex
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#defcomp tex latex slitex
|
||||||
|
|
||||||
|
_files -g '*.(tex|TEX|texinfo|texi)'
|
3
Completion/User/_uncompress
Normal file
3
Completion/User/_uncompress
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#defcomp uncompress zmore
|
||||||
|
|
||||||
|
_files -g '*.Z'
|
5
Completion/User/_x_options
Normal file
5
Completion/User/_x_options
Normal 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
3
Completion/User/_xfig
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#defcomp xfig
|
||||||
|
|
||||||
|
_files -g '*.fig'
|
|
@ -27,5 +27,5 @@
|
||||||
# This must also serve as a shell script, so do not add spaces around the
|
# This must also serve as a shell script, so do not add spaces around the
|
||||||
# `=' signs.
|
# `=' signs.
|
||||||
|
|
||||||
VERSION=3.1.5-pws-9
|
VERSION=3.1.5-pws-10
|
||||||
VERSION_DATE='February 18, 1999'
|
VERSION_DATE='February 26, 1999'
|
||||||
|
|
|
@ -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(prefix) ] [ tt(-S) var(suffix) ])
|
||||||
xitem([ tt(-p) var(hidden-prefix) ] [ tt(-s) var(hidden-suffix) ])
|
xitem([ tt(-p) var(hidden-prefix) ] [ tt(-s) var(hidden-suffix) ])
|
||||||
xitem([ tt(-i) var(ignored-prefix) ] [ tt(-W) var(file-prefix) ])
|
xitem([ tt(-i) var(ignored-prefix) ] [ tt(-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) ])
|
xitem([ tt(-r) var(remove-chars) ] [ tt(-R) var(remove-func) ])
|
||||||
item([ tt(-M) var(match-spec) ] [ tt(--) ] [ var(words) ... ])(
|
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.
|
Like tt(-P) but gives a string that has to be inserted after the match.
|
||||||
)
|
)
|
||||||
item(tt(-p) var(hidden-prefix))(
|
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))(
|
item(tt(-s) var(hidden-suffix))(
|
||||||
...
|
Like `tt(-p)', but gives a string to insert after the match.
|
||||||
)
|
)
|
||||||
item(tt(-i) var(ignored-prefix))(
|
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))(
|
item(tt(-J) var(name))(
|
||||||
As for tt(compctl) and tt(complist) this gives the name of the group
|
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))(
|
item(tt(-V) var(name))(
|
||||||
Like tt(-J) but naming a unsorted group.
|
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))(
|
item(tt(-q))(
|
||||||
This flag has the same meaning as for tt(compctl) and tt(complist),
|
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
|
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)
|
var(min) and equal to or less than var(max)
|
||||||
)
|
)
|
||||||
item(tt(-after) var(string))(
|
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))(
|
item(tt(-mafter) var(pattern))(
|
||||||
like tt(-after) but using pattern matching
|
like tt(-after) but using pattern matching
|
||||||
)
|
)
|
||||||
item(tt(-between) var(string1) var(string2))(
|
item(tt(-between) var(string1) var(string2))(
|
||||||
true if the cursor is after a word that is equal to var(string1), if
|
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
|
there is also a word that is equal to var(string2), this is true only
|
||||||
if the cursor is before it
|
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))(
|
item(tt(-mbetween) var(pattern1) var(pattern2))(
|
||||||
like tt(-between) but using pattern matching
|
like tt(-between) but using pattern matching
|
||||||
|
|
|
@ -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
|
A `tt(-)' or `tt(])' may be matched by including it as the
|
||||||
first character in the list.
|
first character in the list.
|
||||||
There are also several named classes of characters, in the form
|
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,
|
alphanumeric, `tt([:alpha:])' alphabetic,
|
||||||
`tt([:blank:])' space or tab,
|
`tt([:blank:])' space or tab,
|
||||||
`tt([:cntrl:])' control character, `tt([:digit:])' decimal
|
`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
|
Case sensitive: locally negates the effect of tt(i) or tt(l) from
|
||||||
that point on.
|
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()
|
enditem()
|
||||||
|
|
||||||
For example, the test string tt(fooxx) can be matched by the pattern
|
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()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()#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
|
When using the ksh syntax for grouping both tt(KSH_GLOB) and
|
||||||
tt(EXTENDED_GLOB) must be set and the left parenthesis should be
|
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
|
searched for all files which match, so that a pattern of the form
|
||||||
tt(LPAR()#i)tt(RPAR()/foo/bar/...) is potentially slow.
|
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)
|
subsect(Recursive Globbing)
|
||||||
A pathname component of the form `tt(LPAR())var(foo)tt(/RPAR()#)'
|
A pathname component of the form `tt(LPAR())var(foo)tt(/RPAR()#)'
|
||||||
matches a path consisting of zero or more directories
|
matches a path consisting of zero or more directories
|
||||||
|
|
|
@ -144,8 +144,8 @@ then be processed with bf(dvips) and optionally bf(gs) (Ghostscript) to
|
||||||
produce a nicely formatted printed guide.
|
produce a nicely formatted printed guide.
|
||||||
)
|
)
|
||||||
item(The HTML guide)(
|
item(The HTML guide)(
|
||||||
Mark Borges, tt(<mdb@cdc.noaa.gov), maintains an HTML version of this
|
An HTML version of this guide is available at the Zsh web site via
|
||||||
guide at tt(http://www.peak.org/zsh/Doc/zsh_toc.html).
|
tt(http://sunsite.auc.dk/zsh/Doc/index.html).
|
||||||
(The HTML version is produced with bf(texi2html), which may be obtained
|
(The HTML version is produced with bf(texi2html), which may be obtained
|
||||||
from tt(http://wwwcn.cern.ch/dci/texi2html/). The command is
|
from tt(http://wwwcn.cern.ch/dci/texi2html/). The command is
|
||||||
`tt(texi2html -split_chapter -expandinfo zsh.texi)'.)
|
`tt(texi2html -split_chapter -expandinfo zsh.texi)'.)
|
||||||
|
|
|
@ -103,6 +103,7 @@ t :] [:]]#
|
||||||
t [ [[]
|
t [ [[]
|
||||||
t ] []]
|
t ] []]
|
||||||
t [] [^]]]
|
t [] [^]]]
|
||||||
|
# Case insensitive matching
|
||||||
t fooxx (#i)FOOXX
|
t fooxx (#i)FOOXX
|
||||||
f fooxx (#l)FOOXX
|
f fooxx (#l)FOOXX
|
||||||
t FOOXX (#l)fooxx
|
t FOOXX (#l)fooxx
|
||||||
|
@ -113,5 +114,36 @@ f fooxx ((#i)FOOX)X
|
||||||
f BAR (bar|(#i)foo)
|
f BAR (bar|(#i)foo)
|
||||||
t FOO (bar|(#i)foo)
|
t FOO (bar|(#i)foo)
|
||||||
t Modules (#i)*m*
|
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
|
EOT
|
||||||
print "$failed tests failed."
|
print "$failed tests failed."
|
||||||
|
|
|
@ -19,6 +19,7 @@ zsh
|
||||||
libzsh.so*
|
libzsh.so*
|
||||||
sigcount.h
|
sigcount.h
|
||||||
signames.c
|
signames.c
|
||||||
|
version.h
|
||||||
zshpaths.h
|
zshpaths.h
|
||||||
zshxmods.h
|
zshxmods.h
|
||||||
bltinmods.list
|
bltinmods.list
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
|
|
||||||
# include "rlimits.h"
|
# 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
|
static rlim_t
|
||||||
zstrtorlimt(const char *s, char **t, int base)
|
zstrtorlimt(const char *s, char **t, int base)
|
||||||
{
|
{
|
||||||
|
@ -62,9 +62,9 @@ zstrtorlimt(const char *s, char **t, int base)
|
||||||
*t = (char *)s;
|
*t = (char *)s;
|
||||||
return ret;
|
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))
|
# 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' *
|
/* Display resource limits. hard indicates whether `hard' or `soft' *
|
||||||
* limits should be displayed. lim specifies the limit, or may be -1 *
|
* limits should be displayed. lim specifies the limit, or may be -1 *
|
||||||
|
@ -107,9 +107,15 @@ showlimits(int hard, int lim)
|
||||||
else
|
else
|
||||||
printf("%qdkB\n", val / 1024L);
|
printf("%qdkB\n", val / 1024L);
|
||||||
# else
|
# 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));
|
printf("%ldMB\n", val / (1024L * 1024L));
|
||||||
else
|
else
|
||||||
printf("%ldkB\n", val / 1024L);
|
printf("%ldkB\n", val / 1024L);
|
||||||
|
# endif /* RLIM_T_IS_LONG_LONG */
|
||||||
# endif /* RLIM_T_IS_QUAD_T */
|
# endif /* RLIM_T_IS_QUAD_T */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -271,9 +271,10 @@ struct cline {
|
||||||
#define CLF_MISS 4
|
#define CLF_MISS 4
|
||||||
#define CLF_DIFF 8
|
#define CLF_DIFF 8
|
||||||
#define CLF_SUF 16
|
#define CLF_SUF 16
|
||||||
#define CLF_NEW 32
|
#define CLF_PNEW 32
|
||||||
#define CLF_VAR 64
|
#define CLF_SNEW 64
|
||||||
#define CLF_JOIN 128
|
#define CLF_VAR 128
|
||||||
|
#define CLF_JOIN 256
|
||||||
|
|
||||||
/* Flags for makecomplist*(). Things not to do. */
|
/* Flags for makecomplist*(). Things not to do. */
|
||||||
|
|
||||||
|
|
|
@ -49,10 +49,10 @@ void (*makecompparamsptr) _((void));
|
||||||
/* pointers to functions required by compctl and defined by zle */
|
/* 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));
|
int (*getcpatptr) _((char *, int, char *, int));
|
||||||
|
@ -410,6 +410,7 @@ setup_comp1(Module m)
|
||||||
cc_first.mask2 = CC_CCCONT;
|
cc_first.mask2 = CC_CCCONT;
|
||||||
compcontext = compcommand = compprefix = compsuffix =
|
compcontext = compcommand = compprefix = compsuffix =
|
||||||
compiprefix = NULL;
|
compiprefix = NULL;
|
||||||
|
makecompparamsptr = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1676,7 +1676,7 @@ bin_compadd(char *name, char **argv, char *ops, int func)
|
||||||
char *p, **sp, *e;
|
char *p, **sp, *e;
|
||||||
char *ipre = NULL, *ppre = NULL, *psuf = NULL, *prpre = NULL;
|
char *ipre = NULL, *ppre = NULL, *psuf = NULL, *prpre = NULL;
|
||||||
char *pre = NULL, *suf = NULL, *group = NULL, *m = NULL, *rs = 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;
|
int f = 0, a = 0, dm;
|
||||||
Cmatcher match = NULL;
|
Cmatcher match = NULL;
|
||||||
|
|
||||||
|
@ -1757,6 +1757,10 @@ bin_compadd(char *name, char **argv, char *ops, int func)
|
||||||
e = "matching specification expected after -%c";
|
e = "matching specification expected after -%c";
|
||||||
dm = 1;
|
dm = 1;
|
||||||
break;
|
break;
|
||||||
|
case 'X':
|
||||||
|
sp = &expl;
|
||||||
|
e = "string expected after -%c";
|
||||||
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
f |= CMF_REMOVE;
|
f |= CMF_REMOVE;
|
||||||
sp = &rs;
|
sp = &rs;
|
||||||
|
@ -1802,7 +1806,7 @@ bin_compadd(char *name, char **argv, char *ops, int func)
|
||||||
|
|
||||||
match = cpcmatcher(match);
|
match = cpcmatcher(match);
|
||||||
addmatchesptr(ipre, ppre, psuf, prpre, pre, suf, group,
|
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);
|
freecmatcher(match);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2049,8 +2053,8 @@ cond_strcl(char **a, int id)
|
||||||
zerr("zle not loaded, zle condition not available", NULL, 0);
|
zerr("zle not loaded, zle condition not available", NULL, 0);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
i = getcpatptr(comp_strptr(&ipl, NULL), i, s, id);
|
i = getcpatptr(comp_strptr(&ipl, NULL, 1), i, s, id);
|
||||||
if (i != -1) {
|
if (i != -1 && i >= ipl) {
|
||||||
ignore_prefix(i - ipl);
|
ignore_prefix(i - ipl);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -478,6 +478,17 @@ bin_zle_complete(char *name, char **args, char *ops, char func)
|
||||||
Thingy t;
|
Thingy t;
|
||||||
Widget w, cw;
|
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]);
|
t = rthingy(args[1]);
|
||||||
cw = t->widget;
|
cw = t->widget;
|
||||||
unrefthingy(t);
|
unrefthingy(t);
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -2558,7 +2558,7 @@ execarith(Cmd cmd)
|
||||||
val = matheval(e);
|
val = matheval(e);
|
||||||
}
|
}
|
||||||
if (isset(XTRACE)) {
|
if (isset(XTRACE)) {
|
||||||
fprintf(stderr, " ))\n", stderr);
|
fprintf(stderr, " ))\n");
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
}
|
}
|
||||||
errflag = 0;
|
errflag = 0;
|
||||||
|
|
441
Src/glob.c
441
Src/glob.c
|
@ -71,6 +71,7 @@ struct gmatch {
|
||||||
int badcshglob;
|
int badcshglob;
|
||||||
|
|
||||||
static int mode; /* != 0 if we are parsing glob patterns */
|
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 pathpos; /* position in pathbuf */
|
||||||
static int matchsz; /* size of matchbuf */
|
static int matchsz; /* size of matchbuf */
|
||||||
static int matchct; /* number of matches found */
|
static int matchct; /* number of matches found */
|
||||||
|
@ -134,7 +135,7 @@ struct complist {
|
||||||
struct comp {
|
struct comp {
|
||||||
Comp left, right, next, exclude;
|
Comp left, right, next, exclude;
|
||||||
char *str;
|
char *str;
|
||||||
int stat;
|
int stat, errsmax;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Type of Comp: a closure with one or two #'s, the end of a *
|
/* 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_PATHADD 1 /* file glob, adding path components */
|
||||||
#define GF_TOPLEV 2 /* outside (), so ~ ends main match */
|
#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 char *pptr; /* current place in string being matched */
|
||||||
static Comp tail;
|
static Comp tail;
|
||||||
static int first; /* are leading dots special? */
|
static int first; /* are leading dots special? */
|
||||||
|
@ -352,6 +365,25 @@ haswilds(char *str)
|
||||||
return 0;
|
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 *
|
/* Do the globbing: scanner is called recursively *
|
||||||
* with successive bits of the path until we've *
|
* with successive bits of the path until we've *
|
||||||
* tried all of it. */
|
* tried all of it. */
|
||||||
|
@ -363,6 +395,7 @@ scanner(Complist q)
|
||||||
Comp c;
|
Comp c;
|
||||||
int closure;
|
int closure;
|
||||||
int pbcwdsav = pathbufcwd;
|
int pbcwdsav = pathbufcwd;
|
||||||
|
int errssofar = errsfound;
|
||||||
struct dirsav ds;
|
struct dirsav ds;
|
||||||
|
|
||||||
ds.ino = ds.dev = 0;
|
ds.ino = ds.dev = 0;
|
||||||
|
@ -381,7 +414,7 @@ scanner(Complist q)
|
||||||
c = q->comp;
|
c = q->comp;
|
||||||
/* Now the actual matching for the current path section. */
|
/* Now the actual matching for the current path section. */
|
||||||
if (!(c->next || c->left) && !haswilds(c->str)
|
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))) {
|
|| !strcmp(".", c->str) || !strcmp("..", c->str))) {
|
||||||
/*
|
/*
|
||||||
* We always need to match . and .. explicitly, even if we're
|
* 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_pre && !strpfx(glob_pre, fn))
|
||||||
|| (glob_suf && !strsfx(glob_suf, fn))))
|
|| (glob_suf && !strsfx(glob_suf, fn))))
|
||||||
continue;
|
continue;
|
||||||
|
errsfound = errssofar;
|
||||||
if (domatch(fn, c, gf_noglobdots)) {
|
if (domatch(fn, c, gf_noglobdots)) {
|
||||||
/* if this name matchs the pattern... */
|
/* if this name matchs the pattern... */
|
||||||
if (pbcwdsav == pathbufcwd &&
|
if (pbcwdsav == pathbufcwd &&
|
||||||
|
@ -453,7 +487,34 @@ scanner(Complist q)
|
||||||
if (dirs) {
|
if (dirs) {
|
||||||
int l;
|
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 (closure) {
|
||||||
/* if matching multiple directories */
|
/* if matching multiple directories */
|
||||||
struct stat buf;
|
struct stat buf;
|
||||||
|
@ -470,9 +531,14 @@ scanner(Complist q)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
l = strlen(fn) + 1;
|
l = strlen(fn) + 1;
|
||||||
subdirs = hrealloc(subdirs, subdirlen, subdirlen + l);
|
subdirs = hrealloc(subdirs, subdirlen, subdirlen + l
|
||||||
|
+ sizeof(int));
|
||||||
strcpy(subdirs + subdirlen, fn);
|
strcpy(subdirs + subdirlen, fn);
|
||||||
subdirlen += l;
|
subdirlen += l;
|
||||||
|
/* store the count of errors made so far, too */
|
||||||
|
memcpy(subdirs + subdirlen, (char *)&errsfound,
|
||||||
|
sizeof(int));
|
||||||
|
subdirlen += sizeof(int);
|
||||||
} else
|
} else
|
||||||
/* if the last filename component, just add it */
|
/* if the last filename component, just add it */
|
||||||
insert(fn, 1);
|
insert(fn, 1);
|
||||||
|
@ -482,8 +548,11 @@ scanner(Complist q)
|
||||||
if (subdirs) {
|
if (subdirs) {
|
||||||
int oppos = pathpos;
|
int oppos = pathpos;
|
||||||
|
|
||||||
for (fn = subdirs; fn < subdirs+subdirlen; fn += strlen(fn) + 1) {
|
for (fn = subdirs; fn < subdirs+subdirlen; ) {
|
||||||
addpath(fn);
|
addpath(fn);
|
||||||
|
fn += strlen(fn) + 1;
|
||||||
|
memcpy((char *)&errsfound, fn, sizeof(int));
|
||||||
|
fn += sizeof(int);
|
||||||
scanner((q->closure) ? q : q->next); /* scan next level */
|
scanner((q->closure) ? q : q->next); /* scan next level */
|
||||||
pathbuf[pathpos = oppos] = '\0';
|
pathbuf[pathpos = oppos] = '\0';
|
||||||
}
|
}
|
||||||
|
@ -502,16 +571,13 @@ scanner(Complist q)
|
||||||
|
|
||||||
/* Parse a series of path components pointed to by pptr */
|
/* Parse a series of path components pointed to by pptr */
|
||||||
|
|
||||||
/* Flags to apply to current level of grourping */
|
|
||||||
|
|
||||||
static int addflags;
|
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
static Comp
|
static Comp
|
||||||
compalloc(void)
|
compalloc(void)
|
||||||
{
|
{
|
||||||
Comp c = (Comp) alloc(sizeof *c);
|
Comp c = (Comp) alloc(sizeof *c);
|
||||||
c->stat |= addflags;
|
c->stat |= addflags;
|
||||||
|
c->errsmax = errsmax;
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -519,10 +585,19 @@ compalloc(void)
|
||||||
static int
|
static int
|
||||||
getglobflags()
|
getglobflags()
|
||||||
{
|
{
|
||||||
|
char *nptr;
|
||||||
/* (#X): assumes we are still positioned on the initial '(' */
|
/* (#X): assumes we are still positioned on the initial '(' */
|
||||||
pptr++;
|
pptr++;
|
||||||
while (*++pptr && *pptr != Outpar) {
|
while (*++pptr && *pptr != Outpar) {
|
||||||
switch (*pptr) {
|
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':
|
case 'l':
|
||||||
/* Lowercase in pattern matches lower or upper in target */
|
/* Lowercase in pattern matches lower or upper in target */
|
||||||
addflags |= C_LCMATCHUC;
|
addflags |= C_LCMATCHUC;
|
||||||
|
@ -635,6 +710,7 @@ parsecomp(int gflag)
|
||||||
if (eptr == cstr) {
|
if (eptr == cstr) {
|
||||||
/* if no string yet, carry on and get one. */
|
/* if no string yet, carry on and get one. */
|
||||||
c->stat = addflags;
|
c->stat = addflags;
|
||||||
|
c->errsmax = errsmax;
|
||||||
cstr = pptr;
|
cstr = pptr;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -817,6 +893,7 @@ parsecompsw(int gflag)
|
||||||
{
|
{
|
||||||
Comp c1, c2, c3, excl = NULL, stail = tail;
|
Comp c1, c2, c3, excl = NULL, stail = tail;
|
||||||
int oaddflags = addflags;
|
int oaddflags = addflags;
|
||||||
|
int oerrsmax = errsmax;
|
||||||
char *sptr;
|
char *sptr;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -845,12 +922,14 @@ parsecompsw(int gflag)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (isset(EXTENDEDGLOB) && *pptr == Tilde) {
|
if (isset(EXTENDEDGLOB) && *pptr == Tilde) {
|
||||||
/* Matching remainder of pattern excludes the pattern from matching */
|
/* Matching remainder of pattern excludes the pattern from matching */
|
||||||
int oldmode = mode;
|
int oldmode = mode, olderrsmax = errsmax;
|
||||||
|
|
||||||
mode = 1;
|
mode = 1;
|
||||||
|
errsmax = 0;
|
||||||
pptr++;
|
pptr++;
|
||||||
excl = parsecomp(gflag);
|
excl = parsecomp(gflag);
|
||||||
mode = oldmode;
|
mode = oldmode;
|
||||||
|
errsmax = olderrsmax;
|
||||||
if (!excl)
|
if (!excl)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -878,8 +957,10 @@ parsecompsw(int gflag)
|
||||||
c2->stat |= C_PATHADD;
|
c2->stat |= C_PATHADD;
|
||||||
c1 = c2;
|
c1 = c2;
|
||||||
}
|
}
|
||||||
if (!(gflag & GF_TOPLEV))
|
if (!(gflag & GF_TOPLEV)) {
|
||||||
addflags = oaddflags;
|
addflags = oaddflags;
|
||||||
|
errsmax = oerrsmax;
|
||||||
|
}
|
||||||
return c1;
|
return c1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -965,6 +1046,7 @@ parsepat(char *str)
|
||||||
{
|
{
|
||||||
mode = 0; /* path components present */
|
mode = 0; /* path components present */
|
||||||
addflags = 0;
|
addflags = 0;
|
||||||
|
errsmax = 0;
|
||||||
pptr = str;
|
pptr = str;
|
||||||
tail = NULL;
|
tail = NULL;
|
||||||
/*
|
/*
|
||||||
|
@ -1102,7 +1184,7 @@ static int
|
||||||
gmatchcmp(Gmatch a, Gmatch b)
|
gmatchcmp(Gmatch a, Gmatch b)
|
||||||
{
|
{
|
||||||
int i, *s;
|
int i, *s;
|
||||||
long r;
|
long r = 0L;
|
||||||
|
|
||||||
for (i = gf_nsorts, s = gf_sortlist; i; i--, s++) {
|
for (i = gf_nsorts, s = gf_sortlist; i; i--, s++) {
|
||||||
switch (*s & ~GS_DESC) {
|
switch (*s & ~GS_DESC) {
|
||||||
|
@ -1594,10 +1676,14 @@ glob(LinkList list, LinkNode np)
|
||||||
matchptr = matchbuf = (Gmatch)zalloc((matchsz = 16) *
|
matchptr = matchbuf = (Gmatch)zalloc((matchsz = 16) *
|
||||||
sizeof(struct gmatch));
|
sizeof(struct gmatch));
|
||||||
matchct = 0;
|
matchct = 0;
|
||||||
|
errsfound = 0;
|
||||||
|
errsmax = -1;
|
||||||
|
|
||||||
/* The actual processing takes place here: matches go into *
|
/* The actual processing takes place here: matches go into *
|
||||||
* matchbuf. This is the only top-level call to scanner(). */
|
* matchbuf. This is the only top-level call to scanner(). */
|
||||||
|
scanning = 1;
|
||||||
scanner(q);
|
scanner(q);
|
||||||
|
scanning = 0;
|
||||||
|
|
||||||
/* Deal with failures to match depending on options */
|
/* Deal with failures to match depending on options */
|
||||||
if (matchct)
|
if (matchct)
|
||||||
|
@ -2427,6 +2513,14 @@ domatch(char *str, Comp c, int fist)
|
||||||
int ret;
|
int ret;
|
||||||
pptr = str;
|
pptr = str;
|
||||||
first = fist;
|
first = fist;
|
||||||
|
/*
|
||||||
|
* If scanning paths, keep the error count over the whole
|
||||||
|
* filename
|
||||||
|
*/
|
||||||
|
if (!scanning) {
|
||||||
|
errsfound = 0;
|
||||||
|
errsmax = -1;
|
||||||
|
}
|
||||||
if (*pptr == Nularg)
|
if (*pptr == Nularg)
|
||||||
pptr++;
|
pptr++;
|
||||||
PERMALLOC {
|
PERMALLOC {
|
||||||
|
@ -2444,15 +2538,17 @@ static int
|
||||||
excluded(Comp c, char *eptr)
|
excluded(Comp c, char *eptr)
|
||||||
{
|
{
|
||||||
char *saves = pptr;
|
char *saves = pptr;
|
||||||
int savei = first, savel = longest, ret;
|
int savei = first, savel = longest, savee = errsfound, ret;
|
||||||
|
|
||||||
first = 0;
|
first = 0;
|
||||||
/*
|
/*
|
||||||
* Even if we've been told always to match the longest string,
|
* 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
|
* 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.
|
* we've already matched when we're trying to exclude it.
|
||||||
|
* Likewise, approximate matching here is treated separately.
|
||||||
*/
|
*/
|
||||||
longest = 0;
|
longest = 0;
|
||||||
|
errsfound = 0;
|
||||||
if (PATHADDP(c) && pathpos) {
|
if (PATHADDP(c) && pathpos) {
|
||||||
VARARR(char, buf, pathpos + strlen(eptr) + 1);
|
VARARR(char, buf, pathpos + strlen(eptr) + 1);
|
||||||
|
|
||||||
|
@ -2470,13 +2566,18 @@ excluded(Comp c, char *eptr)
|
||||||
pptr = saves;
|
pptr = saves;
|
||||||
first = savei;
|
first = savei;
|
||||||
longest = savel;
|
longest = savel;
|
||||||
|
errsfound = savee;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Structure for storing instances of a pattern in a closured.
|
||||||
|
*/
|
||||||
struct gclose {
|
struct gclose {
|
||||||
char *start;
|
char *start; /* Start of this instance */
|
||||||
char *end;
|
char *end; /* End of this instance */
|
||||||
|
int errsfound; /* Errors found up to start of instance */
|
||||||
};
|
};
|
||||||
typedef struct gclose *Gclose;
|
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
|
* 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
|
* that position (when it was marked), we must already have failed on
|
||||||
* and backtracked over any further closure matches beyond that point.
|
* 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
|
static void
|
||||||
addclosures(Comp c, LinkList closlist, int *pdone, char *trystring)
|
addclosures(Comp c, LinkList closlist, int *pdone, unsigned char *trystring)
|
||||||
{
|
{
|
||||||
Gclose gcnode;
|
Gclose gcnode;
|
||||||
char *opptr = pptr;
|
char *opptr = pptr;
|
||||||
|
unsigned char *tpos;
|
||||||
|
|
||||||
while (*pptr) {
|
while (*pptr) {
|
||||||
if (STARP(c)) {
|
if (STARP(c)) {
|
||||||
if (trystring[(pptr+1)-opptr])
|
if (*(tpos = trystring + ((pptr+1) - opptr))) {
|
||||||
break;
|
if ((unsigned)(errsfound+1) >= *tpos)
|
||||||
|
break;
|
||||||
|
*tpos = (unsigned)(errsfound+1);
|
||||||
|
}
|
||||||
gcnode = (Gclose)zalloc(sizeof(struct gclose));
|
gcnode = (Gclose)zalloc(sizeof(struct gclose));
|
||||||
gcnode->start = pptr;
|
gcnode->start = pptr;
|
||||||
gcnode->end = ++pptr;
|
gcnode->end = METAINC(pptr);
|
||||||
|
gcnode->errsfound = errsfound;
|
||||||
} else {
|
} else {
|
||||||
char *saves = pptr;
|
char *saves = pptr;
|
||||||
|
int savee = errsfound;
|
||||||
if (OPTIONALP(c) && *pdone >= 1)
|
if (OPTIONALP(c) && *pdone >= 1)
|
||||||
return;
|
return;
|
||||||
if (!matchonce(c) || saves == pptr ||
|
if (!matchonce(c) || saves == pptr ||
|
||||||
trystring[pptr-opptr]) {
|
(*(tpos = trystring + (pptr-opptr)) &&
|
||||||
|
(unsigned)(errsfound+1) >= *tpos)) {
|
||||||
pptr = saves;
|
pptr = saves;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (*tpos)
|
||||||
|
*tpos = (unsigned)(errsfound+1);
|
||||||
gcnode = (Gclose)zalloc(sizeof(struct gclose));
|
gcnode = (Gclose)zalloc(sizeof(struct gclose));
|
||||||
gcnode->start = saves;
|
gcnode->start = saves;
|
||||||
gcnode->end = pptr;
|
gcnode->end = pptr;
|
||||||
|
gcnode->errsfound = savee;
|
||||||
}
|
}
|
||||||
pushnode(closlist, gcnode);
|
pushnode(closlist, gcnode);
|
||||||
(*pdone)++;
|
(*pdone)++;
|
||||||
|
@ -2523,13 +2638,29 @@ addclosures(Comp c, LinkList closlist, int *pdone, char *trystring)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Match characters with case-insensitivity.
|
* Match characters with case-insensitivity. Note charmatch(x,y) !=
|
||||||
* Note CHARMATCH(x,y) != CHARMATCH(y,x)
|
* 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 */
|
/* see if current string in pptr matches c */
|
||||||
|
|
||||||
|
@ -2539,14 +2670,16 @@ doesmatch(Comp c)
|
||||||
{
|
{
|
||||||
if (CLOSUREP(c)) {
|
if (CLOSUREP(c)) {
|
||||||
int done, retflag = 0;
|
int done, retflag = 0;
|
||||||
char *saves, *trystring, *opptr;
|
char *saves, *opptr;
|
||||||
|
unsigned char *trystring, *tpos;
|
||||||
|
int savee;
|
||||||
LinkList closlist;
|
LinkList closlist;
|
||||||
Gclose gcnode;
|
Gclose gcnode;
|
||||||
|
|
||||||
if (first && *pptr == '.')
|
if (first && *pptr == '.')
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!inclosure && !c->left) {
|
if (!inclosure && !c->left && !c->errsmax) {
|
||||||
/* We are not inside another closure, and the current
|
/* We are not inside another closure, and the current
|
||||||
* pattern is a simple string. We handle this very common
|
* pattern is a simple string. We handle this very common
|
||||||
* case specially: otherwise, matches like *foo* are
|
* case specially: otherwise, matches like *foo* are
|
||||||
|
@ -2561,26 +2694,30 @@ doesmatch(Comp c)
|
||||||
!itok(looka)) {
|
!itok(looka)) {
|
||||||
/* Another simple optimisation for a very common case:
|
/* Another simple optimisation for a very common case:
|
||||||
* we are processing a * and there is
|
* we are processing a * and there is
|
||||||
* an ordinary character match next. We look ahead for
|
* an ordinary character match (which may not be a Metafied
|
||||||
* that character, taking care of Meta bytes.
|
* character, just to make it easier) next. We look ahead
|
||||||
|
* for that character, taking care of Meta bytes.
|
||||||
*/
|
*/
|
||||||
while (*pptr) {
|
while (*pptr) {
|
||||||
for (; *pptr; pptr++) {
|
for (; *pptr; pptr++) {
|
||||||
if (*pptr == Meta)
|
if (*pptr == Meta)
|
||||||
pptr++;
|
pptr++;
|
||||||
else if (CHARMATCH(STOUC(*pptr), STOUC(looka)))
|
else if (charmatch(c, pptr, &looka))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!*(saves = pptr))
|
if (!*(saves = pptr))
|
||||||
break;
|
break;
|
||||||
|
savee = errsfound;
|
||||||
if (doesmatch(c->next))
|
if (doesmatch(c->next))
|
||||||
return 1;
|
return 1;
|
||||||
pptr = saves+1;
|
pptr = saves+1;
|
||||||
|
errsfound = savee;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Standard track-forward code */
|
/* Standard track-forward code */
|
||||||
for (done = 0; ; done++) {
|
for (done = 0; ; done++) {
|
||||||
saves = pptr;
|
saves = pptr;
|
||||||
|
savee = errsfound;
|
||||||
if ((done || ONEHASHP(c) || OPTIONALP(c)) &&
|
if ((done || ONEHASHP(c) || OPTIONALP(c)) &&
|
||||||
((!c->next && (!LASTP(c) || !*pptr || longest)) ||
|
((!c->next && (!LASTP(c) || !*pptr || longest)) ||
|
||||||
(c->next && doesmatch(c->next))))
|
(c->next && doesmatch(c->next))))
|
||||||
|
@ -2588,6 +2725,7 @@ doesmatch(Comp c)
|
||||||
if (done && OPTIONALP(c))
|
if (done && OPTIONALP(c))
|
||||||
return 0;
|
return 0;
|
||||||
pptr = saves;
|
pptr = saves;
|
||||||
|
errsfound = savee;
|
||||||
first = 0;
|
first = 0;
|
||||||
if (STARP(c)) {
|
if (STARP(c)) {
|
||||||
if (!*pptr)
|
if (!*pptr)
|
||||||
|
@ -2602,7 +2740,7 @@ doesmatch(Comp c)
|
||||||
/* The full, gory backtracking code is now necessary. */
|
/* The full, gory backtracking code is now necessary. */
|
||||||
inclosure++;
|
inclosure++;
|
||||||
closlist = newlinklist();
|
closlist = newlinklist();
|
||||||
trystring = zcalloc(strlen(pptr)+1);
|
trystring = (unsigned char *)zcalloc(strlen(pptr)+1);
|
||||||
opptr = pptr;
|
opptr = pptr;
|
||||||
|
|
||||||
/* Start by making a list where each match is as long
|
/* Start by making a list where each match is as long
|
||||||
|
@ -2621,7 +2759,7 @@ doesmatch(Comp c)
|
||||||
retflag = 1;
|
retflag = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
trystring[saves-opptr] = 1;
|
trystring[saves-opptr] = (unsigned)(errsfound + 1);
|
||||||
/*
|
/*
|
||||||
* If we failed, the first thing to try is whether we can
|
* If we failed, the first thing to try is whether we can
|
||||||
* shorten the match using the last pattern in the closure.
|
* shorten the match using the last pattern in the closure.
|
||||||
|
@ -2633,14 +2771,18 @@ doesmatch(Comp c)
|
||||||
char savec = *gcnode->end;
|
char savec = *gcnode->end;
|
||||||
*gcnode->end = '\0';
|
*gcnode->end = '\0';
|
||||||
pptr = gcnode->start;
|
pptr = gcnode->start;
|
||||||
|
errsfound = gcnode->errsfound;
|
||||||
if (matchonce(c) && pptr != gcnode->start
|
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 = savec;
|
||||||
gcnode->end = pptr;
|
gcnode->end = pptr;
|
||||||
/* Try again to construct a list based on
|
/* Try again to construct a list based on
|
||||||
* this new position
|
* this new position
|
||||||
*/
|
*/
|
||||||
addclosures(c, closlist, &done, trystring+(pptr-opptr));
|
addclosures(c, closlist, &done, tpos);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
*gcnode->end = savec;
|
*gcnode->end = savec;
|
||||||
|
@ -2650,6 +2792,7 @@ doesmatch(Comp c)
|
||||||
*/
|
*/
|
||||||
if ((gcnode = (Gclose)getlinknode(closlist))) {
|
if ((gcnode = (Gclose)getlinknode(closlist))) {
|
||||||
pptr = gcnode->start;
|
pptr = gcnode->start;
|
||||||
|
errsfound = gcnode->errsfound;
|
||||||
zfree(gcnode, sizeof(struct gclose));
|
zfree(gcnode, sizeof(struct gclose));
|
||||||
done--;
|
done--;
|
||||||
} else
|
} 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 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]))
|
#define PPAT(X) (pat[(X)-1] == Meta ? pat[X] ^ 32 : untok(pat[X]))
|
||||||
|
|
||||||
for (pat++; *pat != Outbrack && *pat;
|
for (pat++; *pat != Outbrack && *pat; METAINC(pat)) {
|
||||||
*pat == Meta ? pat += 2 : pat++) {
|
|
||||||
if (*pat == Inbrack) {
|
if (*pat == Inbrack) {
|
||||||
/* Inbrack can only occur inside a range if we found [:...:]. */
|
/* Inbrack can only occur inside a range if we found [:...:]. */
|
||||||
pat += 2;
|
pat += 2;
|
||||||
|
@ -2748,6 +2890,22 @@ rangematch(char **patptr, int ch, int rchar)
|
||||||
*patptr = pat;
|
*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
|
static int
|
||||||
matchonce(Comp c)
|
matchonce(Comp c)
|
||||||
|
@ -2758,7 +2916,7 @@ matchonce(Comp c)
|
||||||
if (!pat || !*pat) {
|
if (!pat || !*pat) {
|
||||||
/* No current pattern (c->str). */
|
/* No current pattern (c->str). */
|
||||||
char *saves;
|
char *saves;
|
||||||
int savei;
|
int savee, savei;
|
||||||
|
|
||||||
if (errflag)
|
if (errflag)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2766,6 +2924,7 @@ matchonce(Comp c)
|
||||||
* check for exclusion of pattern or alternatives. */
|
* check for exclusion of pattern or alternatives. */
|
||||||
saves = pptr;
|
saves = pptr;
|
||||||
savei = first;
|
savei = first;
|
||||||
|
savee = errsfound;
|
||||||
/* Loop over alternatives with exclusions: (foo~bar|...). *
|
/* Loop over alternatives with exclusions: (foo~bar|...). *
|
||||||
* Exclusions apply to the pattern in c->left. */
|
* Exclusions apply to the pattern in c->left. */
|
||||||
if (c->left || c->right) {
|
if (c->left || c->right) {
|
||||||
|
@ -2812,6 +2971,7 @@ matchonce(Comp c)
|
||||||
*/
|
*/
|
||||||
exclend--;
|
exclend--;
|
||||||
pptr = saves;
|
pptr = saves;
|
||||||
|
errsfound = savee;
|
||||||
}
|
}
|
||||||
inclosure--;
|
inclosure--;
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -2822,19 +2982,43 @@ matchonce(Comp c)
|
||||||
if (c->right && (!ret || inclosure)) {
|
if (c->right && (!ret || inclosure)) {
|
||||||
/* If in a closure, we always want the longest match. */
|
/* If in a closure, we always want the longest match. */
|
||||||
char *newpptr = pptr;
|
char *newpptr = pptr;
|
||||||
|
int newerrsfound = errsfound;
|
||||||
pptr = saves;
|
pptr = saves;
|
||||||
first = savei;
|
first = savei;
|
||||||
|
errsfound = savee;
|
||||||
ret2 = doesmatch(c->right);
|
ret2 = doesmatch(c->right);
|
||||||
if (ret && (!ret2 || pptr < newpptr))
|
if (ret && (!ret2 || pptr < newpptr)) {
|
||||||
pptr = newpptr;
|
pptr = newpptr;
|
||||||
|
errsfound = newerrsfound;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!ret && !ret2) {
|
||||||
|
pptr = saves;
|
||||||
|
first = savei;
|
||||||
|
errsfound = savee;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (!ret && !ret2)
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
if (CLOSUREP(c))
|
if (CLOSUREP(c))
|
||||||
return 1;
|
return 1;
|
||||||
if (!c->next) /* no more patterns left */
|
if (!c->next) {
|
||||||
return (!LASTP(c) || !*pptr || longest);
|
/*
|
||||||
|
* 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 */
|
/* optimisation when next pattern is not a closure */
|
||||||
if (!CLOSUREP(c->next)) {
|
if (!CLOSUREP(c->next)) {
|
||||||
c = c->next;
|
c = c->next;
|
||||||
|
@ -2843,7 +3027,10 @@ matchonce(Comp c)
|
||||||
}
|
}
|
||||||
return doesmatch(c->next);
|
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 != '.')
|
if (first && *pptr == '.' && *pat != '.')
|
||||||
return 0;
|
return 0;
|
||||||
if (*pat == Star) { /* final * is not expanded to ?#; returns success */
|
if (*pat == Star) { /* final * is not expanded to ?#; returns success */
|
||||||
|
@ -2852,39 +3039,47 @@ matchonce(Comp c)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
first = 0; /* finished checking start of pattern */
|
first = 0; /* finished checking start of pattern */
|
||||||
if (*pat == Quest && *pptr) {
|
if (*pat == Quest) {
|
||||||
/* match exactly one character */
|
/* match exactly one character */
|
||||||
if (*pptr == Meta)
|
if (!*pptr)
|
||||||
pptr++;
|
break;
|
||||||
pptr++;
|
METAINC(pptr);
|
||||||
pat++;
|
pat++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (*pat == Inbrack) {
|
if (*pat == Inbrack) {
|
||||||
/* Match groups of characters */
|
/* Match groups of characters */
|
||||||
char ch;
|
char ch;
|
||||||
|
char *saves, *savep;
|
||||||
|
|
||||||
if (!*pptr)
|
if (!*pptr)
|
||||||
break;
|
break;
|
||||||
ch = *pptr == Meta ? pptr[1] ^ 32 : *pptr;
|
saves = pptr;
|
||||||
|
savep = pat;
|
||||||
|
ch = UNMETA(pptr);
|
||||||
if (pat[1] == Hat || pat[1] == '^' || pat[1] == '!') {
|
if (pat[1] == Hat || pat[1] == '^' || pat[1] == '!') {
|
||||||
/* group is negated */
|
/* group is negated */
|
||||||
*++pat = Hat;
|
*++pat = Hat;
|
||||||
rangematch(&pat, ch, Hat);
|
rangematch(&pat, ch, Hat);
|
||||||
DPUTS(!*pat, "BUG: something is very wrong in doesmatch()");
|
DPUTS(!*pat, "BUG: something is very wrong in doesmatch()");
|
||||||
if (*pat != Outbrack)
|
if (*pat != Outbrack) {
|
||||||
|
pptr = saves;
|
||||||
|
pat = savep;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
pat++;
|
pat++;
|
||||||
*pptr == Meta ? pptr += 2 : pptr++;
|
METAINC(pptr);
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
/* pattern is not negated (affirmed? asserted?) */
|
/* pattern is not negated (affirmed? asserted?) */
|
||||||
rangematch(&pat, ch, Inbrack);
|
rangematch(&pat, ch, Inbrack);
|
||||||
DPUTS(!pat || !*pat, "BUG: something is very wrong in doesmatch()");
|
DPUTS(!pat || !*pat, "BUG: something is very wrong in doesmatch()");
|
||||||
if (*pat == Outbrack)
|
if (*pat == Outbrack) {
|
||||||
|
pptr = saves;
|
||||||
|
pat = savep;
|
||||||
break;
|
break;
|
||||||
for (*pptr == Meta ? pptr += 2 : pptr++;
|
}
|
||||||
*pat != Outbrack; pat++);
|
for (METAINC(pptr); *pat != Outbrack; pat++);
|
||||||
pat++;
|
pat++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -2892,7 +3087,7 @@ matchonce(Comp c)
|
||||||
if (*pat == Inang) {
|
if (*pat == Inang) {
|
||||||
/* Numeric globbing. */
|
/* Numeric globbing. */
|
||||||
unsigned long t1, t2, t3;
|
unsigned long t1, t2, t3;
|
||||||
char *ptr;
|
char *ptr, *saves = pptr, *savep = pat;
|
||||||
|
|
||||||
if (!idigit(*pptr))
|
if (!idigit(*pptr))
|
||||||
break;
|
break;
|
||||||
|
@ -2933,19 +3128,146 @@ matchonce(Comp c)
|
||||||
pptr--;
|
pptr--;
|
||||||
t1 /= 10;
|
t1 /= 10;
|
||||||
}
|
}
|
||||||
if (t1 < t2 || (!not3 && t1 > t3))
|
if (t1 < t2 || (!not3 && t1 > t3)) {
|
||||||
|
pptr = saves;
|
||||||
|
pat = savep;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (CHARMATCH(STOUC(*pptr), STOUC(*pat))) {
|
/* itok(Meta) is zero */
|
||||||
/* just plain old characters */
|
DPUTS(itok(*pat), "BUG: matching tokenized character");
|
||||||
pptr++;
|
if (charmatch(c, pptr, pat)) {
|
||||||
pat++;
|
/* just plain old characters (or maybe unplain new characters) */
|
||||||
|
METAINC(pptr);
|
||||||
|
METAINC(pat);
|
||||||
continue;
|
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;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2958,6 +3280,7 @@ parsereg(char *str)
|
||||||
remnulargs(str);
|
remnulargs(str);
|
||||||
mode = 1; /* no path components */
|
mode = 1; /* no path components */
|
||||||
addflags = 0;
|
addflags = 0;
|
||||||
|
errsmax = 0;
|
||||||
pptr = str;
|
pptr = str;
|
||||||
tail = NULL;
|
tail = NULL;
|
||||||
return parsecompsw(GF_TOPLEV);
|
return parsecompsw(GF_TOPLEV);
|
||||||
|
|
|
@ -607,6 +607,9 @@ hashdir(char **dirp)
|
||||||
Cmdnam cn;
|
Cmdnam cn;
|
||||||
DIR *dir;
|
DIR *dir;
|
||||||
char *fn;
|
char *fn;
|
||||||
|
#ifdef _WIN32
|
||||||
|
char *exe;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (isrelative(*dirp) || !(dir = opendir(unmeta(*dirp))))
|
if (isrelative(*dirp) || !(dir = opendir(unmeta(*dirp))))
|
||||||
return;
|
return;
|
||||||
|
@ -618,6 +621,23 @@ hashdir(char **dirp)
|
||||||
cn->u.name = dirp;
|
cn->u.name = dirp;
|
||||||
cmdnamtab->addnode(cmdnamtab, ztrdup(fn), cn);
|
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);
|
closedir(dir);
|
||||||
}
|
}
|
||||||
|
|
49
Src/module.c
49
Src/module.c
|
@ -567,6 +567,37 @@ load_module(char const *name)
|
||||||
return m;
|
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
|
void
|
||||||
add_dep(char *name, char *from)
|
add_dep(char *name, char *from)
|
||||||
|
@ -963,22 +994,10 @@ bin_zmodload_load(char *nam, char **args, char *ops)
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
/* load modules */
|
/* load modules */
|
||||||
for (; *args; args++) {
|
for (; *args; args++)
|
||||||
Module m;
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
13
Src/params.c
13
Src/params.c
|
@ -679,11 +679,13 @@ static char **garr;
|
||||||
static long
|
static long
|
||||||
getarg(char **str, int *inv, Value v, int a2, long *w)
|
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;
|
char *s = *str, *sep = NULL, *t, sav, *d, **ta, **p, *tt;
|
||||||
long r = 0;
|
long r = 0;
|
||||||
Comp c;
|
Comp c;
|
||||||
|
|
||||||
|
ishash = (v->pm && PM_TYPE(v->pm->flags) == PM_HASHED);
|
||||||
|
|
||||||
/* first parse any subscription flags */
|
/* first parse any subscription flags */
|
||||||
if (v->pm && (*s == '(' || *s == Inpar)) {
|
if (v->pm && (*s == '(' || *s == Inpar)) {
|
||||||
int escapes = 0;
|
int escapes = 0;
|
||||||
|
@ -771,12 +773,13 @@ getarg(char **str, int *inv, Value v, int a2, long *w)
|
||||||
} else if (rev) {
|
} else if (rev) {
|
||||||
v->isarr |= SCANPM_WANTVALS;
|
v->isarr |= SCANPM_WANTVALS;
|
||||||
}
|
}
|
||||||
if (!down && v->pm && PM_TYPE(v->pm->flags) == PM_HASHED)
|
if (!down && ishash)
|
||||||
v->isarr &= ~SCANPM_MATCHMANY;
|
v->isarr &= ~SCANPM_MATCHMANY;
|
||||||
*inv = ind;
|
*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)
|
if (*t == '[' || *t == Inbrack)
|
||||||
i++;
|
i++;
|
||||||
else if (*t == ']' || *t == Outbrack)
|
else if (*t == ']' || *t == Outbrack)
|
||||||
|
@ -791,7 +794,7 @@ getarg(char **str, int *inv, Value v, int a2, long *w)
|
||||||
singsub(&s);
|
singsub(&s);
|
||||||
|
|
||||||
if (!rev) {
|
if (!rev) {
|
||||||
if (v->pm && PM_TYPE(v->pm->flags) == PM_HASHED) {
|
if (ishash) {
|
||||||
HashTable ht = v->pm->gets.hfn(v->pm);
|
HashTable ht = v->pm->gets.hfn(v->pm);
|
||||||
if (!ht) {
|
if (!ht) {
|
||||||
ht = newparamtable(17, v->pm->nam);
|
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 ((c = parsereg(s))) {
|
||||||
if (v->isarr) {
|
if (v->isarr) {
|
||||||
if (PM_TYPE(v->pm->flags) == PM_HASHED) {
|
if (ishash) {
|
||||||
scancomp = c;
|
scancomp = c;
|
||||||
if (ind)
|
if (ind)
|
||||||
v->isarr |= SCANPM_MATCHKEY;
|
v->isarr |= SCANPM_MATCHKEY;
|
||||||
|
|
|
@ -999,11 +999,12 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
||||||
|
|
||||||
if (!(v = fetchvalue((subexp ? &ov : &s), (wantt ? -1 :
|
if (!(v = fetchvalue((subexp ? &ov : &s), (wantt ? -1 :
|
||||||
((unset(KSHARRAYS) || inbrace) ? 1 : -1)),
|
((unset(KSHARRAYS) || inbrace) ? 1 : -1)),
|
||||||
hkeys|hvals)))
|
hkeys|hvals)) ||
|
||||||
|
(v->pm && (v->pm->flags & PM_UNSET)))
|
||||||
vunset = 1;
|
vunset = 1;
|
||||||
|
|
||||||
if (wantt) {
|
if (wantt) {
|
||||||
if (v) {
|
if (v && v->pm && !(v->pm->flags & PM_UNSET)) {
|
||||||
int f = v->pm->flags;
|
int f = v->pm->flags;
|
||||||
|
|
||||||
switch (PM_TYPE(f)) {
|
switch (PM_TYPE(f)) {
|
||||||
|
|
11
Src/system.h
11
Src/system.h
|
@ -70,8 +70,15 @@ char *alloca _((size_t));
|
||||||
# endif
|
# endif
|
||||||
#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
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_SYS_TYPES_H
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
|
|
|
@ -173,6 +173,7 @@ refreshptr
|
||||||
remlpaths
|
remlpaths
|
||||||
remnulargs
|
remnulargs
|
||||||
removehashnode
|
removehashnode
|
||||||
|
require_module
|
||||||
resetneeded
|
resetneeded
|
||||||
restoredir
|
restoredir
|
||||||
reswdtab
|
reswdtab
|
||||||
|
|
|
@ -196,10 +196,13 @@
|
||||||
/* Define to 1 if system has working FIFO's */
|
/* Define to 1 if system has working FIFO's */
|
||||||
#undef HAVE_FIFOS
|
#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
|
#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
|
#undef RLIM_T_IS_UNSIGNED
|
||||||
|
|
||||||
/* Define to the type used in struct rlimit */
|
/* Define to the type used in struct rlimit */
|
||||||
|
|
54
configure.in
54
configure.in
|
@ -673,7 +673,8 @@ dnl The backslash substitution is to persuade cygwin to cough up
|
||||||
dnl slashes rather than doubled backslashes in the path.
|
dnl slashes rather than doubled backslashes in the path.
|
||||||
echo "#include <signal.h>" > nametmp.c
|
echo "#include <signal.h>" > nametmp.c
|
||||||
sigfile_list="`$CPP 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 }
|
$AWK '{ if (\$1 ~ \"sig\") files[[\$1]] = \$1 }
|
||||||
END { for (var in files) print var }'`"
|
END { for (var in files) print var }'`"
|
||||||
rm -f nametmp.c
|
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 In case we don't get the stuff from the preprocesor, use the old
|
||||||
dnl list of standard places.
|
dnl list of standard places.
|
||||||
sigfile_list="/usr/include/bsd/sys/signal.h
|
sigfile_list="/usr/include/bsd/sys/signal.h
|
||||||
|
/usr/include/signum.h
|
||||||
/usr/include/asm/signum.h
|
/usr/include/asm/signum.h
|
||||||
/usr/include/asm/signal.h
|
/usr/include/asm/signal.h
|
||||||
/usr/include/linux/signal.h
|
/usr/include/linux/signal.h
|
||||||
|
@ -689,9 +691,13 @@ if test -z "$sigfile_list"; then
|
||||||
fi
|
fi
|
||||||
for SIGNAL_H in $sigfile_list
|
for SIGNAL_H in $sigfile_list
|
||||||
do
|
do
|
||||||
test -f $SIGNAL_H && \
|
dnl Try to make sure it doesn't get confused by files that don't
|
||||||
grep '#[ ]*define[ ][ ]*SIG[0-9A-Z]*[ ]*[0-9][0-9]*' $SIGNAL_H > /dev/null && \
|
dnl have real signal definitions in, but do #define SIG* by counting
|
||||||
break
|
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
|
done
|
||||||
zsh_cv_path_signal_h=$SIGNAL_H
|
zsh_cv_path_signal_h=$SIGNAL_H
|
||||||
])
|
])
|
||||||
|
@ -729,20 +735,43 @@ dnl ------------------
|
||||||
dnl rlimit type checks
|
dnl rlimit type checks
|
||||||
dnl ------------------
|
dnl ------------------
|
||||||
DEFAULT_RLIM_T=long
|
DEFAULT_RLIM_T=long
|
||||||
AC_CACHE_CHECK(if rlim_t is quad_t,
|
AC_CACHE_CHECK(if rlim_t is longer than a long,
|
||||||
zsh_cv_rlim_t_is_quad_t,
|
zsh_cv_rlim_t_is_longer,
|
||||||
[AC_TRY_RUN([
|
[AC_TRY_RUN([
|
||||||
#ifdef HAVE_SYS_TIME_H
|
#ifdef HAVE_SYS_TIME_H
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#endif
|
#endif
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
main(){struct rlimit r;exit(sizeof(r.rlim_cur) <= sizeof(long));}],
|
main(){struct rlimit r;exit(sizeof(r.rlim_cur) <= sizeof(long));}],
|
||||||
zsh_cv_rlim_t_is_quad_t=yes,
|
zsh_cv_rlim_t_is_longer=yes,
|
||||||
zsh_cv_rlim_t_is_quad_t=no,
|
zsh_cv_rlim_t_is_longer=no,
|
||||||
zsh_cv_rlim_t_is_quad_t=yes)])
|
zsh_cv_rlim_t_is_longer=yes)])
|
||||||
if test $zsh_cv_rlim_t_is_quad_t = yes; then
|
if test $zsh_cv_rlim_t_is_longer = yes; then
|
||||||
AC_DEFINE(RLIM_T_IS_QUAD_T)
|
AC_CACHE_CHECK(if rlim_t is a quad,
|
||||||
DEFAULT_RLIM_T=quad_t
|
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
|
else
|
||||||
AC_CACHE_CHECK(if the rlim_t is unsigned,
|
AC_CACHE_CHECK(if the rlim_t is unsigned,
|
||||||
zsh_cv_type_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
|
elif test "x$zsh_cv_func_dlsym_needs_underscore" != xno; then
|
||||||
dnl Do not cache failed value
|
dnl Do not cache failed value
|
||||||
unset zsh_cv_func_dlsym_needs_underscore
|
unset zsh_cv_func_dlsym_needs_underscore
|
||||||
dynamic=no
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
117
patchlist.txt
117
patchlist.txt
|
@ -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
|
localoptions' after spending an hour wondering why nothing worked any
|
||||||
more.
|
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,
|
Sven: compcall tries old-style completion from new-style function,
|
||||||
compctl -K ' func' handles newstyle completion, 5059; avoid recursion,
|
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
|
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
|
mypath=foo (and also existing PATH=(foo) bug), 5120
|
||||||
|
|
||||||
Sven: doc fix for glob qualifiers, 5102
|
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
|
Sven: zle and widget information via variables in new completion
|
||||||
functions, 5104
|
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
|
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
|
Drazen Kacar, modified by me: unlock terminal device on Solaris, 5118
|
||||||
(5117 was wrong)
|
(5117 was wrong)
|
||||||
|
|
||||||
pws-7
|
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).
|
patchlist).
|
||||||
|
|
||||||
Bart: finally added missing hunk from 4965 which allowed unsetting an
|
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
|
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,
|
Sven: zle commands which use the minibuffer erase completion listings,
|
||||||
5201
|
5201
|
||||||
|
@ -370,13 +370,13 @@ Sven: ${foo:q}, 5208, preliminary
|
||||||
|
|
||||||
Sven: use ${foo:q} for quoting prefix and suffix in new completion, 5120
|
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
|
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
|
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
|
pws-8
|
||||||
|
|
||||||
|
@ -409,14 +409,14 @@ Sven: compctl matcher to use reference counts, 5316
|
||||||
|
|
||||||
Sven: keys available in zle widget functions, 5320
|
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
|
Sweth, Bart, Me: Functions/allopt, basically as in 2121 with the odd
|
||||||
emulate and local.
|
emulate and local.
|
||||||
|
|
||||||
Me: emulate -L, 5332
|
pws: emulate -L, 5332
|
||||||
|
|
||||||
Sven: printing of zle condition codes, 5335
|
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,
|
Sven: ignoring ignored prefix in new conditions, 5342; related fixes,
|
||||||
5343
|
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
|
Bart's fix so this works on OSes other than AIX, 5361
|
||||||
|
|
||||||
Sven: change fignore handling, 5352
|
Sven: change fignore handling, 5352
|
||||||
|
@ -437,14 +437,14 @@ failed, 5354
|
||||||
|
|
||||||
Sven: compadd -R function for suffix removal, 5355
|
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
|
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
|
pws-9
|
||||||
|
|
||||||
|
@ -458,9 +458,9 @@ Andrej: Reliant UNIX configuration, 5377
|
||||||
|
|
||||||
Sven: Manual for new completion (so far), 5384, 5397
|
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
|
Sven: overhaul of do_ambiguous with some bug-fixage, 5399, 5407
|
||||||
|
|
||||||
|
@ -469,11 +469,11 @@ $COMPDUMP file, 5402
|
||||||
|
|
||||||
Sven: files -> __files, 5401
|
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.
|
Sven: 5412: better matcher control.
|
||||||
|
|
||||||
|
@ -483,7 +483,7 @@ Sven: 5417: multiple subscripts with undefined array
|
||||||
|
|
||||||
Sven: 5418: small addmatches fixes
|
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
|
Sven: 5422: braces in completions were not tokenized; array parameters were
|
||||||
used uncopied
|
used uncopied
|
||||||
|
@ -492,14 +492,73 @@ Sven: 5423: compadd accepts either - or -- to end options
|
||||||
|
|
||||||
Sven: 5424: addmatches fix when not doing matching
|
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: 5429: $CONTEXT strings
|
||||||
|
|
||||||
Sven: 5430: rewrite Functions/Completions with simplified syntax (no #array
|
Sven: 5430: rewrite Functions/Completions with simplified syntax (no #array
|
||||||
type completions).
|
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.
|
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.
|
||||||
|
|
Loading…
Reference in a new issue