1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2025-12-24 06:20:43 -08:00
Commit graph

193 commits

Author SHA1 Message Date
Jim Porter
50339b38fd Use 'unwind-protect' to ensure that Eshell always closes I/O handles
See bug#72220.

* lisp/eshell/esh-cmd.el (eshell-with-handles): New macro...
(eshell-commands): ... use it.
(eshell-with-copied-handles): Remove STEAL-P and allow multiple body
forms (this is an incompatible change, but the macro is currently
internal despite the name).
(eshell-parse-command, eshell-do-pipelines)
(eshell-do-pipelines-synchronously, eshell--invoke-command-directly-p):
Remove handle stealing.
(eshell-structure-basic-command, eshell-do-command)
(eshell-lisp-command): Remove 'eshell-close-handles'.
(eshell-protect): Make obsolete.
(eshell-rewrite-for-command, eshell-rewrite-while-command)
(eshell-rewrite-if-command, (eshell-parse-pipeline): Remove
'eshell-protect'.

* lisp/eshell/esh-io.el (eshell-duplicate-handles): Make STEAL-P
obsolete.

* lisp/eshell/esh-proc.el (eshell-gather-process-output): Call
'eshell-protect-handles' one more time.  Remove 'eshell-close-handles'.

* lisp/eshell/esh-var.el (eshell-parse-variable-ref): Reimplement
$<COMMAND> form using 'eshell-with-handles'.

* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/command-not-found/pipeline): New test.

* test/lisp/eshell/em-tramp-tests.el
(em-tramp-test/should-replace-command): Adjust check for
'eshell-with-copied-handles'.
2024-07-27 13:57:17 -07:00
Jim Porter
8bfdee8689 ; Improve correctness of 'eshell-do-eval' in some edge cases
* lisp/eshell/esh-cmd.el (eshell-do-eval): Make sure that replacing 'if'
forms returns the correct result, and evaluate to 'nil' for 'progn'
forms with no body.
2024-07-27 12:15:14 -07:00
Jim Porter
b7893e7387 Don't set exit info in Eshell if the command is being piped elsewhere
Previously, the exit info in Eshell was that of the last command that
finished, rather than the last command in a pipeline.

* lisp/eshell/esh-cmd.el (eshell-exec-lisp)
(eshell-lisp-command): Check whether the command is being piped.

* lisp/eshell/esh-proc.el (eshell-gather-process-output): Record whether
the command is being piped...
(eshell-sentinel): ... and do the right thing with that info.

* test/lisp/eshell/esh-proc-tests.el
(esh-proc-test/sigpipe-exits-process): Check the exit status to ensure
we don't report the first process's SIGPIPE exit.
2024-07-19 11:22:34 -07:00
Jim Porter
39c704e03d Split out exit code parts of 'eshell-close-handles' into a new function
* lisp/eshell/esh-cmd.el (eshell-last-command-status)
(eshell-last-command-result): Move here from esh-io.el.
(eshell-set-exit-info): New function, extracted from
'eshell-close-handles'.

* lisp/eshell/esh-io.el (eshell-close-handles): Make old calling
convention obsolete.  Update callers to use 'eshell-set-exit-info' as
needed.
2024-07-19 11:22:34 -07:00
Jim Porter
1550213613 Improve handling of deferrable Eshell commands
Now, we use the 'eshell-deferrable' wrapper to wrap a form that returns
a process (or list thereof).  This improves upon the old method, which
failed to handle 'eshell-replace-command' correctly.  In that case,
Eshell would fail to unmark commands as deferrable when necessary
(e.g. for commands in pipelines).

* lisp/eshell/esh-cmd.el (eshell-deferrable-commands): Make into a
defvar.
(eshell-deferrable): New function...
(eshell-structure-basic-command): ... use it.
(eshell-trap-errors): Rename to...
(eshell-do-command): ... this, and use 'eshell-deferrable'.  Update
callers.
(eshell--unmark-deferrable): Remove.  Update callers.
(eshell-execute-pipeline): Remove 'eshell-process-identity'.
(eshell-process-identity, eshell-named-command*, eshell-lisp-command*):
Make obsolete.

