zsh-workers
 help / color / mirror / code / Atom feed
* Short loops?
@ 1997-02-26  2:13 Bart Schaefer
  1997-02-26 16:10 ` Zoltan T. Hidvegi
  0 siblings, 1 reply; 10+ messages in thread
From: Bart Schaefer @ 1997-02-26  2:13 UTC (permalink / raw)
  To: zsh-workers

Nobody responded to my message to zsh-users about `while LIST { LIST }`
syntax.  Is this syntax broken by accident or on purpose?

-- 
Bart Schaefer                             Brass Lantern Enterprises
http://www.well.com/user/barts            http://www.nbn.com/people/lantern


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

* Re: Short loops?
  1997-02-26  2:13 Short loops? Bart Schaefer
@ 1997-02-26 16:10 ` Zoltan T. Hidvegi
  1997-02-26 17:11   ` Bart Schaefer
  0 siblings, 1 reply; 10+ messages in thread
From: Zoltan T. Hidvegi @ 1997-02-26 16:10 UTC (permalink / raw)
  To: schaefer; +Cc: zsh-workers

Bart Schaefer wrote:
> Nobody responded to my message to zsh-users about `while LIST { LIST }`
> syntax.  Is this syntax broken by accident or on purpose?

Sorry for the silence.  I've got a new job and moved to the US, that's why
I was a bit silent recently.  I'd like to buy a computer at home within a
few weeks and than I'll have more time to work on zsh again.

So, the while syntax is not broken.  As you write above,
while LIST { LIST } works.  But

while foo ; { bar }

is just while LIST because foo ; { bar } is a list in itself.  The above
syntax only works if zsh can detect the end of the LIST before reading the
{.

This works:

integer i=0
while ((i++ < 10)) { echo $i }

That's because ((i++ < 10)) { echo $i } is not a valid listso zsh can
detect that the list ends in )).  Similarily [[ ... ]] { ... } works as
well.  It is the same as

if [[ ... ]] then works without a semicolon before then but if true; then
doesn't.

Zoltan


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

* Re: Short loops?
  1997-02-26 16:10 ` Zoltan T. Hidvegi
@ 1997-02-26 17:11   ` Bart Schaefer
  1997-02-26 17:26     ` Zoltan T. Hidvegi
  0 siblings, 1 reply; 10+ messages in thread
From: Bart Schaefer @ 1997-02-26 17:11 UTC (permalink / raw)
  To: Zoltan T. Hidvegi; +Cc: zsh-workers

