Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
PATCH: file completion
- X-seq: zsh-workers 9635
- From: Sven Wischnowsky <wischnow@xxxxxxxxxxxxxxxxxxxxxxx>
- To: zsh-workers@xxxxxxxxxxxxxx
- Subject: PATCH: file completion
- Date: Wed, 9 Feb 2000 17:25:48 +0100 (MET)
- Mailing-list: contact zsh-workers-help@xxxxxxxxxxxxxx; run by ezmlm
This mainly makes _path_files a bit faster.
And then I finally got fed up with those longish while-getopts loops
and added a small builtin (zparseopts) that can be used to replace
such loops.
But still, _path_files could do with some more support by C-code. But I
have problems finding things that are a) important and b) general
enough to be moved into C...
Bye
Sven
diff -ru ../z.old/Completion/Core/_description Completion/Core/_description
--- ../z.old/Completion/Core/_description Wed Feb 9 09:30:54 2000
+++ Completion/Core/_description Wed Feb 9 14:19:42 2000
@@ -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" 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 @@
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
diff -ru ../z.old/Completion/Core/_files Completion/Core/_files
--- ../z.old/Completion/Core/_files Wed Feb 9 09:30:55 2000
+++ Completion/Core/_files Wed Feb 9 16:57:42 2000
@@ -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 @@
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 @@
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 @@
_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 @@
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
diff -ru ../z.old/Completion/Core/_multi_parts Completion/Core/_multi_parts
--- ../z.old/Completion/Core/_multi_parts Wed Feb 9 09:30:55 2000
+++ Completion/Core/_multi_parts Wed Feb 9 16:37:54 2000
@@ -13,22 +13,18 @@
# 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
diff -ru ../z.old/Completion/Core/_path_files Completion/Core/_path_files
--- ../z.old/Completion/Core/_path_files Wed Feb 9 09:30:56 2000
+++ Completion/Core/_path_files Wed Feb 9 17:06:29 2000
@@ -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 @@
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 @@
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 @@
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 [[ "$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 @@
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 @@
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,25 +239,12 @@
tsuf="$suf"
testpath="$donepath"
- tmp1=( "$prepath$realpath$donepath" )
-
- while true; do
-
- # Skip over `./' and `../'.
-
- if [[ "$tpre" = (.|..)/* ]]; then
- tmp1=( ${^tmp1}${tpre%%/*}/ )
- tpre="${tpre#*/}"
- continue
- fi
+ tmp2="${(M)tpre##${~skips}}"
+ tpre="${tpre#$tmp2}"
- # Skip over multiple slashes?
+ tmp1=( "$prepath$realpath$donepath$tmp2" )
- if [[ -n "$skips" && "$tpre" = /* ]]; then
- tmp1=( ${^tmp1}/ )
- tpre="${tpre#/}"
- continue
- fi
+ while true; do
# Get the prefix and suffix for matching.
@@ -289,45 +259,24 @@
# 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 @@
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}"
+ fi
+ else
+ [[ "$tmp1[1]" = */* ]] && tmp2=( "$tmp1[@]" )
- if [[ $#tmp1 -eq 0 && -n "$_comp_correct" ]]; then
- tmp1=( "$tmp2[@]" )
- compadd -D tmp1 -F _comp_ignore "$matcher[@]" - "${(@)tmp2:t}"
+ 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
# 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] ]]
diff -ru ../z.old/Completion/Core/_sep_parts Completion/Core/_sep_parts
--- ../z.old/Completion/Core/_sep_parts Wed Feb 9 09:30:56 2000
+++ Completion/Core/_sep_parts Wed Feb 9 16:40:52 2000
@@ -22,19 +22,16 @@
# 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.
diff -ru ../z.old/Doc/Zsh/mod_zutil.yo Doc/Zsh/mod_zutil.yo
--- ../z.old/Doc/Zsh/mod_zutil.yo Wed Feb 9 09:30:36 2000
+++ Doc/Zsh/mod_zutil.yo Wed Feb 9 17:19:37 2000
@@ -111,4 +111,28 @@
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()
diff -ru ../z.old/Src/Modules/zutil.c Src/Modules/zutil.c
--- ../z.old/Src/Modules/zutil.c Wed Feb 9 09:57:11 2000
+++ Src/Modules/zutil.c Wed Feb 9 15:34:22 2000
@@ -1155,10 +1155,149 @@
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),
};
diff -ru ../z.old/Src/Modules/zutil.mdd Src/Modules/zutil.mdd
--- ../z.old/Src/Modules/zutil.mdd Wed Feb 9 09:57:11 2000
+++ Src/Modules/zutil.mdd Wed Feb 9 17:21:43 2000
@@ -4,4 +4,4 @@
objects="zutil.o"
-autobins="zformat zstyle"
+autobins="zformat zstyle zregexparse zparseopts"
--
Sven Wischnowsky wischnow@xxxxxxxxxxxxxxxxxxxxxxx
Messages sorted by:
Reverse Date,
Date,
Thread,
Author