Subject: Re: bug#60846: 29.0.60; [PATCH] Add more documentation about Eshell command invocation

From: Jim Porter <[email-masked]>
Date: Mon, 16 Jan 2023 12:18:13 -0800

On 1/16/2023 5:38 AM, Eli Zaretskii wrote:
> Thanks.

Thanks for the useful feedback as always.

>> +Unlike regular system shells, Eshell never invokes kernel functions
>> +directly, such as @code{exec(3)}.  Instead, it uses the Lisp functions
>> +available in the Emacs Lisp library.  It does this by transforming the
>> +input line into a callable Lisp form.@footnote{To see the Lisp form
>> +that will be invoked, type: @samp{eshell-parse-command 'echo hello'}}
> 
> This should use the @kbd markup, like any command the user should
> type.  I also suggest to say explicitly that you mean to type this at
> the Eshell prompt, as it wasn't clear when I read it.

Fixed.

>> +The command can be either an Elisp function or an external command.
>> +Eshell looks for the command in the following order:
> 
> Here I would add a few useful index entries
> 
>    @cindex order of looking for commands
>    @cindex command look up, order

Done.

>> +@vindex eshell-prefer-lisp-functions
>> +If you would prefer to use ordinary Lisp functions over external
>> +programs, set the option @code{eshell-prefer-lisp-functions} to
>> +@code{t}.
> 
> I'm guessing this swaps the order of the two last candidates, but the
> text doesn't say that explicitly for some reason.  Just saying
> "prefer" is not enough when you have more than 2 candidates.

Good point. I added an extra sentence explicitly stating that the last 
two items are swapped in priority.

>> +In addition, you can @emph{combine} command forms and Lisp forms
>> +together into single statements, letting you use whatever form is the
>> +most convenient for expressing your intentions.
>> +
>> +@example
>> +~ $ ls *.patch > (format-time-string "%F.log")
>> +@end example
> 
> Either explain here the meaning of redirecting into a Lisp form, or
> add a cross-reference to where it is explained in detail.

Done both. I've explained what the command does as well as 
cross-referenced the globbing and redirection sections.

>> +specify an argument of some other data type, you can use a
>> +@ref{Invocation, Lisp form}:
> 
> This kind of cross-references is usually a bad idea in Texinfo: it
> looks nifty in HTML, but reads awkwardly in all other formats.  It is
> better to use the slightly wordier alternative:
> 
>    specify an argument of some other data type, you can use a Lisp form
>    (@pxref{Invocation}):

Ah ha, I didn't realize. Fixed.

From 7f4089975fb3894cb9af5e5e7913141385d823e6 Mon Sep 17 00:00:00 2001
From: Jim Porter <[email-masked]>
Date: Sun, 15 Jan 2023 18:35:31 -0800
Subject: [PATCH] Add more detail about how to invoke Eshell commands

* doc/misc/eshell.texi (Variables): Move footnote explaining "REPL"
from here...
(Top): ... to its first use here.
(Commands): Move explanation about kernel functions to here.
(Invocation): Describe command form and Lisp form.  Fix documentation
about priority of commands in command form.
(Arguments): Add a cross reference to the Invocation node.
---
 doc/misc/eshell.texi | 136 +++++++++++++++++++++++++++++++------------
 1 file changed, 100 insertions(+), 36 deletions(-)

diff --git a/doc/misc/eshell.texi b/doc/misc/eshell.texi
index fc7d52eb711..ecc7bc3a011 100644
--- a/doc/misc/eshell.texi
+++ b/doc/misc/eshell.texi
@@ -64,10 +64,11 @@ Top
 
 Eshell is a shell-like command interpreter implemented in Emacs Lisp.
 It invokes no external processes except for those requested by the
-user.  It is intended to be an alternative to the IELM (@pxref{Lisp Interaction, Emacs Lisp Interaction, , emacs, The Emacs Editor})
-REPL for Emacs @emph{and} with an interface similar to command shells
-such as @command{bash}, @command{zsh}, @command{rc}, or
-@command{4dos}.
+user.  It is intended to be an alternative to the IELM (@pxref{Lisp
+Interaction, Emacs Lisp Interaction, , emacs, The Emacs Editor})
+REPL@footnote{Short for ``Read-Eval-Print Loop''.} for Emacs
+@emph{and} with an interface similar to command shells such as
+@command{bash}, @command{zsh}, @command{rc}, or @command{4dos}.
 @c This manual is updated to release 2.4 of Eshell.
 
 @insertcopying
@@ -193,6 +194,13 @@ Commands
 chapter covers command invocations in Eshell, including the command
 history and invoking commands in a script file.
 
+Unlike regular system shells, Eshell never invokes kernel functions
+directly, such as @code{exec(3)}.  Instead, it uses the Lisp functions
+available in the Emacs Lisp library.  It does this by transforming the
+input line into a callable Lisp form.@footnote{To see the Lisp form
+that will be invoked, type this as the Eshell prompt:
+@kbd{eshell-parse-command 'echo hello'}}
+
 @menu
 * Invocation::
 * Arguments::
@@ -207,23 +215,16 @@ Commands
 
 @node Invocation
 @section Invocation
-Unlike regular system shells, Eshell never invokes kernel functions
-directly, such as @code{exec(3)}.  Instead, it uses the Lisp functions
-available in the Emacs Lisp library.  It does this by transforming the
-input line into a callable Lisp form.@footnote{To see the Lisp form that will be invoked, type: @samp{eshell-parse-command "echo hello"}}
+Eshell is both a command shell and an Emacs Lisp @acronym{REPL}.  As a
+result, you can invoke commands in two different ways: in @dfn{command
+form} or in @dfn{lisp form}.
 
