zsh-workers
 help / color / mirror / code / Atom feed
* [PATCH] Use == in expressions instead of the deprecated =
@ 2016-09-05 21:27 Teubel György
  2016-09-08  8:35 ` Peter Stephenson
  0 siblings, 1 reply; 21+ messages in thread
From: Teubel György @ 2016-09-05 21:27 UTC (permalink / raw)
  To: zsh-workers

---
 Doc/Zsh/compsys.yo |  2 +-
 Doc/Zsh/cond.yo    |  2 +-
 Doc/Zsh/contrib.yo |  2 +-
 Doc/Zsh/expn.yo    | 18 +++++++++---------
 4 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/Doc/Zsh/compsys.yo b/Doc/Zsh/compsys.yo
index 8c7ef0f..060a5c5 100644
--- a/Doc/Zsh/compsys.yo
+++ b/Doc/Zsh/compsys.yo
@@ -2532,7 +2532,7 @@ current prefix is empty, is a single `tt(.)', or consists only of a path
 beginning with `tt(../)'.  Otherwise the value is `false'.
 
 example(zstyle -e ':completion:*' special-dirs \ 
-   '[[ $PREFIX = LPAR()../RPAR()#LPAR()|.|..RPAR() ]] && reply=LPAR()..RPAR()')
+   '[[ $PREFIX == LPAR()../RPAR()#LPAR()|.|..RPAR() ]] && reply=LPAR()..RPAR()')
 )
 kindex(squeeze-slashes, completion style)
 item(tt(squeeze-slashes))(
diff --git a/Doc/Zsh/cond.yo b/Doc/Zsh/cond.yo
index 3d369fb..e87c1e6 100644
--- a/Doc/Zsh/cond.yo
+++ b/Doc/Zsh/cond.yo
@@ -248,7 +248,7 @@ tt($LPAR()LPAR())var(...)tt(RPAR()RPAR()).
 
 For example, the following:
 
-example([[ ( -f foo || -f bar ) && $report = y* ]] && print File exists.)
+example([[ ( -f foo || -f bar ) && $report == y* ]] && print File exists.)
 
 tests if either file tt(foo) or file tt(bar) exists, and if so, if the
 value of the parameter tt(report) begins with `tt(y)'; if the complete
diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo
index 63df292..cf3a398 100644
--- a/Doc/Zsh/contrib.yo
+++ b/Doc/Zsh/contrib.yo
@@ -540,7 +540,7 @@ at run time:
 
 example(zstyle -e ':chpwd:*' recent-dirs-file pick-recent-dirs-file
 pick-recent-dirs-file+LPAR()RPAR() {
-  if [[ $PWD = ~/text/writing+LPAR()|/*RPAR() ]]; then
+  if [[ $PWD == ~/text/writing+LPAR()|/*RPAR() ]]; then
     reply=(~/.chpwd-recent-dirs-writing)
   else
     reply=(+)
diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo
index ecb1877..40932fe 100644
--- a/Doc/Zsh/expn.yo
+++ b/Doc/Zsh/expn.yo
@@ -967,12 +967,12 @@ for this purpose since quotes are not stripped from non-pattern
 characters by tt(GLOB_SUBST).  In other words,
 
 example(pattern=${(q)str}
-[[ $str = ${~pattern} ]])
+[[ $str == ${~pattern} ]])
 
 works if tt($str) is `tt(a*b)' but not if it is `tt(a b)', whereas
 
 example(pattern=${(b)str}
-[[ $str = ${~pattern} ]])
+[[ $str == ${~pattern} ]])
 
 is always true for any possible value of tt($str).
 )
@@ -1228,7 +1228,7 @@ that follow tt(~) within the same set of parentheses.  Compare with tt(~)
 outside parentheses, which forces the entire substituted string to
 be treated as a pattern.  Hence, for example,
 
-example([[ "?" = ${(~j.|.)array} ]])
+example([[ "?" == ${(~j.|.)array} ]])
 
 treats `tt(|)' as a pattern and succeeds if and only if tt($array)
 contains the string `tt(?)' as an element.  The tt(~) may be
