zsh-workers
 help / color / mirror / code / Atom feed
* unset "hash[key]" isn't matched with what "key" may be
@ 2016-02-07 14:16 Sebastian Gniazdowski
  2016-02-07 19:08 ` Peter Stephenson
  2016-02-07 21:33 ` Bart Schaefer
  0 siblings, 2 replies; 13+ messages in thread
From: Sebastian Gniazdowski @ 2016-02-07 14:16 UTC (permalink / raw)
  To: Zsh hackers list

Hello,
I was testing following plugin:

https://github.com/hchbaw/opp.zsh

It creates functions with sophisticated names, like

opp+aB                               opp+aW
opp+a"                               opp+a'
opp+a(                               opp+a)
opp+a<                               opp+a>
opp+a[                               opp+a]


I had a loop in which I browsed $functions, setting:

                func[$i]=1

where "func" is a hash and "$i" is ${(k)functions}. This worked, however this:

                unset "func[$i]"

yielded:

-zplg-diff-functions:unset:36: func[opp+a\[]: invalid parameter name

Tried ${(q)i}, qq, qqq, qqqq.

Related code:

https://github.com/psprint/zplugin/commit/61a59fe0e2e367b3536fb028f4a36e9730322402

Best regards,
Sebastian Gniazdowski


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

* Re: unset "hash[key]" isn't matched with what "key" may be
  2016-02-07 14:16 unset "hash[key]" isn't matched with what "key" may be Sebastian Gniazdowski
@ 2016-02-07 19:08 ` Peter Stephenson
  2016-02-07 19:10   ` Sebastian Gniazdowski
  2016-02-07 21:33 ` Bart Schaefer
  1 sibling, 1 reply; 13+ messages in thread
From: Peter Stephenson @ 2016-02-07 19:08 UTC (permalink / raw)
  To: Zsh hackers list

On Sun, 7 Feb 2016 15:16:05 +0100
Sebastian Gniazdowski <sgniazdowski@gmail.com> wrote:
> I had a loop in which I browsed $functions, setting:
> 
>                 func[$i]=1
> 
> where "func" is a hash and "$i" is ${(k)functions}. This worked, however this:
> 
>                 unset "func[$i]"

Not sure what you're doing, but it's apparently not equivalent to the
following, which appears to work.  There may be some relevant option,
I suppose.

% i='${(k)functions}'
% typeset -A hash
% hash[$i]=1
% print ${(kv)hash}
${(k)functions} 1
% unset "hash[$i]"
% print ${(kv)hash}
<this line intentionally left blank>

PWS


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

* Re: unset "hash[key]" isn't matched with what "key" may be
  2016-02-07 19:08 ` Peter Stephenson
@ 2016-02-07 19:10   ` Sebastian Gniazdowski
  2016-02-07 19:24     ` Peter Stephenson
  0 siblings, 1 reply; 13+ messages in thread
From: Sebastian Gniazdowski @ 2016-02-07 19:10 UTC (permalink / raw)
  To: Peter Stephenson; +Cc: Zsh hackers list

On 7 February 2016 at 20:08, Peter Stephenson
<p.w.stephenson@ntlworld.com> wrote:
> On Sun, 7 Feb 2016 15:16:05 +0100
> Sebastian Gniazdowski <sgniazdowski@gmail.com> wrote:
>> I had a loop in which I browsed $functions, setting:
>>
>>                 func[$i]=1
>>
>> where "func" is a hash and "$i" is ${(k)functions}. This worked, however this:
>>
>>                 unset "func[$i]"
>
> Not sure what you're doing, but it's apparently not equivalent to the
> following, which appears to work.  There may be some relevant option,
> I suppose.
>
> % i='${(k)functions}'

Sorry, by:

>> where "func" is a hash and "$i" is ${(k)functions}. This worked, however this:

I meant that "$i" iterates over keys of $functions

Best regards,
Sebastian Gniazdowski


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

* Re: unset "hash[key]" isn't matched with what "key" may be
  2016-02-07 19:10   ` Sebastian Gniazdowski
@ 2016-02-07 19:24     ` Peter Stephenson
  0 siblings, 0 replies; 13+ messages in thread
From: Peter Stephenson @ 2016-02-07 19:24 UTC (permalink / raw)
  To: Zsh hackers list

On Sun, 7 Feb 2016 20:10:48 +0100
Sebastian Gniazdowski <sgniazdowski@gmail.com> wrote:
> I meant that "$i" iterates over keys of $functions

Ah, you mean

% i='opp+a[' 
% function 'opp+a[' { print Hi; }
% 'opp+a['
Hi
% unset "function[$i]"
unset: function[opp+a[]: invalid parameter name

That's because i is expanded first, so the brackets get confused.  So
you might expect

i='opp+a\['

to work to compensate, but it doesn't.  Nor does

unset 'function[$i]'

since there's no later expansion.

No, I can't see an obvious answer either, and it's not specific to
$functions, it happens with an ordinary hash.   It's not actually clear
to me what the right answer should be.  Somehow you need to make the
key stand out from the surrounding syntax.  Allowing backslash quoting,
which was the next guess, might be the asnswer, but see
http://xkcd.com/1638 for commentary on backslashes.

pws


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

* Re: unset "hash[key]" isn't matched with what "key" may be
  2016-02-07 14:16 unset "hash[key]" isn't matched with what "key" may be Sebastian Gniazdowski
  2016-02-07 19:08 ` Peter Stephenson
@ 2016-02-07 21:33 ` Bart Schaefer
  2016-02-08  7:05   ` Bart Schaefer
  2016-02-15  7:48   ` Sebastian Gniazdowski
  1 sibling, 2 replies; 13+ messages in thread
From: Bart Schaefer @ 2016-02-07 21:33 UTC (permalink / raw)
  To: Zsh hackers list

[I see PWS has already responded while I was trying to work out what the
code is doing.  Here's what I've written so far, maybe I can come up with
a patch in a bit longer.]

On Feb 7,  3:16pm, Sebastian Gniazdowski wrote:
}
} I was testing following plugin:
} 
} https://github.com/hchbaw/opp.zsh

