Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

PATCH: _path_files cleanup



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