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

PATCH: Re: Associative array ordering and selective unset (Re: Example function)



Bart Schaefer wrote (in 5156, hah!):

> I just thought of a really clever way to do the specific example that I
> gave.  Assume for a moment that the (q) modifier were implemented, i.e.
> that (almost repeating the original example) given
> 
>         typeset -A map
>         map=('*.(gz|Z)' zcat
>              '*.bz2' 'bzip2 -dc'
>              '*.bz' 'bzip -dc'
>              '*' '<')
> 
> then ${map[(q)$argv[i]]} returns the value for the first subscript match
> found, and ${map[(Q)$argv[i]]} returns the array of values for every key
> that matches the subscript.
> 
> (Note that I moved the (qQ) into the subscript flags, which is probably
> where it really has to be.  And I still hope for a better letter.)

This implements that -- but uses the characters `k' and `K' although I 
don't know if this is better.

I hope I tested everything important this time (it seemed so
simple). But it seems to work and `(k)' is as useless as expected.

The manual entry may be a bit short...

Bye
 Sven

diff -u oldsrc/params.c Src/params.c
--- oldsrc/params.c	Thu Oct 14 13:41:49 1999
+++ Src/params.c	Thu Oct 14 16:16:42 1999
@@ -359,6 +359,7 @@
 }
 
 static Patprog scanprog;
+static char *scanstr;
 static char **paramvals;
 
 /**/
@@ -366,12 +367,20 @@
 scanparamvals(HashNode hn, int flags)
 {
     struct value v;
-    if (numparamvals && (flags & (SCANPM_MATCHVAL|SCANPM_MATCHKEY)) &&
-	!(flags & SCANPM_MATCHMANY))
+    Patprog prog;
+
+    if (numparamvals && !(flags & SCANPM_MATCHMANY) &&
+	(flags & (SCANPM_MATCHVAL|SCANPM_MATCHKEY|SCANPM_KEYMATCH)))
 	return;
     v.pm = (Param)hn;
-    if ((flags & SCANPM_MATCHKEY) &&
-	!pattry(scanprog, v.pm->nam)) {
+    if ((flags & SCANPM_KEYMATCH)) {
+	char *tmp = dupstring(v.pm->nam);
+
+	tokenize(tmp);
+
+	if (!(prog = patcompile(tmp, 0, NULL)) || !pattry(prog, scanstr))
+	    return;
+    } else if ((flags & SCANPM_MATCHKEY) && !pattry(scanprog, v.pm->nam)) {
 	return;
     }
     if (flags & SCANPM_WANTKEYS) {
@@ -736,9 +745,10 @@
 getarg(char **str, int *inv, Value v, int a2, zlong *w)
 {
     int hasbeg = 0, word = 0, rev = 0, ind = 0, down = 0, l, i, ishash;
+    int keymatch = 0;
     char *s = *str, *sep = NULL, *t, sav, *d, **ta, **p, *tt;
     zlong num = 1, beg = 0, r = 0;
-    Patprog pprog;
+    Patprog pprog = NULL;
 
     ishash = (v->pm && PM_TYPE(v->pm->flags) == PM_HASHED);
 
@@ -750,18 +760,29 @@
 	    switch (*s) {
 	    case 'r':
 		rev = 1;
-		down = ind = 0;
+		keymatch = down = ind = 0;
 		break;
 	    case 'R':
 		rev = down = 1;
+		keymatch = ind = 0;
+		break;
+	    case 'k':
+		keymatch = ishash;
+		rev = 1;
+		down = ind = 0;
+		break;
+	    case 'K':
+		keymatch = ishash;
+		rev = down = 1;
 		ind = 0;
 		break;
 	    case 'i':
 		rev = ind = 1;
-		down = 0;
+		down = keymatch = 0;
 		break;
 	    case 'I':
 		rev = ind = down = 1;
+		keymatch = 0;
 		break;
 	    case 'w':
 		/* If the parameter is a scalar, then make subscription *
@@ -818,7 +839,7 @@
 	    default:
 	      flagerr:
 		num = 1;
-		word = rev = ind = down = 0;
+		word = rev = ind = down = keymatch = 0;
 		sep = NULL;
 		s = *str - 1;
 	    }
@@ -841,7 +862,7 @@
 		v->isarr &= ~SCANPM_WANTVALS;
 	    } else if (rev)
 		v->isarr |= SCANPM_WANTVALS;
-	    if (!down && ishash)
+	    if (!down && !keymatch && ishash)
 		v->isarr &= ~SCANPM_MATCHMANY;
 	}
 	*inv = ind;
@@ -938,13 +959,16 @@
 	}
 	tokenize(s);
 
-	if ((pprog = patcompile(s, 0, NULL))) {
+	if (keymatch || (pprog = patcompile(s, 0, NULL))) {
 	    int len;
 
 	    if (v->isarr) {
 		if (ishash) {
 		    scanprog = pprog;
-		    if (ind)
+		    scanstr = s;
+		    if (keymatch)
+			v->isarr |= SCANPM_KEYMATCH;
+		    else if (ind)
 			v->isarr |= SCANPM_MATCHKEY;
 		    else
 			v->isarr |= SCANPM_MATCHVAL;
@@ -952,7 +976,8 @@
 			v->isarr |= SCANPM_MATCHMANY;
 		    if ((ta = getvaluearr(v)) &&
 			(*ta || ((v->isarr & SCANPM_MATCHMANY) &&
-				 (v->isarr & (SCANPM_MATCHKEY | SCANPM_MATCHVAL))))) {
+				 (v->isarr & (SCANPM_MATCHKEY | SCANPM_MATCHVAL |
+					      SCANPM_KEYMATCH))))) {
 			*inv = v->inv;
 			*w = v->b;
 			return 1;
@@ -1131,7 +1156,8 @@
 		s++;
 		if (v->isarr && a == b && 
 		    (!(v->isarr & SCANPM_MATCHMANY) ||
-		     !(v->isarr & (SCANPM_MATCHKEY | SCANPM_MATCHVAL))))
+		     !(v->isarr & (SCANPM_MATCHKEY | SCANPM_MATCHVAL |
+				   SCANPM_KEYMATCH))))
 		    v->isarr = 0;
 		v->a = a;
 		v->b = b;
diff -u oldsrc/zsh.h Src/zsh.h
--- oldsrc/zsh.h	Thu Oct 14 13:41:51 1999
+++ Src/zsh.h	Thu Oct 14 15:25:46 1999
@@ -1086,6 +1086,7 @@
 #define SCANPM_MATCHVAL   (1<<4)
 #define SCANPM_MATCHMANY  (1<<5)
 #define SCANPM_ASSIGNING  (1<<6)
+#define SCANPM_KEYMATCH   (1<<7)
 #define SCANPM_ISVAR_AT   ((-1)<<15)	/* Only sign bit is significant */
 
 /*
diff -u olddoc/Zsh/params.yo Doc/Zsh/params.yo
--- olddoc/Zsh/params.yo	Thu Oct 14 13:42:07 1999
+++ Doc/Zsh/params.yo	Thu Oct 14 16:21:16 1999
@@ -139,6 +139,17 @@
 Like `tt(r)', but gives the last match.  For associative arrays, gives
 all possible matches.
 )
+item(tt(k))(
+If used in a subscript on a parameter that is not an associative
+array, this behaves like `tt(r)', but if used on an association, it
+makes the keys be interpreted as patterns and returns the first value
+whose key matches the var(exp).
+)
+item(tt(K))(
+On an associtation this is like `tt(k)' but returns all values whose
+keys match the var(exp). On other types of parameters this has the
+same effect as `tt(R)'.
+)
 item(tt(i))(
 like `tt(r)', but gives the index of the match instead; this may not
 be combined with a second argument.  For associative arrays, the key

--
Sven Wischnowsky                         wischnow@xxxxxxxxxxxxxxxxxxxxxxx



Messages sorted by: Reverse Date, Date, Thread, Author