Which incidentally says (README.md) it is obsolete for zsh >= 5.0.8.

} It creates functions with sophisticated names, like
} 
} opp+a(                               opp+a)
} opp+a<                               opp+a>
} opp+a[                               opp+a]

Ooh, interesting.  Making use of the side-effect that you can give a
ZLE widget a function name that can't normally be typed unquoted on a
command line.  Kinky.

}                 unset "func[$i]"
} 
} yielded:
} 
} -zplg-diff-functions:unset:36: func[opp+a\[]: invalid parameter name

Yep, "unset" is pretty naive about parsing the subscript there.  It wants
the square brackets in balanced pairs and doesn't consider any kind of
quoting.  (The -m option also doesn't work for subscripts.)

For whatever it's worth, this doesn't work in ksh either (at least as of

$ print $KSH_VERSION
Version JM 93u 2011-02-08

) although the error isn't printed in the exact same circumstances; in
some cases it just silently fails:

$ y='['
$ ary=([$y]=1)
$ typeset -p ary
typeset -A ary=(['[']=1)
$ unset ary[$y]
$ typeset -p ary
typeset -A ary=(['[']=1)
$ ary[x]=1
$ typeset -p ary
typeset -A ary=(['[']=1 [x]=1)
$ unset ary[x]
$ typeset -p ary
typeset -A ary=(['[']=1)
$ unset "ary['[']"   
ksh: unset: ary['[']: invalid variable name
$ unset ary[\[]
$ typeset -p ary
typeset -A ary=(['[']=1)
$ 


-- 
Barton E. Schaefer


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

* Re: unset "hash[key]" isn't matched with what "key" may be
  2016-02-07 21:33 ` Bart Schaefer
@ 2016-02-08  7:05   ` Bart Schaefer
  2016-02-09  4:54     ` Bart Schaefer
  2016-02-15  7:48   ` Sebastian Gniazdowski
  1 sibling, 1 reply; 13+ messages in thread
From: Bart Schaefer @ 2016-02-08  7:05 UTC (permalink / raw)
  To: Zsh hackers list

On Feb 7,  1:33pm, Bart Schaefer wrote:
}
} On Feb 7,  3:16pm, Sebastian Gniazdowski wrote:
} }                 unset "func[$i]"
} } -zplg-diff-functions:unset:36: func[opp+a\[]: invalid parameter name
} 
} Yep, "unset" is pretty naive about parsing the subscript there.  It wants
} the square brackets in balanced pairs and doesn't consider any kind of
} quoting.