On Feb 26, 11:10am,  (Zoltan T. Hidvegi) wrote:
> Subject: Re: Short loops?
>
> So, the while syntax is not broken.  As you write above,
> while LIST { LIST } works.  But
> 
> while foo ; { bar }
> 
> is just while LIST because foo ; { bar } is a list in itself.  The above
> syntax only works if zsh can detect the end of the LIST before reading the
> {.

The doc ought to get changed, then.  The two entries for `while' (and
similarly for all the "short" variants) read:

`while LIST do LIST done'
`while LIST { LIST }'

The first and second uses of LIST both require either a newline or a
trailing semicolon; the fourth use of LIST may have a newline or a
semicolon or not, without affecting the result; and the third use
requires not only that there NOT be a newline or semicolon, but also
that the list ends with a [[ ]] (( )) ( ) or { } construct.

This is, if you ask me, completely bogus from a consistency standpoint,
not only in the doc but in the behavior; but its worse that the doc
makes it appear consistent when it isn't.

Furthermore, it's not just the case that zsh must be able to "detect
the end of the list before reading the {" because this:

	while true { echo foo }

doesn't work either, yet `true { ...' is in no sense a valid list.

-- 
Bart Schaefer                             Brass Lantern Enterprises
http://www.well.com/user/barts            http://www.nbn.com/people/lantern


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

* Re: Short loops?
  1997-02-26 17:11   ` Bart Schaefer
@ 1997-02-26 17:26     ` Zoltan T. Hidvegi
  1997-02-26 19:09       ` Bart Schaefer
  0 siblings, 1 reply; 10+ messages in thread
From: Zoltan T. Hidvegi @ 1997-02-26 17:26 UTC (permalink / raw)
  To: schaefer; +Cc: Zsh workers list

Bart Schaefer wrote:
> The doc ought to get changed, then.  The two entries for `while' (and
> similarly for all the "short" variants) read:
>
> `while LIST do LIST done'
> `while LIST { LIST }'
>
> The first and second uses of LIST both require either a newline or a
> trailing semicolon; the fourth use of LIST may have a newline or a
> semicolon or not, without affecting the result; and the third use
> requires not only that there NOT be a newline or semicolon, but also
> that the list ends with a [[ ]] (( )) ( ) or { } construct.

No.  No one of the above four LIST require any trailing semicolons or
newlines.  As decribed in the manual, reserved words like do, done, { are
only recognized in command position.  If you write while true { ... } then
{ is not in command position, it is simply an argument to true.  Words are
in command position after a newline or a semicolon or after )) or ]] or
after do, then, {, } etc.  Zsh has to know that { is not a simple argument
to a command, but a reserved word.  The { echo } case works and seems to be
an exception to this rule but is really a pathologic special case handled
explicitely in lex.c and it only works if ignorebraces is not set.  This
syntax worked in bash-1.14 but it no longer works in bash-2.0 because it
violates POSIX.  When ignorebraces is set (e.g. in sh mode) the following
is perfectly valid:

while true { echo foo }
do
        ...
done

Here true is invoked with four arguments: {, echo, foo and }.

Zoltan


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

* Re: Short loops?
  1997-02-26 17:26     ` Zoltan T. Hidvegi
@ 1997-02-26 19:09       ` Bart Schaefer
  1997-02-26 19:27         ` Zoltan T. Hidvegi
  0 siblings, 1 reply; 10+ messages in thread
From: Bart Schaefer @ 1997-02-26 19:09 UTC (permalink / raw)
  To: Zoltan T. Hidvegi; +Cc: Zsh workers list

On Feb 26, 12:26pm,  (Zoltan T. Hidvegi) wrote:
> Subject: Re: Short loops?
>
> Bart Schaefer wrote:
> > The doc ought to get changed, then.  The two entries for `while' (and
> > similarly for all the "short" variants) read:
> >
> > `while LIST do LIST done'
> > `while LIST { LIST }'
> >
> > The first and second uses of LIST both require either a newline or a
> > trailing semicolon; the fourth use of LIST may have a newline or a
> > semicolon or not, without affecting the result; and the third use
> > requires not only that there NOT be a newline or semicolon, but also
> > that the list ends with a [[ ]] (( )) ( ) or { } construct.
> 
> No.  No one of the above four LIST require any trailing semicolons or
> newlines.  As decribed in the manual, reserved words like do, done, { are
> only recognized in command position.  [....]  Words are
> in command position after a newline or a semicolon or after )) or ]] or
> after do, then, {, } etc.

Which just means that `do' must be *preceded* by a newline or semicolon
or whatever.  Whether it's the list that requires it or the reserved word
that requires it, the effect is the same and the info's syntax summary is
misleading.  The /bin/sh manual can get away with `while LIST do LIST done'
because in /bin/sh the semicolon or newline at the end of a LIST is never
optional (the definition of LIST *includes* the trailing separator in the
/bin/sh manuals).

Just because there's an explanation somewhere else that says that `do' is
only recognized in command position, doesn't mean the manual can get away
with being sloppy in the syntax summary.  It's OK if you want to use LIST
the way that it is used in `while LIST do LIST done', but in that case:

> Zsh has to know that { is not a simple argument
> to a command, but a reserved word.

That's not a sufficient explanation either!  It has to be not just a
reserved word, but a reserved word in a spot where that particular word
doesn't have an alternate meaning -- which means after )) or ]] or ) or },
but NOT after semicolon or newline.  Which is *not the same* as the rule
for where `do' can appear, which IMHO should mean that the syntax summary
should NOT be written `while LIST { LIST }'.

The doc could define a CLOSED construct to be any of (( )) [[ ]] ( ) { },
and define a CLOSEDLIST to be a LIST ending with a CLOSED but that is NOT
followed by the optional separator.  Then it could say:

`if CLOSEDLIST { LIST } [ elif CLOSEDLIST { LIST } ] ... [ else { LIST } ]'
`if CLOSEDLIST SUBLIST'
`while CLOSEDLIST { LIST }'
`until CLOSEDLIST { LIST }'

And then I'd be happy.

> The { echo } case works and seems to be
> an exception to this rule but is really a pathologic special case handled
> explicitely in lex.c and it only works if ignorebraces is not set.

I don't know what you're talking about here at all, I fear.  An exception
to which rule?  `}' is recognized *everywhere* when ignorebraces is not
set.  Which seems bizarre to me anyway -- if `{' is not recognized every-
where, then `}' ought to be recognized only when an unmatched reserved `{'
has preceded it.  One more state flag in the lexer could fix that.

