Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
PATCH: _path_files cleanup
- X-seq: zsh-workers 5489
- From: Sven Wischnowsky <wischnow@xxxxxxxxxxxxxxxxxxxxxxx>
- To: zsh-workers@xxxxxxxxxxxxxx
- Subject: PATCH: _path_files cleanup
- Date: Tue, 23 Feb 1999 13:10:42 +0100 (MET)
- Mailing-list: contact zsh-workers-help@xxxxxxxxxxxxxx; run by ezmlm
Here is the change I described in my reply to Andrej. This adds the
autoloaded functions `_match_test' and `_match_pattern' and makes
`_path_files' and `_comp_parts' use them. The calling convention is
slightly different from what I described in the mail, see the files
for a description and example.
Note that I didn't make `_path_files' accept the `-M' option. Since
this isn't allowed, I hope that it is clear that `_path_files' uses
only the global match specs. And these global match specs are what the
functions are for: emulating them by building a pattern.
Bye
Sven
diff -u of/Completion/_comp_parts Functions/Completion/_comp_parts
--- of/Completion/_comp_parts Mon Feb 22 12:01:43 1999
+++ Functions/Completion/_comp_parts Tue Feb 23 13:06:05 1999
@@ -18,11 +18,12 @@
# were used, so you might want to modify this function.
local str arr sep test testarr tmparr prefix suffixes matchers autosuffix
+local matchflags
# I have a global matching specification with multiple sets and want
# all this tried only once, you may want to change this line.
-[[ MATCHER -gt 1 ]] && return
+_match_test _comp_parts || return
# Get the string from the line.
@@ -46,7 +47,9 @@
# Build a pattern matching the possible matches and get all these
# matches in an array.
test="${str%%${sep}*}"
- test="(#l)$test:gs/./*./:gs/,/*,/:gs/-/*-/:gs/_/*_/:gs/**/*/"
+ 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
@@ -69,7 +72,9 @@
fi
if [[ $# -le 1 || "$str" != *${2}* ]]; then
# No more separators, build the matches.
- test="(#l)$str:gs/./*./:gs/,/*,/:gs/-/*-/:gs/_/*_/:gs/**/*/"
+ matchflags=""
+ _match_pattern _comp_parts test matchflags
+ test="${matchflags}${test}"
testarr=( "${(@M)${(@P)arr}:#${~test}*}" )
fi
@@ -90,7 +95,9 @@
else
test="$str"
fi
- test="(#l)$test:gs/./*./:gs/,/*,/:gs/-/*-/:gs/_/*_/:gs/**/*/"
+ 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.
diff -u of/Completion/_comp_parts~ Functions/Completion/_comp_parts~
--- of/Completion/_comp_parts~ Mon Feb 22 12:01:43 1999
+++ Functions/Completion/_comp_parts~ Mon Feb 22 11:17:34 1999
@@ -19,6 +19,9 @@
local str arr sep test testarr tmparr prefix suffixes matchers autosuffix
+# I have a global matching specification with multiple sets and want
+# all this tried only once, you may want to change this line.
+
[[ MATCHER -gt 1 ]] && return
# Get the string from the line.
diff -u of/Completion/_match_pattern Functions/Completion/_match_pattern
--- of/Completion/_match_pattern Tue Feb 23 13:06:43 1999
+++ Functions/Completion/_match_pattern Tue Feb 23 12:59:07 1999
@@ -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.
diff -u of/Completion/_match_test Functions/Completion/_match_test
--- of/Completion/_match_test Tue Feb 23 13:06:42 1999
+++ Functions/Completion/_match_test Tue Feb 23 12:56:35 1999
@@ -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 ))
diff -u of/Completion/_path_files Functions/Completion/_path_files
--- of/Completion/_path_files Mon Feb 22 12:01:45 1999
+++ Functions/Completion/_path_files Tue Feb 23 13:00:53 1999
@@ -17,13 +17,16 @@
# name extension (a la `fignore'). Files with such an extension will not
# be considered possible completions.
#
-# This function behaves as if you have a matcher definition like:
-# compctl -M 'r:|[-.,_/]=* r:|=* m:{a-z}={A-Z} m:-=_ m:.=,' \
-# 'm:{a-z}={A-Z} l:|=* r:|=*'
-# so you may want to modify this.
+# This function uses the helper functions `_match_test' and `_match_pattern'.
+
+# First see if we should do 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
+local tmp1 collect tmp2 suffixes i ignore matchflags
setopt localoptions nullglob rcexpandparam globdots extendedglob
unsetopt markdirs globsubst shwordsplit nounset
@@ -56,6 +59,11 @@
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.
@@ -83,7 +91,7 @@
shift
fi
- # If this generated any matches, we don't wnat to do in-path completion.
+ # If this generated any matches, we don't want to do in-path completion.
[[ -nmatches nm ]] || return
@@ -109,7 +117,7 @@
# prefix path by setting `prepaths'.
linepath="${str%%/*}/"
- eval realpath\=path
+ eval realpath\=$linepath
str="${str#*/}"
donepath=''
prepaths=( '' )
@@ -148,15 +156,17 @@
str="${str#*/}"
done
-# Now build the glob pattern. As noted above, this function behaves as if
-# a global matcher with two matching specifications are given.
+# 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.
-if [[ -matcher 1 ]]; then
- patstr="$str:gs/,/*,/:gs/_/*_/:gs./.*/.:gs/-/*[-_]/:gs/./*[.,]/:gs-*[.,]*[.,]*/-../-:gs.**.*."
-else
- patstr="${str%/*}/*${str##*/}*"
- patstr="$patstr:gs./.*/.:gs.**.*."
-fi
+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'
@@ -175,7 +185,7 @@
# handled.
rest="${str#*/}"
- tmp1="${prepath}${realpath}${testpath}(#l)${str%%/*}(-/)"
+ tmp1="${prepath}${realpath}${testpath}${~matchflags}${str%%/*}(-/)"
tmp1=( $~tmp1 )
if [[ $#tmp1 -eq 0 ]]; then
@@ -202,7 +212,7 @@
# via globbing.
for i in $tmp1; do
- tmp2=( $~i/(#l)$~suffixes )
+ tmp2=( ${~i}/${~matchflags}${~suffixes} )
[[ $#tmp2 -ne 0 ]] && collect=( $collect $i )
done
@@ -222,7 +232,7 @@
# Now produce all matching pathnames in `collect'.
- collect=( $~collect/(#l)$~suffixes )
+ collect=( ${~collect}/${~matchflags}${~suffixes} )
# And then remove the common path prefix from all these matches.
@@ -267,6 +277,6 @@
tmp1="$prepath$realpath$testpath"
suffixes=( $str$@ )
suffixes=( "${(@)suffixes:gs.**.*.}" )
- tmp2=( $~tmp1(#l)$~suffixes )
+ tmp2=( ${~tmp1}${~matchflags}${~suffixes} )
compadd -p "$linepath$testpath" -W "$prepath$realpath$testpath" -f "$ignore[@]" - ${tmp2#$tmp1}
done
--
Sven Wischnowsky wischnow@xxxxxxxxxxxxxxxxxxxxxxx
Messages sorted by:
Reverse Date,
Date,
Thread,
Author