Patch below for consideration.  This doesn't do any additional expansion,
but it has the effect of allowing backslash-quoting -- which therefore
requires that backslashes themselves be doubled, cf. all the caveats
about subscripts behaving as if double-quoted that appear elsewhere.

After this patch, the best way to handle unset of associative array
elements looks something like

  typeset -A ary
  ary[${key}]=value
  ...
  unset "ary[${(b)key}]"

(or use "noglob" instead of double quotes).

This does reflect a change from previous behavior, so we'll want to
consider it carefully.  If we decide to keep the old behavior, just
remove the call to remnulargs().  I think using parse_subscript() intead
of skipcomm() is still the more sensible approach; in fact, this patch
revealed an error in the E01 test script.

} (The -m option also doesn't work for subscripts.)

I haven't attempted to do anything about that, and I'm not sure that it
makes sense to.


diff --git a/Src/builtin.c b/Src/builtin.c
index 63f964d..4c8fbcd 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -3350,15 +3350,24 @@ bin_unset(char *name, char **argv, Options ops, int func)
     /* do not glob -- unset the given parameter */
     queue_signals();
     while ((s = *argv++)) {
-	char *ss = strchr(s, '[');
-	char *sse = ss;
+	char *ss = strchr(s, '['), *subscript = 0;
 	if (ss) {
-	    if (skipparens('[', ']', &sse) || *sse) {
-		zerrnam(name, "%s: invalid parameter name", s);
-		returnval = 1;
-		continue;
-	    }
+	    char *sse;
 	    *ss = 0;
+	    if ((sse = parse_subscript(ss+1, 1, ']'))) {
+		*sse = 0;
+		subscript = dupstring(ss+1);
+		*sse = ']';
+		remnulargs(subscript);
+		untokenize(subscript);
+	    }
+	}
+	if ((ss && !subscript) || !isident(s)) {
+	    if (ss)
+		*ss = '[';
+	    zerrnam(name, "%s: invalid parameter name", s);
+	    returnval = 1;
+	    continue;
 	}
 	pm = (Param) (paramtab == realparamtab ?
 		      /* getnode2() to avoid autoloading */
@@ -3376,11 +3385,8 @@ bin_unset(char *name, char **argv, Options ops, int func)
 	} else if (ss) {
 	    if (PM_TYPE(pm->node.flags) == PM_HASHED) {
 		HashTable tht = paramtab;
-		if ((paramtab = pm->gsu.h->getfn(pm))) {
-		    *--sse = 0;
-		    unsetparam(ss+1);
-		    *sse = ']';
-		}
+		if ((paramtab = pm->gsu.h->getfn(pm)))
+		    unsetparam(subscript);
 		paramtab = tht;
 	    } else if (PM_TYPE(pm->node.flags) == PM_SCALAR ||
 		       PM_TYPE(pm->node.flags) == PM_ARRAY) {
diff --git a/Test/E01options.ztst b/Test/E01options.ztst
index f270767..40e96af 100644
--- a/Test/E01options.ztst
+++ b/Test/E01options.ztst
@@ -776,7 +776,7 @@
   unsetopt pathdirs
   pathtestdir/findme
   path=($oldpath)
-  unset $oldpath
+  unset oldpath
   rm -rf pdt_topdir pathtestdir
 0:PATH_DIRS option
 >File in upper dir


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

* Re: unset "hash[key]" isn't matched with what "key" may be
  2016-02-08  7:05   ` Bart Schaefer
@ 2016-02-09  4:54     ` Bart Schaefer
  2016-02-09  8:53       ` Peter Stephenson
  0 siblings, 1 reply; 13+ messages in thread
From: Bart Schaefer @ 2016-02-09  4:54 UTC (permalink / raw)
  To: Zsh hackers list

On Feb 7, 11:05pm, Bart Schaefer wrote:
}
} This does reflect a change from previous behavior, so we'll want to
} consider it carefully.

Since no one commented to the contrary, I've pushed this so we can get
some additional experience with it.


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

* Re: unset "hash[key]" isn't matched with what "key" may be
  2016-02-09  4:54     ` Bart Schaefer
@ 2016-02-09  8:53       ` Peter Stephenson
  2016-02-09 15:50         ` Bart Schaefer
  0 siblings, 1 reply; 13+ messages in thread
From: Peter Stephenson @ 2016-02-09  8:53 UTC (permalink / raw)
  To: Zsh hackers list

On Mon, 08 Feb 2016 20:54:18 -0800
Bart Schaefer <schaefer@brasslantern.com> wrote:
> On Feb 7, 11:05pm, Bart Schaefer wrote:
> }
> } This does reflect a change from previous behavior, so we'll want to
> } consider it carefully.
> 
> Since no one commented to the contrary, I've pushed this so we can get
> some additional experience with it.

The old code is clearly unusable for some characters in the key, so a
change of some sort is warranted.

All that occurred to me was an additional option to provoke an extra
expansion step on the argument after locating the brackets.

  unset -? 'hash[$i]'

would then be reliable.  If the extra backslash stripping occurred early
enough it wouldn't get in the way.

pws


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

* Re: unset "hash[key]" isn't matched with what "key" may be
  2016-02-09  8:53       ` Peter Stephenson
@ 2016-02-09 15:50         ` Bart Schaefer
  2016-02-09 16:19           ` Peter Stephenson
  0 siblings, 1 reply; 13+ messages in thread
From: Bart Schaefer @ 2016-02-09 15:50 UTC (permalink / raw)
  To: Zsh hackers list

On Feb 9,  8:53am, Peter Stephenson wrote:
} Subject: Re: unset "hash[key]" isn't matched with what "key" may be
}
} All that occurred to me was an additional option to provoke an extra
} expansion step on the argument after locating the brackets.
} 
}   unset -? 'hash[$i]'
} 
} would then be reliable.  If the extra backslash stripping occurred early
} enough it wouldn't get in the way.

So what magic makes this work for typeset?

torch% typeset -A foo
torch% x='['
torch% typeset "foo[$x]"     
zsh: not an identifier: foo[[]
torch% typeset 'foo[$x]'		<-- note here
torch% typeset -p foo
typeset -A foo=( '[' '' )
torch% 

Or perhaps an equally interesting question is, is that behavior in fact
incorrect and typeset shouldn't do it either?

Ksh:

$ x='['
$ typeset -A foo
$ typeset "foo[$x]"
ksh: typeset: foo[[]: invalid variable name
$ typeset foo[$x]				<-- not an error?
$ typeset -p foo
typeset -A foo=(['[]']=)			<-- but weird
$ typeset 'foo[$x]'
$ typeset -p foo
typeset -A foo=(['$x']= ['[]']=)		<-- no expansion
$ 



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

* Re: unset "hash[key]" isn't matched with what "key" may be
  2016-02-09 15:50         ` Bart Schaefer
@ 2016-02-09 16:19           ` Peter Stephenson
  2016-02-09 18:07             ` Bart Schaefer
  0 siblings, 1 reply; 13+ messages in thread
From: Peter Stephenson @ 2016-02-09 16:19 UTC (permalink / raw)
  To: Zsh hackers list

On Tue, 09 Feb 2016 07:50:50 -0800
Bart Schaefer <schaefer@brasslantern.com> wrote:
> So what magic makes this work for typeset?
> 
> torch% typeset -A foo
> torch% x='['
> torch% typeset "foo[$x]"     
> zsh: not an identifier: foo[[]
> torch% typeset 'foo[$x]'		<-- note here

getindex() does parse_subcript(); later getarg() looks for tokens and if
it finds any calls singsub().  "unset" doesn't have any of this
sophistication.

pws


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

* Re: unset "hash[key]" isn't matched with what "key" may be
  2016-02-09 16:19           ` Peter Stephenson
@ 2016-02-09 18:07             ` Bart Schaefer
  0 siblings, 0 replies; 13+ messages in thread
From: Bart Schaefer @ 2016-02-09 18:07 UTC (permalink / raw)
  To: Zsh hackers list

On Feb 9,  4:19pm, Peter Stephenson wrote:
}
} getindex() does parse_subcript(); later getarg() looks for tokens and
} if it finds any calls singsub(). "unset" doesn't have any of this
} sophistication.