-- 
Bart Schaefer                             Brass Lantern Enterprises
http://www.well.com/user/barts            http://www.nbn.com/people/lantern


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

* Re: Short loops?
  1997-02-26 19:09       ` Bart Schaefer
@ 1997-02-26 19:27         ` Zoltan T. Hidvegi
  1997-02-26 21:14           ` Bart Schaefer
  0 siblings, 1 reply; 10+ messages in thread
From: Zoltan T. Hidvegi @ 1997-02-26 19:27 UTC (permalink / raw)
  To: schaefer; +Cc: hzoli, zsh-workers

Bart Schaefer wrote:
> misleading.  The /bin/sh manual can get away with `while LIST do LIST done'
> because in /bin/sh the semicolon or newline at the end of a LIST is never
> optional (the definition of LIST *includes* the trailing separator in the
> /bin/sh manuals).

Then the /bin/sh manual is wrong.  if (true) then (echo foo) fi works fine
in sh.  Of course any corrections to the manual are welcome.  The manual
now contains a more or less full formal description of the grammar, but I
agree, that it may be hard to interpret it correctly.  In general, it is
not easy to describe the exact grammar of the shell in such a way that it
is easy to understand for the human readers.  Note that ksh has the same
problems here as zsh.  In sh/ksh the question is when is it possible to
omit the semicolon/newline before `then'.  In zsh the brace syntax
complicates this a bit, but it is really the same problem.  If the
newline/semicolon can be omitted in a while LIST do statement then the
while LIST { ... } syntax will work as well.

> > Zsh has to know that { is not a simple argument
> > to a command, but a reserved word.
>
> That's not a sufficient explanation either!  It has to be not just a
> reserved word, but a reserved word in a spot where that particular word
> doesn't have an alternate meaning -- which means after )) or ]] or ) or },
> but NOT after semicolon or newline.  Which is *not the same* as the rule
> for where `do' can appear, which IMHO should mean that the syntax summary
> should NOT be written `while LIST { LIST }'.

If you interpret LIST as the longest string which is synactically a list
than it is correct.  In while true ; { echo foo } the longest possible list
is true ; { echo foo }.  Zsh just parses the list as long as it can, and
when the list parses sees something that cannot continue a list it returns.

>
> The doc could define a CLOSED construct to be any of (( )) [[ ]] ( ) { },
> and define a CLOSEDLIST to be a LIST ending with a CLOSED but that is NOT
> followed by the optional separator.  Then it could say:
>
> `if CLOSEDLIST { LIST } [ elif CLOSEDLIST { LIST } ] ... [ else { LIST } ]'
> `if CLOSEDLIST SUBLIST'
> `while CLOSEDLIST { LIST }'
> `until CLOSEDLIST { LIST }'
>
> And then I'd be happy.

Yes, but that would make the manual quite verbose repeating the same thing
many times.

> > The { echo } case works and seems to be
> > an exception to this rule but is really a pathologic special case handled
> > explicitely in lex.c and it only works if ignorebraces is not set.
>
> I don't know what you're talking about here at all, I fear.  An exception
> to which rule?  `}' is recognized *everywhere* when ignorebraces is not

} is a reserved word, and it should be recognized only in command position.
But it is recognized in other places as well.

> set.  Which seems bizarre to me anyway -- if `{' is not recognized every-
> where, then `}' ought to be recognized only when an unmatched reserved `{'
> has preceded it.  One more state flag in the lexer could fix that.

{ cannot mean command grouping in echo { ... } just line echo ( ... ) does
not do that.  The later is a syntax error in sh.  And I think it would be
even more confusing if echo } works but it stops working after you put it
into a while loop using { ... }.

Zoltan


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

* Re: Short loops?
  1997-02-26 19:27         ` Zoltan T. Hidvegi
@ 1997-02-26 21:14           ` Bart Schaefer
  1997-02-27  9:32             ` Peter Stephenson
  0 siblings, 1 reply; 10+ messages in thread
From: Bart Schaefer @ 1997-02-26 21:14 UTC (permalink / raw)
  To: Zoltan T. Hidvegi; +Cc: zsh-workers

On Feb 26,  2:27pm,  (Zoltan T. Hidvegi) wrote:
> Subject: Re: Short loops?
>
> Bart Schaefer wrote:
> > misleading.  The /bin/sh manual can get away with `while LIST do LIST done'
> > because in /bin/sh the semicolon or newline at the end of a LIST is never
> > optional (the definition of LIST *includes* the trailing separator in the
> > /bin/sh manuals).
> 
> Then the /bin/sh manual is wrong.  if (true) then (echo foo) fi works fine
> in sh.