* test/lisp/eshell/esh-cmd-tests.el (eshell-test-replace-command): New
function.
(esh-cmd-test/pipeline/replace-command): New test.
2024-07-18 11:10:04 -07:00
Po Lu
38fa3e9350 Merge from savannah/emacs-30
a5ef9e2568 Document means of executing Emacs from unrelated Android ...
0de0056fd6 Don't emit a prompt in Eshell when a background command i...
ec1e300a21 Fix reference from buffer-stale-function docstring
2024-07-12 12:15:50 +08:00
Jim Porter
0de0056fd6 Don't emit a prompt in Eshell when a background command is killed
* lisp/eshell/esh-cmd.el (eshell-resume-command): Check for
background-ness before resetting the prompt.

* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/background/simple-command): Make the regexp a bit
stricter.
(esh-cmd-test/background/kill): New test.
2024-07-11 16:39:35 -07:00
Jim Porter
8e46f44ea0 Improve Eshell's behavior when waiting for processes
This has a few benefits.  First, it fixes a race condition when killing
old processes in 'eshell-command'.  Second, the "wait" built-in command
is now more useful.  Finally, killing processes when exiting Eshell (via
'eshell-round-robin-kill') should be much faster.

* lisp/eshell/esh-proc.el (esh-opt): Require.
(eshell-wait-for-process): Make obsolete in favor of...
(eshell-wait-for-processes): ... this.  Accept a timeout and support
PIDs.  Update callers.
(eshell/wait): New implementation accepting -t/--timeout.
(eshell-round-robin-kill): Use 'eshell-wait-for-processes'.

* lisp/eshell/eshell.el (eshell-command): Use 'eshell-round-robin-kill'.

* doc/misc/eshell.texi (List of Built-ins): Document the new "wait"
behavior.