Hmm.  For a normal array:

torch% x=3
torch% typeset 'foo[$x]'=1
torch% typeset -p foo
typeset -a foo=( '' '' 1 )
torch% unset 'foo[$x]'			<-- Note
torch% typeset -p foo
typeset -a foo=( '' '' '' )
torch% 

It didn't actually delete the element, but it did *something*.  (*Should*
it delete the element, as long as we're considering messing with this?)


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

* Re: unset "hash[key]" isn't matched with what "key" may be
  2016-02-07 21:33 ` Bart Schaefer
  2016-02-08  7:05   ` Bart Schaefer
@ 2016-02-15  7:48   ` Sebastian Gniazdowski
  2016-02-15 13:26     ` Nikolay Aleksandrovich Pavlov (ZyX)
  1 sibling, 1 reply; 13+ messages in thread
From: Sebastian Gniazdowski @ 2016-02-15  7:48 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: Zsh hackers list

On 7 February 2016 at 22:33, Bart Schaefer <schaefer@brasslantern.com> wrote:
> [I see PWS has already responded while I was trying to work out what the
> code is doing.  Here's what I've written so far, maybe I can come up with
> a patch in a bit longer.]
>
> On Feb 7,  3:16pm, Sebastian Gniazdowski wrote:
> }
> } I was testing following plugin:
> }
> } https://github.com/hchbaw/opp.zsh
>
> Which incidentally says (README.md) it is obsolete for zsh >= 5.0.8.