Hmm.  Yup, you're right; I dug up my hardcopy of the 4.2 BSD `sh' man page.
I withdraw that objection.

Nevertheless, the point is that the "optional" terminator mentioned in the
definition of a "list" is not optional in the short forms.  It *must* be
left out.

> > The doc could define a CLOSED construct to be any of (( )) [[ ]] ( ) { },
> > and define a CLOSEDLIST to be a LIST ending with a CLOSED but that is NOT
> > followed by the optional separator.
> 
> Yes, but that would make the manual quite verbose repeating the same thing
> many times.

Why would that cause it to repeat itself more than it already does?

However, if something close to this text:

} If you interpret LIST as the longest string which is synactically a list
} than it is correct.  In while true ; { echo foo } the longest possible list
} is true ; { echo foo }.

were added to the section on alternate forms, that would probably clarify
enough.  Maybe also move the reserved words section above the alternate
forms, but that helps only when reading sequentially through the info.

Peter, how about adding something about this to the FAQ as well?

-- 
Bart Schaefer                             Brass Lantern Enterprises
http://www.well.com/user/barts            http://www.nbn.com/people/lantern


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

* Re: Short loops?
  1997-02-26 21:14           ` Bart Schaefer
@ 1997-02-27  9:32             ` Peter Stephenson
  1997-02-27 15:06               ` Zoltan T. Hidvegi
  1997-02-27 18:16               ` Bart Schaefer
  0 siblings, 2 replies; 10+ messages in thread
From: Peter Stephenson @ 1997-02-27  9:32 UTC (permalink / raw)
  To: Zsh hackers list

"Bart Schaefer" wrote:
> Peter, how about adding something about this to the FAQ as well?

It looks like I should be adding two things to the FAQ.  This is the
deyodled text.


3.6: Why does zsh not work in an Emacs shell mode any more?

  (The following is from Bart Schaefer again):

  Emacs 19.29 or thereabouts stopped using a terminal type of "emacs"
  in shell buffers, and instead sets it to "dumb".  Zsh only kicks in
  its special I'm-inside-emacs initialization when the terminal type
  is "emacs".

  Placing a

    (setenv "TERM" "emacs")

  in your ~/.emacs file seems to fix this.  If that confuses other programs
  that are run from within emacs, you can instead use

    (setenv "ESHELL" "~/bin/eshell")

  and then put `TERM=emacs exec zsh' in the file ~/bin/eshell.


3.16: How does the alternative loop syntax, e.g. `while {...} {...}' work?

  Zsh provides an alternative to the traditional sh-like forms with `do',

    while TEST; do COMMANDS; done

  allowing you to have the COMMANDS delimited with some other command
  structure, often `{...}'.  However, to make this work you must make
  sure the TEST itself is clearly delimited.  For example, this works:

    while (( i++ < 10 )) { echo i is $i; }

  but this does _not_:

    while let "i++ < 10"; { echo i is $i; }   # Wrong!

  The reason is that after `while', any sort of command list is valid.
  This includes the whole list `let "i++ < 10"; { echo i $i; }';
  the parser simply doesn't know when to stop.  Furthermore, it is
  wrong to miss out the semicolon, as this makes the `{...}' part
  of the argument to `let'.

  So when using this syntax, the test following the `while' must
  be wrapped up:  any of `((...))', `[[...]]', `{...}' or
  `(...)' will have this effect.  (They have their usual syntactic
  meanings too, of course; they are not interchangeable.)  Note that
  here too it is wrong to put in the semicolon, as then the case
  becomes identical to the preceding one:

    while (( i++ < 10 )); { echo i is $i; }   # Wrong!

  The same is true of the `if' and `until' constructs:

    if { true } { echo yes } else { echo no }

  but with `for', which only needs a list of words, you can get
  away with it:

    for foo in a b; { echo foo is $a; bar=$foo; }

  since the parser knows it only needs everything up to the first
  semicolon. For the same reason, there is no problem with the `repeat',
  `case' or `select' constructs; in fact, `repeat' doesn't even
  need the semicolon since it knows the repeat count is just one word.

  This is independent of the behaviour of the SHORTLOOPS option (see
  manual), which you are in any case encouraged not to use in programs
  as it can be very confusing.

