zsh-workers
 help / color / mirror / code / Atom feed
* Re:  Associative array ordering and selective unset (Re: Example function)
@ 1999-02-02  7:52 Sven Wischnowsky
  1999-02-02 11:10 ` PATCH: 3.1.5-pws-6: unset assoc[key] Bart Schaefer
  0 siblings, 1 reply; 8+ messages in thread
From: Sven Wischnowsky @ 1999-02-02  7:52 UTC (permalink / raw)
  To: zsh-workers


Bart Schaefer wrote:

> ...
> 
> We could go the ksh route and make `noglob unset foo[key]` work.  Like:
> 
> 	function unset() {
> 	    emulate -R zsh
> 	    setopt localoptions extendedglob
> 	    local arg i
> 	    for i
> 	    do
> 		arg=( "${(@s:[:)i}" )
> 		if [[ $#arg > 1 &&
> 		    $(eval print '${(t)'${arg[1]}'}') == association ]]
> 		then
> 		    eval "$arg[1]=( \${(kv)$arg[1][(I)^${(j:[:)arg[2,-1]} )"
> 		else
> 		    builtin unset $i
> 		fi
> 	    done
> 	}

Since even `vared' can now understand the subscripted syntax, I think
adding this to unset (even in C) would be a good thing. (I'm pretty
sure people will want to have a easy way to remove key/value-pairs
from associative arrays).

> Can you think of a better idiom than $(eval print '${(t)'${arg[1]}'}') to
> get the type of the variable whose name is the value of $arg[1] ?  I keep
> thinking there ought to be a way with ${(e)...} but couldn't make it work.

When implementing the new completion example stuff I was somewhat
irritated that there is no easy way to get the value of a parameter of 
which one only has the name in another parameter. Trying to get the
type of that parameter is indeed even more complicated.

Hm, `(e)' is used at the very end and I wouldn't like to change
that. Maybe yet another flag? E.g.: `P' makes the thing after the
flags be used as the name of a parameter. So `${(P)foo}' is the same
as `$foo', but `${(P)${foo}}' will take the value of `foo' as the name 
of a parameter and work on it. So your example would become:

  if [[ $#arg > 1 && ${(Pt)${argv[1]}} == association ]] ...

Looking at the code this doesn't seem too hard to implement (well, I
said `seem'...).

Bye
 Sven


--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


^ permalink raw reply	[flat|nested] 8+ messages in thread
* Re:  Associative array ordering and selective unset (Re: Example function)
@ 1999-02-02 16:58 Sven Wischnowsky
  0 siblings, 0 replies; 8+ messages in thread
From: Sven Wischnowsky @ 1999-02-02 16:58 UTC (permalink / raw)
  To: zsh-workers


I wrote:

