about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Completion/Core/_description16
-rw-r--r--Completion/Core/_main_complete2
-rw-r--r--Completion/Core/_path_files34
-rw-r--r--Doc/Zsh/compsys.yo9
-rw-r--r--Doc/Zsh/compwid.yo34
-rw-r--r--Src/Zle/compcore.c76
6 files changed, 109 insertions, 62 deletions
diff --git a/Completion/Core/_description b/Completion/Core/_description
index c6a7b8807..ffe016df8 100644
--- a/Completion/Core/_description
+++ b/Completion/Core/_description
@@ -1,10 +1,11 @@
 #autoload
 
-local name gropt format gname hidden hide match
+local name gropt format gname hidden hide match ign
 
 gropt=(-J)
 hide=()
 match=()
+ign=()
 
 if [[ "$1" = -([12]|)[VJ] ]]; then
   gropt=("$1")
@@ -29,21 +30,26 @@ zstyle -s ":completion${curcontext}:$1" group-name gname &&
     [[ -z "$gname" ]] && gname="$1"
 zstyle -s ":completion${curcontext}:$1" matcher match &&
     match=(-M "${(q)match}")
+if zstyle -a ":completion${curcontext}:$1" ignored-patterns _comp_ignore; then
+  ign=(-F _comp_ignore)
+else
+  _comp_ignore=()
+fi
 
 shift 2
 [[ -n "$format" ]] && zformat -f format "$format" "d:$1" "${(@)argv[2,-1]}"
 
 if [[ -n "$gname" ]]; then
   if [[ -n "$format" ]]; then
-    eval "${name}=($hide $match $gropt ${(q)gname} -X \"${format}\")"
+    eval "${name}=($hide $match $ign $gropt ${(q)gname} -X \"${format}\")"
   else
-    eval "${name}=($hide $match $gropt ${(q)gname})"
+    eval "${name}=($hide $match $ign $gropt ${(q)gname})"
   fi
 else
   if [[ -n "$format" ]]; then
-    eval "${name}=($hide $match $gropt -default- -X \"${format}\")"
+    eval "${name}=($hide $match $ign $gropt -default- -X \"${format}\")"
   else
-    eval "${name}=($hide $match $gropt -default-)"
+    eval "${name}=($hide $match $ign $gropt -default-)"
   fi
 fi
 
diff --git a/Completion/Core/_main_complete b/Completion/Core/_main_complete
index 53af97dab..09feae10f 100644
--- a/Completion/Core/_main_complete
+++ b/Completion/Core/_main_complete
@@ -19,7 +19,7 @@
 setopt localoptions nullglob rcexpandparam extendedglob
 unsetopt markdirs globsubst shwordsplit nounset ksharrays
 
-local comp post ret=1 _compskip _prio_num=1 format \
+local comp post ret=1 _compskip _prio_num=1 format _comp_ignore \
       context state line opt_args val_args curcontext="$curcontext" \
       _last_nmatches=-1 _last_menu_style _def_menu_style _menu_style sel \
       _saved_exact="${compstate[exact]}" \
diff --git a/Completion/Core/_path_files b/Completion/Core/_path_files
index 12d497a97..a76319030 100644
--- a/Completion/Core/_path_files
+++ b/Completion/Core/_path_files
@@ -55,11 +55,10 @@ while getopts "P:S:qr:R:W:F:J:V:X:f/g:M:12n" opt; do
          ;;
   F)     tmp1="$OPTARG"
          if [[ "$tmp1[1]" = '(' ]]; then
-           ignore=( ${^=tmp1[2,-2]}/ )
+           ignore=( ${=tmp1[2,-2]} )
          else
-           ignore=( ${(P)${tmp1}} )
+           ignore=( ${(P)tmp1} )
          fi
-	 (( $#ignore )) && ignore=(-F "( $ignore )")
          ;;
   [JV])  group=("-$opt" "$OPTARG")
          ;;
@@ -158,18 +157,13 @@ eorig="$orig"
    ( $#compstate[pattern_match] -ne 0 &&
      "${orig#\~}" != "${${orig#\~}:q}" ) ]] && menu=yes
 
-# If given no `-F' option, we want to use the `ignored-suffixes'-style.
+# If given no `-F' option, we may want to use $fignore, turned into patterns.
 
