This could happen when 'eshell-extended-glob' determines that a "glob"
is not really a glob. This mainly happens for remote file names with a
"~" in them, like "/ssh:remote:~/file.txt".
* lisp/eshell/em-glob.el (eshell-extended-glob): Return a list when
'eshell-glob-splice-results' is non-nil.
* test/lisp/eshell/em-glob-tests.el
(em-glob-test/expand/splice-results)
em-glob-test/expand/no-splice-results): Extend tests.
* lisp/eshell/esh-var.el (eshell/env): Throw 'eshell-replace-command' as
needed.
* test/lisp/eshell/esh-var-tests.el
(esh-var-test/local-variables/env/no-locals): New test (bug#73479).
Do not merge to master.
* lisp/eshell/esh-io.el (eshell-output-object-to-target): Don't require
TARGET to be bound.
* lisp/eshell/em-script.el (eshell-execute-file): Quote the output/error
targets.
* test/lisp/eshell/em-script-tests.el (eshell-execute-file-output): New
variable.
(em-script-test/execute-file/output-file)
(em-script-test/execute-file/output-symbol): New tests.
* test/lisp/eshell/esh-io-tests.el (eshell-test-file-string): Move to...
* test/lisp/eshell/eshell-tests-helpers.el (eshell-test-file-string):
... here.
* 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.
Previously, some code executed in a timer, which could execute in the
wrong buffer, leading to a hang.
* lisp/eshell/esh-proc.el (eshell-sentinel): Use 'with-current-buffer'
in the timer function.
* test/lisp/eshell/esh-proc-tests.el (eshell-test-value): New variable.
(esh-proc-test/sentinel/change-buffer): New test.
(cherry picked from commit da4bc5c927)
The previous implementation in 6ae2b74ed2 only stopped at prompts,
which isn't the right behavior (bug#61545).
* lisp/eshell/em-prompt.el (eshell-forward-paragraph)
(eshell-backward-paragraph): Reimplement to handle prompts and
paragraphs (the latter by calling the original 'forward-paragraph').
* test/lisp/eshell/em-prompt-tests.el
(em-prompt-test/next-previous-prompt/multiline): Rename.
(em-prompt-test/forward-backward-paragraph-1): New function.
(em-prompt-test/forward-backward-paragraph)
(em-prompt-test/forward-backward-paragraph/multiline): New tests.
* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/which/plain/external-program): Compare the file name
case-insensitively on case-insensitive file systems.
* test/lisp/eshell/eshell-tests-helpers.el
(eshell-command-result--equal): Revert to the previous implementation.
* test/lisp/eshell/esh-proc-tests.el
(esh-proc-test/kill-process/redirect-message): Move next to its sibling
tests.
(esh-proc-test/remote/remote-path): Rename from 'esh-var-test/...'.
* lisp/eshell/esh-arg.el (eshell-quote-argument): Mention that this
function is for use within Eshell buffers.
(eshell-quote-backslash): Properly quote newlines.
* lisp/eshell/em-unix.el (eshell/cat, eshell/du): Throw
'eshell-external' instead; that's what it's here for.
* test/lisp/eshell/esh-proc-tests.el (esh-proc-test-quote-argument):
Remove.
(esh-proc-test/emacs-command):
* test/lisp/eshell/esh-var-tests.el (esh-var-test/path-var/set)
(esh-var-test/path-var/set-locally): Use 'eshell-quote-argument'.
* test/lisp/eshell/em-unix-tests.el (em-unix-test/compile/interactive):
Use 'shell-quote-argument' (Note: *not* 'eshell-...').
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.
* lisp/eshell/em-script.el (eshell-close-target): New function.
* test/lisp/eshell/em-script-tests.el (em-script-test/batch-file): New
test; rename old one to...
(em-script-test/batch-file/shebang): ... this.
* test/lisp/eshell/esh-proc-tests.el
(esh-proc-test-quote-argument): New function.
(esh-proc-test/emacs-command): Use it instead of
'shell-quote-argument', which allows to go back to
system-independent code.
* lisp/eshell/esh-util.el (eshell-get-path): Don't add "." if it
is already there.
* test/lisp/eshell/esh-var-tests.el
(esh-var-test/path-var/preserve-across-hosts): Skip on MS-Windows.
(esh-var-test/path-var/set, esh-var-test/path-var/set-locally):
Quote the PATH value, for MS-Windows.
* test/lisp/eshell/esh-util-tests.el (esh-util-test/path/get): No
need to add ".": it is already done by 'eshell-get-path'.
* test/lisp/eshell/esh-proc-tests.el
(esh-proc-test/kill-pipeline): Accept empty string as valid
output.
(esh-proc-test/sigpipe-exits-process): Skip on MS-Windows: no
SIGPIPE.
(esh-proc-test/emacs-command): Quote correctly for MS-Windows.
* test/lisp/eshell/em-unix-tests.el
(em-unix-test/compile/interactive): Fix test on MS-Windows.
* test/lisp/eshell/em-script-tests.el (em-script-test/batch-file):
Skip on MS-Windows.
* test/lisp/eshell/eshell-tests-helpers.el
(eshell-command-result--equal): Compare strings (file names)
case-insensitively on MS-Windows.
* lisp/eshell/esh-mode.el (eshell-postoutput-scroll-to-bottom): Use
'get-buffer-window-list' for simplicity.
(eshell-handle-control-codes): Use 're-search-forward'; this way is much
faster.
* test/lisp/eshell/esh-mode-tests.el: New file.
This makes the built-in 'eshell/cat' 5-10x faster on large files in my
(somewhat limited) tests. In addition, this change periodically
redisplays when using the Eshell buffered output so that users can see
some progress.
* lisp/eshell/esh-io.el (eshell-print-queue-size, eshell-print-queue,
eshell-print-queue-count): Make obsolete in favor of...
(eshell-buffered-print-size, eshell--buffered-print-queue)
(eshell--buffered-print-current-size): ... these.
(eshell-buffered-print-redisplay-throttle): New user option.
(eshell--buffered-print-next-redisplay): New variable.
(eshell-init-print-buffer): Make obsolete.
(eshell-flush): Add new REDISPLAY-NOW argument in favor of CLEAR (which
only 'eshell-init-print-buffer' should have used).
(eshell-buffered-print): Compare queued output length to
'eshell--buffered-print-current-size'.
(eshell-with-buffered-print): New macro.
* lisp/eshell/esh-var.el (eshell/env):
* lisp/eshell/em-dirs.el (eshell/cd):
* lisp/eshell/em-hist.el (eshell/history):
* lisp/eshell/em-unix.el (eshell/cat):
* lisp/eshell/em-ls.el (eshell/ls): Use 'eshell-with-buffered-print'.
(flush-func): Remove.
(eshell-ls--insert-directory, eshell-do-ls): Remove 'flush-func'.
* test/lisp/eshell/em-unix-tests.el (em-unix-test/compile/interactive)
(em-unix-test/compile/pipeline, em-unix-test/compile/subcommand): Fix
indentation.
(em-unix-test/cat/file-output): New test.
* etc/NEWS: Announce these improvements.
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.
* lisp/eshell/em-script.el (eshell-source-file): Make obsolete.
(eshell--source-file): Adapt from 'eshell-source-file'...
(eshell-script-initialize, eshell/source, eshell/.): ... use it.
(eshell-princ-target): New struct.
(eshell-output-object-to-target, eshell-target-line-oriented-p): New
implementations for 'eshell-princ-target'.
(eshell-execute-file, eshell-batch-file): New functions.
* lisp/eshell/esh-mode.el (eshell-mode): Just warn if we can't create
the Eshell directory.
* test/lisp/eshell/em-script-tests.el (em-script-test/execute-file):
(em-script-test/execute-file/args), em-script-test/batch-file): New
tests.
* test/lisp/eshell/eshell-tests-helpers.el (with-temp-eshell-settings):
New function...
(with-temp-eshell): ... use it.
* doc/misc/eshell.texi (Control Flow): Update documentation.
* etc/NEWS: Announce this change (bug#70847).
This was documented to work by calling the output function with 'nil',
but that was never actually implemented. Instead, for compatibility,
we now support a new (optional) close function.
* lisp/eshell/esh-io.el (eshell-virtual-targets): Update docstring.
(eshell-generic-target): New struct...
(eshell-function-target): ... inherit from it, and rename from
'eshell-virtual-target'.
(eshell-get-target): Handle already-created 'eshell-generic-target'.
(eshell-close-target): Call the target's close function if present.
* test/lisp/eshell/esh-io-tests.el (esh-io-test/virtual/device-close):
New test.
* doc/misc/eshell.texi (Redirection): Document the new behavior.
This also adds the ability to suppress module loading/unloading
messages, which will be necessary to support running Eshell scripts as
batch scripts.
* lisp/eshell/esh-mode.el (eshell-mode): Move module
loading/initialization to...
* lisp/eshell/esh-module.el (eshell-load-modules)
(eshell-initialize-modules): ... here.
(eshell-module-loading-messages): New option.
(eshell-module--feature-name): Improve docstring.
(eshell-unload-modules): Display a real warning if unable to unload a
module.
* test/lisp/eshell/eshell-tests-helpers.el (with-temp-eshell)
(eshell-command-result-equal):
* test/lisp/eshell/eshell-tests-unload.el (load-eshell): Silence Eshell
loading messages.
* 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.
Erase all existing duplicates instead of just the last duplicate entry
when 'eshell-hist-ignoredups' is set to 'erase'. Multiple duplicates
can exist in case 'eshell-hist-ignoredups' was set to something else
than 'erase' in the past or if the history file contains duplicates
(bug#71107).
* lisp/eshell/em-hist.el (eshell-add-input-to-history): Remove all
duplicates from history ring.
* test/lisp/eshell/em-hist-tests.el
(em-hist-test/add-to-history/erase-existing-dups): New test.
* lisp/eshell/esh-ext.el (eshell-explicit-remote-commands)
(eshell-explicit-command): Update docstrings.
(eshell--local-prefix): New constant.
(eshell-handle-remote-command): Remove.
(eshell-quoted-file-command): New function...
(eshell-ext-initialize): ... add it as a hook.
(eshell-remote-command): Support running commands on localhost.
(eshell-connection-local-command): Rename from
'eshell-external-command'.
(eshell-external-command): New implementation calling
'eshell-remote-command' or 'eshell-connection-local-command' as
appropriate.
* test/lisp/eshell/esh-ext-tests.el
(esh-ext-test/explicitly-local-command): Update test.
* doc/misc/eshell.texi (Remote Access): Update documentation.
* etc/NEWS: Update announcement.
* lisp/eshell/esh-util.el (eshell-split-filename): Escaping shouldn't
matter for splitting the name (no other shells handle it like this).
* test/lisp/eshell/em-glob-tests.el
(em-glob-test/convert/quoted-start-directory): New test.
* lisp/eshell/em-glob.el (eshell-glob-convert): Use 'concat' instead of
'file-name-concat' to avoid extraneous slashes.
(eshell-extended-glob): Bail out if we didn't find a glob after all.
* test/lisp/eshell/em-glob-tests.el (tramp): Require.
(em-glob-test/convert/remote-start-directory): Use the mock remote
connection.
(em-glob-test/remote-user-directory): New test.
* lisp/eshell/em-glob.el (eshell-glob-chars-regexp): New function...
(eshell-glob-regexp): ... use it.
(eshell-glob-p): New function...
(eshell-glob-convert): ... use it, and return the deepest start
directory possible.
* lisp/eshell/esh-util.el (eshell-split-path): Rename to...
(eshell-split-path): ... this, and account for remote file names.
* test/lisp/eshell/em-glob-tests.el
(em-glob-test/convert/current-start-directory)
(em-glob-test/convert/relative-start-directory)
(em-glob-test/convert/absolute-start-directory)
(em-glob-test/convert/remote-start-directory): New tests (bug#69592).
* lisp/eshell/esh-opt.el (eshell--get-option-symbols): New function...
(eshell-eval-using-options): ... use it.
(eshell--do-opts, eshell--process-args): Take OPTION-SYMS.
* test/lisp/eshell/esh-opt-tests.el (esh-opt-test/process-args):
(esh-opt-test/process-args-parse-leading-options-only):
(esh-opt-test/process-args-external): Pass OPTION-SYMS in.
Normally, "echo<RET>" runs the command "echo". Likewise,
"echo\<RET><RET>" should too: we escape the first newline, and then
the second one is unescaped and should send the command input to
Eshell. Previously, you had to press RET a third time, but now it
works as expected.
* lisp/eshell/esh-arg.el (eshell-looking-at-backslash-return): Make
obsolete.
(eshell-parse-backslash): A backslash sequence is only incomplete if
there's nothing at all after it.
* test/lisp/eshell/esh-arg-tests.el (esh-arg-test/escape/newline)
(esh-arg-test/escape-quoted/newline): Remove inaccurate comment;
escaped newlines are always special.
(esh-arg-test/escape/trailing-newline): New test.
This is particularly important when the inner command to execute is an
alias. Aliases throw 'eshell-replace-command' too, so we want to do
this in two phases: first, replace the "sudo"/"doas" with a
let-binding of 'default-directory', and then later, let the alias code
do its own replacement (bug#68074).
* lisp/eshell/em-tramp.el (eshell/sudo, eshell/doas): Use
'eshell-replace-command' to wrap the inner command.
* test/lisp/eshell/em-tramp-tests.el (mock-eshell-named-command):
Remove.
(em-tramp-test/sudo-basic, em-tramp-test/sudo-user)
(em-tramp-test/doas-basic, em-tramp-test/doas-user): Catch
'eshell-replace-command'.
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.
* (eshell-handle-local-variables): Move most of the code to...
(eshell-parse-local-variables): ... here.
(eshell/env): Call 'eshell-parse-local-variables'.
* test/lisp/eshell/esh-var-tests.el
(esh-var-test/local-variables/env): New test.
* doc/misc/eshell.texi (Built-ins): Describe the new behavior.
* etc/NEWS: Announce this change.
This ensures that these commands work the same as normal commands,
aside from making environment variable settings local to that command.
Among other things, this means that "VAR=value cd dir/" now changes
the directory correctly.
* lisp/eshell/esh-var.el (eshell-in-local-scope-p)
(eshell-local-variable-bindings): New variables.
(eshell-var-initialize, eshell-set-variable): Use
'eshell-local-variable-bindings'.
(eshell-handle-local-variables): Don't use 'eshell-as-subcommand'.
* test/lisp/eshell/esh-var-tests.el (esh-var-test/local-variables/cd):
New test.
* test/lisp/eshell/em-hist-tests.el (em-hist-test/check-history-file):
New function. Use it throughout this file.
(em-hist-test/history-append): Rename to...
(em-hist-test/write-history/append): ... this.
(em-hist-test/history-read): Rename to...
(em-hist-test/write-history/overwrite): ... this.
(em-hist-test/write-history/append-multiple-eshells)
(em-hist-test/write-history/overwrite-multiple-shells): New tests.
(em-hist-test/write-history/read-only): Check the resulting history.