> Maybe yet another flag? E.g.: `P' makes the thing after the
> flags be used as the name of a parameter. So `${(P)foo}' is the same
> as `$foo', but `${(P)${foo}}' will take the value of `foo' as the name 
> of a parameter and work on it. So your example would become:
> 
>   if [[ $#arg > 1 && ${(Pt)${argv[1]}} == association ]] ...

The patch below does this (it was quite easy). With it you can do
things like the above or `${(P)+${foo}}' to see if the parameter whose 
name is stored in `foo' is set. If the inner `${...}' produces
multiple words they are joind using IFS which will result in an
invalid parameter name (which is reported as being unset). Maybe we
should make the code test if it is a valid name and barf otherwise. Or 
we could use only the first word. Any other suggestions?

But I don't know if you like this anyway...

The patch also changes the docs and the new-completion-examples.

Bye
 Sven

--- os/subst.c	Mon Feb  1 10:53:56 1999
+++ Src/subst.c	Tue Feb  2 17:27:50 1999
@@ -718,10 +718,12 @@
     int copied = 0;
     int arrasg = 0;
     int eval = 0;
+    int aspar = 0;
     int nojoin = 0;
     char inbrace = 0;		/* != 0 means ${...}, otherwise $... */
     char hkeys = 0;
     char hvals = 0;
+    int subexp;
 
     *s++ = '\0';
     if (!ialnum(*s) && *s != '#' && *s != Pound && *s != '-' &&
@@ -813,6 +815,9 @@
 		case 'e':
 		    eval = 1;
 		    break;
+		case 'P':
+		    aspar = 1;
+		    break;
 
 		case 'c':
 		    whichlen = 1;
@@ -949,7 +954,8 @@
 	    } else
 		globsubst = 1;
 	} else if (*s == '+') {
-	    if (iident(s[1]))
+	    if (iident(s[1]) || (aspar && isstring(s[1]) &&
+				 (s[2] == Inbrace || s[2] == Inpar)))
 		chkset = 1, s++;
 	    else if (!inbrace) {
 		*aptr = '$';
@@ -965,7 +971,8 @@
     globsubst = globsubst && !qt;
 
     idbeg = s;
-    if (s[-1] && isstring(*s) && (s[1] == Inbrace || s[1] == Inpar)) {
+    if ((subexp = (s[-1] && isstring(*s) &&
+		   (s[1] == Inbrace || s[1] == Inpar)))) {
 	int sav;
 	int quoted = *s == Qstring;
 
@@ -973,17 +980,22 @@
 	skipparens(*s, *s == Inpar ? Outpar : Outbrace, &s);
 	sav = *s;
 	*s = 0;
-	if (multsub(&val, &aval, &isarr, NULL) && quoted) {
+	if (multsub(&val, (aspar ? NULL : &aval), &isarr, NULL) && quoted) {
 	    isarr = -1;
 	    aval = alloc(sizeof(char *));
-	}
+	    aspar = 0;
+	} else if (aspar)
+	    idbeg = val;
 	if (isarr)
 	    isarr = -1;
 	copied = 1;
 	*s = sav;
 	v = (Value) NULL;
-    } else {
-	if (!(v = fetchvalue(&s, (wantt ? -1 :
+    }
+    if (!subexp || aspar) {
+	char *ov = val;
+
+	if (!(v = fetchvalue((subexp ? &ov : &s), (wantt ? -1 :
 				  ((unset(KSHARRAYS) || inbrace) ? 1 : -1)),
 			     hkeys|hvals)))
 	    vunset = 1;
--- od/Zsh/expn.yo	Mon Feb  1 10:53:36 1999
+++ Doc/Zsh/expn.yo	Tue Feb  2 17:51:35 1999
@@ -477,9 +477,10 @@
 pindex(GLOB_SUBST)
 Turn on the tt(GLOB_SUBST) option for the evaluation of
 var(spec); if the `tt(~)' is doubled, turn it off.  When this option is
-set, any pattern characters resulting
-from parameter expansion are eligible for filename expansion and filename
-generation.
+set, the string resulting from the expansion will be interpreted as a
+pattern thus becoming eligible for filename expansion and filename
+generation and usable as a pattern in pattern-matching contexts like
+the `tt(=)' and `tt(!=)' operators in conditions.
 )
 enditem()
 
@@ -522,6 +523,15 @@
 Perform em(parameter expansion), em(command substitution) and
 em(arithmetic expansion) on the result. Such expansions can be
 nested but too deep recursion may have unpredictable effects.
+)
+item(tt(P))(
+If used with a parameter name, this flag has no effect. But if it is
+used with a tt(${)...tt(}) type parameter expression or a
+tt($LPAR())...tt(RPAR()) type command substitution in place of
+the parameter name this flag makes the result of the expansion be
+taken as a parameter name which is then used. E.g. if you have
+`tt(foo=bar)' and `tt(bar=baz)', the string `tt(${(P)${foo}})' will be 
+expanded to `tt(baz)'.
 )
 item(tt(o))(
 Sort the resulting words in ascending order.
diff -u om/new-completion-examples Misc/new-completion-examples
--- om/new-completion-examples	Mon Feb  1 10:53:27 1999
+++ Misc/new-completion-examples	Tue Feb  2 17:43:34 1999
@@ -75,11 +75,8 @@
 # the arguments from the command line as its arguments.
 
 call-complete() {
-  local var
-
-  eval var\=\$\{\+$1\}
-  if (( var )); then
-    eval complist \$\{${1}\[\@\]\}
+  if [[ ${(P)+${1}} -eq 1 ]] then
+    complist ${(@P)${1}}
   else
     "$@"
   fi
@@ -96,15 +93,6 @@
   setopt localoptions nullglob rcexpandparam globdots
   unsetopt markdirs globsubst shwordsplit nounset
 
-  # We first try the `compctl's. This is without first (-T) and default (-D)
-  # completion. If you want them add `-T' and/or `-D' to this command.
-  # If this produces any matches, we don't try new style completion. If you
-  # want to have that tried anyway, remove the `[[ -nmatches ... ]] ...'
-  # below.
-
-  compcall
-  [[ -nmatches 0 ]] || return
-
   # An entry for `--first--' is the replacement for `compctl -T'
   # The `|| return 1' is used throughout: if a function producing matches
   # returns non-zero this is interpreted as `do not try to produce more matches'
@@ -117,6 +105,15 @@
   # convenience alias `compsub'.
 
   if [[ $CONTEXT == argument || $CONTEXT == command ]] then
+    # We first try the `compctl's. This is without first (-T) and default (-D)
+    # completion. If you want them add `-T' and/or `-D' to this command.
+    # If this produces any matches, we don't try new style completion. If you
+    # want to have that tried anyway, remove the `[[ -nmatches ... ]] ...'
+    # below.
+
+    compcall
+    [[ -nmatches 0 ]] || return
+
     compsub
   else
     # Let's see if we have a special completion definition for the other
@@ -205,7 +202,7 @@
     if [[ "$a[1]" = '(' ]] then
       ppres=( $a[2,-2]/ )
     else
-      eval ppres\=\( \$$a/ \)
+      ppres=( ${(P)${a}} )
       [[ $#ppres -eq 0 ]] && ppres=( $a/ )
     fi
     [[ $#ppres -eq 0 ]] && ppres=( '' )
@@ -329,11 +326,8 @@
 
 defcomp __subscr --subscr--
 __subscr() {
-  local t
-
-  eval t\=\$\{\(t\)$COMMAND\}
   compalso --math-- "$@"
-  [[ $t = assoc* ]] && eval complist -k \"\(\$\{\(k\)$COMMAND\}\)\"
+  [[ ${(Pt)${COMMAND}} = assoc* ]] && complist -k "( ${(kP)${COMMAND}} )"
 }
 
 # Do sub-completion for pre-command modifiers.

--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


^ permalink raw reply	[flat|nested] 8+ messages in thread
* Re: Associative array ordering and selective unset (Re: Example function)
@ 1999-02-02  8:01 Sven Wischnowsky
  0 siblings, 0 replies; 8+ messages in thread
From: Sven Wischnowsky @ 1999-02-02  8:01 UTC (permalink / raw)
  To: zsh-workers


Bart Schaefer wrote:

> (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.)
> 
> Now change the assignment a little:
> 
>         map=('*.(gz|Z)' ': 1; zcat
>              '*.bz2' ': 2; bzip2 -dc'
>              '*.bz' ': 3; bzip -dc'
>              '*' ': 4; <')
> 
> Now we can use the (o) substitution flag like so:
> 
> 	eval ${${(o)map[(Q)$argv[i]]}[1]} '$argv[i]'
> 
> That says "find all the values for which the key is a pattern that matches
> $argv[i], sort them in ascending order, take the first one, and evaluate
> it as a command with argument $argv[i]."  By embedding the "preferred"
> ordering in the value as a leading ":" command, we're assured of always
> getting the most-specific match.

Hmm, I like this. For bigger arrays one would have to use `01' and so
on, but this should be acceptible.

Bye
 Sven


--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


^ permalink raw reply	[flat|nested] 8+ messages in thread
* Re: Example function
@ 1999-02-01 10:48 Sven Wischnowsky
  1999-02-01 17:02 ` Associative array ordering and selective unset (Re: Example function) Bart Schaefer
  0 siblings, 1 reply; 8+ messages in thread
From: Sven Wischnowsky @ 1999-02-01 10:48 UTC (permalink / raw)
  To: zsh-workers


Bart Schaefer wrote:

> (One of the things on the associative-array wishlist is "reverse pattern"
> lookup, that is, treat the array keys as patterns and match them against
> the subscript.  Then you could do silly stuff like
> 
> 	typeset -A map
> 	map=('*.(gz|Z)'	zcat
> 	     '*.bz2' 'bzip2 -dc'
> 	     '*.bz' 'bzip -dc'
> 	     '*' '<')
> 	eval ${(q)map[$argv[i]]} '$argv[i]'
> 
> where I'm using (q) as the fictional reverse-pattern query flag; probably
> there's a better letter.)
> 
> Incidentally, the reason this isn't there already is that associative arrays
> are unordered hashes, so you can't predict _which_ pattern will match the
> subscript when you do the query -- '*' might match before '*.bz' is tried.

I was thinking about this... we could make the code keep a counter in
assoc arrays, increment it whenever a new key is added and store the
current value in the structure for this new element. Then we can treat 
the whole thing as being sorted by `time of addition'.

Hm, does this sound like the right thing?

Bye
 Sven

P.S.: Is `foo=( ${(kv)foo[(I)^key]} )' the easiest way to remove a
      key/value-pair from an associative array?

--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~1999-02-02 20:07 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1999-02-02  7:52 Associative array ordering and selective unset (Re: Example function) Sven Wischnowsky
1999-02-02 11:10 ` PATCH: 3.1.5-pws-6: unset assoc[key] Bart Schaefer
  -- strict thread matches above, loose matches on Subject: below --
1999-02-02 16:58 Associative array ordering and selective unset (Re: Example function) Sven Wischnowsky
1999-02-02  8:01 Sven Wischnowsky
1999-02-01 10:48 Example function Sven Wischnowsky
1999-02-01 17:02 ` Associative array ordering and selective unset (Re: Example function) Bart Schaefer
1999-02-01 17:39   ` Bruce Stephens
1999-02-01 19:09     ` Bart Schaefer
1999-02-02 20:07   ` Phil Pennock

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).