-if [[ $#ignore -eq 0 && -z $gopt ]]; then
-  if zstyle -a ":completion${curcontext}:files" ignored-suffixes ignore; then
-    ignore=(-F "( $ignore )")
-  else
-
-    # For now we still use the fignore parameter.
-    # This may be removed some day.
+[[ $#ignore -eq 0 && -z $gopt ]] && ignore=( "?*${^fignore[@]}" )
 
-    ignore=(-F fignore)
-  fi
+if (( $#ignore )); then
+  _comp_ignore=( "$_comp_ignore[@]" "$ignore[@]" )
+  (( $expl[(I)-F] )) || expl=( "$expl[@]" -F _comp_ignore )
 fi
 
 # Now let's have a closer look at the string to complete.
@@ -298,11 +292,11 @@ for prepath in "$prepaths[@]"; do
     if [[ -n "$PREFIX$SUFFIX" ]]; then
       # See which of them match what's on the line.
 
-      builtin compadd -D tmp1 "$ignore[@]" "$matcher[@]" - "${(@)tmp1:t}"
+      builtin compadd -D tmp1 -F _comp_ignore "$matcher[@]" - "${(@)tmp1:t}"
 
       if [[ $#tmp1 -eq 0 && -n "$_comp_correct" ]]; then
         tmp1=( "$tmp2[@]" )
-	compadd -D tmp1 "$ignore[@]" "$matcher[@]" - "${(@)tmp2:t}"
+	compadd -D tmp1 -F _comp_ignore "$matcher[@]" - "${(@)tmp2:t}"
       fi
 
       # If no file matches, save the expanded path and continue with
@@ -423,13 +417,13 @@ for prepath in "$prepaths[@]"; do
             compstate[to_end]=''
         if [[ "$tmp3" = */* ]]; then
 	  compadd -Qf "$mopts[@]" -p "$linepath$tmp4" -s "/${tmp3#*/}" \
-	          -W "$prepath$realpath$testpath" "$ignore[@]" \
+	          -W "$prepath$realpath$testpath" \
 		  "$addpfx[@]" "$addsfx[@]" "$remsfx[@]" \
                   -M "r:|/=* r:|=* $mspec" "$group[@]" "$expl[@]" \
 		  - "${(@)tmp1%%/*}"
 	else
 	  compadd -Qf "$mopts[@]" -p "$linepath$tmp4" \
-	          -W "$prepath$realpath$testpath" "$ignore[@]" \
+	          -W "$prepath$realpath$testpath" \
 		   "$addpfx[@]" "$addsfx[@]" "$remsfx[@]" \
                    -M "r:|/=* r:|=* $mspec" "$group[@]" "$expl[@]" \
 		   - "$tmp1[@]"
@@ -437,7 +431,7 @@ for prepath in "$prepaths[@]"; do
       else
         if [[ "$tmp3" = */* ]]; then
 	  atmp=( -Qf "$mopts[@]" -p "$linepath$tmp4"
-	         -W "$prepath$realpath$testpath" "$ignore[@]"
+	         -W "$prepath$realpath$testpath"
 	         "$addpfx[@]" "$addsfx[@]" "$remsfx[@]"
                  -M "r:|/=* r:|=* $mspec" "$group[@]" "$expl[@]" )
           for i in "$tmp1[@]"; do
@@ -445,7 +439,7 @@ for prepath in "$prepaths[@]"; do
 	  done
         else
 	  compadd -Qf "$mopts[@]" -p "$linepath$tmp4" \
-		  -W "$prepath$realpath$testpath" "$ignore[@]" \
+		  -W "$prepath$realpath$testpath" \
 		  "$addpfx[@]" "$addsfx[@]" "$remsfx[@]" \
                   -M "r:|/=* r:|=* $mspec" "$group[@]" "$expl[@]" \
 		  - "$tmp1[@]"
@@ -495,7 +489,7 @@ for prepath in "$prepaths[@]"; do
     tmp4="$testpath"
     compquote tmp4 tmp1
     compadd -Qf "$mopts[@]" -p "$linepath$tmp4" \
-	    -W "$prepath$realpath$testpath" "$ignore[@]" \
+	    -W "$prepath$realpath$testpath" \
 	    "$addpfx[@]" "$addsfx[@]" "$remsfx[@]" \
             -M "r:|/=* r:|=* $mspec" "$group[@]" "$expl[@]" \
 	    - "$tmp1[@]"
diff --git a/Doc/Zsh/compsys.yo b/Doc/Zsh/compsys.yo
index f532ee2d4..fbe5ac265 100644
--- a/Doc/Zsh/compsys.yo
+++ b/Doc/Zsh/compsys.yo
@@ -835,10 +835,11 @@ item(tt(hosts-ports-users))(
 Like tt(hosts-ports) but used for commands like tt(telnet) and
 containing strings of the form `var(host)tt(:)var(port)tt(:)var(user)'.
 )
-item(tt(ignored-suffixes))(
-This style is used with the tt(files) tag and gives suffixes of
-filenames to ignore. The matches ignored will only be completed when
-there are no other matches.  It it is a more configurable version
+item(tt(ignored-patterns))(
+This style is used with the tags used when adding matches and gives a
+number of patterns. All matches that are matched by any of these
+patterns will be ignored as long as there are other matches not
+matched by any of the patterns.  It is a more configurable version
 of the shell parameter tt($fignore).
 )
 item(tt(insert-unambiguous))(
diff --git a/Doc/Zsh/compwid.yo b/Doc/Zsh/compwid.yo
index c32cc402d..d15ee98b2 100644
--- a/Doc/Zsh/compwid.yo
+++ b/Doc/Zsh/compwid.yo
@@ -532,29 +532,27 @@ for testing.  Hence it is only useful if combined with the tt(-f) flag, as
 the tests will not otherwise be performed.
 )
 item(tt(-a))(
-The completion code may
-build two sets of matches: the normal one where words with one of the 
-suffixes in the array parameter tt(fignore) are not considered
-possible matches, and the alternate set where the words excluded
-from the first set are stored. Normally only the matches in the first
-set are used, but if this set is empty, the words from the alternate
-set are used.
-
-The tt(compadd) builtin does not use the tt(fignore) parameter and
-normally stores all words in the first set.  With the tt(-a)-flag
-given, however, the given var(words) are stored in the alternate set unless
-this flag is overridden by the tt(-F) option.
+The completion code may build two sets of matches: the normal and the
+alternate set. Normally only the matches in the first set are used,
+but if this set is empty, the words from the alternate set are
+used. The completion code uses this mechanism, for example, to make
+filenames without one of the suffixes defined with the tt(fignore)
+shell parameter be preferred over filenames with one of these
+suffixes.
+
+With the tt(-a)-flag given, the var(words) are stored in the alternate
+set unless this flag is overridden by the tt(-F) option.
 )
 item(tt(-F) var(array))(
-Specifies an array containing suffixes in the same form as the
-tt(fignore) parameter. Words with one of these suffixes are stored in
-the alternate set of matches and words without one of these suffixes
+Specifies an array containing patterns.
+Words matching one of these patterns are stored in
+the alternate set of matches and words that match none of the patterns
 are stored in the normal set.
 
 The var(array) may be the name of an array parameter or a list of
-literal suffixes enclosed in parentheses and quoted, as in `tt(-F "(.o
-.h)")'. If the name of an array is given, the elements of the array are
-taken as the suffixes.
+literal patterns enclosed in parentheses and quoted, as in `tt(-F "(*?.o
+*?.h)")'. If the name of an array is given, the elements of the array are
+taken as the patterns.
 )
 item(tt(-Q))(
 This flag instructs the completion 
diff --git a/Src/Zle/compcore.c b/Src/Zle/compcore.c
index 4828d6d0b..028536206 100644
--- a/Src/Zle/compcore.c
+++ b/Src/Zle/compcore.c
@@ -1510,15 +1510,16 @@ addmatches(Cadata dat, char **argv)
 {
     char *s, *ms, *lipre = NULL, *lisuf = NULL, *lpre = NULL, *lsuf = NULL;
     char **aign = NULL, **dparr = NULL, *oaq = autoq, *oppre = dat->ppre;
-    char *oqp = qipre, *oqs = qisuf, qc, **disp = NULL;
+    char *oqp = qipre, *oqs = qisuf, qc, **disp = NULL, *ibuf = NULL;
     int lpl, lsl, pl, sl, bcp = 0, bcs = 0, bpadd = 0, bsadd = 0;
+    int ppl = 0, psl = 0;
     int llpl = 0, llsl = 0, nm = mnum, gflags = 0, ohp = haspattern;
     int oisalt = 0, isalt, isexact, doadd, ois = instring, oib = inbackt;
     Cline lc = NULL, pline = NULL, sline = NULL;
     Cmatch cm;
     struct cmlist mst;
     Cmlist oms = mstack;
-    Patprog cp = NULL;
+    Patprog cp = NULL, *pign = NULL;
     LinkList aparl = NULL, oparl = NULL, dparl = NULL;
     Brinfo bp, bpl = brbeg, obpl, bsl = brend, obsl;
 
@@ -1612,8 +1613,29 @@ addmatches(Cadata dat, char **argv)
 		update_bmatchers();
 
 	    /* Get the suffixes to ignore. */
-	    if (dat->ign)
-		aign = get_user_var(dat->ign);
+	    if (dat->ign && (aign = get_user_var(dat->ign))) {
+		char **ap, **sp, *tmp;
+		Patprog *pp, prog;
+
+		pign = (Patprog *) zhalloc((arrlen(aign) + 1) * sizeof(Patprog));
+
+		for (ap = sp = aign, pp = pign; (tmp = *ap); ap++) {
+		    tokenize(tmp);
+		    remnulargs(tmp);
+		    if (((tmp[0] == Quest && tmp[1] == Star) ||
+			 (tmp[1] == Quest && tmp[0] == Star)) &&
+			tmp[2] && !haswilds(tmp + 2))
+			untokenize(*sp++ = tmp + 2);
+		    else if ((prog = patcompile(tmp, 0, NULL)))
+			*pp++ = prog;
+		}
+		*sp = NULL;
+		*pp = NULL;
+		if (!*aign)
+		    aign = NULL;
+		if (!*pign)
+		    pign = NULL;
+	    }
 	    /* Get the display strings. */
 	    if (dat->disp)
 		if ((disp = get_user_var(dat->disp)))
@@ -1794,6 +1816,17 @@ addmatches(Cadata dat, char **argv)
 	    /* Walk through the matches given. */
 	    obpl = bpl;
 	    obsl = bsl;
+	    if (!oisalt && (aign || pign)) {
+		int max = 0;
+		char **ap = argv;
+
+		ppl = (dat->ppre ? strlen(dat->ppre) : 0);
+		while ((s = *ap++))
+		    if ((sl = strlen(s)) > max)
+			max = sl;
+		psl = (dat->psuf ? strlen(dat->psuf) : 0);
+		ibuf = (char *) zhalloc(1 + ppl + max + psl);
+	    }
 	    for (; (s = *argv); argv++) {
 		bpl = obpl;
 		bsl = obsl;
@@ -1803,16 +1836,31 @@ addmatches(Cadata dat, char **argv)
 		}
 		sl = strlen(s);
 		isalt = oisalt;
-		if (doadd && (!dat->psuf || !*(dat->psuf)) && aign) {
-		    /* Do the suffix-test. If the match has one of the
-		     * suffixes from ign, we put it in the alternate set. */
-		    char **pt = aign;
-		    int filell;
-
-		    for (isalt = 0; !isalt && *pt; pt++)
-			if ((filell = strlen(*pt)) < sl
-			    && !strcmp(*pt, s + sl - filell))
-			    isalt = 1;
+		if (!isalt && (aign || pign)) {
+		    int il = ppl + sl + psl;
+
+		    if (ppl)
+			memcpy(ibuf, dat->ppre, ppl);
+		    strcpy(ibuf + ppl, s);
+		    if (psl)
+			strcpy(ibuf + ppl + sl, dat->psuf);
+
+		    if (aign) {
+			/* Do the suffix-test. If the match has one of the
+			 * suffixes from aign, we put it in the alternate set. */
+			char **pt = aign;
+			int filell;
+
+			for (isalt = 0; !isalt && *pt; pt++)
+			    isalt = ((filell = strlen(*pt)) < il &&
+				     !strcmp(*pt, ibuf + il - filell));
+		    }
+		    if (!isalt && pign) {
+			Patprog *pt = pign;
+
+			for (isalt = 0; !isalt && *pt; pt++)
+			    isalt = pattry(*pt, ibuf);
+		    }
 		}
 		if (!(dat->aflags & CAF_MATCH)) {
 		    if (dat->aflags & CAF_QUOTE)