Commit graph

151 commits

Author SHA1 Message Date
Jim Porter
267fca267f Fix using background commands in 'eshell-command'
This regressed due to the patch for bug#53715, which changed how
Eshell pipelines return the processes in the pipeline (bug#62556).

* lisp/eshell/esh-cmd.el (eshell-parse-command): When creating
background commands, wrap the process(es) in a cons cell whose CAR is
':eshell-background'.  This lets us use fewer heuristics...
(eshell-eval-command): ... here.  Additionally, keep the result and
the incomplete delimiter separate.

* lisp/eshell/eshell.el (eshell-command): Check ':eshell-background'
and use a more-robust method for setting the output target.

* test/lisp/eshell/eshell-tests.el (eshell-test/eshell-command/simple)
(eshell-test/eshell-command/pipeline)
(eshell-test/eshell-command/background)
(eshell-test/eshell-command/background-pipeline): New tests.
2023-04-02 15:05:53 -07:00
Jim Porter
00144fa287 ; Add tests for synchronous processes in Eshell
Normally, Eshell only uses synchronous processes on MS-DOS, so this is
hard to test.  To get around this, let the tests explicitly request
synchronous processes.

* lisp/eshell/esh-proc.el (eshell-supports-asynchronous-processes):
New variable...
(eshell-gather-process-output): ... use it, and remove some incorrect
code updating Eshell's internal markers (the async code path doesn't
do this, so neither should the sync path).

* lisp/eshell/esh-cmd.el (eshell-execute-pipeline): Use
'eshell-supports-asynchronous-processes'.

* test/lisp/eshell/esh-proc-tests.el
(esh-proc-test/emacs-command): New function.
(esh-proc-test/emacs-echo, esh-proc-test/emacs-upcase): New variables.
(esh-proc-test/synchronous-proc/simple/interactive)
(esh-proc-test/synchronous-proc/simple/command-result)
(esh-proc-test/synchronous-proc/pipeline/interactive)
(esh-proc-test/synchronous-proc/pipeline/command-result): New tests.
2023-04-02 14:15:45 -07:00
Jim Porter
97e35b1498 Avoid shadowing variables in some Eshell command forms
* lisp/eshell/esh-cmd.el (eshell-rewrite-for-command): Make
'for-items' an uninterned symbol.
(eshell-as-subcommand): Correct docstring.
(eshell-do-command-to-value): Mark obsolete.
(eshell-command-to-value): Move binding of 'value' outside of the
macro's result, and remove call to 'eshell-do-command-to-value'.

* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/subcommand-shadow-value)
(esh-cmd-test/for-loop-for-items-shadow): New tests.
(esh-cmd-test/for-name-loop, esh-cmd-test/for-name-shadow-loop):
Rename to...
(esh-cmd-test/for-loop-name, esh-cmd-test/for-loop-name-shadow):
... these.
2023-04-01 16:24:31 -07:00
Jim Porter
cde38f0df3 Avoid parsing some Eshell forms when performing completion
During completion, we want to evaluate most Eshell forms
(e.g. variable references), but skip others (e.g. globbing,
subcommands).  For globbing, we want to pass the literal glob to
Pcomplete so it can use the glob for selecting completion candidates.
For subcommands (including Lisp forms), we especially want to avoid
evaluation, since they can produce arbitary side effects!  (Bug#50470)

* lisp/eshell/esh-cmd.el (eshell-allow-commands): New variable...
(eshell-commands-forbidden): New error...
(eshell-named-command, eshell-lisp-command): ... use them.

* lisp/eshell/em-cmpl.el (eshell-complete--eval-argument-form):
Disallow command forms and handle errors ourselves.
(eshell-complete-parse-arguments): Don't parse glob characters.

* test/lisp/eshell/em-cmpl-tests.el
(em-cmpl-test/parse-arguments/unevaluated-subcommand)
(em-cmpl-test/parse-arguments/unevaluated-lisp-form)
(em-cmpl-test/parse-arguments/unevaluated-inner-subcommand)
(em-cmpl-test/file-completion/glob, em-cmpl-test/command-completion)
(em-cmpl-test/subcommand-completion): New tests.
(em-cmpl-test/parse-arguments/pipeline): Remove superfluous
let-binding.
(em-cmpl-test/file-completion/after-list): Use a list variable rather
than a subexpression; the latter is no longer evaluated during
completion.
(em-cmpl-test/lisp-function-completion): Check "$(func)" syntax.
2023-03-28 12:03:29 -07:00
Jim Porter
bb088885df Simplify parsing subcommands slightly
This mainly reduces some overly-deep indentation, but also fixes some
minor issues with the "$<subcmd>" form: it unnecessarily added " >
TEMP" (we already set this later via 'eshell-create-handles'), and it
didn't properly unescape inner double quotes.

* lisp/eshell/esh-cmd.el (eshell-parse-subcommand-argument): Simplify.

* lisp/eshell/esh-var.el (eshell-parse-variable-ref): Simplify and
fix edge cases in "$<subcmd>".

* test/lisp/eshell/esh-var-tests.el
(esh-var-test/quoted-interp-temp-cmd): Adjust test to check behavior
of inner double quotes.
2023-03-28 12:02:46 -07:00
Jim Porter
5b005f26a8 ; Fix an edge case in how 'eshell-do-eval' handles 'let' bodies
* lisp/eshell/esh-cmd.el (ehell-do-eval): Use 'car-safe'; the object
in question might not be a cons cell.
2023-03-28 11:43:27 -07:00
Jim Porter
1565dbcae3 Simplify usage of 'while' forms in Eshell's iterative evaluation
Now, 'eshell-do-eval' rewrites 'while' forms to let-bind variables for
the command and test bodies.  This means that external code, such as
command rewriting hooks, no longer has to worry about this, making it
easier to pass "normal" Lisp forms to 'eshell-do-eval' (bug#61954).

* lisp/eshell/esh-cmd.el (eshell-command-body, eshell-test-body): No
longer used outside of 'eshell-do-eval', so rename to...
(eshell--command-body, eshell--test-body): ... these.
(Command evaluation macros): Remove obsolete description about 'if'
and 'while' forms.
(eshell-rewrite-for-command, eshell-structure-basic-command): Remove
'eshell-command-body' and 'eshell-test-body'.
(eshell-do-eval): Reimplement handling of 'while' forms.
2023-03-16 22:17:02 -07:00
Jim Porter
e01660ca50 Simplify how Eshell's iterative evaluation handles 'if' forms
The previous implementation used 'eshell-test-body' and
'eshell-command-body' to track the condition and the then/else forms,
but those special variables are only needed for looping.  'if' only
evaluates each form once at most (bug#61954).

* lisp/eshell/esh-cmd.el (Command evaluation macros): Remove 'if' from
the notes about 'eshell-test-body' and 'eshell-command-body'.
(eshell-do-eval): Reimplement evaluation of 'if' forms.
(eshell-eval-command): Don't let-bind 'eshell-command-body' and
'eshell-test-body'; they're no longer needed here.
2023-03-16 22:16:52 -07:00
Jim Porter
67a2b320f6 Simplify iteration in Eshell for loops
The previous code fixed an issue in Eshell's iterative evaluation
where deferred commands caused an infinite loop (see bug#12571).
However, with the fix to unwinding let forms in 'eshell-do-eval' (see
bug#59469), we can just write this code as we normally would
(bug#61954).

* lisp/eshell/esh-cmd.el (eshell-rewrite-for-command): Simplify.
2023-03-16 22:16:37 -07:00
Jim Porter
2f110132d7 ; Throw strings as the values for 'eshell-incomplete'
This lets us distinguish between cases like "'foo" and "$'foo".

* lisp/eshell/em-cmpl.el (eshell-complete-parse-arguments): Use
strings when checking the delimiter.

* lisp/eshell/em-glob.el (eshell-parse-glob-chars):
* lisp/eshell/em-pred.el (eshell-parse-arg-modifier):
* lisp/eshell/esh-arg.el (eshell-parse-backslash)
(eshell-parse-literal-quote, eshell-parse-double-quote)
(eshell-parse-special-reference):
* lisp/eshell/esh-cmd.el (eshell-parse-subcommand-argument)
(eshell-parse-lisp-argument):
* lisp/eshell/esh-var (eshell-parse-variable-ref)
(eshell-parse-indices): Throw strings instead of characters.

* lisp/eshell/esh-mode.el (eshell-parse-command-input): Print
delimiter as a string.
2023-02-23 14:09:36 -08:00
Jim Porter
c53255f677 Ensure that deferred commands don't make Eshell forget let-bound values
* lisp/eshell/esh-cmd.el (Command evaluation macros): Expand this
documentation to list allowed special forms and caveats for working
with 'if' and 'while'.
(eshell-do-eval): Provide more detail in docstring.  Handle
'eshell-defer' inside 'let' forms.

* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/let-rebinds-after-defer): New test (bug#59469).
2023-02-09 21:38:07 -08:00
Jim Porter
79154f625c Add regression tests for Eshell completions
* lisp/eshell/esh-cmd.el (eshell-complete-lisp-symbols): Fix
docstring.

* test/lisp/eshell/em-cmpl-tests.el: New file.
2023-01-30 17:49:11 -08:00
Eli Zaretskii
3c55fbd4ad Merge from origin/emacs-29
cae528457c ; Add 2023 to copyright years.
b394359261 Improve documentation of 'isearch-open-overlay-temporary'
ab3210e709 Document 'use-package' in the 2 main manuals

# Conflicts:
#	etc/refcards/ru-refcard.tex
#	lib/explicit_bzero.c
#	m4/explicit_bzero.m4
2023-01-01 05:47:47 -05:00
Eli Zaretskii
cae528457c ; Add 2023 to copyright years. 2023-01-01 05:31:12 -05:00
Jim Porter
073da412a1 Fix reference-counting of Eshell I/O handles
This ensures that output targets in Eshell are only closed when Eshell
is actually done with them.  In particular, this means that
"{ echo foo; echo bar } | rev" prints "raboof" as expected
(bug#59545).

* lisp/eshell/esh-io.el (eshell-create-handles): Structure the handles
differently so the targets and their ref-count can be shared.
(eshell-duplicate-handles): Reimplement this to share targets between
the original and new handle sets.  Add STEAL-P argument.
(eshell-protect-handles, eshell-copy-output-handle)
(eshell-interactive-output-p, eshell-output-object): Account for
changes to the handle structure.
(eshell-close-handle): New function...
(eshell-close-handles, eshell-set-output-handle): ... use it.
(eshell-get-targets): Remove.  This only existed to make the previous
implementation of 'eshell-duplicate-handles' work.

* lisp/eshell/esh-cmd.el (eshell-with-copied-handles): New argument
STEAL-P.
(eshell-do-pipelines): Use STEAL-P for the last item in the pipeline.
(eshell-parse-command): Don't copy handles for the last command in the
list; explain why we can't use STEAL-P here.
(eshell-eval-command): When queuing input, set 'eshell-command-body'
and 'eshell-test-body' for the 'if' conditional (see
'eshell-do-eval').

* test/lisp/eshell/esh-io-tests.el (esh-io-test/redirect-pipe): Split
into...
(esh-io-test/pipeline/default, esh-io-test/pipeline/all): ... these.
(esh-io-test/pipeline/subcommands): New test.

* test/lisp/eshell/esh-cmd-tests.el (esh-cmd-test/for-loop-pipe)
(esh-cmd-test/while-loop-pipe, esh-cmd-test/if-statement-pipe)
esh-cmd-test/if-else-statement-pipe): New tests.
(esh-cmd-test/while-loop): Use 'pop' to simplify the test a bit.

* test/lisp/eshell/eshell-test-helpers.el
(eshell-test--max-subprocess-time): Rename to...
(eshell-test--max-wait-time): ... this.
(eshell-wait-for): New function...
(eshell-wait-for-subprocess): ... use it.

* test/lisp/eshell/eshell-tests.el (eshell-test/queue-input): Fix this
test.  Previously, it didn't correctly verify that the original
command completed.

* test/lisp/eshell/em-tramp-tests.el
(em-tramp-test/should-replace-command): New macro...
(em-tramp-test/su-default, em-tramp-test/su-user)
(em-tramp-test/su-login, em-tramp-test/sudo-shell)
(em-tramp-test/sudo-user-shell, em-tramp-test/doas-shell)
(em-tramp-test/doas-user-shell): ... use it.
2022-12-29 22:38:25 -08:00
Jim Porter
6defbd65b6 Fix handling of output handles in nested Eshell forms
Previously, the output handles in nested forms would be reset to the
default, leading to wrong behavior for commands like

  {echo a; echo b} > file

"b" would be written to "file" as expected, but "a" would go to
standard output (bug#59545).

* lisp/eshell/esh-cmd.el (eshell-parse-command): Use
'eshell-with-copied-handles' for each statement within the whole
Eshell command.

* test/lisp/eshell/esh-io-tests.el (esh-io-test/redirect-subcommands)
(esh-io-test/redirect-subcommands/override)
(esh-io-test/redirect-subcommands/interpolated): New tests.

* test/lisp/eshell/em-script-tests.el
(em-script-test/source-script/redirect)
(em-script-test/source-script/redirect/dev-null): New tests.
(em-script-test/source-script, em-script-test/source-script/arg-vars)
(em-script-test/source-script/all-args-var): Tweak names/docstrings.

* test/lisp/eshell/em-extpipe-tests.el (em-extpipe-tests--deftest):
Skip over the newly-added 'eshell-with-copied-handles' form when
checking the parse results.

* test/lisp/eshell/em-tramp-tests.el (em-tramp-test/su-default)
(em-tramp-test/su-user, em-tramp-test/su-login)
(em-tramp-test/sudo-shell, em-tramp-test/sudo-user-shell)
(em-tramp-test/doas-shell, em-tramp-test/doas-user-shell): Update
expected command forms.
2022-12-22 11:35:12 -08:00
Jim Porter
54087e84df Add 'eshell-duplicate-handles' to return a copy of file handles
* lisp/eshell/esh-io.el (eshell-create-handles): Support creating with
multiple targets for stdout and/or stderr.  Make the targets for a
handle always be a list, and store whether the targets are the default
in a separate 'default' field.
(eshell-protect-handles, eshell-close-handles)
(eshell-copy-output-handle, eshell-interactive-output-p)
(eshell-output-object): Update for changes in 'eshell-create-handles'.
(eshell-duplicate-handles, eshell-get-targets): New functions.

* lisp/eshell/esh-cmd.el (eshell-copy-handles): Rename and alias to...
(eshell-with-copied-handles): ... this function, and use
'eshell-duplicate-handles'.
(eshell-execute-pipeline): Use 'eshell-duplicate-handles'.
2022-12-22 11:35:12 -08:00
Jim Porter
e63ef66c57 Add support for the "splice operator" in Eshell
This allows splicing lists in-place in argument lists, which is
particularly important when defining aliases using the '$*' special
variable (bug#59960).

* lisp/eshell/esh-var.el (eshell-parse-variable): Add support for the
splice operator.
(eshell-interpolate-variable): Let 'eshell-parse-variable' handle
adding 'eshell-escape-arg'.
(eshell-complete-variable-reference): Handle the splice operator.

* lisp/eshell/esh-arg.el (eshell-concat-groups)
(eshell-prepare-splice): New functions...
(eshell-resolve-current-argument): ... use them.
(eshell-splice-args): New function.

* lisp/eshell/esh-cmd.el (eshell-rewrite-named-command): Handle
'eshell-splice-args'.

* lisp/eshell/esh-util.el (eshell-list-to-string): New function...
(eshell-flatten-and-stringify): ... use it.

* lisp/eshell/em-cmpl.el (eshell-complete-parse-arguments): Remove
'eshell-splice-args' sigils in Eshell command forms so that we can
perform completion on splice-expansions.

* lisp/eshell/em-unix.el (eshell-complete-host-reference): Don't try
to complete arguments containing "$@".

* test/lisp/eshell/esh-var-tets.el (esh-var-test/interp-list-var)
(esh-var-test/interp-list-var-concat, esh-var-test/interp-var-splice)
(esh-var-test/interp-var-splice-concat)
(esh-var-test/quoted-interp-list-var)
(esh-var-test/quoted-interp-list-var-concat)
(esh-var-test/quoted-interp-var-splice)
(esh-var-test/quoted-interp-var-splice-concat): New tests.

* test/lisp/eshell/em-alias-tests.el
(em-alias-test/alias-all-args-var-splice): New test.

* doc/misc/eshell.texi (Dollars Expansion): Explain the splice
operator.
(Aliases): Expand documentation and use '$@*'.
(Built-ins, Bugs and Ideas): Use '$@*' where appropriate.

* etc/NEWS: Announce this change.
2022-12-15 21:41:03 -08:00
Jim Porter
fd4992d356 Print the correct $PATH when Eshell's 'which' fails to find a command
* lisp/eshell/esh-cmd.el (eshell/which): Use 'eshell-get-path'
(bug#20008).
2022-10-17 18:48:52 -07:00
Jim Porter
7c41016fca Allow setting the values of variable aliases in Eshell
This makes commands like "COLUMNS=40 some-command" work as expected.

* lisp/eshell/esh-cmd.el (eshell-subcommand-bindings): Remove
'process-environment' from here...

* lisp/eshell/esh-var.el (eshell-var-initialize): ... and add to here,
along with 'eshell-variable-aliases-list'.
(eshell-inside-emacs): Convert to a 'defvar-local' to make it settable
in a particular Eshell buffer.
(eshell-variable-aliases-list): Make $?, $$, and $* read-only and
update docstring.
(eshell-set-variable): New function...
(eshell-handle-local-variables, eshell/export, eshell/unset): ... use
it.
(eshell/set, pcomplete/eshell-mode/set): New functions.
(eshell-get-variable): Get the variable alias's getter function when
appropriate and use a safer method for checking function arity.

* test/lisp/eshell/esh-var-tests.el (esh-var-test/set/env-var)
(esh-var-test/set/symbol, esh-var-test/unset/env-var)
(esh-var-test/unset/symbol, esh-var-test/setq, esh-var-test/export)
(esh-var-test/local-variables, esh-var-test/alias/function)
(esh-var-test/alias/function-pair, esh-var-test/alias/string)
(esh-var-test/alias/string/prefer-lisp, esh-var-test/alias/symbol)
(esh-var-test/alias/symbol-pair, esh-var-test/alias/export)
(esh-var-test/alias/local-variables): New tests.

* doc/misc/eshell.texi (Built-ins): Add 'set' and update 'unset'
documentation.
(Variables): Expand documentation of how to get/set variables.
2022-10-17 18:48:52 -07:00
Stefan Monnier
d28581101a Remove redundant let-bindings of inhibit-point-motion-hooks
`inhibit-point-motion-hooks` has defaulted to t (and been declared
obsolete) since Emacs-25, so remove left-over bindings to that
now default value.

* lisp/dabbrev.el (dabbrev--search):
* lisp/format.el (format-insert-file):
* lisp/forms.el (forms-next-field, forms-prev-field):
* lisp/minibuf-eldef.el (minibuf-eldef-setup-minibuffer):
* lisp/simple.el (primitive-undo):
* lisp/cedet/semantic/edit.el (semantic-change-function):
* lisp/cedet/srecode/fields.el (srecode-field-mod-hook):
* lisp/cedet/srecode/insert.el (srecode-insert-fcn):
* lisp/erc/erc-button.el (erc-button-add-buttons):
* lisp/erc/erc.el (erc-display-line):
* lisp/eshell/em-script.el (eshell-source-file):
* lisp/eshell/em-smart.el (eshell-smart-scroll-window):
* lisp/eshell/esh-arg.el (eshell-parse-arguments):
* lisp/eshell/esh-cmd.el (eshell-with-temp-command):
* lisp/eshell/esh-mode.el (eshell-send-input, eshell-output-filter):
* lisp/gnus/gnus-art.el (gnus-with-article-headers)
(article-hide-headers, article-hide-boring-headers)
(article-decode-mime-words, article-decode-charset)
(article-decode-encoded-words, article-decode-group-name)
(article-decode-idna-rhs, article-hide-list-identifiers)
(article-strip-banner, article-really-strip-banner)
(article-strip-leading-blank-lines)
(article-strip-multiple-blank-lines, article-strip-leading-space)
(article-strip-trailing-space, article-strip-all-blank-lines)
(gnus-article-narrow-to-signature, gnus-article-show-hidden-text)
(article-date-ut, article-verify-x-pgp-sig)
(gnus-article-only-boring-p, gnus-article-highlight-signature)
(gnus-article-add-buttons, gnus-signature-toggle, gnus-button-push):
* lisp/gnus/gnus-cite.el (gnus-article-highlight-citation)
(gnus-article-fill-cited-article, gnus-article-hide-citation)
(gnus-article-toggle-cited-text, gnus-article-hide-citation-maybe)
(gnus-cite-parse-wrapper, gnus-cite-add-face, gnus-cite-toggle):
* lisp/gnus/gnus-gravatar.el (gnus-gravatar-insert):
* lisp/gnus/gnus-rfc1843.el (rfc1843-decode-article-body):
* lisp/gnus/gnus-sum.el (gnus-summary-toggle-header):
* lisp/gnus/gnus-util.el (gnus-fetch-field):
* lisp/gnus/message.el (message-fetch-field, message-reply)
(message-followup, message-hide-headers):
* lisp/net/goto-addr.el (goto-address-fontify):
* lisp/obsolete/linum.el (linum-update-window):
* lisp/play/zone.el (zone-shift-left, zone-shift-right)
(zone-fill-out-screen):
* lisp/progmodes/opascal.el (opascal-save-excursion):
* lisp/progmodes/vhdl-mode.el (vhdl-prepare-search-2):
* lisp/textmodes/enriched.el (enriched-encode):
* lisp/textmodes/flyspell.el (flyspell-word-search-backward)
(flyspell-word-search-forward):
* lisp/textmodes/table.el (table--point-entered/left-cell-function):
Remove let-binding of `inhibit-point-motion-hooks`.
2022-10-07 12:16:47 -04:00
Jim Porter
ab7e94fb1d Add support for more kinds of redirect operators in Eshell
* lisp/eshell/esh-arg.el: Require cl-lib.
(eshell-finish-arg): Allow passing multiple ARGUMENTS.
(eshell-quote-argument): Handle the case when 'eshell-finish-arg' was
passed multiple arguments.

* lisp/eshell/esh-cmd.el (eshell-do-pipelines)
(eshell-do-pipelines-synchronously): Only set stdout output handle.

* lisp/eshell/esh-io.el (eshell-redirection-operators-alist): New
constant.
(eshell-io-initialize): Prefer sharp quotes for functions.
(eshell-parse-redirection, eshell-strip-redirections): Add support for
more redirection forms.
(eshell-copy-output-handle, eshell-set-all-output-handles): New
functions.

* test/lisp/eshell/esh-io-tests.el
(esh-io-test/redirect-all/overwrite, esh-io-test/redirect-all/append)
(esh-io-test/redirect-all/insert, esh-io-test/redirect-copy)
(esh-io-test/redirect-copy-first, esh-io-test/redirect-pipe): New
tests.

* doc/misc/eshell.texi (Redirection): Document new redirection syntax.
(Pipelines): Document '|&' syntax.
(Bugs and ideas): Update item about redirection syntax.

* etc/NEWS: Announce this change.
2022-09-04 15:15:01 -07:00
Jim Porter
f9250c5ebc Handle 'eshell-pipe-broken' when evaluating Lisp forms in Eshell
* lisp/eshell/esh-cmd.el (eshell-exec-lisp): Handle
'eshell-pipe-broken'.

* lisp/eshell/esh-io.el (eshell-output-object-to-target): Only signal
'eshell-pipe-broken' if the process being written to has finished.

* test/lisp/eshell/esh-proc-tests.el
(esh-proc-test/pipeline-connection-type/middle)
(esh-proc-test/pipeline-connection-type/last): Remove ':unstable'.

Ref: https://lists.gnu.org/archive/html/emacs-devel/2022-08/msg00524.html
2022-08-29 20:16:31 -07:00
Jim Porter
cf873c1a09 Fix non-interactive use of conditionals in Eshell
* lisp/eshell/esh-cmd.el (eshell-rewrite-if-command): Fix misplaced
't' symbol; it should be passed to 'eshell-invokify-arg'.
(eshell-do-eval): Pass 'synchronous-p' to recursive calls in some
missing cases.

* test/lisp/eshell/esh-cmd-tests.el (esh-cmd-test/if-statement,
(esh-cmd-test/if-else-statement)
(esh-cmd-test/if-else-statement-lisp-form)
(esh-cmd-test/if-else-statement-lisp-form-2)
(esh-cmd-test/if-else-statement-ext-cmd)
(esh-cmd-test/unless-statement)
(esh-cmd-test/unless-else-statement)
(esh-cmd-test/unless-else-statement-lisp-form)
(esh-cmd-test/unless-else-statement-ext-cmd): Use
'eshell-command-result-equal'.
2022-08-15 20:40:27 -07:00
Jim Porter
f3408af0a3 Make '$?' and '$$' variables more consistent in Eshell
Previously, '$?' (last exit code) was only useful for external
commands, and '$$' (last result) was only useful for Lisp commands.

* lisp/eshell/esh-cmd.el (eshell-lisp-form-nil-is-failure): New
option.
(eshell-lisp-command): Set last exit code to 1 when the command
signals an error, and 2 if it returns nil (for Lisp forms only).

* lisp/eshell/esh-proc.el (eshell-sentinel): Set last result to t if
the command succeeded.

* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/while-loop-lisp-form, esh-cmd-test/until-loop-lisp-form)
(esh-cmd-test/if-else-statement-lisp-form)
(esh-cmd-test/if-else-statement-lisp-form-2)
(esh-cmd-test/unless-else-statement-lisp-form): New tests.

* test/lisp/eshell/esh-var-tests.el
(esh-var-test/last-status-var-lisp-command)
(esh-var-test/last-status-var-lisp-form)
(esh-var-test/last-status-var-lisp-form-2)
(esh-var-test/last-status-var-ext-cmd)
(esh-var-test/last-status-var-ext-cmd): New tests.
(esh-var-test/last-result-var2): Rename from this...
( esh-var-test/last-result-var-twice): ... to this.

* doc/misc/eshell.texi (Variables): Update documentation about '$?'
and '$$'.
(Control Flow): Mention that '(lisp forms)' can be used as
conditionals.

* etc/NEWS: Announce this change (bug#57129).
2022-08-12 22:07:13 -07:00
Jim Porter
9d4fa4ed4b Allow using dollar expansions in Eshell conditionals
* lisp/eshell/esh-cmd.el (eshell-structure-basic-command): Forms
beginning with 'eshell-escape-arg' are "data-wise".

* test/lisp/eshell/esh-cmd-tests.el (esh-cmd-test/while-loop)
(esh-cmd-test/until-loop, esh-cmd-test/if-statement)
(esh-cmd-test/if-else-statement, esh-cmd-test/unless-statement)
(esh-cmd-test/unless-else-statement): Use variable interpolation.
(esh-cmd-test/while-loop-ext-cmd, esh-cmd-test/until-loop-ext-cmd)
(esh-cmd-test/if-else-statement-ext-cmd)
(esh-cmd-test/unless-else-statement-ext-cmd): New tests, adapted from
the existing ones.

* doc/misc/eshell.texi (Control Flow): Update documentation for
conditionals (bug#57129).
2022-08-12 22:07:13 -07:00
Jim Porter
30320d9420 Only set Eshell execution result metavariables when non-nil
This simplifies usage of 'eshell-close-handles' in several places and
makes it work more like the docstring indicated it would.

* lisp/eshell/esh-io.el (eshell-close-handles): Only store EXIT-CODE
and RESULT if they're non-nil.  Also, use 'dotimes' and 'dolist' to
simplify the implementation.

* lisp/eshell/em-alias.el (eshell-write-aliases-list):
* lisp/eshell/esh-cmd.el (eshell-rewrite-for-command)
(eshell-structure-basic-command): Adapt calls to
'eshell-close-handles'.

* test/lisp/eshell/eshell-tests.el (eshell-test/simple-command-result)
(eshell-test/lisp-command, eshell-test/lisp-command-with-quote)
(eshell-test/for-loop, eshell-test/for-name-loop)
(eshell-test/for-name-shadow-loop, eshell-test/lisp-command-args)
(eshell-test/subcommand, eshell-test/subcommand-args)
(eshell-test/subcommand-lisp): Move from here...

* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/simple-command-result, esh-cmd-test/lisp-command)
(esh-cmd-test/lisp-command-with-quote, esh-cmd-test/for-loop)
(esh-cmd-test/for-name-loop, esh-cmd-test/for-name-shadow-loop)
(esh-cmd-test/lisp-command-args, esh-cmd-test/subcommand)
(esh-cmd-test/subcommand-args, esh-cmd-test/subcommand-lisp): ... to
here.
(esh-cmd-test/and-operator, esh-cmd-test/or-operator)
(esh-cmd-test/for-loop-list, esh-cmd-test/for-loop-multiple-args)
(esh-cmd-test/while-loop, esh-cmd-test/until-loop)
(esh-cmd-test/if-statement, esh-cmd-test/if-else-statement)
(esh-cmd-test/unless-statement, esh-cmd-test/unless-else-statement):
New tests.

* doc/misc/eshell.texi (Invocation): Explain '&&' and '||'.
(for loop): Move from here...
(Control Flow): ... to here, and add documentation for other control
flow forms.
2022-08-12 22:07:13 -07:00
Jim Porter
0a79e28891 Reset 'eshell-in-pipeline-p' when interpolating commands
* lisp/eshell/esh-cmd.el (eshell-subcommand-bindings)
(eshell-command-to-value): Set 'eshell-in-pipeline-p' to nil.

* test/lisp/eshell/eshell-tests.el
(eshell-test/subcommand-reset-in-pipeline)
(eshell-test/lisp-reset-in-pipeline): New tests (bug#55620).
2022-05-25 14:13:07 +02:00
Jim Porter
a49ecdd0ff Keep subcommands in pipelines from clobbering the head/tail processes
* lisp/eshell/esh-cmd.el (eshell-execute-pipeline): Use 'make-symbol'
for headproc and tailproc.
(eshell-do-pipelines, eshell-do-pipelines-synchronously): Adapt to the
above.

* test/lisp/eshell/eshell-tests.el (eshell-test/pipe-subcommand)
(eshell-test/pipe-subcommand-with-pipe): New test.

* doc/misc/eshell.texi (Bugs and ideas): Remove item about piping to
process from loop; this commit fixes it (bug#55590).
2022-05-24 14:58:00 +02:00
Jim Porter
6358cbc21a Add unit tests and documentation for Eshell predicates/modifiers
* lisp/eshell/esh-cmd.el (eshell-eval-argument): New function.
* lisp/eshell/esh-util.el (eshell-file-attributes): Pass original
value of FILE to 'file-attributes'.
* lisp/eshell/em-pred.el (eshell-predicate-alist): Change socket char
to '=', since 's' conflicts with setuid.
(eshell-modifier-alist): Fix 'E' (eval) modifier by using
'eshell-eval-argument'.  Also improve performance of 'O' (reversed
sort) modifier.
(eshell-modifier-help-string): Fix documentation of global
substitution modifier.
(eshell-pred-substitute): Fix infinite loop in some global
substitutions.
(eshell-join-members): Fix joining with implicit " " delimiter.
(Bug#54470)

* test/lisp/eshell/em-pred-tests.el: New file.

* doc/misc/eshell.texi (Argument Predication): New section.
2022-04-17 10:28:23 +03:00
Jim Porter
58568033f4 Improve wording of Eshell variable interpolation code/documentation
* lisp/eshell/esh-arg.el (eshell-unescape-inner-double-quote): Rename
from 'eshell-parse-inner-double-quote'.

* lisp/eshell/esh-cmd.el (eshell-with-temp-command): Improve
docstring.

* lisp/eshell/esh-var.el (eshell-parse-variable-ref): Use
'eshell-unescape-inner-double-quote' and improve robustness of quoted
variable name matching.
(eshell-parse-indices): Use 'eshell-unescape-inner-double-quote'.

* doc/misc/eshell.texi (Dollars Expansion): Improve wording of
subscript notation.
2022-03-08 15:54:16 +02:00
Jim Porter
ae1acb6017 Add a new macro to simplify parsing temporary Eshell command strings
This abstracts out the somewhat-unusual "insert&delete" logic in
'eshell-parse-command' so that it can be used elsewhere, and also
ensures that the deletion occurs even if an an error occurs.

* lisp/eshell/esh-cmd.el (eshell-with-temp-command): New macro.
(eshell-parse-command): Use it.
2022-03-03 14:59:33 +01:00
Jim Porter
76b91671a1 Improve docstrings for 'eshell-exec-lisp' and functions that call it
* lisp/eshell/esh-cmd.el (eshell-exec-lisp, eshell-apply*)
(eshell-funcall*, eshell-eval*, eshell-apply, eshell-eval)
(eshell-funcall, eshell-applyn, eshell-funcalln, eshell-evaln):
Improve docstrings.
2022-02-21 18:39:40 +01:00
Jim Porter
785a045b86 Ensure that the CAR of 'eshell-last-async-procs' always points to a process
Previously, if a non-process was piped to a process, this could end up
being nil, which isn't correct.  'eshell-last-async-procs' should just
ignore non-process commands in a pipeline.

* lisp/eshell/esh-cmd.el (eshell-do-pipelines): Set 'headproc'
correctly.

* test/lisp/eshell/eshell-tests.el (eshell-test/pipe-headproc): New test.
2022-02-05 07:58:59 +01:00
Jim Porter
3a388ab4a6 When executing an Eshell pipeline, send input to the first process
Previously, input was sent to the last process in the pipeline,
resulting in unexpected behavior when running commands like
'tr a-z A-Z | rev'.

* lisp/eshell/esh-util.el (eshell-process-pair-p)
(eshell-make-process-pair): New functions.

* lisp/eshell/esh-cmd.el (eshell-last-async-proc): Rename to...
(eshell-last-async-procs): ... this, and store a pair of processes.
(eshell-interactive-process): Replace with...
(eshell-interactive-process-p, eshell-head-process)
(eshell-tail-process): ... these.
(eshell-cmd-initialize): Set 'eshell-last-async-procs'.
(eshell-do-pipelines): Set 'headproc'.
(eshell-execute-pipeline): Return 'headproc' and 'tailproc'.
(eshell-resume-eval): Use 'eshell-last-async-procs'.
(eshell-do-eval): Make sure we work with a pair of processes.

* lisp/eshell/esh-proc.el (eshell-send-eof-to-process): Move from
here...
* lisp/eshell/esh-mode.el (eshell-send-eof-to-process): ... to here,
and only send EOF to the head process.

* lisp/eshell/em-cmpl.el (eshell-complete-parse-arguments)
* lisp/eshell/esh-mode.el (eshell-intercept-commands)
(eshell-watch-for-password-prompt):
Use 'eshell-interactive-process-p'.

* lisp/eshell/em-rebind.el (eshell-delchar-or-maybe-eof)
* lisp/eshell/em-term.el (eshell-term-send-raw-string)
* lisp/eshell/esh-mode.el (eshell-self-insert-command)
(eshell-send-input, eshell-send-invisible):
Use 'eshell-head-process'.

* lisp/eshell/esh-cmd.el (eshell-as-subcommand):
Use 'eshell-tail-process'.

* lisp/eshell/eshell.el (eshell-command):
* test/lisp/eshell/eshell-tests-helpers.el
(eshell-wait-for-subprocess):
Use 'eshell-interactive-process-p' and 'eshell-tail-process'.

* test/lisp/eshell/eshell-tests.el (eshell-test/pipe-headproc-stdin):
New test.
2022-02-03 20:02:22 +01:00
Jim Porter
2e60ef696a Ensure that tailproc is set for the last process in an Eshell pipeline
In particular, this used to fail for pipelines where the last process
in the pipeline came from the first element of the pipeline. This
could happen when a process was piped to an ordinary Lisp function,
like in '*echo hi | echo bye'.

* lisp/eshell/esh-cmd.el (eshell-do-pipelines): Set the tailproc even
for the first process in the pipeline.

* test/lisp/eshell/eshell-tests.el (eshell-test/pipe-tailproc): New
test.
2022-02-03 20:02:20 +01:00
Jim Porter
587edc46df Further improve determination of when commands can be invoked directly
This covers the case when a subcommand is to be invoked in more places
than before, for example when a subcommand is concatenated in an
argument.

* lisp/eshell/esh-cmd.el (eshell--find-subcommands): New fuction.
(eshell--invoke-command-directly): Use 'eshell-find-subcommands'.

* test/lisp/eshell/eshell-tests.el
(eshell-test/interp-cmd-external-concat): New test (bug#30725).
2022-01-21 10:32:00 +01:00
Jim Porter
4450c8bdd9 Consider subcommands when deciding to invoke Eshell command directly
When an Eshell command contains an asynchronous subcommand (such as
calling an external process), it must be evaluated iteratively.  See
bug#30725.

* lisp/eshell/esh-cmd.el (eshell-invoke-command): Move most of the
logic from here...
(eshell--invoke-command-directly): ... to here. Also add checks for
subcommands.

* test/lisp/eshell/eshell-tests.el (eshell-test--max-subprocess-time):
New variable.
(eshell-wait-for-subprocess): New function.
(eshell-command-result-p): Use 'eshell-wait-for-subprocess'.
(eshell-test/interp-cmd-external): New test (bug#30725).
2022-01-20 14:37:54 +01:00
Eli Zaretskii
dcd76bd48d Merge from origin/emacs-28
836be7a112 ; * etc/refcards/ru-refcard.tex: Update Copyright year.
86cbc6ee4a * lisp/net/tramp-sh.el: Adapt copyright year
ebe8772f65 ; Minor fixes related to copyright years
23c1ee6989 ; * test/manual/etags/ETAGS.good_N: Adjust to copyright ye...
8d3fc7ec89 * src/xfaces.c (face_for_font): Make 'hash' be uintptr_t.
19dcb237b5 ; Add 2022 to copyright years.

# Conflicts:
#	etc/NEWS
#	etc/refcards/ru-refcard.tex
#	lib/cdefs.h
#	lisp/erc/erc-dcc.el
#	lisp/erc/erc-imenu.el
#	lisp/erc/erc-replace.el
#	lisp/image-dired.el
#	lisp/progmodes/xref.el
#	m4/alloca.m4
#	m4/byteswap.m4
#	m4/errno_h.m4
#	m4/getopt.m4
#	m4/gnulib-common.m4
#	m4/inttypes.m4
#	m4/stddef_h.m4
#	m4/stdint.m4
#	m4/sys_socket_h.m4
2022-01-01 07:03:03 -05:00
Eli Zaretskii
19dcb237b5 ; Add 2022 to copyright years. 2022-01-01 02:45:51 -05:00
Stefan Kangas
5b6c3a20a3 Prefer the defcustom :risky property in eshell
* lisp/eshell/em-banner.el (eshell-banner-message):
* lisp/eshell/em-hist.el (eshell-input-filter):
* lisp/eshell/em-pred.el (eshell-predicate-alist)
(eshell-modifier-alist):
* lisp/eshell/esh-cmd.el (eshell-subcommand-bindings):
* lisp/eshell/esh-io.el (eshell-virtual-targets):
* lisp/eshell/esh-var.el (eshell-variable-aliases-list): Prefer
defcustom :risky property to setting 'risky-local-variable manually.
2021-12-24 15:37:05 +01:00
Po Lu
64ea1a178c Fix eshell for systems that do not have subprocesses
* lisp/eshell/esh-cmd.el (eshell-eval-command): Use
`eshell-processp' instead of `processp'.
2021-12-12 15:50:28 +08:00
Stefan Kangas
434c176e06 ; Stylistic docfixes in eshell/*.el found by checkdoc 2021-09-19 12:59:55 +02:00
Stefan Kangas
25ebb9374b ; More minor docfixes found by checkdoc 2021-09-14 07:57:14 +02:00
Thierry Volpiatto
d0693617b8 Make `eshell-command' also work when asynchronous
* lisp/eshell/esh-cmd.el (eshell-eval-command): Make asynchronous
`eshell-command' work (e.g. `M-x eshell-command RET sleep 10 &')
(bug#50209).
2021-08-27 17:15:17 +02:00
Stefan Kangas
7de495a7c1 Make two eshell aliases obsolete
* lisp/eshell/esh-util.el (eshell-user-name): Redefine as obsolete
function alias for 'user-login-name'.
(eshell-copy-tree): Redefine as obsolete function alias for
'copy-tree'.
* lisp/eshell/esh-cmd.el (eshell-do-eval): Don't use above
obsolete alias.
2021-02-01 12:29:09 +01:00
Paul Eggert
ba05d005e5 Update copyright year to 2021
Run "TZ=UTC0 admin/update-copyright".
2021-01-01 01:13:56 -08:00
Stefan Kangas
78cdf4c762 Prefer setq-local in eshell
* lisp/eshell/em-cmpl.el (eshell-cmpl-initialize):
* lisp/eshell/em-dirs.el (eshell-dirs-initialize):
* lisp/eshell/em-glob.el (eshell-glob-initialize, eshell-glob-regexp):
* lisp/eshell/em-hist.el (eshell-hist-initialize):
* lisp/eshell/em-prompt.el (eshell-prompt-initialize):
* lisp/eshell/em-rebind.el (eshell-rebind-initialize)
(eshell-setup-input-keymap):
* lisp/eshell/em-script.el (eshell-script-initialize):
* lisp/eshell/em-smart.el (eshell-smart-initialize):
* lisp/eshell/em-term.el (eshell-term-initialize, eshell-exec-visual):
* lisp/eshell/em-tramp.el (eshell-tramp-initialize):
* lisp/eshell/em-unix.el (eshell-unix-initialize, eshell/diff):
* lisp/eshell/esh-arg.el (eshell-arg-initialize):
* lisp/eshell/esh-cmd.el (eshell-cmd-initialize):
* lisp/eshell/esh-io.el (eshell-get-target):
* lisp/eshell/esh-mode.el (eshell-mode):
* lisp/eshell/esh-var.el (eshell-var-initialize): Prefer setq-local.
2020-12-04 10:55:56 +01:00
Ruthra Kumar
7ab6213886 Use 'eshell-find-alias-function' instead of fboundp
* lisp/eshell/esh-cmd.el (eshell-invoke-directly): Fix problem
with (require 'em-tramp) making password prompting from "sudo
bash" no longer work (bug#43772).
2020-11-16 23:04:36 +01:00
Stefan Kangas
238261db95 Don't quote lambdas in eshell/*.el
* lisp/eshell/em-basic.el (eshell-echo):
* lisp/eshell/em-cmpl.el (eshell-command-completion-function)
(eshell-default-completion-function, eshell-cmpl-initialize)
(eshell-complete-parse-arguments, eshell-complete-commands-list):
* lisp/eshell/em-dirs.el (eshell-complete-user-reference):
* lisp/eshell/em-hist.el (eshell-hist-unload-hook)
(eshell-hist-initialize):
* lisp/eshell/em-ls.el (eshell-ls-sort-entries):
* lisp/eshell/em-pred.el (eshell-modifier-alist)
(eshell-display-predicate-help, eshell-display-modifier-help)
(eshell-pred-substitute, eshell-split-members):
* lisp/eshell/em-prompt.el (eshell-prompt-function):
* lisp/eshell/em-smart.el (eshell-smart-unload-hook)
(eshell-smart-initialize, eshell-refresh-windows):
* lisp/eshell/em-unix.el (eshell-shuffle-files):
* lisp/eshell/esh-arg.el (eshell-parse-argument-hook):
* lisp/eshell/esh-cmd.el (eshell-cmd-initialize)
(eshell-parse-command):
* lisp/eshell/esh-mode.el (eshell-preinput-scroll-to-bottom)
(eshell-postoutput-scroll-to-bottom):
* lisp/eshell/esh-module.el (eshell-modules-list):
* lisp/eshell/esh-proc.el (eshell-read-process-name)
(eshell-round-robin-kill):
* lisp/eshell/esh-var.el (eshell-envvar-names)
(eshell-variables-list): Don't quote lambdas.
2020-11-16 14:43:55 +01:00