about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSven Wischnowsky <wischnow@users.sourceforge.net>2000-04-26 06:54:26 +0000
committerSven Wischnowsky <wischnow@users.sourceforge.net>2000-04-26 06:54:26 +0000
commitddb16a1b2b2426f14daa54e6ee759bea64f3cb55 (patch)
tree9565d21ca50cbe033a3400774d0e9a5903820ebc
parent9ecbacab6b041c12f2dd3eb1f78ba69ccbff100d (diff)
downloadzsh-ddb16a1b2b2426f14daa54e6ee759bea64f3cb55.tar.gz
zsh-ddb16a1b2b2426f14daa54e6ee759bea64f3cb55.tar.xz
zsh-ddb16a1b2b2426f14daa54e6ee759bea64f3cb55.zip
allow to anchor on gaps between strings in matching control specs (10926)
-rw-r--r--ChangeLog4
-rw-r--r--Completion/X/_x_color31
-rw-r--r--Doc/Zsh/compwid.yo44
-rw-r--r--Src/Zle/complete.c22
-rw-r--r--Src/Zle/compmatch.c64
5 files changed, 125 insertions, 40 deletions
diff --git a/ChangeLog b/ChangeLog
index 6ff62d907..e86e5a4a4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2000-04-26  Sven Wischnowsky  <wischnow@informatik.hu-berlin.de>
 