@@ -1829,20 +1829,20 @@ example(zsh_directory_name+LPAR()RPAR() {
   emulate -L zsh
   setopt extendedglob
   local -a match mbegin mend
-  if [[ $1 = d ]]; then
+  if [[ $1 == d ]]; then
     # turn the directory into a name
-    if [[ $2 = (#b)(/home/pws/perforce/)([^/]##)* ]]; then
+    if [[ $2 == (#b)(/home/pws/perforce/)([^/]##)* ]]; then
       typeset -ga reply
       reply=(p:$match[2] $(( ${#match[1]} + ${#match[2]} )) )
     else
       return 1
     fi
-  elif [[ $1 = n ]]; then
+  elif [[ $1 == n ]]; then
     # turn the name into a directory
     [[ $2 != (#b)p:(?*) ]] && return 1
     typeset -ga reply
     reply=(/home/pws/perforce/$match[1])
-  elif [[ $1 = c ]]; then
+  elif [[ $1 == c ]]; then
     # complete names
     local expl
     local -a dirs
@@ -2206,7 +2206,7 @@ parentheses can be referenced.
 For example,
 
 example(foo="a string with a message"
-if [[ $foo = (a|an)' '(#b)(*)' '* ]]; then
+if [[ $foo == (a|an)' '(#b)(*)' '* ]]; then
   print ${foo[$mbegin[1],$mend[1]]}
 fi)
 
@@ -2224,7 +2224,7 @@ The numbering of backreferences strictly follows the order of the opening
 parentheses from left to right in the pattern string, although sets of
 parentheses may be nested.  There are special rules for parentheses followed
 by `tt(#)' or `tt(##)'.  Only the last match of the parenthesis is
-remembered: for example, in `tt([[ abab = (#b)([ab])# ]])', only the final
+remembered: for example, in `tt([[ abab == (#b)([ab])# ]])', only the final
 `tt(b)' is stored in tt(match[1]).  Thus extra parentheses may be necessary
 to match the complete segment: for example, use
 `tt(X+LPAR()(ab|cd)#+RPAR()Y)' to match
-- 
2.9.3


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

* Re: [PATCH] Use == in expressions instead of the deprecated =
  2016-09-05 21:27 [PATCH] Use == in expressions instead of the deprecated = Teubel György
@ 2016-09-08  8:35 ` Peter Stephenson
  2016-09-08 11:16   ` Peter Stephenson
  0 siblings, 1 reply; 21+ messages in thread
From: Peter Stephenson @ 2016-09-08  8:35 UTC (permalink / raw)
  To: zsh-workers

Actually, describing it as "deprecated" was always a bit of an
exaggeration --- it's standard shell syntax that isn't going anywhere.
There's no pressing reason not to change it in the documentation that I
can think of, but it's not clear if it's worth looking at.

pws


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

* Re: [PATCH] Use == in expressions instead of the deprecated =
  2016-09-08  8:35 ` Peter Stephenson
@ 2016-09-08 11:16   ` Peter Stephenson
  2016-09-08 14:31     ` Stephane Chazelas
  2016-09-09 13:05     ` Peter Stephenson
  0 siblings, 2 replies; 21+ messages in thread
From: Peter Stephenson @ 2016-09-08 11:16 UTC (permalink / raw)
  To: zsh-workers

On Thu, 8 Sep 2016 09:35:16 +0100
Peter Stephenson <p.stephenson@samsung.com> wrote:
> Actually, describing it as "deprecated" was always a bit of an
> exaggeration --- it's standard shell syntax that isn't going anywhere.
> There's no pressing reason not to change it in the documentation that I
> can think of, but it's not clear if it's worth looking at.

We should probably desribe it more like this, I suppose.  I'm presuming
this does describe the intention here.

pws

diff --git a/Doc/Zsh/cond.yo b/Doc/Zsh/cond.yo
index 3d369fb..6fcf3bd 100644
--- a/Doc/Zsh/cond.yo
+++ b/Doc/Zsh/cond.yo
@@ -103,8 +103,8 @@ true if var(file1) and var(file2) exist and refer to the same file.
 xitem(var(string) tt(=) var(pattern))
 item(var(string) tt(==) var(pattern))(
 true if var(string) matches var(pattern).
-The `tt(==)' form is the preferred one.  The `tt(=)' form is for
-backward compatibility and should be considered obsolete.
+The `tt(==)' form is the preferred one for clarity in new shell code
+as it more closely resembles other languages.
 )
 item(var(string) tt(!=) var(pattern))(
 true if var(string) does not match var(pattern).


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

* Re: [PATCH] Use == in expressions instead of the deprecated =
  2016-09-08 11:16   ` Peter Stephenson
@ 2016-09-08 14:31     ` Stephane Chazelas
  2016-09-08 15:06       ` Stephane Chazelas
                         ` (3 more replies)
  2016-09-09 13:05     ` Peter Stephenson
  1 sibling, 4 replies; 21+ messages in thread
From: Stephane Chazelas @ 2016-09-08 14:31 UTC (permalink / raw)
  To: Peter Stephenson; +Cc: zsh-workers

2016-09-08 12:16:28 +0100, Peter Stephenson:
[...]
> diff --git a/Doc/Zsh/cond.yo b/Doc/Zsh/cond.yo
> index 3d369fb..6fcf3bd 100644
> --- a/Doc/Zsh/cond.yo
> +++ b/Doc/Zsh/cond.yo
> @@ -103,8 +103,8 @@ true if var(file1) and var(file2) exist and refer to the same file.
>  xitem(var(string) tt(=) var(pattern))
>  item(var(string) tt(==) var(pattern))(
>  true if var(string) matches var(pattern).
> -The `tt(==)' form is the preferred one.  The `tt(=)' form is for
> -backward compatibility and should be considered obsolete.
> +The `tt(==)' form is the preferred one for clarity in new shell code
> +as it more closely resembles other languages.
[...]

ksh93 also makes "==" obsolete in [[...]]. "==" is still not
POSIX (and likely not going to be soon as requests to add it
have been rejected (IIRC)) for the "test"/"[" utility (or expr).

I suspect the reason David Korn obsoleted "==" is mainly for
consistency with the ((...)) "==" operator. There, "==" is
comparison and "=" is assignment like in C/awk (and other
languages that don't do the disambiguation via some other mean
like :=/= or <-/=).

However inside [[...]], there is no possible confusion between
assignment and comparison as [[...]] is only a construct for
doing tests, so no point in having a "==" there.

I personally use "=" (even for [[...]]), as that's what's
standard for "test"/"[".

The risk with stating that "==" is obsolete is that people are
going to start using [ "$a" == "$b" ] (as many do already)
thinking it's the right thing to do and get bitten when "sh"
changes from bash/zsh/ksh/yash to another sh implementation
whose "test" builtin doesn't support "=="

-- 
Stephane


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

* Re: [PATCH] Use == in expressions instead of the deprecated =
  2016-09-08 14:31     ` Stephane Chazelas
@ 2016-09-08 15:06       ` Stephane Chazelas
  2016-09-08 15:14       ` Peter Stephenson
                         ` (2 subsequent siblings)
  3 siblings, 0 replies; 21+ messages in thread
From: Stephane Chazelas @ 2016-09-08 15:06 UTC (permalink / raw)
  To: Peter Stephenson, zsh-workers

2016-09-08 15:31:28 +0100, Stephane Chazelas:
[...]
> ksh93 also makes "==" obsolete in [[...]]. "==" is still not
> POSIX (and likely not going to be soon as requests to add it
> have been rejected (IIRC)) for the "test"/"[" utility (or expr).
[...]

Appart from bash 2.02, I don't know of a shell implementation
that treats [[ = ]] differently from [[ == ]] (or [ = ] vs [ ==
] for those "[" implementations that support ==) however note
that yash has a 3rd operator: [ === ] that is short for [ '<=' ]
&& [ '>=' ] or [ ! '<' ] && [ ! '>' ].

As in yash like in bash or ksh93 (but not zsh), < and > for
string comparison use strcoll() (like sort/expr or awk's </> for
strings) while == uses strcmp. And in some locales, there are
strings that sort the same even though they are different.

yash's === is a test to check that two strings sort the same,
like the "=" operator of expr (or the == operator of some awk
implementations as currently required by POSIX (though that's
going to change)).

For instance in a en_GB.UTF-8 locale on a GNU system, \u2461
sorts the same as \u2462 (in that case, a bug).

expr $'\u2461' = $'\u2462'
and
yash -c '[ \u2461 === \u2462 ]'

return true while

[[ \u2461 < \u2462 ]] and [[ \u2461 > \u2462 ]]
both return false in bash and ksh93.

zsh's behaviour is more consistent here but means that for
instance

[[ Stéphane < Stuff ]]

returns false (while bash and ksh93 return true) even though
I'd exect é to sort before u.

See also
https://unix.stackexchange.com/questions/56655/what-is-the-difference-between-a-z-and-a-z/56674#56674

-- 
Stephane


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

* Re: [PATCH] Use == in expressions instead of the deprecated =
  2016-09-08 14:31     ` Stephane Chazelas
  2016-09-08 15:06       ` Stephane Chazelas
@ 2016-09-08 15:14       ` Peter Stephenson
  2016-09-08 16:39         ` Mikael Magnusson
  2016-09-09 12:03         ` Vincent Lefevre
  2016-09-09  8:52       ` Stephane Chazelas
  2016-09-09 17:01       ` [PATCH] Use == in expressions instead of the deprecated = Christian Neukirchen
  3 siblings, 2 replies; 21+ messages in thread
From: Peter Stephenson @ 2016-09-08 15:14 UTC (permalink / raw)
  To: zsh-workers

On Thu, 08 Sep 2016 15:31:28 +0100
Stephane Chazelas <stephane.chazelas@gmail.com> wrote:
> 2016-09-08 12:16:28 +0100, Peter Stephenson:
> [...]
> > diff --git a/Doc/Zsh/cond.yo b/Doc/Zsh/cond.yo
> > index 3d369fb..6fcf3bd 100644
> > --- a/Doc/Zsh/cond.yo
> > +++ b/Doc/Zsh/cond.yo
> > @@ -103,8 +103,8 @@ true if var(file1) and var(file2) exist and refer to the same file.
> >  xitem(var(string) tt(=) var(pattern))
> >  item(var(string) tt(==) var(pattern))(
> >  true if var(string) matches var(pattern).
> > -The `tt(==)' form is the preferred one.  The `tt(=)' form is for
> > -backward compatibility and should be considered obsolete.
> > +The `tt(==)' form is the preferred one for clarity in new shell code
> > +as it more closely resembles other languages.
> [...]
> 
> ksh93 also makes "==" obsolete in [[...]]. "==" is still not
> POSIX (and likely not going to be soon as requests to add it
> have been rejected (IIRC)) for the "test"/"[" utility (or expr).

So possibly even saying == is preferred is going a bit far, though
obviously there's no reason ever to remove it...

pws


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

* Re: [PATCH] Use == in expressions instead of the deprecated =
  2016-09-08 15:14       ` Peter Stephenson
@ 2016-09-08 16:39         ` Mikael Magnusson
  2016-09-08 18:47           ` Stephane Chazelas
  2016-09-09 12:03         ` Vincent Lefevre
  1 sibling, 1 reply; 21+ messages in thread
From: Mikael Magnusson @ 2016-09-08 16:39 UTC (permalink / raw)
  To: Peter Stephenson; +Cc: zsh workers

On Thu, Sep 8, 2016 at 5:14 PM, Peter Stephenson
<p.stephenson@samsung.com> wrote:
> On Thu, 08 Sep 2016 15:31:28 +0100
> Stephane Chazelas <stephane.chazelas@gmail.com> wrote:
>> 2016-09-08 12:16:28 +0100, Peter Stephenson:
>> [...]
>> > diff --git a/Doc/Zsh/cond.yo b/Doc/Zsh/cond.yo
>> > index 3d369fb..6fcf3bd 100644
>> > --- a/Doc/Zsh/cond.yo
>> > +++ b/Doc/Zsh/cond.yo
>> > @@ -103,8 +103,8 @@ true if var(file1) and var(file2) exist and refer to the same file.
>> >  xitem(var(string) tt(=) var(pattern))
>> >  item(var(string) tt(==) var(pattern))(
>> >  true if var(string) matches var(pattern).
>> > -The `tt(==)' form is the preferred one.  The `tt(=)' form is for
>> > -backward compatibility and should be considered obsolete.
>> > +The `tt(==)' form is the preferred one for clarity in new shell code
>> > +as it more closely resembles other languages.
>> [...]
>>
>> ksh93 also makes "==" obsolete in [[...]]. "==" is still not
>> POSIX (and likely not going to be soon as requests to add it
>> have been rejected (IIRC)) for the "test"/"[" utility (or expr).

POSIX doesn't have [[...]] so what it says isn't really relevant. [ a
== b ] doesn't work in zsh by default either, you have to use either [
a = b ] or [ a \== b ] and obviously the latter is pretty ridiculous.
:)

-- 
Mikael Magnusson


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

* Re: [PATCH] Use == in expressions instead of the deprecated =
  2016-09-08 16:39         ` Mikael Magnusson
@ 2016-09-08 18:47           ` Stephane Chazelas
  0 siblings, 0 replies; 21+ messages in thread
From: Stephane Chazelas @ 2016-09-08 18:47 UTC (permalink / raw)
  To: zsh-workers

2016-09-08 18:39:55 +0200, Mikael Magnusson:
[...]
> >> ksh93 also makes "==" obsolete in [[...]]. "==" is still not
> >> POSIX (and likely not going to be soon as requests to add it
> >> have been rejected (IIRC)) for the "test"/"[" utility (or expr).
> 
> POSIX doesn't have [[...]] so what it says isn't really relevant. [ a
> == b ] doesn't work in zsh by default either, you have to use either [
> a = b ] or [ a \== b ] and obviously the latter is pretty ridiculous.
> :)
[...]

I only said "==" was not POSIX *for the "test"/"[" utility (or
expr)*.

It's not relevant to [[...]] except that [[..]] was more or less
the "[" utility moved to a new shell construct to avoid some of
the issues with the interpretation of the arguments of the "["
command (most of which have later been fixed by POSIX).

Now, I agree, given that [ a == b ] doesn't work in zsh when not
in sh emulation, that's one more reason zsh maybe shouldn't
consider [[ a = b ]] as obsolete.

AFAICT, none of mksh, pdksh, yash, bash consider [[ = ]]
obsolete ([ = ] for yash which doesn't have [[ ]]).

-- 
Stephane


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

* Re: [PATCH] Use == in expressions instead of the deprecated =
  2016-09-08 14:31     ` Stephane Chazelas
  2016-09-08 15:06       ` Stephane Chazelas
  2016-09-08 15:14       ` Peter Stephenson
@ 2016-09-09  8:52       ` Stephane Chazelas
  2016-09-09  9:31         ` Peter Stephenson
  2016-09-14 22:01         ` PATCH: [[ -v varname ]] Oliver Kiddle
  2016-09-09 17:01       ` [PATCH] Use == in expressions instead of the deprecated = Christian Neukirchen
  3 siblings, 2 replies; 21+ messages in thread
From: Stephane Chazelas @ 2016-09-09  8:52 UTC (permalink / raw)
  To: Peter Stephenson, zsh-workers

2016-09-08 15:31:28 +0100, Stephane Chazelas:
[...]
> ksh93 also makes "==" obsolete in [[...]]. "==" is still not
> POSIX (and likely not going to be soon as requests to add it
> have been rejected (IIRC)) for the "test"/"[" utility (or expr).
[...]

Sorry, bad memory. Though there was some opposition, the "=="
proposal was not rejected:
http://austingroupbugs.net/view.php?id=375 was what I was
vaguely recalling.

It's still possible that the next major POSIX spec will have
[ == ] and maybe even [[ ]].

You guys may want to comment on the latest proposal there:
http://austingroupbugs.net/file_download.php?file_id=31&type=bug

as it would make zsh non-conformant.

In particular, it  proposes specifying [[ =~ ]] the ksh/bash
way, that is where quoting escapes regexp operators (
[[ a =~ "." ]] returns false) and [[ < ]] required to use
collation.

-- 
Stephane


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

* Re: [PATCH] Use == in expressions instead of the deprecated =
  2016-09-09  8:52       ` Stephane Chazelas
@ 2016-09-09  9:31         ` Peter Stephenson
  2016-09-09 16:00           ` Stephane Chazelas
  2016-09-14 22:01         ` PATCH: [[ -v varname ]] Oliver Kiddle
  1 sibling, 1 reply; 21+ messages in thread
From: Peter Stephenson @ 2016-09-09  9:31 UTC (permalink / raw)
  To: zsh-workers

On Fri, 09 Sep 2016 09:52:31 +0100
Stephane Chazelas <stephane.chazelas@gmail.com> wrote:
> It's still possible that the next major POSIX spec will have
> [ == ] and maybe even [[ ]].
> 
> You guys may want to comment on the latest proposal there:
> http://austingroupbugs.net/file_download.php?file_id=31&type=bug
> 
> as it would make zsh non-conformant.
> 
> In particular, it  proposes specifying [[ =~ ]] the ksh/bash
> way, that is where quoting escapes regexp operators (
> [[ a =~ "." ]] returns false) and [[ < ]] required to use
> collation.

If POSIX-like shells already do it that way, the best we could offer
would probably be another kludge-up option anyway.  Not specifying it,
the only other option, isn't really doing anyone any favours in the end.

pws


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

* Re: [PATCH] Use == in expressions instead of the deprecated =
  2016-09-08 15:14       ` Peter Stephenson
  2016-09-08 16:39         ` Mikael Magnusson
@ 2016-09-09 12:03         ` Vincent Lefevre
       [not found]           ` <CGME20160912143133eucas1p11a4e6916dd70b3ceaa163bf3bddfb007@eucas1p1.samsung.com>
  1 sibling, 1 reply; 21+ messages in thread
From: Vincent Lefevre @ 2016-09-09 12:03 UTC (permalink / raw)
  To: zsh-workers

On 2016-09-08 16:14:10 +0100, Peter Stephenson wrote:
> So possibly even saying == is preferred is going a bit far, though
> obviously there's no reason ever to remove it...

I don't mind what is preferred, but zsh should be consistent, and
currently it isn't:

In the man pages:

    string = pattern
    string == pattern
        true if string matches pattern.  The `==' form is the preferred
        one.  The `=' form is for backward compatibility and should  be
        considered obsolete.

But "==" is converted to "=":

zira% f() { [[ a == a ]] }
zira% which f
f () {
        [[ a = a ]]
}

-- 
Vincent Lefèvre <vincent@vinc17.net> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)


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

* Re: [PATCH] Use == in expressions instead of the deprecated =
  2016-09-08 11:16   ` Peter Stephenson
  2016-09-08 14:31     ` Stephane Chazelas
@ 2016-09-09 13:05     ` Peter Stephenson
  1 sibling, 0 replies; 21+ messages in thread
From: Peter Stephenson @ 2016-09-09 13:05 UTC (permalink / raw)
  To: zsh-workers

On Thu, 8 Sep 2016 12:16:28 +0100
Peter Stephenson <p.stephenson@samsung.com> wrote:
> -The `tt(==)' form is the preferred one.  The `tt(=)' form is for
> -backward compatibility and should be considered obsolete.
> +The `tt(==)' form is the preferred one for clarity in new shell code
> +as it more closely resembles other languages.

It's sounding like the less of substance we say the better.

pws

diff --git a/Doc/Zsh/cond.yo b/Doc/Zsh/cond.yo
index 3d369fb..474baa1 100644
--- a/Doc/Zsh/cond.yo
+++ b/Doc/Zsh/cond.yo
@@ -103,8 +103,10 @@ true if var(file1) and var(file2) exist and refer to the same file.
 xitem(var(string) tt(=) var(pattern))
 item(var(string) tt(==) var(pattern))(
 true if var(string) matches var(pattern).
-The `tt(==)' form is the preferred one.  The `tt(=)' form is for
-backward compatibility and should be considered obsolete.
+The two forms are exactly equivalent.  The `tt(=)' form is
+the traditional shell syntax (and hence the only one generally used
+with the tt(test) and tt([) builtins); the `tt(==)' form provides
+compatibility with other sorts of computer language.
 )
 item(var(string) tt(!=) var(pattern))(
 true if var(string) does not match var(pattern).


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

* Re: [PATCH] Use == in expressions instead of the deprecated =
  2016-09-09  9:31         ` Peter Stephenson
@ 2016-09-09 16:00           ` Stephane Chazelas
  0 siblings, 0 replies; 21+ messages in thread
From: Stephane Chazelas @ 2016-09-09 16:00 UTC (permalink / raw)
  To: Peter Stephenson; +Cc: zsh-workers

2016-09-09 10:31:55 +0100, Peter Stephenson:
> On Fri, 09 Sep 2016 09:52:31 +0100
> Stephane Chazelas <stephane.chazelas@gmail.com> wrote:
> > It's still possible that the next major POSIX spec will have
> > [ == ] and maybe even [[ ]].
> > 
> > You guys may want to comment on the latest proposal there:
> > http://austingroupbugs.net/file_download.php?file_id=31&type=bug
> > 
> > as it would make zsh non-conformant.
> > 
> > In particular, it  proposes specifying [[ =~ ]] the ksh/bash
> > way, that is where quoting escapes regexp operators (
> > [[ a =~ "." ]] returns false) and [[ < ]] required to use
> > collation.
> 
> If POSIX-like shells already do it that way, the best we could offer
> would probably be another kludge-up option anyway.  Not specifying it,
> the only other option, isn't really doing anyone any favours in the end.
[...]

Note that doing it properly is tricky. bash has had a number
of bugs before it eventually settled to something reliable
enough.

bash -c '[[ "\\" =~ [^]"."] ]]'

Still return false though.

With zsh supporting both ERE and PCRE, it's going to be even
more pain I would say.

Specifying it (which the current proposal doesn't really
address) is also going to be difficult.

The problem is that the shell needs to know the syntax of the
regular expressions in order to be able to quote the RE
operators properly for the regexp engine.

for instance in [[ x =~ "." ]], the shell has to call
regcomp("\\."), but in [[ x =~ ["."] ]], it must call
regcomp("[.]"), as otherwise a regcomp("[\.]") would also match
on backslash. bash now does that properly in most cases (after I
raised the bug some time ago), but misses the [^]...] case as
I've just realised.

And in [[ x =~ "<" ]], you don't want to do a regcomp("\\<"), as
\< has a special meaning in some regexp engines. So bash does a
regcomp("<") (for both [[ x =~ "<" ]] and [[ x =~ \< ]])
instead. What that means is that you can't use the extensions of
your local regexp library unless you use a variable as in:

var='\<foo\>'
[[ $x =~ $var ]]

because then bash does a regcomp("\\<foo\\>") (just like zsh).

See also:

a='foo\'
[[ 'foo\bar' =~ $a"." ]]

That returns true in bash. (as it does a regcomp("foo\\\\.")),
though here we are asking for trouble in the first place with
that trailing backslash.

In effect at the moment to use =~ portably between ksh, bash,
bash31, zsh, you have to use:

regex=...
[[ $string =~ $regex ]]

And in between yash and zsh:

[ "$string" "=~" "$regex" ]

In PCRE, you have things like (?x) that affect the parsing and
would make things more complicated, but you might be able to
leverage \Q \E.

-- 
Stephane


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

* Re: [PATCH] Use == in expressions instead of the deprecated =
  2016-09-08 14:31     ` Stephane Chazelas
                         ` (2 preceding siblings ...)
  2016-09-09  8:52       ` Stephane Chazelas
@ 2016-09-09 17:01       ` Christian Neukirchen
  2016-09-09 18:54         ` Stephane Chazelas
  3 siblings, 1 reply; 21+ messages in thread
From: Christian Neukirchen @ 2016-09-09 17:01 UTC (permalink / raw)
  To: zsh-workers

Stephane Chazelas <stephane.chazelas@gmail.com> writes:

> 2016-09-08 12:16:28 +0100, Peter Stephenson:
> [...]
>> diff --git a/Doc/Zsh/cond.yo b/Doc/Zsh/cond.yo
>> index 3d369fb..6fcf3bd 100644
>> --- a/Doc/Zsh/cond.yo
>> +++ b/Doc/Zsh/cond.yo
>> @@ -103,8 +103,8 @@ true if var(file1) and var(file2) exist and
>> refer to the same file.
>>  xitem(var(string) tt(=) var(pattern))
>>  item(var(string) tt(==) var(pattern))(
>>  true if var(string) matches var(pattern).
>> -The `tt(==)' form is the preferred one.  The `tt(=)' form is for
>> -backward compatibility and should be considered obsolete.
>> +The `tt(==)' form is the preferred one for clarity in new shell code
>> +as it more closely resembles other languages.
> [...]
>
> ksh93 also makes "==" obsolete in [[...]]. 

My ksh93 (ksh-2012.08.01) man page says:

   Conditional Expressions.
       A conditional expression is used with the [[ compound command to test
       attributes of files and to compare strings.
   ...
       string == pattern
              True, if string matches pattern.  Any part of pattern can be
              quoted to cause it to be matched as a string.  With a successful
              match to a pattern, the .sh.match array variable will contain
              the match and sub-pattern matches.
       string = pattern
              Same as == above, but is obsolete.

-- 
Christian Neukirchen  <chneukirchen@gmail.com>  http://chneukirchen.org


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

* Re: [PATCH] Use == in expressions instead of the deprecated =
  2016-09-09 17:01       ` [PATCH] Use == in expressions instead of the deprecated = Christian Neukirchen
@ 2016-09-09 18:54         ` Stephane Chazelas
  0 siblings, 0 replies; 21+ messages in thread
From: Stephane Chazelas @ 2016-09-09 18:54 UTC (permalink / raw)
  To: Christian Neukirchen; +Cc: zsh-workers

2016-09-09 19:01:27 +0200, Christian Neukirchen:
[...]
> >> -The `tt(==)' form is the preferred one.  The `tt(=)' form is for
> >> -backward compatibility and should be considered obsolete.
[...]
> > ksh93 also makes "==" obsolete in [[...]]. 
> 
> My ksh93 (ksh-2012.08.01) man page says:
> 
>    Conditional Expressions.
>        A conditional expression is used with the [[ compound command to test
>        attributes of files and to compare strings.
>    ...
>        string == pattern
>               True, if string matches pattern.  Any part of pattern can be
>               quoted to cause it to be matched as a string.  With a successful
>               match to a pattern, the .sh.match array variable will contain
>               the match and sub-pattern matches.
>        string = pattern
>               Same as == above, but is obsolete.
[...]

Sorry, that's what I meant and I ended up saying the opposite.
ksh93 also (like zsh) makes "=" obsolete. I assumed the zsh
manual was making = obsolete because ksh did as well (that
[[...]] construct comes from ksh).

-- 
Stephane


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

* Re: [PATCH] Use == in expressions instead of the deprecated =
       [not found]           ` <CGME20160912143133eucas1p11a4e6916dd70b3ceaa163bf3bddfb007@eucas1p1.samsung.com>
@ 2016-09-12 14:31             ` Peter Stephenson
  0 siblings, 0 replies; 21+ messages in thread
From: Peter Stephenson @ 2016-09-12 14:31 UTC (permalink / raw)
  To: zsh-workers

Not that I'm particularly bothered, but it might keep surprises to a
minimum if zsh output either "=" or "==" when showing tests depending
what the user originally typed.

I incremented the dev version as the wordcode is incompatible.

pws

diff --git a/Config/version.mk b/Config/version.mk
index 5577f4a..7d110b2 100644
--- a/Config/version.mk
+++ b/Config/version.mk
@@ -27,5 +27,5 @@
 # This must also serve as a shell script, so do not add spaces around the
 # `=' signs.
 
-VERSION=5.2-dev-1
+VERSION=5.2-dev-2
 VERSION_DATE='January 20, 2015'
diff --git a/Src/cond.c b/Src/cond.c
index 0381fe9..f25ebd4 100644
--- a/Src/cond.c
+++ b/Src/cond.c
@@ -34,7 +34,7 @@
 int tracingcond;    /* updated by execcond() in exec.c */
 
 static char *condstr[COND_MOD] = {
-    "!", "&&", "||", "==", "!=", "<", ">", "-nt", "-ot", "-ef", "-eq",
+    "!", "&&", "||", "=", "==", "!=", "<", ">", "-nt", "-ot", "-ef", "-eq",
     "-ne", "-lt", "-gt", "-le", "-ge", "=~"
 };
 
@@ -196,7 +196,8 @@ evalcond(Estate state, char *fromtest)
 	cond_subst(&left, !fromtest);
 	untokenize(left);
     }
-    if (ctype <= COND_GE && ctype != COND_STREQ && ctype != COND_STRNEQ) {
+    if (ctype <= COND_GE && ctype != COND_STREQ && ctype != COND_STRDEQ &&
+	ctype != COND_STRNEQ) {
 	right = ecgetstr(state, EC_DUPTOK, &htok);
 	if (htok) {
 	    cond_subst(&right, !fromtest);
@@ -208,7 +209,8 @@ evalcond(Estate state, char *fromtest)
 	    fputc(' ',xtrerr);
 	    quotedzputs(left, xtrerr);
 	    fprintf(xtrerr, " %s ", condstr[ctype]);
-	    if (ctype == COND_STREQ || ctype == COND_STRNEQ) {
+	    if (ctype == COND_STREQ || ctype == COND_STRDEQ ||
+		ctype == COND_STRNEQ) {
 		char *rt = dupstring(ecrawstr(state->prog, state->pc, NULL));
 		cond_subst(&rt, !fromtest);
 		quote_tokenized_output(rt, xtrerr);
@@ -287,6 +289,7 @@ evalcond(Estate state, char *fromtest)
 
     switch (ctype) {
     case COND_STREQ:
+    case COND_STRDEQ:
     case COND_STRNEQ:
 	{
 	    int test, npat = state->pc[1];
@@ -313,7 +316,7 @@ evalcond(Estate state, char *fromtest)
 	    state->pc += 2;
 	    test = (pprog && pattry(pprog, left));
 
-	    return !(ctype == COND_STREQ ? test : !test);
+	    return !(ctype == COND_STRNEQ ? !test : test);
 	}
     case COND_STRLT:
 	return !(strcmp(left, right) < 0);
diff --git a/Src/parse.c b/Src/parse.c
index 94ac049..6e7d40e 100644
--- a/Src/parse.c
+++ b/Src/parse.c
@@ -2498,12 +2498,17 @@ par_cond_triple(char *a, char *b, char *c)
 {
     int t0;
 
-    if ((b[0] == Equals || b[0] == '=') &&
-	(!b[1] || ((b[1] == Equals || b[1] == '=') && !b[2]))) {
+    if ((b[0] == Equals || b[0] == '=') && !b[1]) {
 	ecadd(WCB_COND(COND_STREQ, 0));
 	ecstr(a);
 	ecstr(c);
 	ecadd(ecnpats++);
+    } else if ((b[0] == Equals || b[0] == '=') &&
+	       (b[1] == Equals || b[1] == '=') && !b[2]) {
+	ecadd(WCB_COND(COND_STRDEQ, 0));
+	ecstr(a);
+	ecstr(c);
+	ecadd(ecnpats++);
     } else if (b[0] == '!' && (b[1] == Equals || b[1] == '=') && !b[2]) {
 	ecadd(WCB_COND(COND_STRNEQ, 0));
 	ecstr(a);
diff --git a/Src/text.c b/Src/text.c
index d387d36..3658b1b 100644
--- a/Src/text.c
+++ b/Src/text.c
@@ -46,7 +46,7 @@ int text_expand_tabs;
  * et seq. in zsh.h.
  */
 static const char *cond_binary_ops[] = {
-    "=", "!=", "<", ">", "-nt", "-ot", "-ef", "-eq",
+    "=", "==", "!=", "<", ">", "-nt", "-ot", "-ef", "-eq",
     "-ne", "-lt", "-gt", "-le", "-ge", "=~", NULL
 };
 
@@ -934,6 +934,7 @@ gettext2(Estate state)
 			    taddstr(" ");
 			    taddstr(ecgetstr(state, EC_NODUP, NULL));
 			    if (ctype == COND_STREQ ||
+				ctype == COND_STRDEQ ||
 				ctype == COND_STRNEQ)
 				state->pc++;
 			} else {
diff --git a/Src/zsh.h b/Src/zsh.h
index 87e6a98..996bc33 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -622,27 +622,34 @@ struct timedfn {
 /* (1<<4) is used for Z_END, see the wordcode definitions */
 /* (1<<5) is used for Z_SIMPLE, see the wordcode definitions */
 
-/* Condition types. */
+/*
+ * Condition types.
+ *
+ * Careful when changing these: both cond_binary_ops in text.c and
+ * condstr in cond.c depend on these.  (The zsh motto is "two instances
+ * are better than one".  Or something.)
+ */
 
 #define COND_NOT    0
 #define COND_AND    1
 #define COND_OR     2
 #define COND_STREQ  3
-#define COND_STRNEQ 4
-#define COND_STRLT  5
-#define COND_STRGTR 6
-#define COND_NT     7
-#define COND_OT     8
-#define COND_EF     9
-#define COND_EQ    10
-#define COND_NE    11
-#define COND_LT    12
-#define COND_GT    13
-#define COND_LE    14
-#define COND_GE    15
-#define COND_REGEX 16
-#define COND_MOD   17
-#define COND_MODI  18
+#define COND_STRDEQ 4
+#define COND_STRNEQ 5
+#define COND_STRLT  6
+#define COND_STRGTR 7
+#define COND_NT     8
+#define COND_OT     9
+#define COND_EF    10
+#define COND_EQ    11
+#define COND_NE    12
+#define COND_LT    13
+#define COND_GT    14
+#define COND_LE    15
+#define COND_GE    16
+#define COND_REGEX 17
+#define COND_MOD   18
+#define COND_MODI  19
 
 typedef int (*CondHandler) _((char **, int));
 
diff --git a/Test/C02cond.ztst b/Test/C02cond.ztst
index e315f6c..78e644a 100644
--- a/Test/C02cond.ztst
+++ b/Test/C02cond.ztst
@@ -414,6 +414,13 @@ F:Failures in these cases do not indicate a problem in the shell.
 >OK 4
 >OK 5
 
+  fn() { [[ 'a' == 'b' || 'b' = 'c' || 'c' != 'd' ]] }
+  which -x2 fn
+0: = and == appear as input
+>fn () {
+>  [[ 'a' == 'b' || 'b' = 'c' || 'c' != 'd' ]]
+>}
+
 %clean
   # This works around a bug in rm -f in some versions of Cygwin
   chmod 644 unmodish
diff --git a/Test/D01prompt.ztst b/Test/D01prompt.ztst
index 2638e24..607ffb6 100644
--- a/Test/D01prompt.ztst
+++ b/Test/D01prompt.ztst
@@ -196,8 +196,8 @@
 ?+zsh_directory_name:1> emulate -L zsh
 ?+zsh_directory_name:2> setopt extendedglob
 ?+zsh_directory_name:3> local -a match mbegin mend
-?+zsh_directory_name:4> [[ d == n ]]
-?+zsh_directory_name:12> [[ <parent>/very_long_directory_name == (#b)(*)/very_long_directory_name ]]
+?+zsh_directory_name:4> [[ d = n ]]
+?+zsh_directory_name:12> [[ <parent>/very_long_directory_name = (#b)(*)/very_long_directory_name ]]
 ?+zsh_directory_name:14> return 0
 ?+fn:7> local d='~[<parent>:l]'
 ?+fn:8> print '~[<parent>:l]'
diff --git a/Test/E02xtrace.ztst b/Test/E02xtrace.ztst
index 6e425e7..da6191c 100644
--- a/Test/E02xtrace.ztst
+++ b/Test/E02xtrace.ztst
@@ -120,13 +120,15 @@
 ?+./fnfile:3> print This is fn.
 
  set -x
+ [[ 'f o' == 'f x'* || 'b r' != 'z o' && 'squashy sound' < 'squishy sound' ]]
  [[ 'f o' = 'f x'* || 'b r' != 'z o' && 'squashy sound' < 'squishy sound' ]]
  [[ -e nonexistentfile || ( -z '' && -t 3 ) ]]
  set +x
 0:Trace for conditions
 ?+(eval):2> [[ 'f o' == f\ x* || 'b r' != z\ o && 'squashy sound' < 'squishy sound' ]]
-?+(eval):3> [[ -e nonexistentfile || -z '' && -t 3 ]]
-?+(eval):4> set +x
+?+(eval):3> [[ 'f o' = f\ x* || 'b r' != z\ o && 'squashy sound' < 'squishy sound' ]]
+?+(eval):4> [[ -e nonexistentfile || -z '' && -t 3 ]]
+?+(eval):5> set +x
 
   # Part 1: Recurses into nested anonymous functions
   fn() {


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

* PATCH: [[ -v varname ]]
  2016-09-09  8:52       ` Stephane Chazelas
  2016-09-09  9:31         ` Peter Stephenson
@ 2016-09-14 22:01         ` Oliver Kiddle
  2016-09-15 10:55           ` Vincent Lefevre
  2016-09-15 11:08           ` Stephane Chazelas
  1 sibling, 2 replies; 21+ messages in thread
From: Oliver Kiddle @ 2016-09-14 22:01 UTC (permalink / raw)
  To: zsh-workers

On 9 Sep, Stephane Chazelas wrote:
> You guys may want to comment on the latest proposal there:
> http://austingroupbugs.net/file_download.php?file_id=31&type=bug
> as it would make zsh non-conformant.

One thing it also includes is the bash/ksh [[ -v ... ]] condition for
checking if a particular variable is set. Zsh has the ${+varname} syntax
which provides the same functionality in a different form. The following
patch adds the ksh form for compatibility.

The code for ${+...} is mixed in with the rest of the parameter
substitution code so I couldn't easily reuse it. There may be subtle
differences as a result. In particular it returns false for a string
slice. That's arguably not a variable and would raise the question
of string slices on an array slice.

There's also subtle differences relative to bash/ksh. local/typeset
in bash/ksh leave the variable undefined until it is given a value
rather than making it an empty scalar. And bash doesn't seem to handle
the positional parameters.

Oliver

diff --git a/Completion/Zsh/Context/_condition b/Completion/Zsh/Context/_condition
index 6f5e601..0285911 100644
--- a/Completion/Zsh/Context/_condition
+++ b/Completion/Zsh/Context/_condition
@@ -8,6 +8,8 @@ elif [[ "$prev" = -([a-hkprsuwxLOGSN]|[no]t|ef) ]]; then
   _tags -C "$prev" files && _files
 elif [[ "$prev" = -t ]]; then
   _file_descriptors
+elif [[ "$prev" = -v ]]; then
+  _parameters -r "\= \t\n\[\-"
 else
   if [[ "$PREFIX" = -* ]] ||
      ! zstyle -T ":completion:${curcontext}:options" prefix-needed; then
@@ -30,6 +32,7 @@ else
 	           -s:non-empty\ file
 	           -t:terminal\ file\ descriptor
 	           -u:setuid\ bit
+		   -v:set\ variable
 	           -w:writable\ file
 	           -x:executable\ file
 	           -z:empty\ string
diff --git a/Doc/Zsh/cond.yo b/Doc/Zsh/cond.yo
index 474baa1..e08fc0d 100644
--- a/Doc/Zsh/cond.yo
+++ b/Doc/Zsh/cond.yo
@@ -63,6 +63,9 @@ is open and associated with a terminal device.
 item(tt(-u) var(file))(
 true if var(file) exists and has its setuid bit set.
 )
+item(tt(-v) var(varname))(
+true if shell variable var(varname) is set.
+)
 item(tt(-w) var(file))(
 true if var(file) exists and is writable by current process.
 )
diff --git a/Src/cond.c b/Src/cond.c
index f25ebd4..42e9de3 100644
--- a/Src/cond.c
+++ b/Src/cond.c
@@ -351,6 +351,8 @@ evalcond(Estate state, char *fromtest)
 	return (!S_ISSOCK(dostat(left)));
     case 'u':
 	return (!(dostat(left) & S_ISUID));
+    case 'v':
+	return (!issetvar(left));
     case 'w':
 	return (!doaccess(left, W_OK));
     case 'x':
diff --git a/Src/params.c b/Src/params.c
index 842b2f0..5c534af 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -626,6 +626,36 @@ getvaluearr(Value v)
 	return NULL;
 }
 
+/* Return whether the variable is set         *
+ * checks that array slices are within range  *
+ * used for [[ -v ... ]] condition test       */
+
+/**/
+int
+issetvar(char *name)
+{
+    struct value vbuf;
+    Value v;
+    int slice;
+    char **arr;
+
+    if (!(v = getvalue(&vbuf, &name, 1)) || *name)
+	return 0; /* no value or more chars after the variable name */
+    if (v->isarr & ~SCANPM_ARRONLY)
+	return v->end > 1; /* for extracted elements, end gives us a count */
+
+    slice = v->start != 0 || v->end != -1;
+    if (PM_TYPE(v->pm->node.flags) != PM_ARRAY || !slice)
+	return !slice && !(v->pm->node.flags & PM_UNSET);
+
+    if (!v->end) /* empty array slice */
+	return 0;
+    /* get the array and check end is within range */
+    if (!(arr = getvaluearr(v)))
+	return 0;
+    return arrlen_ge(arr, v->end < 0 ? - v->end : v->end);
+}
+
 /*
  * Split environment string into (name, value) pair.
  * this is used to avoid in-place editing of environment table
diff --git a/Src/parse.c b/Src/parse.c
index 6e7d40e..2f81939 100644
--- a/Src/parse.c
+++ b/Src/parse.c
@@ -2386,7 +2386,7 @@ par_cond_2(void)
     s1 = tokstr;
     dble = (s1 && *s1 == '-'
 	    && (!n_testargs
-		|| strspn(s1+1, "abcdefghknoprstuwxzLONGS") == 1)
+		|| strspn(s1+1, "abcdefghknoprstuvwxzLONGS") == 1)
 	    && !s1[2]);
     if (tok != STRING) {
 	/* Check first argument for [[ STRING ]] re-interpretation */
@@ -2465,7 +2465,7 @@ par_cond_double(char *a, char *b)
 {
     if (a[0] != '-' || !a[1])
 	COND_ERROR("parse error: condition expected: %s", a);
-    else if (!a[2] && strspn(a+1, "abcdefgknoprstuwxzhLONGS") == 1) {
+    else if (!a[2] && strspn(a+1, "abcdefgknoprstuvwxzhLONGS") == 1) {
 	ecadd(WCB_COND(a[1], 0));
 	ecstr(b);
     } else {
diff --git a/Test/C02cond.ztst b/Test/C02cond.ztst
index 78e644a..40e4dfb 100644
--- a/Test/C02cond.ztst
+++ b/Test/C02cond.ztst
@@ -269,6 +269,25 @@ F:Failures in these cases do not indicate a problem in the shell.
 0:-nt shouldn't abort on non-existent files
 >status = 1
 
+  str='string' empty=''
+  [[ -v IFS && -v str && -v empty && ! -v str[3] && ! -v not_a_variable ]]
+0:-v cond
+
+  arr=( 1 2 3 4 ) empty=()
+  [[ -v arr && -v arr[1,4] && -v arr[1] && -v arr[4] && -v arr[-4] &&
+    -v arr[(i)3] && ! -v arr[(i)x] &&
+    ! -v arr[0] && ! -v arr[5] && ! -v arr[-5] && ! -v arr[2][1] &&
+    ! -v arr[3]extra && -v empty && ! -v empty[1] ]]
+0:-v cond with array
+
+  typeset -A assoc=( key val num 4 )
+  [[ -v assoc && -v assoc[key] && -v assoc[(i)*] && -v assoc[(I)*] &&
+    ! -v assoc[x] && ! -v assoc[key][1] ]]
+0:-v cond with association
+
+  () { [[ -v 0 && -v 1 && -v 2 && ! -v 3 ]] } arg ''
+0:-v cond with positional parameters
+
 # core dumps on failure
   if zmodload zsh/regex 2>/dev/null; then
      echo >regex_test.sh 'if [[ $# = 1 ]]; then


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

* Re: PATCH: [[ -v varname ]]
  2016-09-14 22:01         ` PATCH: [[ -v varname ]] Oliver Kiddle
@ 2016-09-15 10:55           ` Vincent Lefevre
  2016-09-16  0:36             ` Bart Schaefer
  2016-09-15 11:08           ` Stephane Chazelas
  1 sibling, 1 reply; 21+ messages in thread
From: Vincent Lefevre @ 2016-09-15 10:55 UTC (permalink / raw)
  To: zsh-workers

On 2016-09-15 00:01:50 +0200, Oliver Kiddle wrote:
> One thing it also includes is the bash/ksh [[ -v ... ]] condition for
> checking if a particular variable is set. Zsh has the ${+varname} syntax
> which provides the same functionality in a different form. The following
> patch adds the ksh form for compatibility.
> 
> The code for ${+...} is mixed in with the rest of the parameter
> substitution code so I couldn't easily reuse it. There may be subtle
> differences as a result. In particular it returns false for a string
> slice. That's arguably not a variable and would raise the question
> of string slices on an array slice.
> 
> There's also subtle differences relative to bash/ksh. local/typeset
> in bash/ksh leave the variable undefined until it is given a value
> rather than making it an empty scalar. And bash doesn't seem to handle
> the positional parameters.

Shouldn't there be 3 states?
* not declared / not set
* declared but not set
* set

-- 
Vincent Lefèvre <vincent@vinc17.net> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)


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

* Re: PATCH: [[ -v varname ]]
  2016-09-14 22:01         ` PATCH: [[ -v varname ]] Oliver Kiddle
  2016-09-15 10:55           ` Vincent Lefevre
@ 2016-09-15 11:08           ` Stephane Chazelas
  2016-09-15 11:22             ` wrong "export -p" output for exported but not set variables (Was: PATCH: [[ -v varname ]]) Stephane Chazelas
  1 sibling, 1 reply; 21+ messages in thread
From: Stephane Chazelas @ 2016-09-15 11:08 UTC (permalink / raw)
  To: Oliver Kiddle; +Cc: zsh-workers

2016-09-15 00:01:50 +0200, Oliver Kiddle:
> On 9 Sep, Stephane Chazelas wrote:
> > You guys may want to comment on the latest proposal there:
> > http://austingroupbugs.net/file_download.php?file_id=31&type=bug
> > as it would make zsh non-conformant.
> 
> One thing it also includes is the bash/ksh [[ -v ... ]] condition for
> checking if a particular variable is set. Zsh has the ${+varname} syntax
> which provides the same functionality in a different form. The following
> patch adds the ksh form for compatibility.
[...]

Note that there's a lot of variation between the ksh93 and bash
implementation of [[ -v ]] (though maybe not so much on the part
covered by POSIX), for instance on variables that have been
declared (or exported or marked readonly) with different types
but not assigned to (at least in zsh, declared/exported
variables are always given a default value), on arrays or hashs
that have no element (or no element of indice 0 or "0"; for a
hash in bash [[ -v h ]] returns true iff h[0] is set and in ksh
never ([[ -v h[@] ]] doesn't work either)).

Also note that in ksh/bash, it's only for variables, not other
types of parameters ([[ -v 0 ]], [[ -v "#" ]] return false).

See also:

$ a='b[0`uname>&2`]' bash -c '[[ -v $a ]]'
Linux

$ bash -c 'typeset -n a=b; [[ -v a ]]'; echo $?
1
$ b= bash -c 'typeset -n a=b; [[ -v a ]]'; echo $?
0

Spurious error message:

$ ksh -c 'typeset -T A=(a=a); A a; [[ -v a.x ]]'
ksh: x: is not an element of a

a.x returns false if $a has a x but that's a discipline (or
array/hash with 0 element not set).


In any case, it looks like your patch does the sensible thing in
all the cases I've tried except that [[ -v @ ]] returns false
(while [[ -v * ]] return true). No big deal as nobody would ever
want to do that.

What to do in zsh (where scalar and arrays are distinct types) for 

zsh -c 'a=1234; [[ -v a[1] ]]

is up to debate (currently returns false).

See also
https://unix.stackexchange.com/questions/212183/how-do-i-check-if-a-variable-exists-in-an-if-statement/246703#246703

-- 
Stephane


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

* wrong "export -p" output for exported but not set variables (Was: PATCH: [[ -v varname ]])
  2016-09-15 11:08           ` Stephane Chazelas
@ 2016-09-15 11:22             ` Stephane Chazelas
  0 siblings, 0 replies; 21+ messages in thread
From: Stephane Chazelas @ 2016-09-15 11:22 UTC (permalink / raw)
  To: Oliver Kiddle, zsh-workers

2016-09-15 12:08:54 +0100, Stephane Chazelas:
[...]
> declared (or exported or marked readonly) with different types
> but not assigned to (at least in zsh, declared/exported
> variables are always given a default value)
[...]

Actually, I was wrong about that and was basing it on the output
of typeset -p.

$ zsh -c 'export a; export -p a'
typeset -x a=''

(BTW, it would be nice to have sh-compatible (POSIX at least) output in:
$ ARGV0=sh zsh -c 'export a; export -p a'
typeset -x a=''
)

$ zsh -c 'export a; printenv a'
$ zsh -c 'export a=; printenv a'

$

$a was not given a default empty value there. It's considered as set though:

$ zsh -c 'export a; echo ${a+foo}'
foo

Which I think breaks POSIX compliance (and no other shell
outputs foo there)..

It's different for "readonly":

$ zsh -c 'readonly a; echo ${a+foo}'
foo
$ ARGV0=sh zsh -c 'readonly a; echo ${a+foo}'

$

-- 
Stephane


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

* Re: PATCH: [[ -v varname ]]
  2016-09-15 10:55           ` Vincent Lefevre
@ 2016-09-16  0:36             ` Bart Schaefer
  0 siblings, 0 replies; 21+ messages in thread
From: Bart Schaefer @ 2016-09-16  0:36 UTC (permalink / raw)
  To: zsh-workers

On Sep 15, 12:55pm, Vincent Lefevre wrote:
}
} Shouldn't there be 3 states?
} * not declared / not set
} * declared but not set
} * set

There are, but the test in question only distinguishes set/not, there
traditionally has not been a test for whether declared.

The issue at hand (well, one of them) is that zsh treats

    declare var
as 
    declare var=

so you get different results from

    declare var
    [[ -v var ]]

in different shells.


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

end of thread, other threads:[~2016-09-16  3:14 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-09-05 21:27 [PATCH] Use == in expressions instead of the deprecated = Teubel György
2016-09-08  8:35 ` Peter Stephenson
2016-09-08 11:16   ` Peter Stephenson
2016-09-08 14:31     ` Stephane Chazelas
2016-09-08 15:06       ` Stephane Chazelas
2016-09-08 15:14       ` Peter Stephenson
2016-09-08 16:39         ` Mikael Magnusson
2016-09-08 18:47           ` Stephane Chazelas
2016-09-09 12:03         ` Vincent Lefevre
     [not found]           ` <CGME20160912143133eucas1p11a4e6916dd70b3ceaa163bf3bddfb007@eucas1p1.samsung.com>
2016-09-12 14:31             ` Peter Stephenson
2016-09-09  8:52       ` Stephane Chazelas
2016-09-09  9:31         ` Peter Stephenson
2016-09-09 16:00           ` Stephane Chazelas
2016-09-14 22:01         ` PATCH: [[ -v varname ]] Oliver Kiddle
2016-09-15 10:55           ` Vincent Lefevre
2016-09-16  0:36             ` Bart Schaefer
2016-09-15 11:08           ` Stephane Chazelas
2016-09-15 11:22             ` wrong "export -p" output for exported but not set variables (Was: PATCH: [[ -v varname ]]) Stephane Chazelas
2016-09-09 17:01       ` [PATCH] Use == in expressions instead of the deprecated = Christian Neukirchen
2016-09-09 18:54         ` Stephane Chazelas
2016-09-09 13:05     ` Peter Stephenson

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