Subject: 29.0.50; Improve behavior of conditionals in Eshell
From: Jim Porter <[email-masked]>
To: [email-masked]
Date: Wed, 10 Aug 2022 19:43:22 -0700
List-Id: <debbugs-submit.debbugs.gnu.org>

In Eshell, you can use conditionals pretty much like you'd expect from 
other shells. Starting from 'emacs -Q -f eshell':

   ~ $ [ foo = foo ] && echo hi
   hi
   ~ $ [ foo = bar ] && echo hi
   ~ $ [ foo = foo ] || echo hi
   ~ $ [ foo = bar ] || echo hi
   hi
   ~ $ if {[ foo = foo ]} {echo yes} {echo no}
   yes
   ~ $ if {[ foo = bar ]} {echo yes} {echo no}
   no

However, that only works for external commands. If the command is 
implemented in Lisp, it doesn't work:

   ~ $ (zerop 0) && echo hi
   t
   hi
   ~ $ (zerop 1) && echo hi
   hi  ;; Shouldn't say hi.

That's because the exit status is always 0 for Lisp commands. This works 
correctly for external commands:

   ~ $ [ foo = foo ]; echo status $? result $$
   ("status" 0 "result" nil)
   ~ $ [ foo = bar ]; echo status $? result $$
   ("status" 1 "result" nil)

But not for Lisp commands:

   ~ $ (zerop 0); echo status $? result $$
   t
   ("status" 0 "result" t)
   ~ $ (zerop 1); echo status $? result $$
   ("status" 0 "result" nil)
   ~ $ (zerop "foo"); echo status $? result $$
   Wrong type argument: number-or-marker-p, "foo"
   ("status" 0 "result" nil)

The manual says that the status should be 1 when a Lisp command fails, 
but it's 0 no matter what, even if it signaled an error. (Likewise, the 
manual says that the "result" variable should be t for successful 
external commands, but it's always nil.)

Similarly to the above, you can't use variable expansions for conditionals:

   ~ $ (setq foo t)
   t
   ~ $ if $foo {echo yes} {echo no}
   yes
   ~ $ (setq foo nil)
   ~ $ if $foo {echo yes} {echo no}
   yes  ;; Should say no.

Patch forthcoming. Just splitting it into two messages since it seemed 
more readable that way...