Which is rather a public suicide than the truth. I didn't seen any
functionality in Zsh >= 5.0.8 that would allow to jump between opening
and closing parentheses with "%" key.

Best regards,
Sebastian Gniazdowski


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

* Re: unset "hash[key]" isn't matched with what "key" may be
  2016-02-15  7:48   ` Sebastian Gniazdowski
@ 2016-02-15 13:26     ` Nikolay Aleksandrovich Pavlov (ZyX)
  0 siblings, 0 replies; 13+ messages in thread
From: Nikolay Aleksandrovich Pavlov (ZyX) @ 2016-02-15 13:26 UTC (permalink / raw)
  To: Sebastian Gniazdowski, Bart Schaefer; +Cc: Zsh hackers list



15.02.2016, 10:49, "Sebastian Gniazdowski" <sgniazdowski@gmail.com>:
> On 7 February 2016 at 22:33, Bart Schaefer <schaefer@brasslantern.com> wrote:
>>  [I see PWS has already responded while I was trying to work out what the
>>  code is doing. Here's what I've written so far, maybe I can come up with
>>  a patch in a bit longer.]
>>
>>  On Feb 7, 3:16pm, Sebastian Gniazdowski wrote:
>>  }
>>  } I was testing following plugin:
>>  }
>>  } https://github.com/hchbaw/opp.zsh
>>
>>  Which incidentally says (README.md) it is obsolete for zsh >= 5.0.8.
>
> Which is rather a public suicide than the truth. I didn't seen any
> functionality in Zsh >= 5.0.8 that would allow to jump between opening
> and closing parentheses with "%" key.

I have zsh-5.1.1 and it works with `bindkey -v`. This is vi-match-bracket widget that is bound to `%` in vicmd keymap.

>
> Best regards,
> Sebastian Gniazdowski


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

end of thread, other threads:[~2016-02-15 13:32 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-02-07 14:16 unset "hash[key]" isn't matched with what "key" may be Sebastian Gniazdowski
2016-02-07 19:08 ` Peter Stephenson
2016-02-07 19:10   ` Sebastian Gniazdowski
2016-02-07 19:24     ` Peter Stephenson
2016-02-07 21:33 ` Bart Schaefer
2016-02-08  7:05   ` Bart Schaefer
2016-02-09  4:54     ` Bart Schaefer
2016-02-09  8:53       ` Peter Stephenson
2016-02-09 15:50         ` Bart Schaefer
2016-02-09 16:19           ` Peter Stephenson
2016-02-09 18:07             ` Bart Schaefer
2016-02-15  7:48   ` Sebastian Gniazdowski
2016-02-15 13:26     ` Nikolay Aleksandrovich Pavlov (ZyX)

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).