+	* 10926: Completion/X/_x_color, Doc/Zsh/compwid.yo, Src/Zle/complete.c,
+ 	Src/Zle/compmatch.c: allow to anchor on gaps between strings in
+ 	matching control specs
+	
 	* 10925: Src/Zle/compmatch.c: faster test for `*'-patterns in
  	matching control; prefer direct character matches over match specs
  	in recursive invocations of match_str()
diff --git a/Completion/X/_x_color b/Completion/X/_x_color
index 346142eea..8df656fe1 100644
--- a/Completion/X/_x_color
+++ b/Completion/X/_x_color
@@ -1,5 +1,13 @@
 #autoload
 
+# This tries to automatically find the rgb.txt color database. If this
+# in an unusual place on your system or you want a personal database,
+# you can use the configuration key:
+#
+#  colors_path
+#    Path to a file containing the names of colors you want to
+#    complete. In the form of a X11 rgb.txt file.
+
 local expl
 
 if (( ! $+_color_cache )); then
@@ -7,18 +15,21 @@ if (( ! $+_color_cache )); then
 
   # Cache of color names doesn't exist yet, create it.
 
-  file=( /usr/{lib,{{X11R6,openwin},local{,/X11{,R6}}}/lib}/X11/rgb.txt(N) )
-
-  if (( $#file )); then
-    _color_cache=( "${(@)${(@f)$(< $file[1])}[2,-1]##*		}" )
+  zstyle -s ":completion:${curcontext}:colors" path file
+  if [[ -n "$file" ]]; then
+    _color_cache=( "${(@)${(@f)$(< $file)}[2,-1]##*		}" )
   else
+    file=( /usr/{lib,{{X11R6,openwin},local{,/X11{,R6}}}/lib}/X11/rgb.txt(N) )
 
-    # Stupid default value.
-
-    _color_cache=(white black gray red blue green)
+    (( $#file )) &&
+        _color_cache=( "${(@)${(@)${(@f)$(< $file[1])}[2,-1]##*		}:#* *}" )
   fi
+
+  # Stupid default value.
+
+  (( $#_color_cache )) || _color_cache=(white black gray red blue green)
 fi
 
-_description expl 'color specification'
-compadd "$@" "$expl[@]" -M 'm:{a-z}={A-Z} m:-=\  r:|[ A-Z0-9]=* r:|=*' - \
-        "$_color_cache[@]"
+_wanted colors expl 'color specification' \
+    compadd "$@" -M 'm:{a-z}={A-Z} m:-=\  r:[^ A-Z0-9]||[ A-Z0-9]=* r:|=*' - \
+            "$_color_cache[@]"
diff --git a/Doc/Zsh/compwid.yo b/Doc/Zsh/compwid.yo
index f2280df77..007f23431 100644
--- a/Doc/Zsh/compwid.yo
+++ b/Doc/Zsh/compwid.yo
@@ -764,21 +764,30 @@ item(tt(M:)var(lpat)tt(=)var(tpat))(
 Here, var(lpat) is a pattern that matches on the command line,
 corresponding to var(tpat) which matches in the trial completion.
 )
-xitem(tt(l:)var(anchor)tt(|)var(lpat)tt(=)var(tpat))
-item(tt(L:)var(anchor)tt(|)var(lpat)tt(=)var(tpat))(
+xitem(tt(l:)var(lanchor)tt(|)var(lpat)tt(=)var(tpat))
+xitem(tt(L:)var(lanchor)tt(|)var(lpat)tt(=)var(tpat))
+xitem(tt(l:)var(lanchor)tt(||)var(ranchor)tt(=)var(tpat))
+item(tt(L:)var(lanchor)tt(||)var(ranchor)tt(=)var(tpat))(
 These letters are for patterns that are anchored by another pattern on
 the left side. Matching for var(lpat) and var(tpat) is as for tt(m) and
 tt(M), but the pattern var(lpat) matched on the command line must be
-preceeded by the pattern var(anchor).  The var(anchor) can be blank to
+preceeded by the pattern var(lanchor).  The var(lanchor) can be blank to
 anchor the match to the start of the command line string; otherwise the
 anchor can occur anywhere, but must match in both the command line and
 trial completion strings.
+
+If no var(lpat) is given, but a var(ranchor), this matches the gap
+between substrings matched by var(lanchor) an var(ranchor). Unlike
+var(lanchor), the var(ranchor) only needs to match the trial
+completion string.
 )
-xitem(tt(r:)var(lpat)tt(|)var(anchor)tt(=)var(tpat))
-item(tt(R:)var(lpat)tt(|)var(anchor)tt(=)var(tpat))(
+xitem(tt(r:)var(lpat)tt(|)var(ranchor)tt(=)var(tpat))
+xitem(tt(R:)var(lpat)tt(|)var(ranchor)tt(=)var(tpat))
+xitem(tt(r:)var(lanchor)tt(||)var(ranchor)tt(=)var(tpat))
+item(tt(R:)var(lanchor)tt(||)var(ranchor)tt(=)var(tpat))(
 As tt(l) and tt(L) with the difference that the command line and trial
 completion patterns are anchored on the right side.  Here an empty
-var(anchor) forces the match to the end of the command line string.
+var(ranchor) forces the match to the end of the command line string.
 )
 enditem()
 
@@ -903,6 +912,29 @@ complete tt(veryverylongfile.c) rather than tt(veryverylongheader.h)
 with the above in effect, you can just type tt(very.c) before attempting
 completion.
 
+The specifications with both a left and a right anchor are useful to
+complete partial words whose parts are not really separated by some
+special character. For example, in some places strings have to be
+completed that are formed `tt(LikeThis)' (i.e. the separate parts are
+determined by a leading uppercase letter) or maybe one has to
+complete strings with trailing numbers. Here one could use the simple
+form with only one anchor as in:
+
+example(compadd -M 'r:|[A-Z0-9]=* r:|=*' LikeTHIS FooHoo foo123 bar234)
+
+But with this, the string `tt(H)' would be completed to `tt(FooHoo)'
+em(and) tt(LikeTHIS) and `tt(2)' would be completed to the other two
+strings because characters can be inserted before every uppercase
+letter and digit. To avoid this one would use:
+
+example(compadd -M 'r:[^A-Z0-9]||[A-Z0-9]=* r:|=*' \
+    LikeTHIS FooHoo foo123 bar234)
+
+By using these two anchors, a `tt(H)' matches only uppercase `H's that 
+are immediately preceded by something matching the left anchor
+`tt([^A-Z0-9])'. The effect is, of course, that `tt(H)' matches only
+the string `tt(FooHoo)', a `tt(2)' matches only `tt(bar234)' and so on.
+
 When using the completion system (see
 ifzman(zmanref(zshcompsys))\
 ifnzman(noderef(Completion System))\
diff --git a/Src/Zle/complete.c b/Src/Zle/complete.c
index 58cd8a216..2746f52d3 100644
--- a/Src/Zle/complete.c
+++ b/Src/Zle/complete.c
@@ -182,12 +182,15 @@ parse_cmatcher(char *name, char *s)
 {
     Cmatcher ret = NULL, r = NULL, n;
     Cpattern line, word, left, right;
-    int fl, ll, wl, lal, ral, err;
+    int fl, ll, wl, lal, ral, err, both;
 
     if (!*s)
 	return NULL;
 
     while (*s) {
+	lal = ral = both = 0;
+	left = right = NULL;
+
 	while (*s && inblank(*s)) s++;
 
 	if (!*s) break;
@@ -216,6 +219,10 @@ parse_cmatcher(char *name, char *s)
 	    left = parse_pattern(name, &s, &lal, '|', &err);
 	    if (err)
 		return pcm_err;
+
+	    if ((both = (*s == '|')))
+		s++;
+
 	    if (!*s || !*++s) {
 		zwarnnam(name, "missing line pattern", NULL, 0);
 		return pcm_err;
@@ -227,6 +234,12 @@ parse_cmatcher(char *name, char *s)
 			     &err);
 	if (err)
 	    return pcm_err;
+	if (both) {
+	    right = line;
+	    ral = ll;
+	    line = NULL;
+	    ll = 0;
+	}
 	if ((fl & CMF_RIGHT) && (!*s || !*++s)) {
 	    zwarnnam(name, "missing right anchor", NULL, 0);
 	} else if (!(fl & CMF_RIGHT)) {
@@ -237,6 +250,13 @@ parse_cmatcher(char *name, char *s)
 	    s++;
 	}
 	if (fl & CMF_RIGHT) {
+	    if (*s == '|') {
+		left = line;
+		lal = ll;
+		line = NULL;
+		ll = 0;
+		s++;
+	    }
 	    right = parse_pattern(name, &s, &ral, '=', &err);
 	    if (err)
 		return pcm_err;
diff --git a/Src/Zle/compmatch.c b/Src/Zle/compmatch.c
index 24f482669..3a6a849b9 100644
--- a/Src/Zle/compmatch.c
+++ b/Src/Zle/compmatch.c
@@ -57,11 +57,9 @@ cmp_cmatchers(Cmatcher a, Cmatcher b)
 	     a->llen == b->llen && a->wlen == b->wlen &&
 	     (!a->llen || cmp_cpatterns(a->line, b->line)) &&
 	     (a->wlen <= 0 || cmp_cpatterns(a->word, b->word)) &&
-	     (!(a->flags & CMF_LEFT) ||
-	      (a->lalen == b->lalen &&
-	       (!a->lalen || cmp_cpatterns(a->left, b->left)))) &&
-	     (!(a->flags & CMF_RIGHT) ||
-	      (a->ralen == b->ralen &&
+	     (!(a->flags & (CMF_LEFT | CMF_RIGHT)) ||
+	      (a->lalen == b->lalen && a->ralen == b->ralen &&
+	       (!a->lalen || cmp_cpatterns(a->left, b->left)) &&
 	       (!a->ralen || cmp_cpatterns(a->right, b->right))))));
 }
 
@@ -514,29 +512,32 @@ match_str(char *l, char *w, Brinfo *bpp, int bc, int *rwlp,
 		    continue;
 
 		if (mp->wlen < 0) {
-		    int both, loff, aoff, llen, alen, zoff, moff, ct, ict;
+		    int both, loff, aoff, llen, alen, zoff, moff, ct, ict, aol;
 		    char *tp, savl = '\0', savw;
-		    Cpattern ap;
+		    Cpattern ap, aop;
 
 		    /* This is for `*' patterns, first initialise some
 		     * local variables. */
 		    llen = mp->llen;
-		    alen = (mp->flags & CMF_LEFT ? mp->lalen : mp->ralen);
-
+		    if (mp->flags & CMF_LEFT) {
+			alen = mp->lalen; aol = mp->ralen;
+		    } else {
+			alen = mp->ralen; aol = mp->lalen;
+		    }
 		    /* Give up if we don't have enough characters for the
 		     * line-string and the anchor. */
-		    if (ll < llen + alen || lw < alen)
+		    if (ll < llen + alen || lw < alen + aol)
 			continue;
 
 		    if (mp->flags & CMF_LEFT) {
-			ap = mp->left; zoff = 0; moff = alen;
+			ap = mp->left; zoff = 0; moff = alen; aop = mp->right;
 			if (sfx) {
 			    both = 0; loff = -llen; aoff = -(llen + alen);
 			} else {
 			    both = 1; loff = alen; aoff = 0;
 			}
 		    } else {
-			ap = mp->right; zoff = alen; moff = 0;
+			ap = mp->right; zoff = alen; moff = 0; aop = mp->left;
 			if (sfx) {
 			    both = 1; loff = -(llen + alen); aoff = -alen;
 			} else {
@@ -548,9 +549,11 @@ match_str(char *l, char *w, Brinfo *bpp, int bc, int *rwlp,
 			continue;
 		    if (ap) {
 			if (!pattern_match(ap, l + aoff, NULL, NULL) ||
-			    (both && (!pattern_match(ap, w + aoff, NULL, NULL) ||
-				      !match_parts(l + aoff, w + aoff, alen,
-						   part))))
+			    (both &&
+			     (!pattern_match(ap, w + aoff, NULL, NULL) ||
+			      (aol && !pattern_match(aop, w + aoff - aol,
+						     NULL, NULL)) ||
+			      !match_parts(l + aoff, w + aoff, alen, part))))
 				continue;
 		    } else if (!both || il || iw)
 			continue;
@@ -566,9 +569,13 @@ match_str(char *l, char *w, Brinfo *bpp, int bc, int *rwlp,
 			 tp += add, ct++, ict--) {
 			if ((both &&
 			     (!ap || !test ||
-			      !pattern_match(ap, tp + aoff, NULL, NULL))) ||
+			      !pattern_match(ap, tp + aoff, NULL, NULL) ||
+			      (aol && !pattern_match(aop, tp + aoff - aol,
+						     NULL, NULL)))) ||
 			    (!both &&
 			     pattern_match(ap, tp - moff, NULL, NULL) &&
+			     (!aol || pattern_match(aop, tp - moff - aol,
+						    NULL, NULL)) &&
 			     match_parts(l + aoff , tp - moff, alen, part))) {
 			    if (sfx) {
 				savw = tp[-zoff];
@@ -699,28 +706,36 @@ match_str(char *l, char *w, Brinfo *bpp, int bc, int *rwlp,
 		    }
 		    if (mp->flags & CMF_LEFT) {
 			/* Try to match the left anchor, if any. */
-			if (til < mp->lalen || tiw < mp->lalen)
+			if (til < mp->lalen || tiw < mp->lalen + mp->ralen)
 			    continue;
 			else if (mp->left)
 			    t = pattern_match(mp->left, tl - mp->lalen,
 					      NULL, NULL) &&
 				pattern_match(mp->left, tw - mp->lalen,
-					      NULL, NULL);
+					      NULL, NULL) &&
+				(!mp->ralen ||
+				 pattern_match(mp->right,
+					       tw - mp->lalen - mp->ralen,
+					       NULL, NULL));
 			else
 			    t = (!sfx && !il && !iw);
 		    }
 		    if (mp->flags & CMF_RIGHT) {
 			/* Try to match the right anchor, if any. */
 			if (tll < mp->llen + mp->ralen ||
-			    tlw < mp->wlen + mp->ralen)
+			    tlw < mp->wlen + mp->ralen + mp->lalen)
 			    continue;
-			else if (mp->left)
+			else if (mp->right)
 			    t = pattern_match(mp->right,
 					      tl + mp->llen - mp->ralen,
 					      NULL, NULL) &&
 				pattern_match(mp->right,
 					      tw + mp->wlen - mp->ralen,
-					      NULL, NULL);
+					      NULL, NULL) &&
+				(!mp->lalen ||
+				 pattern_match(mp->left, tw + mp->wlen -
+					       mp->ralen - mp->lalen,
+					       NULL, NULL));
 			else
 			    t = (sfx && !il && !iw);
 		    }
@@ -1044,8 +1059,11 @@ bld_parts(char *str, int len, int plen, Cline *lp)
 	for (t = 0, ms = bmatchers; ms && !t; ms = ms->next) {
 	    mp = ms->matcher;
 	    if (mp && mp->flags == CMF_RIGHT && mp->wlen < 0 &&
-		!mp->llen && len >= mp->ralen && mp->ralen &&
-		pattern_match(mp->right, str, NULL, NULL)) {
+		!mp->llen && len >= mp->ralen + mp->lalen && mp->ralen &&
+		pattern_match(mp->right, str, NULL, NULL) &&
+		(!mp->lalen ||
+		 ((str - p) >= mp->lalen &&
+		  pattern_match(mp->left, str - mp->lalen, NULL, NULL)))) {
 		int olen = str - p, llen;
 
 		/* We found an anchor, create a new cline. The NEW flag