* etc/NEWS: Announce this change.
2024-07-09 17:28:32 -07:00
Stefan Kangas
7350457c79 Checkdoc fixes in eshell/*.el
* lisp/eshell/em-elecslash.el:
* lisp/eshell/em-extpipe.el:
* lisp/eshell/em-pred.el (eshell-get-delimited-modifier-argument):
* lisp/eshell/esh-cmd.el (eshell--unmark-deferrable)
(eshell-named-command-hook):
* lisp/eshell/esh-module.el (eshell-module--feature-name):
* lisp/eshell/esh-util.el (eshell-find-delimiter): Checkdoc fixes.
2024-07-08 16:51:05 +02:00
Jim Porter
00649042f3 Remove empty Eshell commands when parsing
This improves the logic for copying/stealing handles when constructing
the command form: now, we should always steal the handles for the last
real command, even if there were some trailing semicolons.

* lisp/eshell/esh-arg.el (eshell-parse-delimiter): Be stricter about
parsing so that things like "& &" aren't parsed as a single "&&" token.

* lisp/eshell/esh-cmd.el (eshell-parse-command): Get the commands in
reverse, and remove any nil commands.
(eshell-split-commands): Always return the trailing terms (except when
there were no terms to begin with).

* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/empty-background-command): New test.
2024-06-09 13:31:08 -07:00
Jim Porter
1df3554f07 Make Eshell's "which" command extensible
Since 'eshell-named-command-hook' already makes execution of commands
extensible, "which" should be too.  This makes sure that "which" returns
the right result for quoted commands like "/:cat".

* lisp/eshell/em-alias.el (eshell-aliases-file): Allow it to be nil.
(eshell-read-aliases-list, eshell-write-aliases-list): Check if
'eshell-aliases-file' is nil.
(eshell-maybe-replace-by-alias--which): New function...
(eshell-maybe-replace-by-alias): ... use it.

* lisp/eshell/esh-cmd.el (eshell-named-command-hook): Update docstring.
(eshell/which): Make extensible.
(eshell--find-plain-lisp-command, eshell-plain-command--which): New
functions.
(eshell-plain-command): Use 'eshell--find-plain-lisp-command'.

* lisp/eshell/esh-ext.el (eshell-explicit-command--which): New
function...
(eshell-explicit-command): ... unise it.
(eshell-quoted-file-command--which): New function...
(eshell-quoted-file-command): ... use it.
(eshell-external-command--which): New function.

* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/which/plain/eshell-builtin)
(esh-cmd-test/which/plain/external-program)
(esh-cmd-test/which/plain/not-found, esh-cmd-test/which/alias)
(esh-cmd-test/which/explicit, esh-cmd-test/which/explicit/not-found)
(esh-cmd-test/which/quoted-file)
(esh-cmd-test/which/quoted-file/not-found): New tests.

* test/lisp/eshell/eshell-tests-helpers.el (with-temp-eshell-settings):
Don't load or save aliases.
(eshell-command-result--match,eshell-command-result--match-explainer)
(eshell-command-result-match): New functions.
2024-05-29 19:33:13 -07:00
Jim Porter
6a0f4d333a ; Improve recent change to deferred evaluation in Eshell
* lisp/eshell/esh-cmd.el (eshell-do-eval): Move active check later.
2024-05-29 17:27:01 -07:00
Jim Porter
eac608cb80 Rework how 'eshell-ensure-newline-p' adds newlines
This allows for other output targets (see the following commit) to be
"line-oriented".

* lisp/eshell/esh-io.el (eshell-ensure-newline-p): Move from esh-cmd.el.
(eshell-target-line-oriented-p, eshell--output-maybe-n)
(eshell-print-maybe-n, eshell-error-maybe-n)
(eshell-maybe-output-newline): New functions.

* lisp/eshell/esh-cmd.el (eshell-lisp-command): Don't print a newline
in this function directly; instead, use 'eshell-print-maybe-n' and
'eshell-error-maybe-n'.
(eshell-ensure-newline-p): Move to esh-io.el.

* lisp/eshell/em-unix.el (eshell/cat): Remove now-unnecessary override
of 'eshell-ensure-newline-p'.
2024-05-29 12:09:06 -07:00
Jim Porter
57dc1ed665 Fix a race condition when evaluating Eshell commands
* lisp/eshell/esh-cmd.el (eshell-do-eval): Don't defer when all the
processes are done.

* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/pipeline-wait/nested-pipes): New test.
2024-05-25 13:46:24 -07:00
Jim Porter
2f7d011d18 Add new Eshell built-in command 'funcall'
* lisp/eshell/esh-cmd.el (eshell/funcall): New function...

* test/lisp/eshell/em-glob-tests.el (em-glob-test/expand/splice-results)
(em-glob-test/expand/no-splice-results)
(em-glob-test/expand/explicitly-splice-results)
(em-glob-test/expand/explicitly-listify-results):
* test/lisp/eshell/esh-var-tests.el
(esh-var-test/quoted-interp-lisp-indices)
(esh-var-test/quoted-interp-cmd-indices)
(esh-var-test/interp-convert-quoted-var-number)
(esh-var-test/quoted-interp-convert-var-number)
(esh-var-test/quoted-interp-convert-quoted-var-number)
(esh-var-test/last-status-var-lisp-command)
(esh-var-test/last-result-var-split-indices)
(esh-var-test/last-arg-var-split-indices): ... use it in tests.

* doc/misc/eshell.texi (List of Built-ins): Describe this command.
2024-05-16 20:33:18 -07:00
Jim Porter
ffc70962ca ; Clean up some 'require' and 'declare-function' calls in Eshell
* lisp/eshell/em-ls.el:
* lisp/eshell/esh-cmd.el:
* lisp/eshell/esh-mode.el:
* lisp/eshell/esh-ext.el: Remove superfluous 'declare-function' calls.

* lisp/eshell/esh-proc.el (pcomplete): Require this explicitly instead
of transitively.
2024-05-10 09:27:30 -07:00
Jim Porter
33878f29d1 ; Remove unnecessary defvars defined in a file we already 'require'
* lisp/eshell/esh-cmd.el (eshell-output-handle, eshell-error-handle):
Remove superfluous declarations.
2024-05-09 22:02:00 -07:00
Jim Porter
047607f6e6 Fix detection of directly-invokable commands in Eshell
I think this regressed partly due to eef32d13da, so let's add some
regression tests to make sure that doesn't happen again.

* lisp/eshell/em-unix.el (eshell-unix-initialize): Add "compile".

* lisp/eshell/esh-cmd.el (eshell--find-subcommands): Yield the second
element of the subcommand.
(eshell--invoke-command-directly-p): Rename and account for
'eshell-with-copied-handles'.
(eshell-invoke-directly): Rename to...
(eshell-invoke-directly-p): ... this, and use 'pcase' to make the
logic clearer.

* lisp/eshell/esh-mode.el (eshell-send-input): Always queue input if
the process is running; rename some locals to be clearer.

* lisp/eshell/esh-var.el (eshell-var-initialize): Add "env" as a
complex command.

* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test--deftest-invoke-directly): New macro.
(no-args, with-args, multiple-cmds, subcmd, complex, complex-subcmd):
New test cases.
2024-01-26 10:17:19 -08:00
Po Lu
ecf08f0621 Merge from savannah/emacs-29
dc4e6b1329 ; Update copyright years in more files
64b3777631 ; Run set-copyright from admin.el
8e1c56ae46 ; Add 2024 to copyright years

# Conflicts:
#	doc/misc/modus-themes.org
#	doc/misc/texinfo.tex
#	etc/NEWS
#	etc/refcards/ru-refcard.tex
#	etc/themes/modus-operandi-theme.el
#	etc/themes/modus-themes.el
#	etc/themes/modus-vivendi-theme.el
#	lib/alloca.in.h
#	lib/binary-io.h
#	lib/c-ctype.h
#	lib/c-strcasecmp.c
#	lib/c-strncasecmp.c
#	lib/careadlinkat.c
#	lib/cloexec.c
#	lib/close-stream.c
#	lib/diffseq.h
#	lib/dup2.c
#	lib/filemode.h
#	lib/fpending.c
#	lib/fpending.h
#	lib/fsusage.c
#	lib/getgroups.c
#	lib/getloadavg.c
#	lib/gettext.h
#	lib/gettime.c
#	lib/gettimeofday.c
#	lib/group-member.c
#	lib/malloc.c
#	lib/md5-stream.c
#	lib/md5.c
#	lib/md5.h
#	lib/memmem.c
#	lib/memrchr.c
#	lib/nanosleep.c
#	lib/save-cwd.h
#	lib/sha1.c
#	lib/sig2str.c
#	lib/stdlib.in.h
#	lib/strtoimax.c
#	lib/strtol.c
#	lib/strtoll.c
#	lib/time_r.c
#	lib/xalloc-oversized.h
#	lisp/auth-source-pass.el
#	lisp/emacs-lisp/lisp-mnt.el
#	lisp/emacs-lisp/timer.el
#	lisp/info-look.el
#	lisp/jit-lock.el
#	lisp/loadhist.el
#	lisp/mail/rmail.el
#	lisp/net/ntlm.el
#	lisp/net/webjump.el
#	lisp/progmodes/asm-mode.el
#	lisp/progmodes/project.el
#	lisp/progmodes/sh-script.el
#	lisp/textmodes/flyspell.el
#	lisp/textmodes/reftex-toc.el
#	lisp/textmodes/reftex.el
#	lisp/textmodes/tex-mode.el
#	lisp/url/url-gw.el
#	m4/alloca.m4
#	m4/clock_time.m4
#	m4/d-type.m4
#	m4/dirent_h.m4
#	m4/dup2.m4
#	m4/euidaccess.m4
#	m4/fchmodat.m4
#	m4/filemode.m4
#	m4/fsusage.m4
#	m4/getgroups.m4
#	m4/getloadavg.m4
#	m4/getrandom.m4
#	m4/gettime.m4
#	m4/gettimeofday.m4
#	m4/gnulib-common.m4
#	m4/group-member.m4
#	m4/inttypes.m4
#	m4/malloc.m4
#	m4/manywarnings.m4
#	m4/mempcpy.m4
#	m4/memrchr.m4
#	m4/mkostemp.m4
#	m4/mktime.m4
#	m4/nproc.m4
#	m4/nstrftime.m4
#	m4/pathmax.m4
#	m4/pipe2.m4
#	m4/pselect.m4
#	m4/pthread_sigmask.m4
#	m4/readlink.m4
#	m4/realloc.m4
#	m4/sig2str.m4
#	m4/ssize_t.m4
#	m4/stat-time.m4
#	m4/stddef_h.m4
#	m4/stdint.m4
#	m4/stdio_h.m4
#	m4/stdlib_h.m4
#	m4/stpcpy.m4
#	m4/strnlen.m4
#	m4/strtoimax.m4
#	m4/strtoll.m4
#	m4/time_h.m4
#	m4/timegm.m4
#	m4/timer_time.m4
#	m4/timespec.m4
#	m4/unistd_h.m4
#	m4/warnings.m4
#	nt/configure.bat
#	nt/preprep.c
#	test/lisp/register-tests.el
2024-01-02 10:28:14 +08:00
Po Lu
8e1c56ae46 ; Add 2024 to copyright years 2024-01-02 09:47:10 +08:00
Jim Porter
69e8333210 Add 'eshell-special-ref-alist' to allow extending Eshell special refs
* lisp/eshell/esh-cmd.el (eshell--region-p, eshell-with-temp-command):
Move to...
* lisp/eshell/esh-util.el (eshell--region-p)
(eshell-with-temp-command): ... here.

* lisp/eshell/em-cmpl.el (eshell-complete-parse-arguments): Fix edge
case when 'end' is at beginning of (possibly-narrowed) buffer.

* lisp/eshell/esh-arg.el (eshell-special-ref-alist) New variable...
(eshell-special-ref-default): ... New option...
(eshell--special-ref-function): ... New function...
(eshell-parse-special-reference): ... use them.
(eshell-insert-special-reference): New function.
(eshell-complete-special-reference): Reimplement to use a nested call
to Pcomplete.
(eshell-complete-buffer-ref): New function.

* lisp/eshell/esh-proc.el (eshell-proc-initialize): Add "process"
special ref type here.
(eshell-complete-process-ref): New function.

* doc/misc/eshell.texi (Bugs and ideas): Remove now-implemented idea.
2023-10-24 11:36:27 -07:00
Jim Porter
498d31e9f0 Support Eshell iterative evaluation in the background
This really just generalizes Eshell's previous support for iterative
evaluation of a single current command to a list of multiple commands,
of which at most one can be in the foreground (bug#66066).

* lisp/eshell/esh-cmd.el (eshell-last-async-procs)
(eshell-current-command): Make obsolete in favor of...
(eshell-foreground-command): ... this
(eshell-background-commands): New variable.
(eshell-interactive-process-p): Make obsolete.
(eshell-head-process, eshell-tail-process): Use
'eshell-foreground-command'.
(eshell-cmd-initialize): Initialize new variables.
(eshell-add-command, eshell-remove-command)
(eshell-commands-for-process): New functions.
(eshell-parse-command): Make 'eshell-do-subjob' the outermost call.
(eshell-do-subjob): Call 'eshell-resume-eval' to split this command
off from its parent forms.
(eshell-eval-command): Use 'eshell-add-command'.
(eshell-resume-command): Use 'eshell-commands-for-process'.
(eshell-resume-eval): Take a COMMAND argument.  Return
':eshell-background' form for deferred background commands.
(eshell-do-eval): Remove check for 'eshell-current-subjob-p'.  This is
handled differently now.

* lisp/eshell/eshell.el (eshell-command): Wait for all processes to
exit when running synchronously.

* lisp/eshell/esh-mode.el (eshell-intercept-commands)
(eshell-watch-for-password-prompt):
* lisp/eshell/em-cmpl.el (eshell-complete-parse-arguments):
* lisp/eshell/em-smart.el (eshell-smart-display-move): Use
'eshell-foreground-command'.

* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/background/simple-command)
(esh-cmd-test/background/subcommand): New tests.
(esh-cmd-test/throw): Use 'eshell-foreground-command'.

* test/lisp/eshell/eshell-tests.el (eshell-test/queue-input): Use
'eshell-foreground-command'.

* test/lisp/eshell/em-script-tests.el
(em-script-test/source-script/background): Make the test script more
complex.

* test/lisp/eshell/eshell-tests.el
(eshell-test/eshell-command/pipeline-wait): New test.

* doc/misc/eshell.texi (Bugs and ideas): Remove implemented feature.
2023-10-02 20:49:41 -07:00
Jim Porter
8f2cfe15a7 Don't print subjob messages when running an Eshell script in the background
* lisp/eshell/esh-proc.el (eshell-subjob-messages): New variable...
(eshell-record-process-object)
(eshell-remove-process-entry): ... check it.

* lisp/eshell/em-script.el (eshell-source-file): Set
'eshell-subjob-messages' to nil.

* lisp/eshell/esh-cmd.el (eshell-do-subjob): Set
'eshell-subjob-messages' to t.

* test/lisp/eshell/em-script-tests.el
(em-script-test/source-script/background): New test.
2023-10-02 20:49:40 -07:00
Jim Porter
eef32d13da Use 'unwind-protect' in more places in Eshell
This lets us simplify the logic for how we reset
'eshell-current-command' and 'eshell-last-async-procs', as well as
improving correctness of Eshell command forms in a few esoteric
scenarios.  Additionally, this helps set the stage for better support
of background commands in Eshell (bug#66164).

* lisp/eshell/esh-cmd.el (eshell-cmd-initialize): Remove addition to
'eshell-post-command-hook'; this is handled in 'eshell-resume-command'
and 'eshell-resume-eval' now.
(eshell-resume-command): Handle resetting the prompt as needed.
(eshell-resume-eval): Use 'unwind-protect' to ensure that we set
'eshell-last-async-procs' and 'eshell-current-comment' at the right
times.
(eshell-parse-command, eshell-trap-errors, eshell-manipulate): Use
'unwind-protect'.
(eshell-do-eval): Allow 'eshell-defer' to pass through
'unwind-protect' forms without actually calling the unwinding forms
(yet).

* lisp/eshell/esh-proc.el (eshell-kill-process-function)
(eshell-reset-after-proc): Make obsolete.  The behavior is now handled
in 'eshell-resume-command'.
(eshell-gather-process-output, eshell-sentinel)
(eshell-interrupt-process, eshell-kill-process, eshell-quit-process)
(eshell-stop-process, eshell-continue-process): Run 'eshell-kill-hook'
directly.

* test/lisp/eshell/esh-cmd-tests.el (esh-cmd-test/throw): New test.
2023-09-26 12:29:52 -07:00
Jim Porter
acdb77c289 ; Add debug instrumention for queueing commands in Eshell
* lisp/eshell/esh-cmd.el (eshell-eval-command): Log the new command
form.
2023-09-18 18:00:07 -07:00
Jim Porter
146bd41dde Fix another race condition when waiting for Eshell processes
When checking if the other processes in our pipeline are "alive", we
also need to check whether their sentinels are finished.  Otherwise,
we might proceed with command evaluation while one of the other
processes is still cleaning up.

* lisp/eshell/esh-proc.el (eshell-process-active-p): New function...
(eshell-wait-for-process)
* lisp/eshell/esh-cmd.el (eshell-resume-command): ... use it.
2023-09-18 10:26:34 -07:00
Jim Porter
9ab8b968d6 Use 'eshell-with-temp-command' (indirectly) to parse Eshell script files
* lisp/eshell/esh-cmd.el (eshell--region-p): New function.
(eshell-with-temp-command, eshell-parse-command): Support
'(:file . FILENAME)' to use the contents of FILENAME.

* lisp/eshell/em-script.el (eshell-source-file): Call
'eshell-parse-command' and use backticks.
2023-09-17 21:10:28 -07:00
Jim Porter
7d2870dc85 Fix running background commands via 'eshell-command'
This regressed (I believe) due to 2ec41c174f.

* lisp/eshell/esh-cmd.el (eshell-resume-eval): Check for non-nil
'retval' instead of for a process list (nil is also a technically a
process list!).

* test/lisp/eshell/eshell-tests.el
(eshell-test/eshell-command/background-pipeline): Remove unnecessary
'copy-tree'.
(eshell-test/eshell-command/output-buffer/sync)
(eshell-test/eshell-command/output-buffer/async): New tests.
2023-09-17 15:45:45 -07:00
Jim Porter
ae983e9283 ; Fix a recent change in Eshell
* lisp/eshell/esh-cmd.el (eshell-manipulate): Fix 'eshell-stringify' calls.
(eshell-do-eval): Simplify 'if' condition.
2023-09-17 11:22:19 -07:00
Jim Porter
bc25d76650 Fix documented Eshell behavior of ignoring leading nils in commands
* lisp/eshell/esh-var.el (eshell-handle-local-variables): Simplify,
and move leading-nil handling to...
* lisp/eshell/esh-cmd.el (eshell-named-command): ... here.

* test/lisp/eshell/esh-cmd-tests.el (esh-cmd-test/skip-leading-nils):
* test/lisp/eshell/esh-var-tests.el
(esh-var-test/local-variables/skip-nil): New tests.

* doc/misc/eshell.texi (Expansion): Document this behavior.
2023-09-15 13:43:07 -07:00
Jim Porter
cadd332662 Collapse 'if' forms in Eshell iterative evaluation
* lisp/eshell/esh-cmd.el (eshell-do-eval): After evaluating 'if'
conditional, replace the form with the THEN or ELSE body.
2023-09-14 17:54:41 -07:00
Jim Porter
7e50861ca7 ; Simplify how to use 'eshell-debug-command'
Now, 'eshell-debug-command' works more like 'format-message', which is
how we usually use it.

* lisp/eshell/esh-util.el (eshell-always-debug-command): New function.
(eshell-debug-command): Simplify.  Update callers.
2023-09-14 17:54:26 -07:00
Jim Porter
922d76e856 ; Fix an Eshell error when calling a lambda with form logging enabled
* lisp/eshell/esh-cmd.el (eshell-do-eval): Don't call 'symbol-name';
the function might be a closure.
2023-09-13 12:48:52 -07:00
Jim Porter
0fe1cd4929 ; * lisp/eshell/esh-cmd.el (eshell-do-eval): Fix 'eshell-manipulate' call. 2023-09-13 11:31:36 -07:00
Jim Porter
2ec41c174f Wait for all processes in a pipeline before resuming an Eshell command
Previously, we only waited until the tail process was finished, but
now, we wait for all of them.  This is more consistent with other
shells, and prevents some cases of a process's output coming *after*
we continued past its pipeline.

* lisp/eshell/esh-cmd.el (eshell-resume-command): Simplify
conditionals, and check that all the foreground processes are dead
before resuming Eshell command.

* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/pipeline-wait/multi-proc): New test.
2023-09-10 10:38:25 -07:00
Jim Porter
f9667836c4 Collect all processes in an Eshell pipeline, not just the head and tail
This has the extra benefit that Eshell now only considers a pipeline
to be done when *all* of its processes are done (previously, it
checked only the last one in the pipeline).

* lisp/eshell/esh-util.el (eshell-process-pair-p)
(eshell-make-process-pair): Rename to...
(eshell-process-list-p, eshell-make-process-list): ... these, and
handle lists of processes.  Update callers.

* lisp/eshell/esh-cmd.el (eshell-head-process): Use 'car'.
(eshell-tail-process): Get the last element of the list.
(eshell-do-pipelines): Return a list of all processes in the pipeline.
(eshell-do-pipelines-synchronously): Return the result of the first
command (usually t or nil).
(eshell-execute-pipeline): Simplify.
(eshell-do-eval): Pass all processes to 'eshell/wait'.
2023-09-10 10:38:25 -07:00
Jim Porter
dd2438eeaa ; Make Eshell synchronous pipeline code more similar to asynchronous
* lisp/eshell/esh-cmd.el (eshell-do-pipelines-synchronously): Use
'eshell-with-copied-handles'.
(eshell-execute-pipeline): Remove now-unnecessary let-bindings.
2023-09-10 10:38:25 -07:00
Jim Porter
6419f318e4 ; Move common Eshell pipeline code to a separate function
* lisp/eshell/esh-cmd.el (eshell-do-pipelines)
(eshell-do-pipelines-synchronously): Move code for manipulating
deferrable command forms to...
(eshell--unmark-deferrable): ... here.
2023-09-10 10:38:25 -07:00
Jim Porter
ccb62321d2 Fix handling of Eshell debug modes
Previously, these were enabled/disabled at byte-compilation time, but
we want to control them at runtime.

* lisp/eshell/esh-cmd.el (eshell-eval-command): Call
'eshell-debug-command-start'.
(eshell-manipulate): Check 'eshell-debug-command' at runtime.  Update
callers.
(eshell-debug-command): Move to "esh-util.el".
(eshell/eshell-debug, pcomplate/eshell-mode/eshell-debug): Move to
"em-basic.el".
(eshell-debug-show-parsed-args): Update implementation.

* lisp/eshell/esh-util.el (eshell-debug-command): Move from
"esh-cmd.el" and convert to a list.
(eshell-debug-command-buffer): New variable.
(eshell-condition-case): Check 'eshell-handle-errors' at runtime.
(eshell-debug-command-start): New function.
(eshell-debug-command): Move from "esh-cmd.el" and convert to a macro.

* lisp/eshell/em-basic.el (eshell/eshell-debug)
(pcomplete/eshell-mode/eshell-debug): Move from "esh-cmd.el" and
reimplement.

* lisp/eshell/eshell.el (eshell-command): Pass the original input to
'eshell-eval-command'.

* doc/misc/eshell.texi (Built-ins): Update documentation for
'eshell-debug'.
2023-08-31 18:42:03 -07:00
Jim Porter
60090abcbc Return separators from 'eshell-split-commands' directly when requested
This eliminates the need for using a dynamically-bound variable to
hold the list of separators.

* lisp/eshell/esh-cmd.el (eshell--sep-terms): Remove.
(eshell-split-commands): New function, adapted from
'eshell-separate-commands'.
(eshell-separate-commands): Make obsolete, and call
'eshell-split-commands'.
(eshell-parse-command, eshell-parse-pipeline): Use
'eshell-split-commands'.

* lisp/eshell/esh-arg.el (eshell-parse-delimiter): Update comment.
2023-08-10 10:55:49 -07:00
Jim Porter
3659fc3ed8 Simplify command parsing in Eshell
* lisp/eshell/esh-cmd.el (eshell-parse-command): Do all modifications
to each command in a single pass.
(eshell-parse-pipeline): Remove unncessary reversing of parsed
results.
2023-08-10 10:55:49 -07:00
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
6419d78fa6 Fix using background commands in 'eshell-command'
Do not merge to master.

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-eval-command): Allow process-pairs.

* 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-03-31 13:07:36 -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