-- 
Peter Stephenson <pws@ifh.de>       Tel: +49 33762 77366
WWW:  http://www.ifh.de/~pws/       Fax: +49 33762 77413
Deutsches Elektronen-Synchrotron --- Institut fuer Hochenergiephysik Zeuthen
DESY-IfH, 15735 Zeuthen, Germany.


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

* Re: Short loops?
  1997-02-27  9:32             ` Peter Stephenson
@ 1997-02-27 15:06               ` Zoltan T. Hidvegi
  1997-02-27 18:16               ` Bart Schaefer
  1 sibling, 0 replies; 10+ messages in thread
From: Zoltan T. Hidvegi @ 1997-02-27 15:06 UTC (permalink / raw)
  To: Peter Stephenson; +Cc: zsh-workers

Peter Stephenson wrote:
>     while (( i++ < 10 )); { echo i is $i; }   # Wrong!

I would add that

while (( i++ < 10 ))
{
        echo i is $i
}

is also wrong, since newline behaves line a semicolon.  And I would not
encourage the usage of this brace syntax in scrips because these syntax
rules are quite complicated.  The old sh syntax do not have these hidden
traps.  A lengthy discussion of this syntax in the FAQ may seem to
encourage the usage.

Zoltan


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

* Re: Short loops?
  1997-02-27  9:32             ` Peter Stephenson
  1997-02-27 15:06               ` Zoltan T. Hidvegi
@ 1997-02-27 18:16               ` Bart Schaefer
  1 sibling, 0 replies; 10+ messages in thread
From: Bart Schaefer @ 1997-02-27 18:16 UTC (permalink / raw)
  To: Peter Stephenson, Zsh hackers list

On Feb 27, 10:32am, Peter Stephenson wrote:
} Subject: Re: Short loops?
}
} "Bart Schaefer" wrote:
} > Peter, how about adding something about this to the FAQ as well?
} 
} It looks like I should be adding two things to the FAQ.  This is the
} deyodled text.
} 
} 3.6: Why does zsh not work in an Emacs shell mode any more?
} 
}   Placing a
} 
}     (setenv "TERM" "emacs")
} 
}   in your ~/.emacs file seems to fix this.

This may not be universal, based on the discussion on zsh-users.  It
appears to work for the default shell-mode (shell.el) but not for the
enhanced shell-mode supplied by comint (comint.el).

Looking at the lisp code in comint.el, it appears emacs forces TERM=dumb
for systems where emacs is compiled with terminfo, and TERM=emacs for
those where it's compiled with termcap.  There's no hook to override
this; you can only redefine comint-exec-1 as in the sample I sent, which
is bad if comint gets upgraded.

This:

}   that are run from within emacs, you can instead use
} 
}     (setenv "ESHELL" "~/bin/eshell")
} 
}   and then put `TERM=emacs exec zsh' in the file ~/bin/eshell.

ought to work in either case, though for the FAQ I'd restate it as

    and then put

      #!/bin/sh
      TERM=emacs exec zsh

   in the file ~/bin/eshell, and `chmod +x ~/bin/eshell'.

Finally I'd add (via Alain Caron <alainc@nortel.ca>):

   If none of the above works, place

      [[ -n "$EMACS" ]] && unsetopt zle

   in your $ZDOTDIR/.zshrc file.

If you want to say something about terminal mode:

   [[ -n "$EMACS" ]] && {
     [[ "$TERM" = eterm ]] && TERM=vt100 || unsetopt zle
   }

} 3.16: How does the alternative loop syntax, e.g. `while {...} {...}' work?

I agree with Zoltan's remarks about this; particularly about stronger
admonition to avoid the short forms in scripts.

-- 
Bart Schaefer                             Brass Lantern Enterprises
http://www.well.com/user/barts            http://www.nbn.com/people/lantern


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

end of thread, other threads:[~1997-02-27 18:23 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1997-02-26  2:13 Short loops? Bart Schaefer
1997-02-26 16:10 ` Zoltan T. Hidvegi
1997-02-26 17:11   ` Bart Schaefer
1997-02-26 17:26     ` Zoltan T. Hidvegi
1997-02-26 19:09       ` Bart Schaefer
1997-02-26 19:27         ` Zoltan T. Hidvegi
1997-02-26 21:14           ` Bart Schaefer
1997-02-27  9:32             ` Peter Stephenson
1997-02-27 15:06               ` Zoltan T. Hidvegi
1997-02-27 18:16               ` Bart Schaefer

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