-The command can be either an Elisp function or an external command.
-Eshell looks first for an alias (@pxref{Aliases}) with the same name as the
-command, then a built-in (@pxref{Built-ins}) or a function with the
-same name; if there is no match, it then tries to execute it as an
-external command.
-
-The semicolon (@code{;}) can be used to separate multiple command
-invocations on a single line.  You can also separate commands with
-@code{&&} or @code{||}. When using @code{&&}, Eshell will execute the
-second command only if the first succeeds (i.e.@: has an exit
-status of 0); with @code{||}, Eshell will execute the second command
-only if the first fails.
+You can use the semicolon (@code{;}) to separate multiple command
+invocations on a single line, executing each in turn.  You can also
+separate commands with @code{&&} or @code{||}. When using @code{&&},
+Eshell will execute the second command only if the first succeeds
+(i.e.@: has an exit status of 0); with @code{||}, Eshell will execute
+the second command only if the first fails.
 
 A command invocation followed by an ampersand (@code{&}) will be run
 in the background.  Eshell has no job control, so you can not suspend
@@ -232,12 +233,80 @@ Invocation
 can be controlled the same way as any other background process in
 Emacs.
 
+@subsection Command form
+Command form looks much the same as in other shells.  A command
+consists of arguments separated by spaces; the first argument is the
+command to run, with any subsequent arguments being passed to that
+command.
+
+@example
+~ $ echo hello
+hello
+@end example
+
+@cindex order of looking for commands
+@cindex command lookup order
+The command can be either an Elisp function or an external command.
+Eshell looks for the command in the following order:
+
+@enumerate
+@item
+As a command alias (@pxref{Aliases})
+
+@item
+As a built-in command (@pxref{Built-ins})
+
+@item
+As an external program
+
+@item
+As an ordinary Lisp function
+@end enumerate
+
+@vindex eshell-prefer-lisp-functions
+If you would prefer to use ordinary Lisp functions over external
+programs, set the option @code{eshell-prefer-lisp-functions} to
+@code{t}.  This will swap the lookup order of the last two items.
+
+You can also group command forms together into a subcommand with curly
+braces (@code{@{@}}).  This lets you use the output of a subcommand as
+an argument to another command, or within control flow statements
+(@pxref{Control Flow}).
+
+@example
+~ $ echo @{echo hello; echo there@}
+hellothere
+@end example
+
+@subsection Lisp form
+Lisp form looks like ordinary Emacs Lisp code, because that's what it
+is.  As a result, you can use any syntax normally available to an
+Emacs Lisp program (@pxref{Top, , , elisp, The Emacs Lisp Reference
+Manual}).
+
+@example
+~ $ (format "hello, %s" user-login-name)
+hello, user
+@end example
+
+In addition, you can @emph{combine} command forms and Lisp forms
+together into single statements, letting you use whatever form is the
+most convenient for expressing your intentions.
+
+@example
+~ $ ls *.patch > (format-time-string "%F.log")
+@end example
+
+This command writes a list of all files matching the glob pattern
+@code{*.patch} (@pxref{Globbing}) to a file named
+@code{@var{current-date}.log} (@pxref{Redirection}).
+
 @node Arguments
 @section Arguments
-Ordinarily, command arguments are parsed by Eshell as either strings
+Ordinarily, Eshell parses arguments in command form as either strings
 or numbers, depending on what the parser thinks they look like.  To
-specify an argument of some other data type, you can use an
-@ref{Dollars Expansion, Elisp expression}:
+specify an argument of some other data type, you can use a Lisp form
+(@pxref{Invocation}):
 
 @example
 ~ $ echo (list 1 2 3)
@@ -354,10 +423,6 @@ Built-ins
 sudo is an alias, defined as "*sudo $@@*"
 @end example
 
-@vindex eshell-prefer-lisp-functions
-If you would prefer to use the built-in commands instead of the external
-commands, set @code{eshell-prefer-lisp-functions} to @code{t}.
-
 Some of the built-in commands have different behavior from their
 external counterparts, and some have no external counterpart.  Most of
 these will print a usage message when given the @code{--help} option.
@@ -923,15 +988,14 @@ Built-ins
 @node Variables
 @section Variables
 @vindex eshell-prefer-lisp-variables
-Since Eshell is a combination of an Emacs @acronym{REPL}@footnote{
-Short for ``Read-Eval-Print Loop''.
-} and a command shell, it can refer to variables from two different
-sources: ordinary Emacs Lisp variables, as well as environment
-variables.  By default, when using a variable in Eshell, it will first
-look in the list of built-in variables, then in the list of
-environment variables, and finally in the list of Lisp variables.  If
-you would prefer to use Lisp variables over environment variables, you
-can set @code{eshell-prefer-lisp-variables} to @code{t}.
+Since Eshell is a combination of an Emacs @acronym{REPL} and a command
+shell, it can refer to variables from two different sources: ordinary
+Emacs Lisp variables, as well as environment variables.  By default,
+when using a variable in Eshell, it will first look in the list of
+built-in variables, then in the list of environment variables, and
+finally in the list of Lisp variables.  If you would prefer to use
+Lisp variables over environment variables, you can set
+@code{eshell-prefer-lisp-variables} to @code{t}.
 
 You can set variables in a few different ways.  To set a Lisp
 variable, you can use the command @samp{setq @var{name} @var{value}},
-- 
2.25.1