mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-12-07 06:02:21 +01:00
zsh-workers/9635
This commit is contained in:
parent
06cd60e1cf
commit
74ccd8d5a3
8 changed files with 378 additions and 242 deletions
|
|
@ -1,14 +1,11 @@
|
|||
#autoload
|
||||
|
||||
local name gropt format gname hidden hide match ign
|
||||
local name gropt=-J format gname hidden hide match opts
|
||||
|
||||
gropt=(-J)
|
||||
hide=()
|
||||
match=()
|
||||
ign=()
|
||||
opts=()
|
||||
|
||||
if [[ "$1" = -([12]|)[VJ] ]]; then
|
||||
gropt=("$1")
|
||||
gropt="$1"
|
||||
shift
|
||||
fi
|
||||
|
||||
|
|
@ -24,14 +21,14 @@ zstyle -s ":completion:${curcontext}:$1" format format ||
|
|||
zstyle -s ":completion:${curcontext}:$1" hidden hidden
|
||||
if [[ "$hidden" = (all|yes|true|1|on) ]]; then
|
||||
[[ "$hidden" = all ]] && format=''
|
||||
hide=(-n)
|
||||
opts=(-n)
|
||||
fi
|
||||
zstyle -s ":completion:${curcontext}:$1" group-name gname &&
|
||||
[[ -z "$gname" ]] && gname="$1"
|
||||
zstyle -s ":completion:${curcontext}:$1" matcher match &&
|
||||
match=(-M "${(q)match}")
|
||||
opts=($opts -M "${(q)match}")
|
||||
if zstyle -a ":completion:${curcontext}:$1" ignored-patterns _comp_ignore; then
|
||||
ign=(-F _comp_ignore)
|
||||
opts=( $opts -F _comp_ignore)
|
||||
else
|
||||
_comp_ignore=()
|
||||
fi
|
||||
|
|
@ -41,15 +38,15 @@ shift 2
|
|||
|
||||
if [[ -n "$gname" ]]; then
|
||||
if [[ -n "$format" ]]; then
|
||||
eval "${name}=($hide $match $ign $gropt ${(q)gname} -X \"${format}\")"
|
||||
eval "${name}=($opts $gropt ${(q)gname} -X \"${format}\")"
|
||||
else
|
||||
eval "${name}=($hide $match $ign $gropt ${(q)gname})"
|
||||
eval "${name}=($opts $gropt ${(q)gname})"
|
||||
fi
|
||||
else
|
||||
if [[ -n "$format" ]]; then
|
||||
eval "${name}=($hide $match $ign $gropt -default- -X \"${format}\")"
|
||||
eval "${name}=($opts $gropt -default- -X \"${format}\")"
|
||||
else
|
||||
eval "${name}=($hide $match $ign $gropt -default-)"
|
||||
eval "${name}=($opts $gropt -default-)"
|
||||
fi
|
||||
fi
|
||||
|
||||
|
|
|
|||
|
|
@ -3,24 +3,21 @@
|
|||
local opts opt type=file glob group gopts dopts aopts tmp _file_pat_checked=yes
|
||||
local hasign ign
|
||||
|
||||
opts=()
|
||||
group=()
|
||||
gopts=()
|
||||
dopts=(-/)
|
||||
aopts=(-f)
|
||||
ign=()
|
||||
while getopts "P:S:qr:R:W:F:J:V:X:f/g:M:12n" opt; do
|
||||
case "$opt" in
|
||||
/) type="${type}dir" ;;
|
||||
g) type="${type}glob"; gopts=(-g "$OPTARG") ;;
|
||||
[qn12]) opts=("$opts[@]" "-$opt" ) ;;
|
||||
[JV]) group=( "-$opt" "$OPTARG") ;;
|
||||
F) opts=("$opts[@]" "-$opt" "$OPTARG"); hasign=yes ;;
|
||||
[^f]) opts=("$opts[@]" "-$opt" "$OPTARG") ;;
|
||||
esac
|
||||
done
|
||||
zparseopts \
|
||||
/tmp ftmp g+tmp \
|
||||
qopts nopts 1opts 2opts P:opts S:opts r:opts R:opts W:opts X:opts M:opts \
|
||||
F:opts J:group V:group
|
||||
|
||||
if [[ "$group[2]" = files ]]; then
|
||||
type="${(@j::M)${(@)tmp#-}#?}"
|
||||
[[ -n "$type" ]] || type=f
|
||||
if (( $tmp[(I)-g*] )); then
|
||||
gopts=( -g ${(j: :)${(M)tmp:#-g*}#-g} )
|
||||
else
|
||||
gopts=()
|
||||
fi
|
||||
(( $opts[(I)-F*] )) && hasign=yes
|
||||
|
||||
if [[ "$group[1]" = -?files ]]; then
|
||||
opts=("$opts[@]" "$group[@]")
|
||||
group=()
|
||||
fi
|
||||
|
|
@ -32,36 +29,36 @@ fi
|
|||
if zstyle -s ":completion:${curcontext}:directories" file-patterns tmp &&
|
||||
[[ -n "$tmp" ]]; then
|
||||
dopts=(-g "$tmp")
|
||||
if [[ "$type" = (*dir*glob*|*glob*dir*) ]]; then
|
||||
type=glob
|
||||
elif [[ "$type" != *(dir|glob)* ]]; then
|
||||
type="${type}dir"
|
||||
if [[ "$type" = (*/*g*|*g*/*) ]]; then
|
||||
type=g
|
||||
elif [[ "$type" != *[/g]* ]]; then
|
||||
type="${type}/"
|
||||
fi
|
||||
fi
|
||||
if zstyle -s ":completion:${curcontext}:globbed-files" file-patterns tmp &&
|
||||
[[ -n "$tmp" ]]; then
|
||||
gopts=(-g "$tmp")
|
||||
if [[ "$type" != (*dir*glob*|*glob*dir*) ]]; then
|
||||
if [[ "$type" = *(dir|glob)* ]]; then
|
||||
type=glob
|
||||
if [[ "$type" != (*/*g*|*g*/*) ]]; then
|
||||
if [[ "$type" = *[g/]* ]]; then
|
||||
type=g
|
||||
else
|
||||
type=globall
|
||||
type=ga
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
case "$type" in
|
||||
*dir*glob*|*glob*dir*) _tags globbed-files all-files ;;
|
||||
*all*glob*|*glob*all*) _tags globbed-files all-files ;;
|
||||
*glob*) _tags globbed-files directories all-files ;;
|
||||
*dir*) _tags directories all-files ;;
|
||||
*) _tags all-files ;;
|
||||
*/*g*|*g*/*) _tags globbed-files all-files ;;
|
||||
*a*g*|*g*a*) _tags globbed-files all-files ;;
|
||||
*g*) _tags globbed-files directories all-files ;;
|
||||
*/*) _tags directories all-files ;;
|
||||
*) _tags all-files ;;
|
||||
esac
|
||||
|
||||
while _tags; do
|
||||
if _requested all-files; then
|
||||
if (( $#group )); then
|
||||
group[2]=all-files
|
||||
group[1]="${group[1][1,2]}all-files"
|
||||
_setup all-files
|
||||
[[ -z "$hasign" ]] &&
|
||||
zstyle -a ":completion:${curcontext}:all-files" ignored-patterns _comp_ignore &&
|
||||
|
|
@ -72,7 +69,7 @@ while _tags; do
|
|||
elif _requested directories; then
|
||||
if _requested globbed-files; then
|
||||
if (( $#group )); then
|
||||
group[2]=globbed-files
|
||||
group[1]="${group[1][1,2]}globbed-files"
|
||||
_setup globbed-files
|
||||
[[ -z "$hasign" ]] &&
|
||||
zstyle -a ":completion:${curcontext}:all-files" ignored-patterns _comp_ignore &&
|
||||
|
|
@ -81,7 +78,7 @@ while _tags; do
|
|||
_path_files "$opts[@]" "$ign[@]" "$dopts[@]" "$gopts[@]" && return 0
|
||||
else
|
||||
if (( $#group )); then
|
||||
group[2]=directories
|
||||
group[1]="${group[1][1,2]}directories"
|
||||
_setup directories
|
||||
[[ -z "$hasign" ]] &&
|
||||
zstyle -a ":completion:${curcontext}:all-files" ignored-patterns _comp_ignore &&
|
||||
|
|
@ -91,13 +88,13 @@ while _tags; do
|
|||
fi
|
||||
elif _requested globbed-files; then
|
||||
if (( $#group )); then
|
||||
group[2]=globbed-files
|
||||
group[1]="${group[1][1,2]}globbed-files"
|
||||
_setup globbed-files
|
||||
[[ -z "$hasign" ]] &&
|
||||
zstyle -a ":completion:${curcontext}:all-files" ignored-patterns _comp_ignore &&
|
||||
ign=(-F _comp_ignore)
|
||||
fi
|
||||
if [[ "$type" = (*dir*glob*|*glob*dir*) ]]; then
|
||||
if [[ "$type" = (*/*g*|*g*/*) ]]; then
|
||||
_path_files "$opts[@]" "$ign[@]" "$dopts[@]" "$gopts[@]" && return 0
|
||||
else
|
||||
_path_files "$opts[@]" "$ign[@]" "$gopts[@]" && return 0
|
||||
|
|
|
|||
|
|
@ -13,22 +13,18 @@ typeset -U tmp2
|
|||
|
||||
# Get the options.
|
||||
|
||||
group=()
|
||||
expl=()
|
||||
opts=()
|
||||
sopts=()
|
||||
while getopts "J:V:X:P:F:S:r:R:qM:12n" opt; do
|
||||
case "$opt" in
|
||||
[JV]) group=("-$opt" "$OPTARG");;
|
||||
X) expl=(-X "$OPTARG");;
|
||||
[PF]) opts=( "$opts[@]" "-$opt" "$OPTARG")
|
||||
sopts=( "$sopts[@]" "-$opt" "$OPTARG");;
|
||||
[SrR]) sopts=( "$sopts[@]" -P "$OPTARG");;
|
||||
[q12n]) sopts=( "$sopts[@]" "-$opt");;
|
||||
M) match="$OPTARG";;
|
||||
esac
|
||||
done
|
||||
shift OPTIND-1
|
||||
zparseopts -D \
|
||||
J:group V:group X:expl \
|
||||
P:opts F:opts \
|
||||
S:sopts r:sopts R:sopts qsopts 1sopts 2sopts nsopts \
|
||||
M:match
|
||||
|
||||
sopts=( "$sopts[@]" "$opts[@]" )
|
||||
if (( $#match )); then
|
||||
match="${match[1][3,-1]}"
|
||||
else
|
||||
match=''
|
||||
fi
|
||||
|
||||
# Get the arguments, first the separator, then the array. The array is
|
||||
# stored in `matches'. Further on this array will always contain those
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@
|
|||
# Utility function for in-path completion. This allows `/u/l/b<TAB>'
|
||||
# to complete to `/usr/local/bin'.
|
||||
|
||||
local linepath realpath donepath prepath testpath exppath skips
|
||||
local linepath realpath donepath prepath testpath exppath skips skipped
|
||||
local tmp1 tmp2 tmp3 tmp4 i orig eorig pre suf tpre tsuf opre osuf cpre
|
||||
local pats haspats=no ignore group expl addpfx addsfx remsfx rem remt
|
||||
local pats haspats=no ignore pfxsfx rem remt sopt gopt opt
|
||||
local nm=$compstate[nmatches] menu mspec matcher mopts atmp sort match
|
||||
|
||||
typeset -U prepaths exppaths
|
||||
|
|
@ -13,73 +13,50 @@ typeset -U prepaths exppaths
|
|||
setopt localoptions nullglob rcexpandparam
|
||||
unsetopt markdirs globsubst shwordsplit nounset
|
||||
|
||||
local sopt='-' gopt='' opt
|
||||
exppaths=()
|
||||
prepaths=('')
|
||||
ignore=()
|
||||
group=()
|
||||
pats=()
|
||||
addpfx=()
|
||||
addsfx=()
|
||||
remsfx=()
|
||||
expl=()
|
||||
matcher=()
|
||||
mopts=()
|
||||
|
||||
# Get the options.
|
||||
|
||||
while getopts "P:S:qr:R:W:F:J:V:X:f/g:M:12n" opt; do
|
||||
case "$opt" in
|
||||
[12n]) mopts=( "$mopts[@]" "-$opt" )
|
||||
;;
|
||||
P) addpfx=(-P "$OPTARG")
|
||||
;;
|
||||
S) addsfx=(-S "$OPTARG")
|
||||
;;
|
||||
q) tmp1=yes
|
||||
;;
|
||||
[rR]) remsfx=("-$opt" "$OPTARG")
|
||||
;;
|
||||
W) tmp1="$OPTARG"
|
||||
if [[ "$tmp1[1]" = '(' ]]; then
|
||||
prepaths=( ${^=tmp1[2,-2]%/}/ )
|
||||
elif [[ "$tmp1[1]" = '/' ]]; then
|
||||
prepaths=( "$tmp1/" )
|
||||
else
|
||||
# In this case the variable should be an array, so
|
||||
# don't use an extra ${=...}.
|
||||
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
|
||||
;;
|
||||
[JV]) group=("-$opt" "$OPTARG")
|
||||
;;
|
||||
X) expl=(-X "$OPTARG")
|
||||
;;
|
||||
f) sopt="${sopt}f"
|
||||
pats=("$pats[@]" '*')
|
||||
;;
|
||||
/) sopt="${sopt}/"
|
||||
pats=("$pats[@]" '*(-/)')
|
||||
haspats=yes
|
||||
;;
|
||||
g) gopt='-g'
|
||||
pats=("$pats[@]" ${=OPTARG})
|
||||
haspats=yes
|
||||
;;
|
||||
M) mspec="$OPTARG"
|
||||
matcher=(-M "$OPTARG")
|
||||
;;
|
||||
esac
|
||||
done
|
||||
zparseopts \
|
||||
P:pfxsfx S:pfxsfx qpfxsfx r:pfxsfx R:pfxsfx \
|
||||
W:prepaths F:ignore M+matcher \
|
||||
J:mopts V:mopts X:mopts 1:mopts 2:mopts n:mopts \
|
||||
ftmp1 /tmp1 g+tmp1
|
||||
|
||||
sopt="-${(@j::M)${(@)tmp1#-}#?}"
|
||||
(( $tmp1[(I)-[/g]*] )) && haspats=yes
|
||||
(( $tmp1[(I)-g*] )) && gopt=yes
|
||||
if (( $tmp1[(I)-/] )); then
|
||||
pats=( '*(-/)' ${=${(M)tmp1:#-g*}#-g} )
|
||||
else
|
||||
pats=( "${(@)=${(@M)tmp1:#-g*}#-g}" )
|
||||
fi
|
||||
|
||||
if (( $#prepaths )); then
|
||||
tmp1="${prepaths[1][3,-1]}"
|
||||
if [[ "$tmp1[1]" = '(' ]]; then
|
||||
prepaths=( ${^=tmp1[2,-2]%/}/ )
|
||||
elif [[ "$tmp1[1]" = '/' ]]; then
|
||||
prepaths=( "$tmp1/" )
|
||||
else
|
||||
prepaths=( ${(P)^tmp1%/}/ )
|
||||
(( ! $#prepaths )) && prepaths=( ${tmp1%/}/ )
|
||||
fi
|
||||
(( ! $#prepaths )) && prepaths=( '' )
|
||||
else
|
||||
prepaths=( '' )
|
||||
fi
|
||||
|
||||
if (( $#ignore )); then
|
||||
tmp1="${ignore[1][3,-1]}"
|
||||
if [[ "$tmp1[1]" = '(' ]]; then
|
||||
ignore=( ${=tmp1[2,-2]} )
|
||||
else
|
||||
ignore=( ${(P)tmp1} )
|
||||
fi
|
||||
fi
|
||||
|
||||
(( $#matcher )) && mspec="${matcher[1][3,-1]}"
|
||||
|
||||
if [[ -z "$_file_pat_checked" ]] &&
|
||||
zstyle -s ":completion:${curcontext}:files" file-patterns tmp1 &&
|
||||
|
|
@ -88,20 +65,34 @@ if [[ -z "$_file_pat_checked" ]] &&
|
|||
gopt=''
|
||||
sopt=-/
|
||||
else
|
||||
gopt='-g'
|
||||
gopt=yes
|
||||
sopt=-
|
||||
fi
|
||||
pats=( $=tmp1 )
|
||||
haspats=yes
|
||||
fi
|
||||
|
||||
if (( ! ( $#group + $#expl ) )); then
|
||||
# If we were given no file selection option, we behave as if we were given
|
||||
# a `-f'.
|
||||
|
||||
if [[ "$sopt" = -(f|) ]]; then
|
||||
if [[ -z "$gopt" ]]; then
|
||||
sopt='-f'
|
||||
pats=('*')
|
||||
else
|
||||
unset sopt
|
||||
fi
|
||||
fi
|
||||
|
||||
if (( ! $mopts[(I)-[JVX]*] )); then
|
||||
local expl
|
||||
|
||||
if [[ -z "$gopt" && "$sopt" = -/ ]]; then
|
||||
_description directories expl directory
|
||||
else
|
||||
_description files expl file
|
||||
fi
|
||||
tmp1=$expl[(I)-M]
|
||||
tmp1=$expl[(I)-M*]
|
||||
if (( tmp1 )); then
|
||||
mspec="$mspec $expl[1+tmp1]"
|
||||
if (( $#matcher )); then
|
||||
|
|
@ -110,20 +101,7 @@ if (( ! ( $#group + $#expl ) )); then
|
|||
matcher=(-M "$expl[1+tmp1]")
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
[[ -n "$tmp1" && $#addsfx -ne 0 ]] && addsfx[1]=-qS
|
||||
|
||||
# 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
|
||||
mopts=( "$mopts[@]" "$expl[@]" )
|
||||
fi
|
||||
|
||||
if zstyle -s ":completion:${curcontext}:files" sort tmp1; then
|
||||
|
|
@ -140,8 +118,7 @@ if zstyle -s ":completion:${curcontext}:files" sort tmp1; then
|
|||
if [[ "$sort" = on ]]; then
|
||||
sort=''
|
||||
else
|
||||
group=( "${(@)group/#-J/-V}" )
|
||||
expl=( "${(@)expl/#-J/-V}" )
|
||||
mopts=( "${(@)mopts/#-J/-V}" )
|
||||
|
||||
tmp2=()
|
||||
for tmp1 in "$pats[@]"; do
|
||||
|
|
@ -157,9 +134,15 @@ if zstyle -s ":completion:${curcontext}:files" sort tmp1; then
|
|||
fi
|
||||
fi
|
||||
|
||||
# Skip over sequences of slashes.
|
||||
# Check if we have to skip over sequences of slashes. The value of $skips
|
||||
# is used below to match the pathname components we always have to accept
|
||||
# immediatly.
|
||||
|
||||
zstyle -t ":completion:${curcontext}:paths" squeeze-slashes && skips=yes
|
||||
if zstyle -t ":completion:${curcontext}:paths" squeeze-slashes; then
|
||||
skips='((.|..|)/)##'
|
||||
else
|
||||
skips='((.|..)/)##'
|
||||
fi
|
||||
|
||||
# We get the prefix and the suffix from the line and save the whole
|
||||
# original string. Then we see if we will do menucompletion.
|
||||
|
|
@ -182,7 +165,7 @@ eorig="$orig"
|
|||
|
||||
if (( $#ignore )); then
|
||||
_comp_ignore=( "$_comp_ignore[@]" "$ignore[@]" )
|
||||
(( $expl[(I)-F] )) || expl=( "$expl[@]" -F _comp_ignore )
|
||||
(( $mopts[(I)-F*] )) || mopts=( "$mopts[@]" -F _comp_ignore )
|
||||
fi
|
||||
|
||||
# Now let's have a closer look at the string to complete.
|
||||
|
|
@ -256,26 +239,13 @@ for prepath in "$prepaths[@]"; do
|
|||
tsuf="$suf"
|
||||
testpath="$donepath"
|
||||
|
||||
tmp1=( "$prepath$realpath$donepath" )
|
||||
tmp2="${(M)tpre##${~skips}}"
|
||||
tpre="${tpre#$tmp2}"
|
||||
|
||||
tmp1=( "$prepath$realpath$donepath$tmp2" )
|
||||
|
||||
while true; do
|
||||
|
||||
# Skip over `./' and `../'.
|
||||
|
||||
if [[ "$tpre" = (.|..)/* ]]; then
|
||||
tmp1=( ${^tmp1}${tpre%%/*}/ )
|
||||
tpre="${tpre#*/}"
|
||||
continue
|
||||
fi
|
||||
|
||||
# Skip over multiple slashes?
|
||||
|
||||
if [[ -n "$skips" && "$tpre" = /* ]]; then
|
||||
tmp1=( ${^tmp1}/ )
|
||||
tpre="${tpre#/}"
|
||||
continue
|
||||
fi
|
||||
|
||||
# Get the prefix and suffix for matching.
|
||||
|
||||
if [[ "$tpre" = */* ]]; then
|
||||
|
|
@ -289,45 +259,24 @@ for prepath in "$prepaths[@]"; do
|
|||
# Get the matching files by globbing.
|
||||
|
||||
if [[ "$tpre$tsuf" = */* ]]; then
|
||||
tmp2=( ${^tmp1}*(-/) )
|
||||
[[ ! -o globdots && "$PREFIX" = .* ]] &&
|
||||
tmp2=( "$tmp2[@]" ${^tmp1}.*(-/) )
|
||||
if [[ ! -o globdots && "$PREFIX" = .* ]]; then
|
||||
tmp1=( ${^tmp1}${skipped}*(-/) ${^tmp1}${slash}.*(-/) )
|
||||
else
|
||||
tmp1=( ${^tmp1}${skipped}*(-/) )
|
||||
fi
|
||||
if [[ -o globdots || "$PREFIX" = .* ]] &&
|
||||
zstyle -s ":completion:${curcontext}:paths" special-dirs atmp; then
|
||||
if [[ "$atmp" = (yes|true|1|on) ]]; then
|
||||
tmp2=( "$tmp2[@]" . .. )
|
||||
tmp1=( "$tmp1[@]" . .. )
|
||||
elif [[ "$atmp" = .. ]]; then
|
||||
tmp2=( "$tmp2[@]" .. )
|
||||
tmp1=( "$tmp1[@]" .. )
|
||||
fi
|
||||
fi
|
||||
else
|
||||
tmp2=( ${^tmp1}${^~pats} )
|
||||
[[ ! -o globdots && "$PREFIX" = .* ]] &&
|
||||
tmp2=( "$tmp2[@]" ${^tmp1}.${^~pats} )
|
||||
if (( $#tmp2 )) &&
|
||||
zstyle -s ":completion:${curcontext}:files" ignore-parents rem &&
|
||||
[[ ( "$rem" != *dir* || "$pats" = '*(-/)' ) &&
|
||||
( "$rem" != *..* || "$tmp1" = *../* ) ]]; then
|
||||
if [[ "$rem" = *parent* ]]; then
|
||||
for i in "$tmp2[@]"; do
|
||||
if [[ -d "$i" && "$i" = */* ]]; then
|
||||
remt="${i%/*}"
|
||||
while [[ "$remt" = */* ]]; do
|
||||
[[ "$remt" -ef "$i" ]] && break
|
||||
remt="${remt%/*}"
|
||||
done
|
||||
[[ "$remt" = */* || "$remt" -ef "$i" ]] &&
|
||||
_comp_ignore=( "$_comp_ignore[@]" "${(q)i}" )
|
||||
fi
|
||||
done
|
||||
fi
|
||||
if [[ "$rem" = *pwd* ]]; then
|
||||
for i in "$tmp2[@]"; do
|
||||
[[ "$i" -ef "$PWD" ]] && _comp_ignore=( "$_comp_ignore[@]" "${(q)i}" )
|
||||
done
|
||||
fi
|
||||
(( $#_comp_ignore )) && (( $expl[(I)-F] )) ||
|
||||
expl=( "$expl[@]" -F _comp_ignore )
|
||||
if [[ ! -o globdots && "$PREFIX" = .* ]]; then
|
||||
tmp1=( ${^tmp1}${skipped}${^~pats} ${^tmp1}${slash}.${^~pats} )
|
||||
else
|
||||
tmp1=( ${^tmp1}${skipped}${^~pats} )
|
||||
fi
|
||||
if [[ "$sopt" = *[/f]* && ( -o globdots || "$PREFIX" = .* ) ]] &&
|
||||
zstyle -s ":completion:${curcontext}:paths" special-dirs atmp; then
|
||||
|
|
@ -338,22 +287,28 @@ for prepath in "$prepaths[@]"; do
|
|||
fi
|
||||
fi
|
||||
fi
|
||||
tmp1=( "$tmp2[@]" )
|
||||
|
||||
if [[ -n "$PREFIX$SUFFIX" ]]; then
|
||||
# See which of them match what's on the line.
|
||||
|
||||
builtin compadd -D tmp1 -F _comp_ignore "$matcher[@]" - "${(@)tmp1:t}"
|
||||
if [[ -n "$_comp_correct" ]]; then
|
||||
tmp2=( "$tmp1[@]" )
|
||||
builtin compadd -D tmp1 -F _comp_ignore "$matcher[@]" - "${(@)tmp1:t}"
|
||||
|
||||
if [[ $#tmp1 -eq 0 && -n "$_comp_correct" ]]; then
|
||||
tmp1=( "$tmp2[@]" )
|
||||
compadd -D tmp1 -F _comp_ignore "$matcher[@]" - "${(@)tmp2:t}"
|
||||
if [[ $#tmp1 -eq 0 && -n "$_comp_correct" ]]; then
|
||||
tmp1=( "$tmp2[@]" )
|
||||
compadd -D tmp1 -F _comp_ignore "$matcher[@]" - "${(@)tmp2:t}"
|
||||
fi
|
||||
else
|
||||
[[ "$tmp1[1]" = */* ]] && tmp2=( "$tmp1[@]" )
|
||||
|
||||
builtin compadd -D tmp1 -F _comp_ignore "$matcher[@]" - "${(@)tmp1:t}"
|
||||
fi
|
||||
|
||||
# If no file matches, save the expanded path and continue with
|
||||
# the outer loop.
|
||||
|
||||
if [[ $#tmp1 -eq 0 ]]; then
|
||||
if (( ! $#tmp1 )); then
|
||||
if [[ "$tmp2[1]" = */* ]]; then
|
||||
tmp2=( "${(@)tmp2#${prepath}${realpath}}" )
|
||||
if [[ "$tmp2[1]" = */* ]]; then
|
||||
|
|
@ -384,8 +339,7 @@ for prepath in "$prepaths[@]"; do
|
|||
|
||||
if [[ -z "$tpre$tsuf" && -n "$pre$suf" ]]; then
|
||||
tmp1=( "$tmp2[@]" )
|
||||
addsfx=(-S '')
|
||||
remsfx=()
|
||||
pfxsfx=(-S '' "$pfxsfx[@]")
|
||||
break;
|
||||
elif [[ "$haspats" = no && -z "$tpre$tsuf" &&
|
||||
"$pre" = */ && -z "$suf" ]]; then
|
||||
|
|
@ -397,6 +351,29 @@ for prepath in "$prepaths[@]"; do
|
|||
continue 2
|
||||
fi
|
||||
|
||||
if [[ "$tpre$tsuf" != */* && $#tmp1 -ne 0 ]] &&
|
||||
zstyle -s ":completion:${curcontext}:files" ignore-parents rem &&
|
||||
[[ ( "$rem" != *dir* || "$pats" = '*(-/)' ) &&
|
||||
( "$rem" != *..* || "$tmp1" = *../* ) ]]; then
|
||||
if [[ "$rem" = *parent* ]]; then
|
||||
for i in ${(M)^tmp1:#*/*}(-/); do
|
||||
remt="${${i#$prepath$realpath$donepath}%/*}"
|
||||
while [[ "$remt" = */* ]]; do
|
||||
[[ "$prepath$realpath$donepath$remt" -ef "$i" ]] && break
|
||||
remt="${remt%/*}"
|
||||
done
|
||||
[[ "$remt" = */* || "$remt" -ef "$i" ]] &&
|
||||
_comp_ignore=( "$_comp_ignore[@]" "${(q)i}" )
|
||||
done
|
||||
fi
|
||||
if [[ "$rem" = *pwd* ]]; then
|
||||
for i in ${^tmp1}(-/); do
|
||||
[[ "$i" -ef "$PWD" ]] && _comp_ignore=( "$_comp_ignore[@]" "${(q)i}" )
|
||||
done
|
||||
fi
|
||||
(( $#_comp_ignore && $mopts[(I)-F*] )) || mopts=( "$mopts[@]" -F _comp_ignore )
|
||||
fi
|
||||
|
||||
# Step over to the next component, if any.
|
||||
|
||||
if [[ "$tpre" = */* ]]; then
|
||||
|
|
@ -408,10 +385,16 @@ for prepath in "$prepaths[@]"; do
|
|||
break
|
||||
fi
|
||||
|
||||
# There are more components, so add a slash to the files we are
|
||||
# collecting.
|
||||
# There are more components, so skip over the next components and make a
|
||||
# slash be added.
|
||||
|
||||
tmp1=( ${^tmp1}/ )
|
||||
tmp2="${(M)tpre##((.|..|)/)##}" ###
|
||||
if [[ -n "$tmp2" ]]; then
|
||||
skipped="/$tmp2"
|
||||
tpre="${tpre#$tmp2}"
|
||||
else
|
||||
skipped=/
|
||||
fi
|
||||
done
|
||||
|
||||
# The next loop searches the first ambiguous component.
|
||||
|
|
@ -471,30 +454,30 @@ for prepath in "$prepaths[@]"; do
|
|||
if [[ "$tmp3" = */* ]]; then
|
||||
compadd -Qf "$mopts[@]" -p "$linepath$tmp2" -s "/${tmp3#*/}" \
|
||||
-W "$prepath$realpath$testpath" \
|
||||
"$addpfx[@]" "$addsfx[@]" "$remsfx[@]" \
|
||||
-M "r:|/=* r:|=* $mspec" "$group[@]" "$expl[@]" \
|
||||
"$pfxsfx[@]" \
|
||||
-M "r:|/=* r:|=* $mspec" \
|
||||
- "${(@)tmp1%%/*}"
|
||||
else
|
||||
compadd -Qf "$mopts[@]" -p "$linepath$tmp2" \
|
||||
-W "$prepath$realpath$testpath" \
|
||||
"$addpfx[@]" "$addsfx[@]" "$remsfx[@]" \
|
||||
-M "r:|/=* r:|=* $mspec" "$group[@]" "$expl[@]" \
|
||||
"$pfxsfx[@]" \
|
||||
-M "r:|/=* r:|=* $mspec" \
|
||||
- "$tmp1[@]"
|
||||
fi
|
||||
else
|
||||
if [[ "$tmp3" = */* ]]; then
|
||||
atmp=( -Qf "$mopts[@]" -p "$linepath$tmp2"
|
||||
-W "$prepath$realpath$testpath"
|
||||
"$addpfx[@]" "$addsfx[@]" "$remsfx[@]"
|
||||
-M "r:|/=* r:|=* $mspec" "$group[@]" "$expl[@]" )
|
||||
"$pfxsfx[@]" \
|
||||
-M "r:|/=* r:|=* $mspec" )
|
||||
for i in "$tmp1[@]"; do
|
||||
compadd "$atmp[@]" -s "/${i#*/}" - "${i%%/*}"
|
||||
done
|
||||
else
|
||||
compadd -Qf "$mopts[@]" -p "$linepath$tmp2" \
|
||||
-W "$prepath$realpath$testpath" \
|
||||
"$addpfx[@]" "$addsfx[@]" "$remsfx[@]" \
|
||||
-M "r:|/=* r:|=* $mspec" "$group[@]" "$expl[@]" \
|
||||
"$pfxsfx[@]" \
|
||||
-M "r:|/=* r:|=* $mspec" \
|
||||
- "$tmp1[@]"
|
||||
fi
|
||||
fi
|
||||
|
|
@ -543,8 +526,8 @@ for prepath in "$prepaths[@]"; do
|
|||
compquote tmp4 tmp1
|
||||
compadd -Qf "$mopts[@]" -p "$linepath$tmp4" \
|
||||
-W "$prepath$realpath$testpath" \
|
||||
"$addpfx[@]" "$addsfx[@]" "$remsfx[@]" \
|
||||
-M "r:|/=* r:|=* $mspec" "$group[@]" "$expl[@]" \
|
||||
"$pfxsfx[@]" \
|
||||
-M "r:|/=* r:|=* $mspec" \
|
||||
- "$tmp1[@]"
|
||||
fi
|
||||
done
|
||||
|
|
@ -553,14 +536,17 @@ done
|
|||
# expanded paths that are different from the string on the line, we add
|
||||
# them as possible matches.
|
||||
|
||||
exppaths=( "${(@)exppaths:#$eorig}" )
|
||||
|
||||
if zstyle -t ":completion:${curcontext}:paths" expand prefix &&
|
||||
[[ $#exppaths -gt 0 && nm -eq compstate[nmatches] ]]; then
|
||||
PREFIX="${opre}"
|
||||
SUFFIX="${osuf}"
|
||||
compadd -Q "$mopts[@]" -S '' "$group[@]" "$expl[@]" \
|
||||
-M "r:|/=* r:|=* $mspec" -p "$linepath" - "$exppaths[@]"
|
||||
[[ nm -eq compstate[nmatches] ]]; then
|
||||
|
||||
exppaths=( "${(@)exppaths:#$eorig}" )
|
||||
|
||||
if (( $#exppaths )); then
|
||||
PREFIX="${opre}"
|
||||
SUFFIX="${osuf}"
|
||||
compadd -Q "$mopts[@]" -S '' \
|
||||
-M "r:|/=* r:|=* $mspec" -p "$linepath" - "$exppaths[@]"
|
||||
fi
|
||||
fi
|
||||
|
||||
[[ nm -ne compstate[nmatches] ]]
|
||||
|
|
|
|||
|
|
@ -22,19 +22,16 @@ local matchflags opt group expl nm=$compstate[nmatches] opre osuf opts match
|
|||
|
||||
# Get the options.
|
||||
|
||||
group=()
|
||||
expl=()
|
||||
opts=()
|
||||
while getopts "J:V:X:P:F:S:r:R:qM:12n" opt; do
|
||||
case "$opt" in
|
||||
[JV]) group=("-$opt" "$OPTARG");;
|
||||
X) expl=(-X "$OPTARG");;
|
||||
[q12n]) opts=( "$opts[@]" "-$opt" );;
|
||||
M) match="$OPTARG";;
|
||||
*) opts=( "$opts[@]" "-$opt" "$OPTARG" );;
|
||||
esac
|
||||
done
|
||||
shift OPTIND-1
|
||||
zparseopts -D \
|
||||
J:group V:group \
|
||||
P:opts F:opts S:opts r:opts R:opts qopts 1opts 2opts nopts \
|
||||
X:expl M:match
|
||||
|
||||
if (( $#match )); then
|
||||
match="${match[1][3,-1]}"
|
||||
else
|
||||
match=''
|
||||
fi
|
||||
|
||||
# Get the string from the line.
|
||||
|
||||
|
|
|
|||
|
|
@ -111,4 +111,28 @@ The resulting strings are stored in the var(array).
|
|||
item(tt(zregexparse))(
|
||||
This implements the internals of the `tt(_regex_arguments)'.
|
||||
)
|
||||
item(tt(zparseopts) [ tt(-D) ] var(specs))(
|
||||
This builtin can be used to parse the positional arguments and put
|
||||
options found in them into separate arrays. Each var(spec) describes
|
||||
one option which is given as its first character. If the second
|
||||
character is either `tt(:)' or `tt(+)', the option takes an argument
|
||||
(either directly following the option in the same word or in the next
|
||||
word). After the option character or the `tt(:)' or `tt(+)' follows
|
||||
the name of the array in which the option should be stored. The only
|
||||
difference between the form with a `t(:)' and the one with a `tt(+)'
|
||||
is that in the first case the option and its argument will be put in
|
||||
the array only once (later occurrences overwriting earlier ones),
|
||||
whereas with `tt(+)' all occurrences are moved to the array.
|
||||
|
||||
If the tt(-D) option is given, all options found are removed from the
|
||||
positional parameters leaving only those strings that did not match
|
||||
any of the var(specs).
|
||||
|
||||
For example, calling `tt(zparseopts afoo b:bar c+bar)' with the
|
||||
strings `tt(-a)', `tt(-bx)', `tt(-c)', `tt(y)', `tt(-cz)', `tt(baz)'
|
||||
and `tt(-cend)' as positional arguments will set the array tt(foo) to
|
||||
contain the element `tt(-a)' and the array tt(bar) to the strings
|
||||
`tt(-bx)', `tt(-cy)' and `tt(-cz)'. The `tt(baz)' and any strings
|
||||
after it will not be used.
|
||||
)
|
||||
enditem()
|
||||
|
|
|
|||
|
|
@ -1155,10 +1155,149 @@ bin_zregexparse(char *nam, char **args, char *ops, int func)
|
|||
return ret;
|
||||
}
|
||||
|
||||
typedef struct zoptdesc *Zoptdesc;
|
||||
typedef struct zoptarr *Zoptarr;
|
||||
typedef struct zoptval *Zoptval;
|
||||
|
||||
struct zoptdesc {
|
||||
int arg;
|
||||
Zoptarr arr;
|
||||
};
|
||||
|
||||
struct zoptarr {
|
||||
char *name;
|
||||
Zoptval vals, last;
|
||||
Zoptarr next;
|
||||
int num;
|
||||
};
|
||||
|
||||
#define ZOF_ARG 1
|
||||
#define ZOF_ADD 2
|
||||
|
||||
struct zoptval {
|
||||
char *str;
|
||||
Zoptval next;
|
||||
};
|
||||
|
||||
static Zoptarr opt_arrs;
|
||||
|
||||
static Zoptarr
|
||||
get_opt_arr(char *name)
|
||||
{
|
||||
Zoptarr p;
|
||||
|
||||
for (p = opt_arrs; p; p = p->next)
|
||||
if (!strcmp(name, p->name))
|
||||
return p;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
bin_zparseopts(char *nam, char **args, char *ops, int func)
|
||||
{
|
||||
char *o, *n, **pp, *str, **aval;
|
||||
Zoptdesc opts[256], d;
|
||||
Zoptarr a;
|
||||
Zoptval v;
|
||||
|
||||
memset(opts, 0, 256 * sizeof(Zoptdesc));
|
||||
opt_arrs = NULL;
|
||||
|
||||
while ((o = *args++)) {
|
||||
if (opts[STOUC(*o)]) {
|
||||
zerrnam(nam, "option described more than once: %s", o, 0);
|
||||
return 1;
|
||||
}
|
||||
d = (Zoptdesc) zhalloc(sizeof(*d));
|
||||
d->arg = (o[1] == ':' ? ZOF_ARG : (o[1] == '+' ? ZOF_ADD : 0));
|
||||
if (!(a = get_opt_arr((n = o + (d->arg ? 2 : 1))))) {
|
||||
a = (Zoptarr) zhalloc(sizeof(*a));
|
||||
a->name = n;
|
||||
a->num = 0;
|
||||
a->vals = a->last = NULL;
|
||||
a->next = opt_arrs;
|
||||
opt_arrs = a;
|
||||
}
|
||||
d->arr = a;
|
||||
opts[STOUC(*o)] = d;
|
||||
}
|
||||
for (pp = pparams; (o = *pp); pp++) {
|
||||
if (*o != '-')
|
||||
break;
|
||||
while (*++o) {
|
||||
if (!(d = opts[STOUC(*o)]))
|
||||
break;
|
||||
if (d->arg) {
|
||||
if (o[1]) {
|
||||
str = (char *) zhalloc(strlen(o) + 2);
|
||||
str[0] = '-';
|
||||
strcpy(str + 1, o);
|
||||
} else if (!pp[1]) {
|
||||
zerrnam(nam, "missing argument for option: -%c", NULL, *o);
|
||||
return 1;
|
||||
} else {
|
||||
str = (char *) zhalloc(strlen(pp[1]) + 3);
|
||||
str[0] = '-';
|
||||
str[1] = *o;
|
||||
strcpy(str + 2, pp[1]);
|
||||
pp++;
|
||||
}
|
||||
o = "" - 1;
|
||||
} else {
|
||||
str = (char *) zhalloc(3);
|
||||
str[0] = '-';
|
||||
str[1] = *o;
|
||||
str[2] = '\0';
|
||||
}
|
||||
if (d->arg != ZOF_ADD) {
|
||||
for (v = d->arr->vals; v; v = v->next) {
|
||||
if (str[1] == v->str[1]) {
|
||||
v->str = str;
|
||||
str = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (str) {
|
||||
v = (Zoptval) zhalloc(sizeof(*v));
|
||||
v->str = str;
|
||||
v->next = NULL;
|
||||
|
||||
if (d->arr->last)
|
||||
d->arr->last->next = v;
|
||||
else
|
||||
d->arr->vals = v;
|
||||
d->arr->last = v;
|
||||
d->arr->num++;
|
||||
}
|
||||
}
|
||||
if (*o)
|
||||
break;
|
||||
}
|
||||
if (ops['D']) {
|
||||
PERMALLOC {
|
||||
pp = arrdup(pp);
|
||||
} LASTALLOC;
|
||||
|
||||
freearray(pparams);
|
||||
pparams = pp;
|
||||
}
|
||||
for (a = opt_arrs; a; a = a->next) {
|
||||
aval = (char **) zalloc((a->num + 1) * sizeof(char *));
|
||||
for (pp = aval, v = a->vals; v; pp++, v = v->next)
|
||||
*pp = ztrdup(v->str);
|
||||
*pp = NULL;
|
||||
setaparam(a->name, aval);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct builtin bintab[] = {
|
||||
BUILTIN("zstyle", 0, bin_zstyle, 0, -1, 0, NULL, NULL),
|
||||
BUILTIN("zformat", 0, bin_zformat, 3, -1, 0, NULL, NULL),
|
||||
BUILTIN("zregexparse", 0, bin_zregexparse, 3, -1, 0, "c", NULL),
|
||||
BUILTIN("zparseopts", 0, bin_zparseopts, 1, -1, 0, "D", NULL),
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -4,4 +4,4 @@ moddeps="zsh/complete"
|
|||
|
||||
objects="zutil.o"
|
||||
|
||||
autobins="zformat zstyle"
|
||||
autobins="zformat zstyle zregexparse zparseopts"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue