From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 29015 invoked from network); 23 Feb 1999 12:12:00 -0000 Received: from sunsite.auc.dk (130.225.51.30) by ns1.primenet.com.au with SMTP; 23 Feb 1999 12:12:00 -0000 Received: (qmail 2485 invoked by alias); 23 Feb 1999 12:11:31 -0000 Mailing-List: contact zsh-workers-help@sunsite.auc.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 5489 Received: (qmail 2477 invoked from network); 23 Feb 1999 12:11:30 -0000 Date: Tue, 23 Feb 1999 13:10:42 +0100 (MET) Message-Id: <199902231210.NAA24406@beta.informatik.hu-berlin.de> From: Sven Wischnowsky To: zsh-workers@sunsite.auc.dk Subject: 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@informatik.hu-berlin.de