From 30320d9420b2850341e94fa1b10476344bfa9589 Mon Sep 17 00:00:00 2001 From: Jim Porter Date: Sat, 6 Aug 2022 13:37:28 -0700 Subject: 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. --- test/lisp/eshell/esh-cmd-tests.el | 189 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 189 insertions(+) create mode 100644 test/lisp/eshell/esh-cmd-tests.el (limited to 'test/lisp/eshell/esh-cmd-tests.el') diff --git a/test/lisp/eshell/esh-cmd-tests.el b/test/lisp/eshell/esh-cmd-tests.el new file mode 100644 index 00000000000..1d5cd29d7cf --- /dev/null +++ b/test/lisp/eshell/esh-cmd-tests.el @@ -0,0 +1,189 @@ +;;; esh-cmd-tests.el --- esh-cmd test suite -*- lexical-binding:t -*- + +;; Copyright (C) 2022 Free Software Foundation, Inc. + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Commentary: + +;; Tests for Eshell's command invocation. + +;;; Code: + +(require 'ert) +(require 'esh-mode) +(require 'eshell) + +(require 'eshell-tests-helpers + (expand-file-name "eshell-tests-helpers" + (file-name-directory (or load-file-name + default-directory)))) + +(defvar eshell-test-value nil) + +;;; Tests: + + +;; Command invocation + +(ert-deftest esh-cmd-test/simple-command-result () + "Test invocation with a simple command." + (should (equal (eshell-test-command-result "+ 1 2") 3))) + +(ert-deftest esh-cmd-test/lisp-command () + "Test invocation with an elisp command." + (should (equal (eshell-test-command-result "(+ 1 2)") 3))) + +(ert-deftest esh-cmd-test/lisp-command-with-quote () + "Test invocation with an elisp command containing a quote." + (should (equal (eshell-test-command-result "(eq 'foo nil)") nil))) + +(ert-deftest esh-cmd-test/lisp-command-args () + "Test invocation with elisp and trailing args. +Test that trailing arguments outside the S-expression are +ignored. e.g. \"(+ 1 2) 3\" => 3" + (should (equal (eshell-test-command-result "(+ 1 2) 3") 3))) + +(ert-deftest esh-cmd-test/subcommand () + "Test invocation with a simple subcommand." + (should (equal (eshell-test-command-result "{+ 1 2}") 3))) + +(ert-deftest esh-cmd-test/subcommand-args () + "Test invocation with a subcommand and trailing args. +Test that trailing arguments outside the subcommand are ignored. +e.g. \"{+ 1 2} 3\" => 3" + (should (equal (eshell-test-command-result "{+ 1 2} 3") 3))) + +(ert-deftest esh-cmd-test/subcommand-lisp () + "Test invocation with an elisp subcommand and trailing args. +Test that trailing arguments outside the subcommand are ignored. +e.g. \"{(+ 1 2)} 3\" => 3" + (should (equal (eshell-test-command-result "{(+ 1 2)} 3") 3))) + + +;; Logical operators + +(ert-deftest esh-cmd-test/and-operator () + "Test logical && operator." + (skip-unless (executable-find "[")) + (with-temp-eshell + (eshell-command-result-p "[ foo = foo ] && echo hi" + "hi\n") + (eshell-command-result-p "[ foo = bar ] && echo hi" + "\\`\\'"))) + +(ert-deftest esh-cmd-test/or-operator () + "Test logical || operator." + (skip-unless (executable-find "[")) + (with-temp-eshell + (eshell-command-result-p "[ foo = foo ] || echo hi" + "\\`\\'") + (eshell-command-result-p "[ foo = bar ] || echo hi" + "hi\n"))) + + +;; Control flow statements + +(ert-deftest esh-cmd-test/for-loop () + "Test invocation of a for loop." + (with-temp-eshell + (eshell-command-result-p "for i in 5 { echo $i }" + "5\n"))) + +(ert-deftest esh-cmd-test/for-loop-list () + "Test invocation of a for loop iterating over a list." + (with-temp-eshell + (eshell-command-result-p "for i in (list 1 2 (list 3 4)) { echo $i }" + "1\n2\n(3 4)\n"))) + +(ert-deftest esh-cmd-test/for-loop-multiple-args () + "Test invocation of a for loop iterating over multiple arguments." + (with-temp-eshell + (eshell-command-result-p "for i in 1 2 (list 3 4) { echo $i }" + "1\n2\n3\n4\n"))) + +(ert-deftest esh-cmd-test/for-name-loop () ; bug#15231 + "Test invocation of a for loop using `name'." + (let ((process-environment (cons "name" process-environment))) + (should (equal (eshell-test-command-result + "for name in 3 { echo $name }") + 3)))) + +(ert-deftest esh-cmd-test/for-name-shadow-loop () ; bug#15372 + "Test invocation of a for loop using an env-var." + (let ((process-environment (cons "name=env-value" process-environment))) + (with-temp-eshell + (eshell-command-result-p + "echo $name; for name in 3 { echo $name }; echo $name" + "env-value\n3\nenv-value\n")))) + +(ert-deftest esh-cmd-test/while-loop () + "Test invocation of a while loop." + (skip-unless (executable-find "[")) + (with-temp-eshell + (let ((eshell-test-value 0)) + (eshell-command-result-p + (concat "while {[ $eshell-test-value -ne 3 ]} " + "{ setq eshell-test-value (1+ eshell-test-value) }") + "1\n2\n3\n")))) + +(ert-deftest esh-cmd-test/until-loop () + "Test invocation of an until loop." + (skip-unless (executable-find "[")) + (with-temp-eshell + (let ((eshell-test-value 0)) + (eshell-command-result-p + (concat "until {[ $eshell-test-value -eq 3 ]} " + "{ setq eshell-test-value (1+ eshell-test-value) }") + "1\n2\n3\n")))) + +(ert-deftest esh-cmd-test/if-statement () + "Test invocation of an if statement." + (skip-unless (executable-find "[")) + (with-temp-eshell + (eshell-command-result-p "if {[ foo = foo ]} {echo yes}" + "yes\n") + (eshell-command-result-p "if {[ foo = bar ]} {echo yes}" + "\\`\\'"))) + +(ert-deftest esh-cmd-test/if-else-statement () + "Test invocation of an if/else statement." + (skip-unless (executable-find "[")) + (with-temp-eshell + (eshell-command-result-p "if {[ foo = foo ]} {echo yes} {echo no}" + "yes\n") + (eshell-command-result-p "if {[ foo = bar ]} {echo yes} {echo no}" + "no\n"))) + +(ert-deftest esh-cmd-test/unless-statement () + "Test invocation of an unless statement." + (skip-unless (executable-find "[")) + (with-temp-eshell + (eshell-command-result-p "unless {[ foo = foo ]} {echo no}" + "\\`\\'") + (eshell-command-result-p "unless {[ foo = bar ]} {echo no}" + "no\n"))) + +(ert-deftest esh-cmd-test/unless-else-statement () + "Test invocation of an unless/else statement." + (skip-unless (executable-find "[")) + (with-temp-eshell + (eshell-command-result-p "unless {[ foo = foo ]} {echo no} {echo yes}" + "yes\n") + (eshell-command-result-p "unless {[ foo = bar ]} {echo no} {echo yes}" + "no\n"))) + +;; esh-cmd-tests.el ends here -- cgit v1.2.3 From 9d4fa4ed4b1f2b081e8ed14cbe16d9ec4b993988 Mon Sep 17 00:00:00 2001 From: Jim Porter Date: Mon, 8 Aug 2022 21:24:27 -0700 Subject: 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). --- doc/misc/eshell.texi | 43 +++++++++++++++------------- lisp/eshell/esh-cmd.el | 9 +++--- test/lisp/eshell/esh-cmd-tests.el | 60 ++++++++++++++++++++++++++++++++------- 3 files changed, 79 insertions(+), 33 deletions(-) (limited to 'test/lisp/eshell/esh-cmd-tests.el') diff --git a/doc/misc/eshell.texi b/doc/misc/eshell.texi index d643cb50960..141c30ae9b9 100644 --- a/doc/misc/eshell.texi +++ b/doc/misc/eshell.texi @@ -1020,27 +1020,32 @@ Because Eshell commands can not (easily) be combined with lisp forms, Eshell provides command-oriented control flow statements for convenience. +Most of Eshell's control flow statements accept a @var{conditional}. +This can take a few different forms. If @var{conditional} is a dollar +expansion, the condition is satisfied if the result is a +non-@code{nil} value. If @var{conditional} is a @samp{@{ +@var{subcommand} @}}, the condition is satisfied if the +@var{subcommand}'s exit status is 0. + @table @code -@item if @{ @var{conditional} @} @{ @var{true-commands} @} -@itemx if @{ @var{conditional} @} @{ @var{true-commands} @} @{ @var{false-commands} @} -Evaluate @var{true-commands} if @var{conditional} returns success -(i.e.@: its exit code is zero); otherwise, evaluate -@var{false-commands}. - -@item unless @{ @var{conditional} @} @{ @var{false-commands} @} -@itemx unless @{ @var{conditional} @} @{ @var{false-commands} @} @{ @var{true-commands} @} -Evaluate @var{false-commands} if @var{conditional} returns failure -(i.e.@: its exit code is non-zero); otherwise, evaluate -@var{true-commands}. - -@item while @{ @var{conditional} @} @{ @var{commands} @} -Repeatedly evaluate @var{commands} so long as @var{conditional} -returns success. - -@item until @{ @var{conditional} @} @{ @var{commands} @} -Repeatedly evaluate @var{commands} so long as @var{conditional} -returns failure. +@item if @var{conditional} @{ @var{true-commands} @} +@itemx if @var{conditional} @{ @var{true-commands} @} @{ @var{false-commands} @} +Evaluate @var{true-commands} if @var{conditional} is satisfied; +otherwise, evaluate @var{false-commands}. + +@item unless @var{conditional} @{ @var{false-commands} @} +@itemx unless @var{conditional} @{ @var{false-commands} @} @{ @var{true-commands} @} +Evaluate @var{false-commands} if @var{conditional} is not satisfied; +otherwise, evaluate @var{true-commands}. + +@item while @var{conditional} @{ @var{commands} @} +Repeatedly evaluate @var{commands} so long as @var{conditional} is +satisfied. + +@item until @var{conditional} @{ @var{commands} @} +Repeatedly evaluate @var{commands} until @var{conditional} is +satisfied. @item for @var{var} in @var{list}@dots{} @{ @var{commands} @} Iterate over each element of of @var{list}, storing the element in diff --git a/lisp/eshell/esh-cmd.el b/lisp/eshell/esh-cmd.el index 96272ca1a3d..454a90e91d3 100644 --- a/lisp/eshell/esh-cmd.el +++ b/lisp/eshell/esh-cmd.el @@ -549,10 +549,11 @@ implemented via rewriting, rather than as a function." The first of NAMES should be the positive form, and the second the negative. It's not likely that users should ever need to call this function." - ;; If the test form begins with `eshell-convert', it means - ;; something data-wise will be returned, and we should let - ;; that determine the truth of the statement. - (unless (eq (car test) 'eshell-convert) + ;; If the test form begins with `eshell-convert' or + ;; `eshell-escape-arg', it means something data-wise will be + ;; returned, and we should let that determine the truth of the + ;; statement. + (unless (memq (car test) '(eshell-convert eshell-escape-arg)) (setq test `(progn ,test (eshell-exit-success-p)))) diff --git a/test/lisp/eshell/esh-cmd-tests.el b/test/lisp/eshell/esh-cmd-tests.el index 1d5cd29d7cf..b31159a1a8f 100644 --- a/test/lisp/eshell/esh-cmd-tests.el +++ b/test/lisp/eshell/esh-cmd-tests.el @@ -132,6 +132,15 @@ e.g. \"{(+ 1 2)} 3\" => 3" (ert-deftest esh-cmd-test/while-loop () "Test invocation of a while loop." + (with-temp-eshell + (let ((eshell-test-value '(0 1 2))) + (eshell-command-result-p + (concat "while $eshell-test-value " + "{ setq eshell-test-value (cdr eshell-test-value) }") + "(1 2)\n(2)\n")))) + +(ert-deftest esh-cmd-test/while-loop-ext-cmd () + "Test invocation of a while loop using an external command." (skip-unless (executable-find "[")) (with-temp-eshell (let ((eshell-test-value 0)) @@ -142,6 +151,15 @@ e.g. \"{(+ 1 2)} 3\" => 3" (ert-deftest esh-cmd-test/until-loop () "Test invocation of an until loop." + (with-temp-eshell + (let ((eshell-test-value nil)) + (eshell-command-result-p + (concat "until $eshell-test-value " + "{ setq eshell-test-value t }") + "t\n")))) + +(ert-deftest esh-cmd-test/until-loop-ext-cmd () + "Test invocation of an until loop using an external command." (skip-unless (executable-find "[")) (with-temp-eshell (let ((eshell-test-value 0)) @@ -152,15 +170,26 @@ e.g. \"{(+ 1 2)} 3\" => 3" (ert-deftest esh-cmd-test/if-statement () "Test invocation of an if statement." - (skip-unless (executable-find "[")) (with-temp-eshell - (eshell-command-result-p "if {[ foo = foo ]} {echo yes}" - "yes\n") - (eshell-command-result-p "if {[ foo = bar ]} {echo yes}" - "\\`\\'"))) + (let ((eshell-test-value t)) + (eshell-command-result-p "if $eshell-test-value {echo yes}" + "yes\n")) + (let ((eshell-test-value nil)) + (eshell-command-result-p "if $eshell-test-value {echo yes}" + "\\`\\'")))) (ert-deftest esh-cmd-test/if-else-statement () "Test invocation of an if/else statement." + (with-temp-eshell + (let ((eshell-test-value t)) + (eshell-command-result-p "if $eshell-test-value {echo yes} {echo no}" + "yes\n")) + (let ((eshell-test-value nil)) + (eshell-command-result-p "if $eshell-test-value {echo yes} {echo no}" + "no\n")))) + +(ert-deftest esh-cmd-test/if-else-statement-ext-cmd () + "Test invocation of an if/else statement using an external command." (skip-unless (executable-find "[")) (with-temp-eshell (eshell-command-result-p "if {[ foo = foo ]} {echo yes} {echo no}" @@ -170,15 +199,26 @@ e.g. \"{(+ 1 2)} 3\" => 3" (ert-deftest esh-cmd-test/unless-statement () "Test invocation of an unless statement." - (skip-unless (executable-find "[")) (with-temp-eshell - (eshell-command-result-p "unless {[ foo = foo ]} {echo no}" - "\\`\\'") - (eshell-command-result-p "unless {[ foo = bar ]} {echo no}" - "no\n"))) + (let ((eshell-test-value t)) + (eshell-command-result-p "unless $eshell-test-value {echo no}" + "\\`\\'")) + (let ((eshell-test-value nil)) + (eshell-command-result-p "unless $eshell-test-value {echo no}" + "no\n")))) (ert-deftest esh-cmd-test/unless-else-statement () "Test invocation of an unless/else statement." + (with-temp-eshell + (let ((eshell-test-value t)) + (eshell-command-result-p "unless $eshell-test-value {echo no} {echo yes}" + "yes\n")) + (let ((eshell-test-value nil)) + (eshell-command-result-p "unless $eshell-test-value {echo no} {echo yes}" + "no\n")))) + +(ert-deftest esh-cmd-test/unless-else-statement-ext-cmd () + "Test invocation of an unless/else statement using an external command." (skip-unless (executable-find "[")) (with-temp-eshell (eshell-command-result-p "unless {[ foo = foo ]} {echo no} {echo yes}" -- cgit v1.2.3 From f3408af0a3251a744cb0b55b5e153565bfd57ea3 Mon Sep 17 00:00:00 2001 From: Jim Porter Date: Tue, 9 Aug 2022 20:09:57 -0700 Subject: 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). --- doc/misc/eshell.texi | 14 +++++--- etc/NEWS | 7 ++++ lisp/eshell/esh-cmd.el | 68 +++++++++++++++++++++++---------------- lisp/eshell/esh-proc.el | 68 +++++++++++++++++++-------------------- test/lisp/eshell/esh-cmd-tests.el | 54 +++++++++++++++++++++++++++++++ test/lisp/eshell/esh-var-tests.el | 56 +++++++++++++++++++++++++++++++- 6 files changed, 199 insertions(+), 68 deletions(-) (limited to 'test/lisp/eshell/esh-cmd-tests.el') diff --git a/doc/misc/eshell.texi b/doc/misc/eshell.texi index 141c30ae9b9..aae779575d5 100644 --- a/doc/misc/eshell.texi +++ b/doc/misc/eshell.texi @@ -890,14 +890,18 @@ command (excluding the command name itself). @vindex $$ @item $$ -This is the result of the last command. In case of an external -command, it is @code{t} or @code{nil}. +This is the result of the last command. For external commands, it is +@code{t} if the exit code was 0 or @code{nil} otherwise. +@vindex eshell-lisp-form-nil-is-failure @vindex $? @item $? This variable contains the exit code of the last command. If the last command was a Lisp function, it is 0 for successful completion or 1 -otherwise. +otherwise. If @code{eshell-lisp-form-nil-is-failure} is +non-@code{nil}, then a command with a Lisp form, like +@samp{(@var{command} @var{args}@dots{})}, that returns @code{nil} will +set this variable to 2. @vindex $COLUMNS @vindex $LINES @@ -1024,8 +1028,8 @@ Most of Eshell's control flow statements accept a @var{conditional}. This can take a few different forms. If @var{conditional} is a dollar expansion, the condition is satisfied if the result is a non-@code{nil} value. If @var{conditional} is a @samp{@{ -@var{subcommand} @}}, the condition is satisfied if the -@var{subcommand}'s exit status is 0. +@var{subcommand} @}} or @samp{(@var{lisp form})}, the condition is +satisfied if the command's exit status is 0. @table @code diff --git a/etc/NEWS b/etc/NEWS index be647f6bbbc..f876916bb6f 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2162,6 +2162,13 @@ Additionally, globs ending with '**/' or '***/' no longer raise an error, and now expand to all directories recursively (following symlinks in the latter case). ++++ +*** Lisp forms in Eshell now treat a 'nil' result as a failed exit status. +When executing a command that looks like '(lisp form)', Eshell will +set the exit status (available in the '$?' variable) to 2. This +allows commands like that to be used as conditionals. To change this +behavior, customize the new 'eshell-lisp-form-nil-is-failure' option. + ** Shell --- diff --git a/lisp/eshell/esh-cmd.el b/lisp/eshell/esh-cmd.el index 454a90e91d3..62c95056fd2 100644 --- a/lisp/eshell/esh-cmd.el +++ b/lisp/eshell/esh-cmd.el @@ -133,6 +133,10 @@ There are several different kinds of commands, however." Such arguments will be passed to `read', and then evaluated." :type 'regexp) +(defcustom eshell-lisp-form-nil-is-failure t + "If non-nil, Lisp forms like (COMMAND ARGS) treat a nil result as failure." + :type 'boolean) + (defcustom eshell-pre-command-hook nil "A hook run before each interactive command is invoked." :type 'hook) @@ -1412,43 +1416,53 @@ via `eshell-errorn'." (defun eshell-lisp-command (object &optional args) "Insert Lisp OBJECT, using ARGS if a function." (catch 'eshell-external ; deferred to an external command + (setq eshell-last-command-status 0 + eshell-last-arguments args) (let* ((eshell-ensure-newline-p (eshell-interactive-output-p)) + (command-form-p (functionp object)) (result - (if (functionp object) - (progn - (setq eshell-last-arguments args - eshell-last-command-name + (if command-form-p + (let ((numeric (not (get object + 'eshell-no-numeric-conversions))) + (fname-args (get object 'eshell-filename-arguments))) + (when (or numeric fname-args) + (while args + (let ((arg (car args))) + (cond + ((and numeric (stringp arg) (> (length arg) 0) + (text-property-any 0 (length arg) + 'number t arg)) + ;; If any of the arguments are flagged as + ;; numbers waiting for conversion, convert + ;; them now. + (setcar args (string-to-number arg))) + ((and fname-args (stringp arg) + (string-equal arg "~")) + ;; If any of the arguments match "~", + ;; prepend "./" to treat it as a regular + ;; file name. + (setcar args (concat "./" arg))))) + (setq args (cdr args)))) + (setq eshell-last-command-name (concat "#")) - (let ((numeric (not (get object - 'eshell-no-numeric-conversions))) - (fname-args (get object 'eshell-filename-arguments))) - (when (or numeric fname-args) - (while args - (let ((arg (car args))) - (cond ((and numeric (stringp arg) (> (length arg) 0) - (text-property-any 0 (length arg) - 'number t arg)) - ;; If any of the arguments are - ;; flagged as numbers waiting for - ;; conversion, convert them now. - (setcar args (string-to-number arg))) - ((and fname-args (stringp arg) - (string-equal arg "~")) - ;; If any of the arguments match "~", - ;; prepend "./" to treat it as a - ;; regular file name. - (setcar args (concat "./" arg))))) - (setq args (cdr args))))) (eshell-apply object eshell-last-arguments)) - (setq eshell-last-arguments args - eshell-last-command-name "#") + (setq eshell-last-command-name "#") (eshell-eval object)))) (if (and eshell-ensure-newline-p (save-excursion (goto-char eshell-last-output-end) (not (bolp)))) (eshell-print "\n")) - (eshell-close-handles 0 (list 'quote result))))) + (eshell-close-handles + ;; If `eshell-lisp-form-nil-is-failure' is non-nil, Lisp forms + ;; that succeeded but have a nil result should have an exit + ;; status of 2. + (when (and eshell-lisp-form-nil-is-failure + (not command-form-p) + (= eshell-last-command-status 0) + (not result)) + 2) + (list 'quote result))))) (defalias 'eshell-lisp-command* #'eshell-lisp-command) diff --git a/lisp/eshell/esh-proc.el b/lisp/eshell/esh-proc.el index 99b43661f2c..c367b5cd643 100644 --- a/lisp/eshell/esh-proc.el +++ b/lisp/eshell/esh-proc.el @@ -346,7 +346,9 @@ Used only on systems which do not support async subprocesses.") (defvar eshell-last-output-end) ;Defined in esh-mode.el. (eshell-update-markers eshell-last-output-end) ;; Simulate the effect of eshell-sentinel. - (eshell-close-handles (if (numberp exit-status) exit-status -1)) + (eshell-close-handles + (if (numberp exit-status) exit-status -1) + (list 'quote (and (numberp exit-status) (= exit-status 0)))) (eshell-kill-process-function command exit-status) (or (bound-and-true-p eshell-in-pipeline-p) (setq eshell-last-sync-output-start nil)) @@ -398,40 +400,36 @@ PROC is the process that's exiting. STRING is the exit message." (when (buffer-live-p (process-buffer proc)) (with-current-buffer (process-buffer proc) (unwind-protect - (let ((entry (assq proc eshell-process-list))) -; (if (not entry) -; (error "Sentinel called for unowned process `%s'" -; (process-name proc)) - (when entry - (unwind-protect - (progn - (unless (string= string "run") - ;; Write the exit message if the status is - ;; abnormal and the process is already writing - ;; to the terminal. - (when (and (eq proc (eshell-tail-process)) - (not (string-match "^\\(finished\\|exited\\)" - string))) - (funcall (process-filter proc) proc string)) - (let ((handles (nth 1 entry)) - (str (prog1 (nth 3 entry) - (setf (nth 3 entry) nil))) - (status (process-exit-status proc))) - ;; If we're in the middle of handling output - ;; from this process then schedule the EOF for - ;; later. - (letrec ((finish-io - (lambda () - (if (nth 4 entry) - (run-at-time 0 nil finish-io) - (when str - (ignore-error 'eshell-pipe-broken - (eshell-output-object - str nil handles))) - (eshell-close-handles - status 'nil handles))))) - (funcall finish-io))))) - (eshell-remove-process-entry entry)))) + (when-let ((entry (assq proc eshell-process-list))) + (unwind-protect + (unless (string= string "run") + ;; Write the exit message if the status is + ;; abnormal and the process is already writing + ;; to the terminal. + (when (and (eq proc (eshell-tail-process)) + (not (string-match "^\\(finished\\|exited\\)" + string))) + (funcall (process-filter proc) proc string)) + (let ((handles (nth 1 entry)) + (str (prog1 (nth 3 entry) + (setf (nth 3 entry) nil))) + (status (process-exit-status proc))) + ;; If we're in the middle of handling output + ;; from this process then schedule the EOF for + ;; later. + (letrec ((finish-io + (lambda () + (if (nth 4 entry) + (run-at-time 0 nil finish-io) + (when str + (ignore-error 'eshell-pipe-broken + (eshell-output-object + str nil handles))) + (eshell-close-handles + status (list 'quote (= status 0)) + handles))))) + (funcall finish-io)))) + (eshell-remove-process-entry entry))) (eshell-kill-process-function proc string))))) (defun eshell-process-interact (func &optional all query) diff --git a/test/lisp/eshell/esh-cmd-tests.el b/test/lisp/eshell/esh-cmd-tests.el index b31159a1a8f..e86985ec717 100644 --- a/test/lisp/eshell/esh-cmd-tests.el +++ b/test/lisp/eshell/esh-cmd-tests.el @@ -139,6 +139,15 @@ e.g. \"{(+ 1 2)} 3\" => 3" "{ setq eshell-test-value (cdr eshell-test-value) }") "(1 2)\n(2)\n")))) +(ert-deftest esh-cmd-test/while-loop-lisp-form () + "Test invocation of a while loop using a Lisp form." + (with-temp-eshell + (let ((eshell-test-value 0)) + (eshell-command-result-p + (concat "while (/= eshell-test-value 3) " + "{ setq eshell-test-value (1+ eshell-test-value) }") + "1\n2\n3\n")))) + (ert-deftest esh-cmd-test/while-loop-ext-cmd () "Test invocation of a while loop using an external command." (skip-unless (executable-find "[")) @@ -158,6 +167,16 @@ e.g. \"{(+ 1 2)} 3\" => 3" "{ setq eshell-test-value t }") "t\n")))) +(ert-deftest esh-cmd-test/until-loop-lisp-form () + "Test invocation of an until loop using a Lisp form." + (skip-unless (executable-find "[")) + (with-temp-eshell + (let ((eshell-test-value 0)) + (eshell-command-result-p + (concat "until (= eshell-test-value 3) " + "{ setq eshell-test-value (1+ eshell-test-value) }") + "1\n2\n3\n")))) + (ert-deftest esh-cmd-test/until-loop-ext-cmd () "Test invocation of an until loop using an external command." (skip-unless (executable-find "[")) @@ -188,6 +207,30 @@ e.g. \"{(+ 1 2)} 3\" => 3" (eshell-command-result-p "if $eshell-test-value {echo yes} {echo no}" "no\n")))) +(ert-deftest esh-cmd-test/if-else-statement-lisp-form () + "Test invocation of an if/else statement using a Lisp form." + (with-temp-eshell + (eshell-command-result-p "if (zerop 0) {echo yes} {echo no}" + "yes\n") + (eshell-command-result-p "if (zerop 1) {echo yes} {echo no}" + "no\n") + (let ((debug-on-error nil)) + (eshell-command-result-p "if (zerop \"foo\") {echo yes} {echo no}" + "no\n")))) + +(ert-deftest esh-cmd-test/if-else-statement-lisp-form-2 () + "Test invocation of an if/else statement using a Lisp form. +This tests when `eshell-lisp-form-nil-is-failure' is nil." + (let ((eshell-lisp-form-nil-is-failure nil)) + (with-temp-eshell + (eshell-command-result-p "if (zerop 0) {echo yes} {echo no}" + "yes\n") + (eshell-command-result-p "if (zerop 1) {echo yes} {echo no}" + "yes\n") + (let ((debug-on-error nil)) + (eshell-command-result-p "if (zerop \"foo\") {echo yes} {echo no}" + "no\n"))))) + (ert-deftest esh-cmd-test/if-else-statement-ext-cmd () "Test invocation of an if/else statement using an external command." (skip-unless (executable-find "[")) @@ -217,6 +260,17 @@ e.g. \"{(+ 1 2)} 3\" => 3" (eshell-command-result-p "unless $eshell-test-value {echo no} {echo yes}" "no\n")))) +(ert-deftest esh-cmd-test/unless-else-statement-lisp-form () + "Test invocation of an unless/else statement using a Lisp form." + (with-temp-eshell + (eshell-command-result-p "unless (zerop 0) {echo no} {echo yes}" + "yes\n") + (eshell-command-result-p "unless (zerop 1) {echo no} {echo yes}" + "no\n") + (let ((debug-on-error nil)) + (eshell-command-result-p "unless (zerop \"foo\") {echo no} {echo yes}" + "no\n")))) + (ert-deftest esh-cmd-test/unless-else-statement-ext-cmd () "Test invocation of an unless/else statement using an external command." (skip-unless (executable-find "[")) diff --git a/test/lisp/eshell/esh-var-tests.el b/test/lisp/eshell/esh-var-tests.el index 54e701a6aab..66dabd424bd 100644 --- a/test/lisp/eshell/esh-var-tests.el +++ b/test/lisp/eshell/esh-var-tests.el @@ -500,18 +500,72 @@ inside double-quotes" (eshell-command-result-p "echo $INSIDE_EMACS[, 1]" "eshell"))) +(ert-deftest esh-var-test/last-status-var-lisp-command () + "Test using the \"last exit status\" ($?) variable with a Lisp command" + (with-temp-eshell + (eshell-command-result-p "zerop 0; echo $?" + "t\n0\n") + (eshell-command-result-p "zerop 1; echo $?" + "0\n") + (let ((debug-on-error nil)) + (eshell-command-result-p "zerop foo; echo $?" + "1\n")))) + +(ert-deftest esh-var-test/last-status-var-lisp-form () + "Test using the \"last exit status\" ($?) variable with a Lisp form" + (let ((eshell-lisp-form-nil-is-failure t)) + (with-temp-eshell + (eshell-command-result-p "(zerop 0); echo $?" + "t\n0\n") + (eshell-command-result-p "(zerop 1); echo $?" + "2\n") + (let ((debug-on-error nil)) + (eshell-command-result-p "(zerop \"foo\"); echo $?" + "1\n"))))) + +(ert-deftest esh-var-test/last-status-var-lisp-form-2 () + "Test using the \"last exit status\" ($?) variable with a Lisp form. +This tests when `eshell-lisp-form-nil-is-failure' is nil." + (let ((eshell-lisp-form-nil-is-failure nil)) + (with-temp-eshell + (eshell-command-result-p "(zerop 0); echo $?" + "0\n") + (eshell-command-result-p "(zerop 0); echo $?" + "0\n") + (let ((debug-on-error nil)) + (eshell-command-result-p "(zerop \"foo\"); echo $?" + "1\n"))))) + +(ert-deftest esh-var-test/last-status-var-ext-cmd () + "Test using the \"last exit status\" ($?) variable with an external command" + (skip-unless (executable-find "[")) + (with-temp-eshell + (eshell-command-result-p "[ foo = foo ]; echo $?" + "0\n") + (eshell-command-result-p "[ foo = bar ]; echo $?" + "1\n"))) + (ert-deftest esh-var-test/last-result-var () "Test using the \"last result\" ($$) variable" (with-temp-eshell (eshell-command-result-p "+ 1 2; + $$ 2" "3\n5\n"))) -(ert-deftest esh-var-test/last-result-var2 () +(ert-deftest esh-var-test/last-result-var-twice () "Test using the \"last result\" ($$) variable twice" (with-temp-eshell (eshell-command-result-p "+ 1 2; + $$ $$" "3\n6\n"))) +(ert-deftest esh-var-test/last-result-var-ext-cmd () + "Test using the \"last result\" ($$) variable with an external command" + (skip-unless (executable-find "[")) + (with-temp-eshell + (eshell-command-result-p "[ foo = foo ]; format \"%s\" $$" + "t\n") + (eshell-command-result-p "[ foo = bar ]; format \"%s\" $$" + "nil\n"))) + (ert-deftest esh-var-test/last-result-var-split-indices () "Test using the \"last result\" ($$) variable with split indices" (with-temp-eshell -- cgit v1.2.3 From 07b8fb197a3057a3419be0335236547e4d7a326b Mon Sep 17 00:00:00 2001 From: Jim Porter Date: Sat, 13 Aug 2022 20:31:11 -0700 Subject: Provide ERT explainer for 'eshell-match-command-output' This was formerly named 'eshell-command-result-p', but "result" isn't quite the right terminology, since this function specifically tested the output of a command, not its Lisp result (as 'eshell-command-result' would return). * test/lisp/eshell/eshell-tests-helpers.el (eshell-insert-command): Provide a more-complete docstring. (eshell-match-result): Rename to... (eshell-match-output): ... this. (eshell-match-output--explainer): New function. (eshell-command-result-p): Rename to... (eshell-match-command-output): ... this. * test/lisp/eshell/em-alias-tests.el * test/lisp/eshell/em-dirs-tests.el * test/lisp/eshell/em-extpipe-tests.el * test/lisp/eshell/em-script-tests.el * test/lisp/eshell/esh-cmd-tests.el * test/lisp/eshell/esh-proc-tests.el * test/lisp/eshell/esh-var-tests.el * test/lisp/eshell/eshell-tests-helpers.el * test/lisp/eshell/eshell-tests.el: Use 'eshell-match-command-output'. --- test/lisp/eshell/em-alias-tests.el | 28 +++---- test/lisp/eshell/em-dirs-tests.el | 40 +++++----- test/lisp/eshell/em-extpipe-tests.el | 18 ++--- test/lisp/eshell/em-script-tests.el | 20 ++--- test/lisp/eshell/esh-cmd-tests.el | 128 ++++++++++++++++--------------- test/lisp/eshell/esh-proc-tests.el | 4 +- test/lisp/eshell/esh-var-tests.el | 110 +++++++++++++------------- test/lisp/eshell/eshell-tests-helpers.el | 38 +++++---- test/lisp/eshell/eshell-tests.el | 44 +++++------ 9 files changed, 222 insertions(+), 208 deletions(-) (limited to 'test/lisp/eshell/esh-cmd-tests.el') diff --git a/test/lisp/eshell/em-alias-tests.el b/test/lisp/eshell/em-alias-tests.el index 497159e3460..aca622220e3 100644 --- a/test/lisp/eshell/em-alias-tests.el +++ b/test/lisp/eshell/em-alias-tests.el @@ -38,50 +38,50 @@ "Test a simple alias with no arguments" (with-temp-eshell (eshell-insert-command "alias say-hi 'echo hi'") - (eshell-command-result-p "say-hi" "hi\n") - (eshell-command-result-p "say-hi bye" "hi\n"))) + (eshell-match-command-output "say-hi" "hi\n") + (eshell-match-command-output "say-hi bye" "hi\n"))) (ert-deftest em-alias-test/alias-arg-vars () "Test alias with $0, $1, ... variables" (with-temp-eshell (eshell-insert-command "alias show-args 'printnl $0 \"$1 $2\"'") - (eshell-command-result-p "show-args one two" "show-args\none two\n"))) + (eshell-match-command-output "show-args one two" "show-args\none two\n"))) (ert-deftest em-alias-test/alias-arg-vars-indices () "Test alias with $1, $2, ... variables using indices" (with-temp-eshell (eshell-insert-command "alias funny-sum '+ $1[0] $2[1]'") - (eshell-command-result-p "funny-sum (list 1 2) (list 3 4)" - "5\n"))) + (eshell-match-command-output "funny-sum (list 1 2) (list 3 4)" + "5\n"))) (ert-deftest em-alias-test/alias-arg-vars-split-indices () "Test alias with $0, $1, ... variables using split indices" (with-temp-eshell (eshell-insert-command "alias my-prefix 'echo $0[- 0]'") - (eshell-command-result-p "my-prefix" - "my\n") + (eshell-match-command-output "my-prefix" + "my\n") (eshell-insert-command "alias funny-sum '+ $1[: 0] $2[: 1]'") - (eshell-command-result-p "funny-sum 1:2 3:4" - "5\n"))) + (eshell-match-command-output "funny-sum 1:2 3:4" + "5\n"))) (ert-deftest em-alias-test/alias-all-args-var () "Test alias with the $* variable" (with-temp-eshell (eshell-insert-command "alias show-all-args 'printnl $*'") - (eshell-command-result-p "show-all-args" "\\`\\'") - (eshell-command-result-p "show-all-args a" "a\n") - (eshell-command-result-p "show-all-args a b c" "a\nb\nc\n"))) + (eshell-match-command-output "show-all-args" "\\`\\'") + (eshell-match-command-output "show-all-args a" "a\n") + (eshell-match-command-output "show-all-args a b c" "a\nb\nc\n"))) (ert-deftest em-alias-test/alias-all-args-var-indices () "Test alias with the $* variable using indices" (with-temp-eshell (eshell-insert-command "alias add-pair '+ $*[0] $*[1]'") - (eshell-command-result-p "add-pair 1 2" "3\n"))) + (eshell-match-command-output "add-pair 1 2" "3\n"))) (ert-deftest em-alias-test/alias-all-args-var-split-indices () "Test alias with the $* variable using split indices" (with-temp-eshell (eshell-insert-command "alias add-funny-pair '+ $*[0][: 0] $*[1][: 1]'") - (eshell-command-result-p "add-funny-pair 1:2 3:4" "5\n"))) + (eshell-match-command-output "add-funny-pair 1:2 3:4" "5\n"))) ;; em-alias-tests.el ends here diff --git a/test/lisp/eshell/em-dirs-tests.el b/test/lisp/eshell/em-dirs-tests.el index 8e96cc07471..9e44ef98512 100644 --- a/test/lisp/eshell/em-dirs-tests.el +++ b/test/lisp/eshell/em-dirs-tests.el @@ -58,45 +58,45 @@ "Test using the $OLDPWD variable." (let (eshell-last-dir-ring-file-name) (with-temp-eshell - (eshell-command-result-p "echo $OLDPWD" - "\\`\\'") + (eshell-match-command-output "echo $OLDPWD" + "\\`\\'") (ring-insert eshell-last-dir-ring "/some/path") - (eshell-command-result-p "echo $OLDPWD" - "/some/path\n")))) + (eshell-match-command-output "echo $OLDPWD" + "/some/path\n")))) (ert-deftest em-dirs-test/oldpwd-var-indices () "Test using the $OLDPWD variable with indices." (let (eshell-last-dir-ring-file-name) (with-temp-eshell (ring-insert eshell-last-dir-ring "/some/path/here") - (eshell-command-result-p "echo $OLDPWD[/ 1]" - "some\n") - (eshell-command-result-p "echo $OLDPWD[/ 1 3]" - "(\"some\" \"here\")\n")))) + (eshell-match-command-output "echo $OLDPWD[/ 1]" + "some\n") + (eshell-match-command-output "echo $OLDPWD[/ 1 3]" + "(\"some\" \"here\")\n")))) (ert-deftest em-dirs-test/directory-ring-var () "Test using the $- (directory ring) variable." (let (eshell-last-dir-ring-file-name) (with-temp-eshell - (eshell-command-result-p "echo $-" - "\\`\\'") + (eshell-match-command-output "echo $-" + "\\`\\'") (ring-insert eshell-last-dir-ring "/some/path") (ring-insert eshell-last-dir-ring "/other/path") - (eshell-command-result-p "echo $-" - "/other/path\n") - (eshell-command-result-p "echo $-[0]" - "/other/path\n") - (eshell-command-result-p "echo $-[1]" - "/some/path\n")))) + (eshell-match-command-output "echo $-" + "/other/path\n") + (eshell-match-command-output "echo $-[0]" + "/other/path\n") + (eshell-match-command-output "echo $-[1]" + "/some/path\n")))) (ert-deftest em-dirs-test/directory-ring-var-indices () "Test using the $- (directory ring) variable with multiple indices." (let (eshell-last-dir-ring-file-name) (with-temp-eshell (ring-insert eshell-last-dir-ring "/some/path/here") - (eshell-command-result-p "echo $-[0][/ 1]" - "some\n") - (eshell-command-result-p "echo $-[1][/ 1 3]" - "(\"some\" \"here\")\n")))) + (eshell-match-command-output "echo $-[0][/ 1]" + "some\n") + (eshell-match-command-output "echo $-[1][/ 1 3]" + "(\"some\" \"here\")\n")))) ;; em-dirs-tests.el ends here diff --git a/test/lisp/eshell/em-extpipe-tests.el b/test/lisp/eshell/em-extpipe-tests.el index 29f5dc05512..04e78279427 100644 --- a/test/lisp/eshell/em-extpipe-tests.el +++ b/test/lisp/eshell/em-extpipe-tests.el @@ -80,7 +80,7 @@ (should-parse '(eshell-named-command "sh" (list "-c" "echo \"bar\" | rev >temp"))) (with-substitute-for-temp - (eshell-command-result-p input "^$") + (eshell-match-command-output input "^$") (temp-should-string= "rab"))) (em-extpipe-tests--deftest em-extpipe-test-2 @@ -91,7 +91,7 @@ '((eshell-named-command "echo" (list (eshell-escape-arg "bar"))) (eshell-named-command "sh" (list "-c" "rev >temp"))))) (with-substitute-for-temp - (eshell-command-result-p input "^$") + (eshell-match-command-output input "^$") (temp-should-string= "rab"))) (em-extpipe-tests--deftest em-extpipe-test-3 "foo *| bar | baz -d" @@ -111,7 +111,7 @@ (eshell-named-command "sh" (list "-c" "echo \"bar\" | rev")))) (with-substitute-for-temp - (eshell-command-result-p input "^$") + (eshell-match-command-output input "^$") (temp-buffer-should-string= "rab"))) (em-extpipe-tests--deftest em-extpipe-test-5 @@ -177,7 +177,7 @@ (should-parse '(eshell-named-command "sh" (list "-c" "tac 3" "Test logical && operator." (skip-unless (executable-find "[")) (with-temp-eshell - (eshell-command-result-p "[ foo = foo ] && echo hi" - "hi\n") - (eshell-command-result-p "[ foo = bar ] && echo hi" - "\\`\\'"))) + (eshell-match-command-output "[ foo = foo ] && echo hi" + "hi\n") + (eshell-match-command-output "[ foo = bar ] && echo hi" + "\\`\\'"))) (ert-deftest esh-cmd-test/or-operator () "Test logical || operator." (skip-unless (executable-find "[")) (with-temp-eshell - (eshell-command-result-p "[ foo = foo ] || echo hi" - "\\`\\'") - (eshell-command-result-p "[ foo = bar ] || echo hi" - "hi\n"))) + (eshell-match-command-output "[ foo = foo ] || echo hi" + "\\`\\'") + (eshell-match-command-output "[ foo = bar ] || echo hi" + "hi\n"))) ;; Control flow statements @@ -100,20 +100,20 @@ e.g. \"{(+ 1 2)} 3\" => 3" (ert-deftest esh-cmd-test/for-loop () "Test invocation of a for loop." (with-temp-eshell - (eshell-command-result-p "for i in 5 { echo $i }" - "5\n"))) + (eshell-match-command-output "for i in 5 { echo $i }" + "5\n"))) (ert-deftest esh-cmd-test/for-loop-list () "Test invocation of a for loop iterating over a list." (with-temp-eshell - (eshell-command-result-p "for i in (list 1 2 (list 3 4)) { echo $i }" - "1\n2\n(3 4)\n"))) + (eshell-match-command-output "for i in (list 1 2 (list 3 4)) { echo $i }" + "1\n2\n(3 4)\n"))) (ert-deftest esh-cmd-test/for-loop-multiple-args () "Test invocation of a for loop iterating over multiple arguments." (with-temp-eshell - (eshell-command-result-p "for i in 1 2 (list 3 4) { echo $i }" - "1\n2\n3\n4\n"))) + (eshell-match-command-output "for i in 1 2 (list 3 4) { echo $i }" + "1\n2\n3\n4\n"))) (ert-deftest esh-cmd-test/for-name-loop () ; bug#15231 "Test invocation of a for loop using `name'." @@ -126,7 +126,7 @@ e.g. \"{(+ 1 2)} 3\" => 3" "Test invocation of a for loop using an env-var." (let ((process-environment (cons "name=env-value" process-environment))) (with-temp-eshell - (eshell-command-result-p + (eshell-match-command-output "echo $name; for name in 3 { echo $name }; echo $name" "env-value\n3\nenv-value\n")))) @@ -134,7 +134,7 @@ e.g. \"{(+ 1 2)} 3\" => 3" "Test invocation of a while loop." (with-temp-eshell (let ((eshell-test-value '(0 1 2))) - (eshell-command-result-p + (eshell-match-command-output (concat "while $eshell-test-value " "{ setq eshell-test-value (cdr eshell-test-value) }") "(1 2)\n(2)\n")))) @@ -143,7 +143,7 @@ e.g. \"{(+ 1 2)} 3\" => 3" "Test invocation of a while loop using a Lisp form." (with-temp-eshell (let ((eshell-test-value 0)) - (eshell-command-result-p + (eshell-match-command-output (concat "while (/= eshell-test-value 3) " "{ setq eshell-test-value (1+ eshell-test-value) }") "1\n2\n3\n")))) @@ -153,7 +153,7 @@ e.g. \"{(+ 1 2)} 3\" => 3" (skip-unless (executable-find "[")) (with-temp-eshell (let ((eshell-test-value 0)) - (eshell-command-result-p + (eshell-match-command-output (concat "while {[ $eshell-test-value -ne 3 ]} " "{ setq eshell-test-value (1+ eshell-test-value) }") "1\n2\n3\n")))) @@ -162,7 +162,7 @@ e.g. \"{(+ 1 2)} 3\" => 3" "Test invocation of an until loop." (with-temp-eshell (let ((eshell-test-value nil)) - (eshell-command-result-p + (eshell-match-command-output (concat "until $eshell-test-value " "{ setq eshell-test-value t }") "t\n")))) @@ -172,7 +172,7 @@ e.g. \"{(+ 1 2)} 3\" => 3" (skip-unless (executable-find "[")) (with-temp-eshell (let ((eshell-test-value 0)) - (eshell-command-result-p + (eshell-match-command-output (concat "until (= eshell-test-value 3) " "{ setq eshell-test-value (1+ eshell-test-value) }") "1\n2\n3\n")))) @@ -182,7 +182,7 @@ e.g. \"{(+ 1 2)} 3\" => 3" (skip-unless (executable-find "[")) (with-temp-eshell (let ((eshell-test-value 0)) - (eshell-command-result-p + (eshell-match-command-output (concat "until {[ $eshell-test-value -eq 3 ]} " "{ setq eshell-test-value (1+ eshell-test-value) }") "1\n2\n3\n")))) @@ -191,93 +191,95 @@ e.g. \"{(+ 1 2)} 3\" => 3" "Test invocation of an if statement." (with-temp-eshell (let ((eshell-test-value t)) - (eshell-command-result-p "if $eshell-test-value {echo yes}" - "yes\n")) + (eshell-match-command-output "if $eshell-test-value {echo yes}" + "yes\n")) (let ((eshell-test-value nil)) - (eshell-command-result-p "if $eshell-test-value {echo yes}" - "\\`\\'")))) + (eshell-match-command-output "if $eshell-test-value {echo yes}" + "\\`\\'")))) (ert-deftest esh-cmd-test/if-else-statement () "Test invocation of an if/else statement." (with-temp-eshell (let ((eshell-test-value t)) - (eshell-command-result-p "if $eshell-test-value {echo yes} {echo no}" - "yes\n")) + (eshell-match-command-output "if $eshell-test-value {echo yes} {echo no}" + "yes\n")) (let ((eshell-test-value nil)) - (eshell-command-result-p "if $eshell-test-value {echo yes} {echo no}" - "no\n")))) + (eshell-match-command-output "if $eshell-test-value {echo yes} {echo no}" + "no\n")))) (ert-deftest esh-cmd-test/if-else-statement-lisp-form () "Test invocation of an if/else statement using a Lisp form." (with-temp-eshell - (eshell-command-result-p "if (zerop 0) {echo yes} {echo no}" - "yes\n") - (eshell-command-result-p "if (zerop 1) {echo yes} {echo no}" - "no\n") + (eshell-match-command-output "if (zerop 0) {echo yes} {echo no}" + "yes\n") + (eshell-match-command-output "if (zerop 1) {echo yes} {echo no}" + "no\n") (let ((debug-on-error nil)) - (eshell-command-result-p "if (zerop \"foo\") {echo yes} {echo no}" - "no\n")))) + (eshell-match-command-output "if (zerop \"foo\") {echo yes} {echo no}" + "no\n")))) (ert-deftest esh-cmd-test/if-else-statement-lisp-form-2 () "Test invocation of an if/else statement using a Lisp form. This tests when `eshell-lisp-form-nil-is-failure' is nil." (let ((eshell-lisp-form-nil-is-failure nil)) (with-temp-eshell - (eshell-command-result-p "if (zerop 0) {echo yes} {echo no}" - "yes\n") - (eshell-command-result-p "if (zerop 1) {echo yes} {echo no}" - "yes\n") + (eshell-match-command-output "if (zerop 0) {echo yes} {echo no}" + "yes\n") + (eshell-match-command-output "if (zerop 1) {echo yes} {echo no}" + "yes\n") (let ((debug-on-error nil)) - (eshell-command-result-p "if (zerop \"foo\") {echo yes} {echo no}" - "no\n"))))) + (eshell-match-command-output "if (zerop \"foo\") {echo yes} {echo no}" + "no\n"))))) (ert-deftest esh-cmd-test/if-else-statement-ext-cmd () "Test invocation of an if/else statement using an external command." (skip-unless (executable-find "[")) (with-temp-eshell - (eshell-command-result-p "if {[ foo = foo ]} {echo yes} {echo no}" - "yes\n") - (eshell-command-result-p "if {[ foo = bar ]} {echo yes} {echo no}" - "no\n"))) + (eshell-match-command-output "if {[ foo = foo ]} {echo yes} {echo no}" + "yes\n") + (eshell-match-command-output "if {[ foo = bar ]} {echo yes} {echo no}" + "no\n"))) (ert-deftest esh-cmd-test/unless-statement () "Test invocation of an unless statement." (with-temp-eshell (let ((eshell-test-value t)) - (eshell-command-result-p "unless $eshell-test-value {echo no}" - "\\`\\'")) + (eshell-match-command-output "unless $eshell-test-value {echo no}" + "\\`\\'")) (let ((eshell-test-value nil)) - (eshell-command-result-p "unless $eshell-test-value {echo no}" - "no\n")))) + (eshell-match-command-output "unless $eshell-test-value {echo no}" + "no\n")))) (ert-deftest esh-cmd-test/unless-else-statement () "Test invocation of an unless/else statement." (with-temp-eshell (let ((eshell-test-value t)) - (eshell-command-result-p "unless $eshell-test-value {echo no} {echo yes}" - "yes\n")) + (eshell-match-command-output + "unless $eshell-test-value {echo no} {echo yes}" + "yes\n")) (let ((eshell-test-value nil)) - (eshell-command-result-p "unless $eshell-test-value {echo no} {echo yes}" - "no\n")))) + (eshell-match-command-output + "unless $eshell-test-value {echo no} {echo yes}" + "no\n")))) (ert-deftest esh-cmd-test/unless-else-statement-lisp-form () "Test invocation of an unless/else statement using a Lisp form." (with-temp-eshell - (eshell-command-result-p "unless (zerop 0) {echo no} {echo yes}" - "yes\n") - (eshell-command-result-p "unless (zerop 1) {echo no} {echo yes}" - "no\n") + (eshell-match-command-output "unless (zerop 0) {echo no} {echo yes}" + "yes\n") + (eshell-match-command-output "unless (zerop 1) {echo no} {echo yes}" + "no\n") (let ((debug-on-error nil)) - (eshell-command-result-p "unless (zerop \"foo\") {echo no} {echo yes}" - "no\n")))) + (eshell-match-command-output "unless (zerop \"foo\") {echo no} {echo yes}" + "no\n")))) (ert-deftest esh-cmd-test/unless-else-statement-ext-cmd () "Test invocation of an unless/else statement using an external command." (skip-unless (executable-find "[")) (with-temp-eshell - (eshell-command-result-p "unless {[ foo = foo ]} {echo no} {echo yes}" - "yes\n") - (eshell-command-result-p "unless {[ foo = bar ]} {echo no} {echo yes}" - "no\n"))) + (eshell-match-command-output "unless {[ foo = foo ]} {echo no} {echo yes}" + "yes\n") + (eshell-match-command-output "unless {[ foo = bar ]} {echo no} {echo yes}" + "no\n"))) ;; esh-cmd-tests.el ends here diff --git a/test/lisp/eshell/esh-proc-tests.el b/test/lisp/eshell/esh-proc-tests.el index 734bb91a6a5..f538e8c43a0 100644 --- a/test/lisp/eshell/esh-proc-tests.el +++ b/test/lisp/eshell/esh-proc-tests.el @@ -43,7 +43,7 @@ (executable-find "echo") (executable-find "sleep"))) (with-temp-eshell - (eshell-command-result-p + (eshell-match-command-output ;; The first command is like `yes' but slower. This is to prevent ;; it from taxing Emacs's process filter too much and causing a ;; hang. @@ -136,4 +136,4 @@ prompt. See bug#54136." (kill-process (caar eshell-process-list)) ;; Give `eshell-sentinel' a chance to run. (sit-for 0.1) - (eshell-match-result "\\[sh\\(\\.exe\\)?\\] [[:digit:]]+\n"))) + (should (eshell-match-output "\\[sh\\(\\.exe\\)?\\] [[:digit:]]+\n")))) diff --git a/test/lisp/eshell/esh-var-tests.el b/test/lisp/eshell/esh-var-tests.el index 0c094ee5a79..ca74ad1959d 100644 --- a/test/lisp/eshell/esh-var-tests.el +++ b/test/lisp/eshell/esh-var-tests.el @@ -153,15 +153,15 @@ "Interpolate command result from external command" (skip-unless (executable-find "echo")) (with-temp-eshell - (eshell-command-result-p "echo ${*echo hi}" - "hi\n"))) + (eshell-match-command-output "echo ${*echo hi}" + "hi\n"))) (ert-deftest esh-var-test/interp-cmd-external-indices () "Interpolate command result from external command with index" (skip-unless (executable-find "echo")) (with-temp-eshell - (eshell-command-result-p "echo ${*echo \"hi\nbye\"}[1]" - "bye\n"))) + (eshell-match-command-output "echo ${*echo \"hi\nbye\"}[1]" + "bye\n"))) (ert-deftest esh-var-test/interp-temp-cmd () "Interpolate command result redirected to temp file" @@ -196,8 +196,8 @@ "Interpolate command result from external command with concatenation" (skip-unless (executable-find "echo")) (with-temp-eshell - (eshell-command-result-p "echo ${echo hi}-${*echo there}" - "hi-there\n"))) + (eshell-match-command-output "echo ${echo hi}-${*echo there}" + "hi-there\n"))) (ert-deftest esh-var-test/quoted-interp-var () "Interpolate variable inside double-quotes" @@ -490,72 +490,72 @@ inside double-quotes" (ert-deftest esh-var-test/inside-emacs-var () "Test presence of \"INSIDE_EMACS\" in subprocesses" (with-temp-eshell - (eshell-command-result-p "env" - (format "INSIDE_EMACS=%s,eshell" - emacs-version)))) + (eshell-match-command-output "env" + (format "INSIDE_EMACS=%s,eshell" + emacs-version)))) (ert-deftest esh-var-test/inside-emacs-var-split-indices () "Test using \"INSIDE_EMACS\" with split indices" (with-temp-eshell - (eshell-command-result-p "echo $INSIDE_EMACS[, 1]" - "eshell"))) + (eshell-match-command-output "echo $INSIDE_EMACS[, 1]" + "eshell"))) (ert-deftest esh-var-test/last-status-var-lisp-command () "Test using the \"last exit status\" ($?) variable with a Lisp command" (with-temp-eshell - (eshell-command-result-p "zerop 0; echo $?" - "t\n0\n") - (eshell-command-result-p "zerop 1; echo $?" - "0\n") + (eshell-match-command-output "zerop 0; echo $?" + "t\n0\n") + (eshell-match-command-output "zerop 1; echo $?" + "0\n") (let ((debug-on-error nil)) - (eshell-command-result-p "zerop foo; echo $?" - "1\n")))) + (eshell-match-command-output "zerop foo; echo $?" + "1\n")))) (ert-deftest esh-var-test/last-status-var-lisp-form () "Test using the \"last exit status\" ($?) variable with a Lisp form" (let ((eshell-lisp-form-nil-is-failure t)) - (with-temp-eshell - (eshell-command-result-p "(zerop 0); echo $?" - "t\n0\n") - (eshell-command-result-p "(zerop 1); echo $?" - "2\n") - (let ((debug-on-error nil)) - (eshell-command-result-p "(zerop \"foo\"); echo $?" - "1\n"))))) + (with-temp-eshell + (eshell-match-command-output "(zerop 0); echo $?" + "t\n0\n") + (eshell-match-command-output "(zerop 1); echo $?" + "2\n") + (let ((debug-on-error nil)) + (eshell-match-command-output "(zerop \"foo\"); echo $?" + "1\n"))))) (ert-deftest esh-var-test/last-status-var-lisp-form-2 () "Test using the \"last exit status\" ($?) variable with a Lisp form. This tests when `eshell-lisp-form-nil-is-failure' is nil." (let ((eshell-lisp-form-nil-is-failure nil)) (with-temp-eshell - (eshell-command-result-p "(zerop 0); echo $?" - "0\n") - (eshell-command-result-p "(zerop 0); echo $?" - "0\n") + (eshell-match-command-output "(zerop 0); echo $?" + "0\n") + (eshell-match-command-output "(zerop 0); echo $?" + "0\n") (let ((debug-on-error nil)) - (eshell-command-result-p "(zerop \"foo\"); echo $?" - "1\n"))))) + (eshell-match-command-output "(zerop \"foo\"); echo $?" + "1\n"))))) (ert-deftest esh-var-test/last-status-var-ext-cmd () "Test using the \"last exit status\" ($?) variable with an external command" (skip-unless (executable-find "[")) (with-temp-eshell - (eshell-command-result-p "[ foo = foo ]; echo $?" - "0\n") - (eshell-command-result-p "[ foo = bar ]; echo $?" - "1\n"))) + (eshell-match-command-output "[ foo = foo ]; echo $?" + "0\n") + (eshell-match-command-output "[ foo = bar ]; echo $?" + "1\n"))) (ert-deftest esh-var-test/last-result-var () "Test using the \"last result\" ($$) variable" (with-temp-eshell - (eshell-command-result-p "+ 1 2; + $$ 2" - "3\n5\n"))) + (eshell-match-command-output "+ 1 2; + $$ 2" + "3\n5\n"))) (ert-deftest esh-var-test/last-result-var-twice () "Test using the \"last result\" ($$) variable twice" (with-temp-eshell - (eshell-command-result-p "+ 1 2; + $$ $$" - "3\n6\n"))) + (eshell-match-command-output "+ 1 2; + $$ $$" + "3\n6\n"))) (ert-deftest esh-var-test/last-result-var-ext-cmd () "Test using the \"last result\" ($$) variable with an external command" @@ -564,41 +564,41 @@ This tests when `eshell-lisp-form-nil-is-failure' is nil." ;; MS-DOS/MS-Windows have an external command 'format', which we ;; don't want here. (let ((eshell-prefer-lisp-functions t)) - (eshell-command-result-p "[ foo = foo ]; format \"%s\" $$" - "t\n") - (eshell-command-result-p "[ foo = bar ]; format \"%s\" $$" - "nil\n")))) + (eshell-match-command-output "[ foo = foo ]; format \"%s\" $$" + "t\n") + (eshell-match-command-output "[ foo = bar ]; format \"%s\" $$" + "nil\n")))) (ert-deftest esh-var-test/last-result-var-split-indices () "Test using the \"last result\" ($$) variable with split indices" (with-temp-eshell - (eshell-command-result-p + (eshell-match-command-output "string-join (list \"01\" \"02\") :; + $$[: 1] 3" "01:02\n5\n") - (eshell-command-result-p + (eshell-match-command-output "string-join (list \"01\" \"02\") :; echo \"$$[: 1]\"" "01:02\n02\n"))) (ert-deftest esh-var-test/last-arg-var () "Test using the \"last arg\" ($_) variable" (with-temp-eshell - (eshell-command-result-p "+ 1 2; + $_ 4" - "3\n6\n"))) + (eshell-match-command-output "+ 1 2; + $_ 4" + "3\n6\n"))) (ert-deftest esh-var-test/last-arg-var-indices () "Test using the \"last arg\" ($_) variable with indices" (with-temp-eshell - (eshell-command-result-p "+ 1 2; + $_[0] 4" - "3\n5\n") - (eshell-command-result-p "+ 1 2; + $_[1] 4" - "3\n6\n"))) + (eshell-match-command-output "+ 1 2; + $_[0] 4" + "3\n5\n") + (eshell-match-command-output "+ 1 2; + $_[1] 4" + "3\n6\n"))) (ert-deftest esh-var-test/last-arg-var-split-indices () "Test using the \"last arg\" ($_) variable with split indices" (with-temp-eshell - (eshell-command-result-p "concat 01:02 03:04; + $_[0][: 1] 5" - "01:0203:04\n7\n") - (eshell-command-result-p "concat 01:02 03:04; echo \"$_[0][: 1]\"" - "01:0203:04\n02\n"))) + (eshell-match-command-output "concat 01:02 03:04; + $_[0][: 1] 5" + "01:0203:04\n7\n") + (eshell-match-command-output "concat 01:02 03:04; echo \"$_[0][: 1]\"" + "01:0203:04\n02\n"))) ;; esh-var-tests.el ends here diff --git a/test/lisp/eshell/eshell-tests-helpers.el b/test/lisp/eshell/eshell-tests-helpers.el index 4ad76ca6978..778087bd755 100644 --- a/test/lisp/eshell/eshell-tests-helpers.el +++ b/test/lisp/eshell/eshell-tests-helpers.el @@ -65,24 +65,36 @@ raise an error." (error "timed out waiting for subprocess(es)")) (sit-for 0.1)))) -(defun eshell-insert-command (text &optional func) - "Insert a command at the end of the buffer." +(defun eshell-insert-command (command &optional func) + "Insert a COMMAND at the end of the buffer. +After inserting, call FUNC. If FUNC is nil, instead call +`eshell-send-input'." (goto-char eshell-last-output-end) - (insert-and-inherit text) + (insert-and-inherit command) (funcall (or func 'eshell-send-input))) -(defun eshell-match-result (regexp) - "Check that output of last command matches REGEXP." - (should - (string-match-p +(defun eshell-match-output (regexp) + "Test whether the output of the last command matches REGEXP." + (string-match-p regexp (buffer-substring-no-properties - (eshell-beginning-of-output) (eshell-end-of-output))))) - -(defun eshell-command-result-p (text regexp &optional func) - "Insert a command at the end of the buffer." - (eshell-insert-command text func) + (eshell-beginning-of-output) (eshell-end-of-output)))) + +(defun eshell-match-output--explainer (regexp) + "Explain the result of `eshell-match-output'." + `(mismatched-output + (command ,(buffer-substring-no-properties + eshell-last-input-start eshell-last-input-end)) + (output ,(buffer-substring-no-properties + (eshell-beginning-of-output) (eshell-end-of-output))) + (regexp ,regexp))) + +(put 'eshell-match-output 'ert-explainer #'eshell-match-output--explainer) + +(defun eshell-match-command-output (command regexp &optional func) + "Insert a COMMAND at the end of the buffer and match the output with REGEXP." + (eshell-insert-command command func) (eshell-wait-for-subprocess) - (eshell-match-result regexp)) + (should (eshell-match-output regexp))) (defvar eshell-history-file-name) diff --git a/test/lisp/eshell/eshell-tests.el b/test/lisp/eshell/eshell-tests.el index 8423500ea7d..c7a9516bea4 100644 --- a/test/lisp/eshell/eshell-tests.el +++ b/test/lisp/eshell/eshell-tests.el @@ -40,15 +40,15 @@ "Check that piping a non-process to a process command waits for the process" (skip-unless (executable-find "cat")) (with-temp-eshell - (eshell-command-result-p "echo hi | *cat" - "hi"))) + (eshell-match-command-output "echo hi | *cat" + "hi"))) (ert-deftest eshell-test/pipe-tailproc () "Check that piping a process to a non-process command waits for the process" (skip-unless (executable-find "echo")) (with-temp-eshell - (eshell-command-result-p "*echo hi | echo bye" - "bye\nhi\n"))) + (eshell-match-command-output "*echo hi | echo bye" + "bye\nhi\n"))) (ert-deftest eshell-test/pipe-headproc-stdin () "Check that standard input is sent to the head process in a pipeline" @@ -59,23 +59,23 @@ (eshell-insert-command "hello") (eshell-send-eof-to-process) (eshell-wait-for-subprocess) - (eshell-match-result "OLLEH\n"))) + (should (eshell-match-output "OLLEH\n")))) (ert-deftest eshell-test/pipe-subcommand () "Check that piping with an asynchronous subcommand works" (skip-unless (and (executable-find "echo") (executable-find "cat"))) (with-temp-eshell - (eshell-command-result-p "echo ${*echo hi} | *cat" - "hi"))) + (eshell-match-command-output "echo ${*echo hi} | *cat" + "hi"))) (ert-deftest eshell-test/pipe-subcommand-with-pipe () "Check that piping with an asynchronous subcommand with its own pipe works" (skip-unless (and (executable-find "echo") (executable-find "cat"))) (with-temp-eshell - (eshell-command-result-p "echo ${*echo hi | *cat} | *cat" - "hi"))) + (eshell-match-command-output "echo ${*echo hi | *cat} | *cat" + "hi"))) (ert-deftest eshell-test/subcommand-reset-in-pipeline () "Check that subcommands reset `eshell-in-pipeline-p'." @@ -129,32 +129,32 @@ "Test that \"\\c\" and \"c\" are equivalent when \"c\" is not a special character." (with-temp-eshell - (eshell-command-result-p "echo he\\llo" - "hello\n"))) + (eshell-match-command-output "echo he\\llo" + "hello\n"))) (ert-deftest eshell-test/escape-nonspecial-unicode () "Test that \"\\c\" and \"c\" are equivalent when \"c\" is a unicode character (unicode characters are nonspecial by definition)." (with-temp-eshell - (eshell-command-result-p "echo Vid\\éos" - "Vidéos\n"))) + (eshell-match-command-output "echo Vid\\éos" + "Vidéos\n"))) (ert-deftest eshell-test/escape-nonspecial-quoted () "Test that the backslash is preserved for escaped nonspecial chars" (with-temp-eshell - (eshell-command-result-p "echo \"h\\i\"" - ;; Backslashes are doubled for regexp. - "h\\\\i\n"))) + (eshell-match-command-output "echo \"h\\i\"" + ;; Backslashes are doubled for regexp. + "h\\\\i\n"))) (ert-deftest eshell-test/escape-special-quoted () "Test that the backslash is not preserved for escaped special chars" (with-temp-eshell - (eshell-command-result-p "echo \"\\\"hi\\\\\"" - ;; Backslashes are doubled for regexp. - "\\\"hi\\\\\n"))) + (eshell-match-command-output "echo \"\\\"hi\\\\\"" + ;; Backslashes are doubled for regexp. + "\\\"hi\\\\\n"))) (ert-deftest eshell-test/command-running-p () "Modeline should show no command running" @@ -188,15 +188,15 @@ chars" (> count 0)) (sit-for 1) (setq count (1- count)))) - (eshell-match-result "alpha\n"))) + (should (eshell-match-output "alpha\n")))) (ert-deftest eshell-test/flush-output () "Test flushing of previous output" (with-temp-eshell (eshell-insert-command "echo alpha") (eshell-kill-output) - (eshell-match-result - (concat "^" (regexp-quote "*** output flushed ***\n") "$")))) + (should (eshell-match-output + (concat "^" (regexp-quote "*** output flushed ***\n") "$"))))) (ert-deftest eshell-test/run-old-command () "Re-run an old command" -- cgit v1.2.3 From c1f1be4b73072440518f02356998cf58ba127ebd Mon Sep 17 00:00:00 2001 From: Jim Porter Date: Sun, 14 Aug 2022 13:44:04 -0700 Subject: Add 'eshell-command-result-equal' with an ERT explainer * test/lisp/eshell/eshell-tests-helpers.el (eshell-command-result--equal, eshell-command-result--equal-explainer) (eshell-command-result-equal): New functions. * test/lisp/eshell/em-basic-tests.el * test/lisp/eshell/em-dirs-tests.el * test/lisp/eshell/esh-cmd-tests.el * test/lisp/eshell/esh-proc-tests.el * test/lisp/eshell/esh-var-tests.el * test/lisp/eshell/eshell-tests.el: Use 'eshell-command-result-equal'. --- test/lisp/eshell/em-basic-tests.el | 18 +- test/lisp/eshell/em-dirs-tests.el | 16 +- test/lisp/eshell/esh-cmd-tests.el | 19 +- test/lisp/eshell/esh-proc-tests.el | 31 +-- test/lisp/eshell/esh-var-tests.el | 391 ++++++++++++++----------------- test/lisp/eshell/eshell-tests-helpers.el | 21 ++ test/lisp/eshell/eshell-tests.el | 31 ++- 7 files changed, 254 insertions(+), 273 deletions(-) (limited to 'test/lisp/eshell/esh-cmd-tests.el') diff --git a/test/lisp/eshell/em-basic-tests.el b/test/lisp/eshell/em-basic-tests.el index 7a24f8b46c3..bc8baeaa035 100644 --- a/test/lisp/eshell/em-basic-tests.el +++ b/test/lisp/eshell/em-basic-tests.el @@ -36,25 +36,25 @@ (ert-deftest em-basic-test/umask-print-numeric () "Test printing umask numerically." (cl-letf (((symbol-function 'default-file-modes) (lambda () #o775))) - (should (equal (eshell-test-command-result "umask") "002\n"))) + (eshell-command-result-equal "umask" "002\n")) (cl-letf (((symbol-function 'default-file-modes) (lambda () #o654))) - (should (equal (eshell-test-command-result "umask") "123\n"))) + (eshell-command-result-equal "umask" "123\n")) ;; Make sure larger numbers don't cause problems. (cl-letf (((symbol-function 'default-file-modes) (lambda () #o1775))) - (should (equal (eshell-test-command-result "umask") "002\n")))) + (eshell-command-result-equal "umask" "002\n"))) (ert-deftest em-basic-test/umask-read-symbolic () "Test printing umask symbolically." (cl-letf (((symbol-function 'default-file-modes) (lambda () #o775))) - (should (equal (eshell-test-command-result "umask -S") - "u=rwx,g=rwx,o=rx\n"))) + (eshell-command-result-equal "umask -S" + "u=rwx,g=rwx,o=rx\n")) (cl-letf (((symbol-function 'default-file-modes) (lambda () #o654))) - (should (equal (eshell-test-command-result "umask -S") - "u=wx,g=rx,o=x\n"))) + (eshell-command-result-equal "umask -S" + "u=wx,g=rx,o=x\n")) ;; Make sure larger numbers don't cause problems. (cl-letf (((symbol-function 'default-file-modes) (lambda () #o1775))) - (should (equal (eshell-test-command-result "umask -S") - "u=rwx,g=rwx,o=rx\n")))) + (eshell-command-result-equal "umask -S" + "u=rwx,g=rwx,o=rx\n"))) (ert-deftest em-basic-test/umask-set () "Test setting umask." diff --git a/test/lisp/eshell/em-dirs-tests.el b/test/lisp/eshell/em-dirs-tests.el index 9e44ef98512..f72d708dcae 100644 --- a/test/lisp/eshell/em-dirs-tests.el +++ b/test/lisp/eshell/em-dirs-tests.el @@ -37,22 +37,22 @@ (ert-deftest em-dirs-test/pwd-var () "Test using the $PWD variable." (let ((default-directory "/some/path")) - (should (equal (eshell-test-command-result "echo $PWD") - (expand-file-name default-directory))))) + (eshell-command-result-equal "echo $PWD" + (expand-file-name default-directory)))) (ert-deftest em-dirs-test/pwd-var-indices () "Test using the $PWD variable with indices." (let ((default-directory "/some/path/here")) - (should (equal (eshell-test-command-result "echo $PWD[/ 1]") - "some")) - (should (equal (eshell-test-command-result "echo $PWD[/ 1 3]") - '("some" "here"))))) + (eshell-command-result-equal "echo $PWD[/ 1]" + "some") + (eshell-command-result-equal "echo $PWD[/ 1 3]" + '("some" "here")))) (ert-deftest em-dirs-test/short-pwd-var () "Test using the $+ (current directory) variable." (let ((default-directory "/some/path")) - (should (equal (eshell-test-command-result "echo $+") - (expand-file-name default-directory))))) + (eshell-command-result-equal "echo $+" + (expand-file-name default-directory)))) (ert-deftest em-dirs-test/oldpwd-var () "Test using the $OLDPWD variable." diff --git a/test/lisp/eshell/esh-cmd-tests.el b/test/lisp/eshell/esh-cmd-tests.el index 05635e8a7b5..c5d780a399d 100644 --- a/test/lisp/eshell/esh-cmd-tests.el +++ b/test/lisp/eshell/esh-cmd-tests.el @@ -41,37 +41,37 @@ (ert-deftest esh-cmd-test/simple-command-result () "Test invocation with a simple command." - (should (equal (eshell-test-command-result "+ 1 2") 3))) + (eshell-command-result-equal "+ 1 2" 3)) (ert-deftest esh-cmd-test/lisp-command () "Test invocation with an elisp command." - (should (equal (eshell-test-command-result "(+ 1 2)") 3))) + (eshell-command-result-equal "(+ 1 2)" 3)) (ert-deftest esh-cmd-test/lisp-command-with-quote () "Test invocation with an elisp command containing a quote." - (should (equal (eshell-test-command-result "(eq 'foo nil)") nil))) + (eshell-command-result-equal "(eq 'foo nil)" nil)) (ert-deftest esh-cmd-test/lisp-command-args () "Test invocation with elisp and trailing args. Test that trailing arguments outside the S-expression are ignored. e.g. \"(+ 1 2) 3\" => 3" - (should (equal (eshell-test-command-result "(+ 1 2) 3") 3))) + (eshell-command-result-equal "(+ 1 2) 3" 3)) (ert-deftest esh-cmd-test/subcommand () "Test invocation with a simple subcommand." - (should (equal (eshell-test-command-result "{+ 1 2}") 3))) + (eshell-command-result-equal "{+ 1 2}" 3)) (ert-deftest esh-cmd-test/subcommand-args () "Test invocation with a subcommand and trailing args. Test that trailing arguments outside the subcommand are ignored. e.g. \"{+ 1 2} 3\" => 3" - (should (equal (eshell-test-command-result "{+ 1 2} 3") 3))) + (eshell-command-result-equal "{+ 1 2} 3" 3)) (ert-deftest esh-cmd-test/subcommand-lisp () "Test invocation with an elisp subcommand and trailing args. Test that trailing arguments outside the subcommand are ignored. e.g. \"{(+ 1 2)} 3\" => 3" - (should (equal (eshell-test-command-result "{(+ 1 2)} 3") 3))) + (eshell-command-result-equal "{(+ 1 2)} 3" 3)) ;; Logical operators @@ -118,9 +118,8 @@ e.g. \"{(+ 1 2)} 3\" => 3" (ert-deftest esh-cmd-test/for-name-loop () ; bug#15231 "Test invocation of a for loop using `name'." (let ((process-environment (cons "name" process-environment))) - (should (equal (eshell-test-command-result - "for name in 3 { echo $name }") - 3)))) + (eshell-command-result-equal "for name in 3 { echo $name }" + 3))) (ert-deftest esh-cmd-test/for-name-shadow-loop () ; bug#15372 "Test invocation of a for loop using an env-var." diff --git a/test/lisp/eshell/esh-proc-tests.el b/test/lisp/eshell/esh-proc-tests.el index f538e8c43a0..2369bb5cc00 100644 --- a/test/lisp/eshell/esh-proc-tests.el +++ b/test/lisp/eshell/esh-proc-tests.el @@ -56,36 +56,37 @@ (ert-deftest esh-proc-test/pipeline-connection-type/no-pipeline () "Test that all streams are PTYs when a command is not in a pipeline." (skip-unless (executable-find "sh")) - (should (equal (eshell-test-command-result esh-proc-test--detect-pty-cmd) - ;; PTYs aren't supported on MS-Windows. - (unless (eq system-type 'windows-nt) - "stdin\nstdout\nstderr\n")))) + (eshell-command-result-equal + esh-proc-test--detect-pty-cmd + ;; PTYs aren't supported on MS-Windows. + (unless (eq system-type 'windows-nt) + "stdin\nstdout\nstderr\n"))) (ert-deftest esh-proc-test/pipeline-connection-type/first () "Test that only stdin is a PTY when a command starts a pipeline." (skip-unless (and (executable-find "sh") (executable-find "cat"))) - (should (equal (eshell-test-command-result - (concat esh-proc-test--detect-pty-cmd " | cat")) - (unless (eq system-type 'windows-nt) - "stdin\n")))) + (eshell-command-result-equal + (concat esh-proc-test--detect-pty-cmd " | cat") + (unless (eq system-type 'windows-nt) + "stdin\n"))) (ert-deftest esh-proc-test/pipeline-connection-type/middle () "Test that all streams are pipes when a command is in the middle of a pipeline." (skip-unless (and (executable-find "sh") (executable-find "cat"))) - (should (equal (eshell-test-command-result - (concat "echo | " esh-proc-test--detect-pty-cmd " | cat")) - nil))) + (eshell-command-result-equal + (concat "echo | " esh-proc-test--detect-pty-cmd " | cat") + nil)) (ert-deftest esh-proc-test/pipeline-connection-type/last () "Test that only output streams are PTYs when a command ends a pipeline." (skip-unless (executable-find "sh")) - (should (equal (eshell-test-command-result - (concat "echo | " esh-proc-test--detect-pty-cmd)) - (unless (eq system-type 'windows-nt) - "stdout\nstderr\n")))) + (eshell-command-result-equal + (concat "echo | " esh-proc-test--detect-pty-cmd) + (unless (eq system-type 'windows-nt) + "stdout\nstderr\n"))) (ert-deftest esh-proc-test/kill-pipeline () "Test that killing a pipeline of processes only emits a single diff --git a/test/lisp/eshell/esh-var-tests.el b/test/lisp/eshell/esh-var-tests.el index ca74ad1959d..bebc57d3592 100644 --- a/test/lisp/eshell/esh-var-tests.el +++ b/test/lisp/eshell/esh-var-tests.el @@ -41,113 +41,107 @@ (ert-deftest esh-var-test/interp-var () "Interpolate variable" - (should (equal (eshell-test-command-result "echo $user-login-name") - user-login-name))) + (eshell-command-result-equal "echo $user-login-name" + user-login-name)) (ert-deftest esh-var-test/interp-quoted-var () "Interpolate quoted variable" - (should (equal (eshell-test-command-result "echo $'user-login-name'") - user-login-name)) - (should (equal (eshell-test-command-result "echo $\"user-login-name\"") - user-login-name))) + (eshell-command-result-equal "echo $'user-login-name'" + user-login-name) + (eshell-command-result-equal "echo $\"user-login-name\"" + user-login-name)) (ert-deftest esh-var-test/interp-quoted-var-concat () "Interpolate and concat quoted variable" - (should (equal (eshell-test-command-result "echo $'user-login-name'-foo") - (concat user-login-name "-foo"))) - (should (equal (eshell-test-command-result "echo $\"user-login-name\"-foo") - (concat user-login-name "-foo")))) + (eshell-command-result-equal "echo $'user-login-name'-foo" + (concat user-login-name "-foo")) + (eshell-command-result-equal "echo $\"user-login-name\"-foo" + (concat user-login-name "-foo"))) (ert-deftest esh-var-test/interp-var-indices () "Interpolate list variable with indices" (let ((eshell-test-value '("zero" "one" "two" "three" "four"))) - (should (equal (eshell-test-command-result "echo $eshell-test-value[0]") - "zero")) - (should (equal (eshell-test-command-result "echo $eshell-test-value[0 2]") - '("zero" "two"))) - (should (equal (eshell-test-command-result "echo $eshell-test-value[0 2 4]") - '("zero" "two" "four"))))) + (eshell-command-result-equal "echo $eshell-test-value[0]" + "zero") + (eshell-command-result-equal "echo $eshell-test-value[0 2]" + '("zero" "two")) + (eshell-command-result-equal "echo $eshell-test-value[0 2 4]" + '("zero" "two" "four")))) (ert-deftest esh-var-test/interp-var-split-indices () "Interpolate string variable with indices" (let ((eshell-test-value "zero one two three four")) - (should (equal (eshell-test-command-result "echo $eshell-test-value[0]") - "zero")) - (should (equal (eshell-test-command-result "echo $eshell-test-value[0 2]") - '("zero" "two"))) - (should (equal (eshell-test-command-result "echo $eshell-test-value[0 2 4]") - '("zero" "two" "four"))))) + (eshell-command-result-equal "echo $eshell-test-value[0]" + "zero") + (eshell-command-result-equal "echo $eshell-test-value[0 2]" + '("zero" "two")) + (eshell-command-result-equal "echo $eshell-test-value[0 2 4]" + '("zero" "two" "four")))) (ert-deftest esh-var-test/interp-var-string-split-indices () "Interpolate string variable with string splitter and indices" (let ((eshell-test-value "zero:one:two:three:four")) - (should (equal (eshell-test-command-result "echo $eshell-test-value[: 0]") - "zero")) - (should (equal (eshell-test-command-result "echo $eshell-test-value[: 0 2]") - '("zero" "two")))) + (eshell-command-result-equal "echo $eshell-test-value[: 0]" + "zero") + (eshell-command-result-equal "echo $eshell-test-value[: 0 2]" + '("zero" "two"))) (let ((eshell-test-value "zeroXoneXtwoXthreeXfour")) - (should (equal (eshell-test-command-result "echo $eshell-test-value[X 0]") - "zero")) - (should (equal (eshell-test-command-result "echo $eshell-test-value[X 0 2]") - '("zero" "two"))))) + (eshell-command-result-equal "echo $eshell-test-value[X 0]" + "zero") + (eshell-command-result-equal "echo $eshell-test-value[X 0 2]" + '("zero" "two")))) (ert-deftest esh-var-test/interp-var-regexp-split-indices () "Interpolate string variable with regexp splitter and indices" (let ((eshell-test-value "zero:one!two:three!four")) - (should (equal (eshell-test-command-result - "echo $eshell-test-value['[:!]' 0]") - "zero")) - (should (equal (eshell-test-command-result - "echo $eshell-test-value['[:!]' 0 2]") - '("zero" "two"))) - (should (equal (eshell-test-command-result - "echo $eshell-test-value[\"[:!]\" 0]") - "zero")) - (should (equal (eshell-test-command-result - "echo $eshell-test-value[\"[:!]\" 0 2]") - '("zero" "two"))))) + (eshell-command-result-equal "echo $eshell-test-value['[:!]' 0]" + "zero") + (eshell-command-result-equal "echo $eshell-test-value['[:!]' 0 2]" + '("zero" "two")) + (eshell-command-result-equal "echo $eshell-test-value[\"[:!]\" 0]" + "zero") + (eshell-command-result-equal "echo $eshell-test-value[\"[:!]\" 0 2]" + '("zero" "two")))) (ert-deftest esh-var-test/interp-var-assoc () "Interpolate alist variable with index" (let ((eshell-test-value '(("foo" . 1)))) - (should (eq (eshell-test-command-result "echo $eshell-test-value[foo]") - 1)))) + (eshell-command-result-equal "echo $eshell-test-value[foo]" + 1))) (ert-deftest esh-var-test/interp-var-length-list () "Interpolate length of list variable" (let ((eshell-test-value '((1 2) (3) (5 (6 7 8 9))))) - (should (eq (eshell-test-command-result "echo $#eshell-test-value") 3)) - (should (eq (eshell-test-command-result "echo $#eshell-test-value[1]") 1)) - (should (eq (eshell-test-command-result "echo $#eshell-test-value[2][1]") - 4)))) + (eshell-command-result-equal "echo $#eshell-test-value" 3) + (eshell-command-result-equal "echo $#eshell-test-value[1]" 1) + (eshell-command-result-equal "echo $#eshell-test-value[2][1]" 4))) (ert-deftest esh-var-test/interp-var-length-string () "Interpolate length of string variable" (let ((eshell-test-value "foobar")) - (should (eq (eshell-test-command-result "echo $#eshell-test-value") 6)))) + (eshell-command-result-equal "echo $#eshell-test-value" 6))) (ert-deftest esh-var-test/interp-var-length-alist () "Interpolate length of alist variable" (let ((eshell-test-value '(("foo" . (1 2 3))))) - (should (eq (eshell-test-command-result "echo $#eshell-test-value") 1)) - (should (eq (eshell-test-command-result "echo $#eshell-test-value[foo]") - 3)))) + (eshell-command-result-equal "echo $#eshell-test-value" 1) + (eshell-command-result-equal "echo $#eshell-test-value[foo]" 3))) (ert-deftest esh-var-test/interp-lisp () "Interpolate Lisp form evaluation" - (should (equal (eshell-test-command-result "+ $(+ 1 2) 3") 6))) + (eshell-command-result-equal "+ $(+ 1 2) 3" 6)) (ert-deftest esh-var-test/interp-lisp-indices () "Interpolate Lisp form evaluation with index" - (should (equal (eshell-test-command-result "+ $(list 1 2)[1] 3") 5))) + (eshell-command-result-equal "+ $(list 1 2)[1] 3" 5)) (ert-deftest esh-var-test/interp-cmd () "Interpolate command result" - (should (equal (eshell-test-command-result "+ ${+ 1 2} 3") 6))) + (eshell-command-result-equal "+ ${+ 1 2} 3" 6)) (ert-deftest esh-var-test/interp-cmd-indices () "Interpolate command result with index" - (should (equal (eshell-test-command-result "+ ${listify 1 2}[1] 3") 5))) + (eshell-command-result-equal "+ ${listify 1 2}[1] 3" 5)) (ert-deftest esh-var-test/interp-cmd-external () "Interpolate command result from external command" @@ -165,32 +159,32 @@ (ert-deftest esh-var-test/interp-temp-cmd () "Interpolate command result redirected to temp file" - (should (equal (eshell-test-command-result "cat $") "hi"))) + (eshell-command-result-equal "cat $" "hi")) (ert-deftest esh-var-test/interp-concat-lisp () "Interpolate and concat Lisp form" - (should (equal (eshell-test-command-result "+ $(+ 1 2)3 3") 36))) + (eshell-command-result-equal "+ $(+ 1 2)3 3" 36)) (ert-deftest esh-var-test/interp-concat-lisp2 () "Interpolate and concat two Lisp forms" - (should (equal (eshell-test-command-result "+ $(+ 1 2)$(+ 1 2) 3") 36))) + (eshell-command-result-equal "+ $(+ 1 2)$(+ 1 2) 3" 36)) (ert-deftest esh-var-test/interp-concat-cmd () "Interpolate and concat command with literal" - (should (equal (eshell-test-command-result "+ ${+ 1 2}3 3") 36)) - (should (equal (eshell-test-command-result "echo ${*echo \"foo\nbar\"}-baz") - '("foo" "bar-baz"))) + (eshell-command-result-equal "+ ${+ 1 2}3 3" 36) + (eshell-command-result-equal "echo ${*echo \"foo\nbar\"}-baz" + '("foo" "bar-baz")) ;; Concatenating to a number in a list should produce a number... - (should (equal (eshell-test-command-result "echo ${*echo \"1\n2\"}3") - '(1 23))) + (eshell-command-result-equal "echo ${*echo \"1\n2\"}3" + '(1 23)) ;; ... but concatenating to a string that looks like a number in a list ;; should produce a string. - (should (equal (eshell-test-command-result "echo ${*echo \"hi\n2\"}3") - '("hi" "23")))) + (eshell-command-result-equal "echo ${*echo \"hi\n2\"}3" + '("hi" "23"))) (ert-deftest esh-var-test/interp-concat-cmd2 () "Interpolate and concat two commands" - (should (equal (eshell-test-command-result "+ ${+ 1 2}${+ 1 2} 3") 36))) + (eshell-command-result-equal "+ ${+ 1 2}${+ 1 2} 3" 36)) (ert-deftest esh-var-test/interp-concat-cmd-external () "Interpolate command result from external command with concatenation" @@ -201,151 +195,128 @@ (ert-deftest esh-var-test/quoted-interp-var () "Interpolate variable inside double-quotes" - (should (equal (eshell-test-command-result "echo \"$user-login-name\"") - user-login-name))) + (eshell-command-result-equal "echo \"$user-login-name\"" + user-login-name)) (ert-deftest esh-var-test/quoted-interp-quoted-var () "Interpolate quoted variable inside double-quotes" - (should (equal (eshell-test-command-result - "echo \"hi, $'user-login-name'\"") - (concat "hi, " user-login-name))) - (should (equal (eshell-test-command-result - "echo \"hi, $\\\"user-login-name\\\"\"") - (concat "hi, " user-login-name)))) + (eshell-command-result-equal "echo \"hi, $'user-login-name'\"" + (concat "hi, " user-login-name)) + (eshell-command-result-equal "echo \"hi, $\\\"user-login-name\\\"\"" + (concat "hi, " user-login-name))) (ert-deftest esh-var-test/quoted-interp-var-indices () "Interpolate string variable with indices inside double-quotes" (let ((eshell-test-value '("zero" "one" "two" "three" "four"))) - (should (equal (eshell-test-command-result - "echo \"$eshell-test-value[0]\"") - "zero")) + (eshell-command-result-equal "echo \"$eshell-test-value[0]\"" + "zero") ;; FIXME: These tests would use the 0th index like the other tests ;; here, but evaluating the command just above adds an `escaped' ;; property to the string "zero". This results in the output ;; printing the string properties, which is probably the wrong ;; behavior. See bug#54486. - (should (equal (eshell-test-command-result - "echo \"$eshell-test-value[1 2]\"") - "(\"one\" \"two\")")) - (should (equal (eshell-test-command-result - "echo \"$eshell-test-value[1 2 4]\"") - "(\"one\" \"two\" \"four\")")))) + (eshell-command-result-equal "echo \"$eshell-test-value[1 2]\"" + "(\"one\" \"two\")") + (eshell-command-result-equal "echo \"$eshell-test-value[1 2 4]\"" + "(\"one\" \"two\" \"four\")"))) (ert-deftest esh-var-test/quoted-interp-var-split-indices () "Interpolate string variable with indices inside double-quotes" (let ((eshell-test-value "zero one two three four")) - (should (equal (eshell-test-command-result - "echo \"$eshell-test-value[0]\"") - "zero")) - (should (equal (eshell-test-command-result - "echo \"$eshell-test-value[0 2]\"") - "(\"zero\" \"two\")")))) + (eshell-command-result-equal "echo \"$eshell-test-value[0]\"" + "zero") + (eshell-command-result-equal "echo \"$eshell-test-value[0 2]\"" + "(\"zero\" \"two\")"))) (ert-deftest esh-var-test/quoted-interp-var-string-split-indices () "Interpolate string variable with string splitter and indices inside double-quotes" (let ((eshell-test-value "zero:one:two:three:four")) - (should (equal (eshell-test-command-result - "echo \"$eshell-test-value[: 0]\"") - "zero")) - (should (equal (eshell-test-command-result - "echo \"$eshell-test-value[: 0 2]\"") - "(\"zero\" \"two\")"))) + (eshell-command-result-equal "echo \"$eshell-test-value[: 0]\"" + "zero") + (eshell-command-result-equal "echo \"$eshell-test-value[: 0 2]\"" + "(\"zero\" \"two\")")) (let ((eshell-test-value "zeroXoneXtwoXthreeXfour")) - (should (equal (eshell-test-command-result - "echo \"$eshell-test-value[X 0]\"") - "zero")) - (should (equal (eshell-test-command-result - "echo \"$eshell-test-value[X 0 2]\"") - "(\"zero\" \"two\")")))) + (eshell-command-result-equal "echo \"$eshell-test-value[X 0]\"" + "zero") + (eshell-command-result-equal "echo \"$eshell-test-value[X 0 2]\"" + "(\"zero\" \"two\")"))) (ert-deftest esh-var-test/quoted-interp-var-regexp-split-indices () "Interpolate string variable with regexp splitter and indices" (let ((eshell-test-value "zero:one!two:three!four")) - (should (equal (eshell-test-command-result - "echo \"$eshell-test-value['[:!]' 0]\"") - "zero")) - (should (equal (eshell-test-command-result - "echo \"$eshell-test-value['[:!]' 0 2]\"") - "(\"zero\" \"two\")")) - (should (equal (eshell-test-command-result - "echo \"$eshell-test-value[\\\"[:!]\\\" 0]\"") - "zero")) - (should (equal (eshell-test-command-result - "echo \"$eshell-test-value[\\\"[:!]\\\" 0 2]\"") - "(\"zero\" \"two\")")))) + (eshell-command-result-equal "echo \"$eshell-test-value['[:!]' 0]\"" + "zero") + (eshell-command-result-equal "echo \"$eshell-test-value['[:!]' 0 2]\"" + "(\"zero\" \"two\")") + (eshell-command-result-equal "echo \"$eshell-test-value[\\\"[:!]\\\" 0]\"" + "zero") + (eshell-command-result-equal + "echo \"$eshell-test-value[\\\"[:!]\\\" 0 2]\"" + "(\"zero\" \"two\")"))) (ert-deftest esh-var-test/quoted-interp-var-assoc () "Interpolate alist variable with index inside double-quotes" (let ((eshell-test-value '(("foo" . 1)))) - (should (equal (eshell-test-command-result - "echo \"$eshell-test-value[foo]\"") - "1")))) + (eshell-command-result-equal "echo \"$eshell-test-value[foo]\"" + "1"))) (ert-deftest esh-var-test/quoted-interp-var-length-list () "Interpolate length of list variable inside double-quotes" (let ((eshell-test-value '((1 2) (3) (5 (6 7 8 9))))) - (should (equal (eshell-test-command-result "echo \"$#eshell-test-value\"") - "3")) - (should (equal (eshell-test-command-result - "echo \"$#eshell-test-value[1]\"") - "1")) - (should (equal (eshell-test-command-result - "echo \"$#eshell-test-value[2][1]\"") - "4")))) + (eshell-command-result-equal "echo \"$#eshell-test-value\"" + "3") + (eshell-command-result-equal "echo \"$#eshell-test-value[1]\"" + "1") + (eshell-command-result-equal "echo \"$#eshell-test-value[2][1]\"" + "4"))) (ert-deftest esh-var-test/quoted-interp-var-length-string () "Interpolate length of string variable inside double-quotes" (let ((eshell-test-value "foobar")) - (should (equal (eshell-test-command-result "echo \"$#eshell-test-value\"") - "6")))) + (eshell-command-result-equal "echo \"$#eshell-test-value\"" + "6"))) (ert-deftest esh-var-test/quoted-interp-var-length-alist () "Interpolate length of alist variable inside double-quotes" (let ((eshell-test-value '(("foo" . (1 2 3))))) - (should (equal (eshell-test-command-result "echo \"$#eshell-test-value\"") - "1")) - (should (equal (eshell-test-command-result - "echo \"$#eshell-test-value[foo]\"") - "3")))) + (eshell-command-result-equal "echo \"$#eshell-test-value\"" + "1") + (eshell-command-result-equal "echo \"$#eshell-test-value[foo]\"" + "3")) (ert-deftest esh-var-test/quoted-interp-lisp () "Interpolate Lisp form evaluation inside double-quotes" - (should (equal (eshell-test-command-result - "echo \"hi $(concat \\\"the\\\" \\\"re\\\")\"") - "hi there"))) + (eshell-command-result-equal "echo \"hi $(concat \\\"the\\\" \\\"re\\\")\"" + "hi there")) (ert-deftest esh-var-test/quoted-interp-lisp-indices () "Interpolate Lisp form evaluation with index" - (should (equal (eshell-test-command-result "concat \"$(list 1 2)[1]\" cool") - "2cool"))) + (eshell-command-result-equal "concat \"$(list 1 2)[1]\" cool" + "2cool")) (ert-deftest esh-var-test/quoted-interp-cmd () "Interpolate command result inside double-quotes" - (should (equal (eshell-test-command-result - "echo \"hi ${echo \\\"there\\\"}\"") - "hi there"))) + (eshell-command-result-equal "echo \"hi ${echo \\\"there\\\"}\"" + "hi there")) (ert-deftest esh-var-test/quoted-interp-cmd-indices () "Interpolate command result with index inside double-quotes" - (should (equal (eshell-test-command-result - "concat \"${listify 1 2}[1]\" cool") - "2cool"))) + (eshell-command-result-equal "concat \"${listify 1 2}[1]\" cool" + "2cool")) (ert-deftest esh-var-test/quoted-interp-temp-cmd () "Interpolate command result redirected to temp file inside double-quotes" (let ((temporary-file-directory (file-name-as-directory (make-temp-file "esh-vars-tests" t)))) (unwind-protect - (should (equal (eshell-test-command-result "cat \"$\"") - "hi")) + (eshell-command-result-equal "cat \"$\"" "hi")) (delete-directory temporary-file-directory t)))) (ert-deftest esh-var-test/quoted-interp-concat-cmd () "Interpolate and concat command with literal" - (should (equal (eshell-test-command-result - "echo \"${echo \\\"foo\nbar\\\"} baz\"") - "foo\nbar baz"))) + (eshell-command-result-equal "echo \"${echo \\\"foo\nbar\\\"} baz\"" + "foo\nbar baz")) ;; Interpolated variable conversion @@ -353,139 +324,129 @@ inside double-quotes" (ert-deftest esh-var-test/interp-convert-var-number () "Interpolate numeric variable" (let ((eshell-test-value 123)) - (should (equal (eshell-test-command-result "type-of $eshell-test-value") - 'integer)))) + (eshell-command-result-equal "type-of $eshell-test-value" + 'integer))) (ert-deftest esh-var-test/interp-convert-var-split-indices () "Interpolate and convert string variable with indices" ;; Check that numeric forms are converted to numbers. (let ((eshell-test-value "000 010 020 030 040")) - (should (equal (eshell-test-command-result "echo $eshell-test-value[0]") - 0)) - (should (equal (eshell-test-command-result "echo $eshell-test-value[0 2]") - '(0 20)))) + (eshell-command-result-equal "echo $eshell-test-value[0]" + 0) + (eshell-command-result-equal "echo $eshell-test-value[0 2]" + '(0 20))) ;; Check that multiline forms are preserved as-is. (let ((eshell-test-value "foo\nbar:baz\n")) - (should (equal (eshell-test-command-result "echo $eshell-test-value[: 0]") - "foo\nbar")) - (should (equal (eshell-test-command-result "echo $eshell-test-value[: 1]") - "baz\n")))) + (eshell-command-result-equal "echo $eshell-test-value[: 0]" + "foo\nbar") + (eshell-command-result-equal "echo $eshell-test-value[: 1]" + "baz\n"))) (ert-deftest esh-var-test/interp-convert-quoted-var-number () "Interpolate numeric quoted numeric variable" (let ((eshell-test-value 123)) - (should (equal (eshell-test-command-result "type-of $'eshell-test-value'") - 'integer)) - (should (equal (eshell-test-command-result "type-of $\"eshell-test-value\"") - 'integer)))) + (eshell-command-result-equal "type-of $'eshell-test-value'" + 'integer) + (eshell-command-result-equal "type-of $\"eshell-test-value\"" + 'integer))) (ert-deftest esh-var-test/interp-convert-quoted-var-split-indices () "Interpolate and convert quoted string variable with indices" (let ((eshell-test-value "000 010 020 030 040")) - (should (equal (eshell-test-command-result "echo $'eshell-test-value'[0]") - 0)) - (should (equal (eshell-test-command-result "echo $'eshell-test-value'[0 2]") - '(0 20))))) + (eshell-command-result-equal "echo $'eshell-test-value'[0]" + 0) + (eshell-command-result-equal "echo $'eshell-test-value'[0 2]" + '(0 20)))) (ert-deftest esh-var-test/interp-convert-cmd-string-newline () "Interpolate trailing-newline command result" - (should (equal (eshell-test-command-result "echo ${echo \"foo\n\"}") "foo"))) + (eshell-command-result-equal "echo ${echo \"foo\n\"}" "foo")) (ert-deftest esh-var-test/interp-convert-cmd-multiline () "Interpolate multi-line command result" - (should (equal (eshell-test-command-result "echo ${echo \"foo\nbar\"}") - '("foo" "bar"))) + (eshell-command-result-equal "echo ${echo \"foo\nbar\"}" + '("foo" "bar")) ;; Numeric output should be converted to numbers... - (should (equal (eshell-test-command-result "echo ${echo \"01\n02\n03\"}") - '(1 2 3))) + (eshell-command-result-equal "echo ${echo \"01\n02\n03\"}" + '(1 2 3)) ;; ... but only if every line is numeric. - (should (equal (eshell-test-command-result "echo ${echo \"01\n02\nhi\"}") - '("01" "02" "hi")))) + (eshell-command-result-equal "echo ${echo \"01\n02\nhi\"}" + '("01" "02" "hi"))) (ert-deftest esh-var-test/interp-convert-cmd-number () "Interpolate numeric command result" - (should (equal (eshell-test-command-result "echo ${echo \"1\"}") 1))) + (eshell-command-result-equal "echo ${echo \"1\"}" 1)) (ert-deftest esh-var-test/interp-convert-cmd-split-indices () "Interpolate command result with indices" - (should (equal (eshell-test-command-result "echo ${echo \"000 010 020\"}[0]") - 0)) - (should (equal (eshell-test-command-result - "echo ${echo \"000 010 020\"}[0 2]") - '(0 20)))) + (eshell-command-result-equal "echo ${echo \"000 010 020\"}[0]" + 0) + (eshell-command-result-equal "echo ${echo \"000 010 020\"}[0 2]" + '(0 20))) (ert-deftest esh-var-test/quoted-interp-convert-var-number () "Interpolate numeric variable inside double-quotes" (let ((eshell-test-value 123)) - (should (equal (eshell-test-command-result "type-of \"$eshell-test-value\"") - 'string)))) + (eshell-command-result-equal "type-of \"$eshell-test-value\"" + 'string))) (ert-deftest esh-var-test/quoted-interp-convert-var-split-indices () "Interpolate string variable with indices inside double-quotes" (let ((eshell-test-value "000 010 020 030 040")) - (should (equal (eshell-test-command-result - "echo \"$eshell-test-value[0]\"") - "000")) - (should (equal (eshell-test-command-result - "echo \"$eshell-test-value[0 2]\"") - "(\"000\" \"020\")")))) + (eshell-command-result-equal "echo \"$eshell-test-value[0]\"" + "000") + (eshell-command-result-equal "echo \"$eshell-test-value[0 2]\"" + "(\"000\" \"020\")"))) (ert-deftest esh-var-test/quoted-interp-convert-quoted-var-number () "Interpolate numeric quoted variable inside double-quotes" (let ((eshell-test-value 123)) - (should (equal (eshell-test-command-result - "type-of \"$'eshell-test-value'\"") - 'string)) - (should (equal (eshell-test-command-result - "type-of \"$\\\"eshell-test-value\\\"\"") - 'string)))) + (eshell-command-result-equal "type-of \"$'eshell-test-value'\"" + 'string) + (eshell-command-result-equal "type-of \"$\\\"eshell-test-value\\\"\"" + 'string))) (ert-deftest esh-var-test/quoted-interp-convert-quoted-var-split-indices () "Interpolate quoted string variable with indices inside double-quotes" (let ((eshell-test-value "000 010 020 030 040")) - (should (equal (eshell-test-command-result - "echo \"$eshell-test-value[0]\"") - "000")) - (should (equal (eshell-test-command-result - "echo \"$eshell-test-value[0 2]\"") - "(\"000\" \"020\")")))) + (eshell-command-result-equal "echo \"$eshell-test-value[0]\"" + "000") + (eshell-command-result-equal "echo \"$eshell-test-value[0 2]\"" + "(\"000\" \"020\")"))) (ert-deftest esh-var-test/quoted-interp-convert-cmd-string-newline () "Interpolate trailing-newline command result inside double-quotes" - (should (equal (eshell-test-command-result "echo \"${echo \\\"foo\n\\\"}\"") - "foo")) - (should (equal (eshell-test-command-result "echo \"${echo \\\"foo\n\n\\\"}\"") - "foo"))) + (eshell-command-result-equal "echo \"${echo \\\"foo\n\\\"}\"" + "foo") + (eshell-command-result-equal "echo \"${echo \\\"foo\n\n\\\"}\"" + "foo")) (ert-deftest esh-var-test/quoted-interp-convert-cmd-multiline () "Interpolate multi-line command result inside double-quotes" - (should (equal (eshell-test-command-result - "echo \"${echo \\\"foo\nbar\\\"}\"") - "foo\nbar"))) + (eshell-command-result-equal "echo \"${echo \\\"foo\nbar\\\"}\"" + "foo\nbar")) (ert-deftest esh-var-test/quoted-interp-convert-cmd-number () "Interpolate numeric command result inside double-quotes" - (should (equal (eshell-test-command-result "echo \"${echo \\\"1\\\"}\"") - "1"))) + (eshell-command-result-equal "echo \"${echo \\\"1\\\"}\"" "1")) (ert-deftest esh-var-test/quoted-interp-convert-cmd-split-indices () "Interpolate command result with indices inside double-quotes" - (should (equal (eshell-test-command-result - "echo \"${echo \\\"000 010 020\\\"}[0]\"") - "000"))) + (eshell-command-result-equal "echo \"${echo \\\"000 010 020\\\"}[0]\"" + "000")) ;; Built-in variables (ert-deftest esh-var-test/lines-var () "$LINES should equal (window-body-height nil 'remap)" - (should (equal (eshell-test-command-result "echo $LINES") - (window-body-height nil 'remap)))) + (eshell-command-result-equal "echo $LINES" + (window-body-height nil 'remap))) (ert-deftest esh-var-test/columns-var () "$COLUMNS should equal (window-body-width nil 'remap)" - (should (equal (eshell-test-command-result "echo $COLUMNS") - (window-body-width nil 'remap)))) + (eshell-command-result-equal "echo $COLUMNS" + (window-body-width nil 'remap))) (ert-deftest esh-var-test/inside-emacs-var () "Test presence of \"INSIDE_EMACS\" in subprocesses" diff --git a/test/lisp/eshell/eshell-tests-helpers.el b/test/lisp/eshell/eshell-tests-helpers.el index 778087bd755..8f0f993447f 100644 --- a/test/lisp/eshell/eshell-tests-helpers.el +++ b/test/lisp/eshell/eshell-tests-helpers.el @@ -104,6 +104,27 @@ After inserting, call FUNC. If FUNC is nil, instead call (let ((eshell-history-file-name nil)) (eshell-command-result command)))) +(defun eshell-command-result--equal (_command actual expected) + "Compare the ACTUAL result of a COMMAND with its EXPECTED value." + (equal actual expected)) + +(defun eshell-command-result--equal-explainer (command actual expected) + "Explain the result of `eshell-command-result--equal'." + `(nonequal-result + (command ,command) + (result ,actual) + (expected ,expected))) + +(put 'eshell-command-result--equal 'ert-explainer + #'eshell-command-result--equal-explainer) + +(defun eshell-command-result-equal (command result) + "Execute COMMAND non-interactively and compare it to RESULT." + (should (eshell-command-result--equal + command + (eshell-test-command-result command) + result))) + (provide 'eshell-tests-helpers) ;;; eshell-tests-helpers.el ends here diff --git a/test/lisp/eshell/eshell-tests.el b/test/lisp/eshell/eshell-tests.el index c7a9516bea4..1845dba2809 100644 --- a/test/lisp/eshell/eshell-tests.el +++ b/test/lisp/eshell/eshell-tests.el @@ -83,28 +83,27 @@ (dolist (template '("echo {%s} | *cat" "echo ${%s} | *cat" "*cat $<%s> | *cat")) - (should (equal (eshell-test-command-result - (format template "echo $eshell-in-pipeline-p")) - nil)) - (should (equal (eshell-test-command-result - (format template "echo | echo $eshell-in-pipeline-p")) - "last")) - (should (equal (eshell-test-command-result - (format template "echo $eshell-in-pipeline-p | echo")) - "first")) - (should (equal (eshell-test-command-result - (format template - "echo | echo $eshell-in-pipeline-p | echo")) - "t")))) + (eshell-command-result-equal + (format template "echo $eshell-in-pipeline-p") + nil) + (eshell-command-result-equal + (format template "echo | echo $eshell-in-pipeline-p") + "last") + (eshell-command-result-equal + (format template "echo $eshell-in-pipeline-p | echo") + "first") + (eshell-command-result-equal + (format template "echo | echo $eshell-in-pipeline-p | echo") + "t"))) (ert-deftest eshell-test/lisp-reset-in-pipeline () "Check that interpolated Lisp forms reset `eshell-in-pipeline-p'." (skip-unless (executable-find "cat")) (dolist (template '("echo (%s) | *cat" "echo $(%s) | *cat")) - (should (equal (eshell-test-command-result - (format template "format \"%s\" eshell-in-pipeline-p")) - "nil")))) + (eshell-command-result-equal + (format template "format \"%s\" eshell-in-pipeline-p") + "nil"))) (ert-deftest eshell-test/redirect-buffer () "Check that piping to a buffer works" -- cgit v1.2.3 From cf873c1a090b95746cf2f2a9a24a5e4bd7cc2cd6 Mon Sep 17 00:00:00 2001 From: Jim Porter Date: Sun, 14 Aug 2022 13:48:22 -0700 Subject: 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'. --- lisp/eshell/esh-cmd.el | 7 ++- test/lisp/eshell/esh-cmd-tests.el | 119 ++++++++++++++++++-------------------- 2 files changed, 59 insertions(+), 67 deletions(-) (limited to 'test/lisp/eshell/esh-cmd-tests.el') diff --git a/lisp/eshell/esh-cmd.el b/lisp/eshell/esh-cmd.el index 62c95056fd2..2f77f3f4974 100644 --- a/lisp/eshell/esh-cmd.el +++ b/lisp/eshell/esh-cmd.el @@ -607,7 +607,7 @@ must be implemented via rewriting, rather than as a function." t)) (if (= (length terms) 4) `(eshell-protect - ,(eshell-invokify-arg (car (last terms)))) t)))) + ,(eshell-invokify-arg (car (last terms)) t)))))) (defvar eshell-last-command-result) ;Defined in esh-io.el. @@ -1122,7 +1122,7 @@ be finished later after the completion of an asynchronous subprocess." (setcar eshell-test-body nil)) (unless (car eshell-test-body) (setcar eshell-test-body (copy-tree (car args)))) - (while (cadr (eshell-do-eval (car eshell-test-body))) + (while (cadr (eshell-do-eval (car eshell-test-body) synchronous-p)) (setcar eshell-command-body (if (cddr args) `(progn ,@(copy-tree (cdr args))) @@ -1142,7 +1142,8 @@ be finished later after the completion of an asynchronous subprocess." (setcar eshell-test-body (copy-tree (car args)))) (setcar eshell-command-body (copy-tree - (if (cadr (eshell-do-eval (car eshell-test-body))) + (if (cadr (eshell-do-eval (car eshell-test-body) + synchronous-p)) (cadr args) (car (cddr args))))) (eshell-do-eval (car eshell-command-body) synchronous-p)) diff --git a/test/lisp/eshell/esh-cmd-tests.el b/test/lisp/eshell/esh-cmd-tests.el index c5d780a399d..3a582965d62 100644 --- a/test/lisp/eshell/esh-cmd-tests.el +++ b/test/lisp/eshell/esh-cmd-tests.el @@ -188,97 +188,88 @@ e.g. \"{(+ 1 2)} 3\" => 3" (ert-deftest esh-cmd-test/if-statement () "Test invocation of an if statement." - (with-temp-eshell - (let ((eshell-test-value t)) - (eshell-match-command-output "if $eshell-test-value {echo yes}" - "yes\n")) - (let ((eshell-test-value nil)) - (eshell-match-command-output "if $eshell-test-value {echo yes}" - "\\`\\'")))) + (let ((eshell-test-value t)) + (eshell-command-result-equal "if $eshell-test-value {echo yes}" + "yes")) + (let ((eshell-test-value nil)) + (eshell-command-result-equal "if $eshell-test-value {echo yes}" + nil))) (ert-deftest esh-cmd-test/if-else-statement () "Test invocation of an if/else statement." - (with-temp-eshell - (let ((eshell-test-value t)) - (eshell-match-command-output "if $eshell-test-value {echo yes} {echo no}" - "yes\n")) - (let ((eshell-test-value nil)) - (eshell-match-command-output "if $eshell-test-value {echo yes} {echo no}" - "no\n")))) + (let ((eshell-test-value t)) + (eshell-command-result-equal "if $eshell-test-value {echo yes} {echo no}" + "yes")) + (let ((eshell-test-value nil)) + (eshell-command-result-equal "if $eshell-test-value {echo yes} {echo no}" + "no"))) (ert-deftest esh-cmd-test/if-else-statement-lisp-form () "Test invocation of an if/else statement using a Lisp form." - (with-temp-eshell - (eshell-match-command-output "if (zerop 0) {echo yes} {echo no}" - "yes\n") - (eshell-match-command-output "if (zerop 1) {echo yes} {echo no}" - "no\n") - (let ((debug-on-error nil)) - (eshell-match-command-output "if (zerop \"foo\") {echo yes} {echo no}" - "no\n")))) + (eshell-command-result-equal "if (zerop 0) {echo yes} {echo no}" + "yes") + (eshell-command-result-equal "if (zerop 1) {echo yes} {echo no}" + "no") + (let ((debug-on-error nil)) + (eshell-command-result-equal "if (zerop \"foo\") {echo yes} {echo no}" + "no"))) (ert-deftest esh-cmd-test/if-else-statement-lisp-form-2 () "Test invocation of an if/else statement using a Lisp form. This tests when `eshell-lisp-form-nil-is-failure' is nil." (let ((eshell-lisp-form-nil-is-failure nil)) - (with-temp-eshell - (eshell-match-command-output "if (zerop 0) {echo yes} {echo no}" - "yes\n") - (eshell-match-command-output "if (zerop 1) {echo yes} {echo no}" - "yes\n") - (let ((debug-on-error nil)) - (eshell-match-command-output "if (zerop \"foo\") {echo yes} {echo no}" - "no\n"))))) + (eshell-command-result-equal "if (zerop 0) {echo yes} {echo no}" + "yes") + (eshell-command-result-equal "if (zerop 1) {echo yes} {echo no}" + "yes") + (let ((debug-on-error nil)) + (eshell-command-result-equal "if (zerop \"foo\") {echo yes} {echo no}" + "no")))) (ert-deftest esh-cmd-test/if-else-statement-ext-cmd () "Test invocation of an if/else statement using an external command." (skip-unless (executable-find "[")) - (with-temp-eshell - (eshell-match-command-output "if {[ foo = foo ]} {echo yes} {echo no}" - "yes\n") - (eshell-match-command-output "if {[ foo = bar ]} {echo yes} {echo no}" - "no\n"))) + (eshell-command-result-equal "if {[ foo = foo ]} {echo yes} {echo no}" + "yes") + (eshell-command-result-equal "if {[ foo = bar ]} {echo yes} {echo no}" + "no")) (ert-deftest esh-cmd-test/unless-statement () "Test invocation of an unless statement." - (with-temp-eshell - (let ((eshell-test-value t)) - (eshell-match-command-output "unless $eshell-test-value {echo no}" - "\\`\\'")) - (let ((eshell-test-value nil)) - (eshell-match-command-output "unless $eshell-test-value {echo no}" - "no\n")))) + (let ((eshell-test-value t)) + (eshell-command-result-equal "unless $eshell-test-value {echo no}" + nil)) + (let ((eshell-test-value nil)) + (eshell-command-result-equal "unless $eshell-test-value {echo no}" + "no"))) (ert-deftest esh-cmd-test/unless-else-statement () "Test invocation of an unless/else statement." - (with-temp-eshell - (let ((eshell-test-value t)) - (eshell-match-command-output - "unless $eshell-test-value {echo no} {echo yes}" - "yes\n")) - (let ((eshell-test-value nil)) - (eshell-match-command-output - "unless $eshell-test-value {echo no} {echo yes}" - "no\n")))) + (let ((eshell-test-value t)) + (eshell-command-result-equal + "unless $eshell-test-value {echo no} {echo yes}" + "yes")) + (let ((eshell-test-value nil)) + (eshell-command-result-equal + "unless $eshell-test-value {echo no} {echo yes}" + "no"))) (ert-deftest esh-cmd-test/unless-else-statement-lisp-form () "Test invocation of an unless/else statement using a Lisp form." - (with-temp-eshell - (eshell-match-command-output "unless (zerop 0) {echo no} {echo yes}" - "yes\n") - (eshell-match-command-output "unless (zerop 1) {echo no} {echo yes}" - "no\n") - (let ((debug-on-error nil)) - (eshell-match-command-output "unless (zerop \"foo\") {echo no} {echo yes}" - "no\n")))) + (eshell-command-result-equal "unless (zerop 0) {echo no} {echo yes}" + "yes") + (eshell-command-result-equal "unless (zerop 1) {echo no} {echo yes}" + "no") + (let ((debug-on-error nil)) + (eshell-command-result-equal "unless (zerop \"foo\") {echo no} {echo yes}" + "no"))) (ert-deftest esh-cmd-test/unless-else-statement-ext-cmd () "Test invocation of an unless/else statement using an external command." (skip-unless (executable-find "[")) - (with-temp-eshell - (eshell-match-command-output "unless {[ foo = foo ]} {echo no} {echo yes}" - "yes\n") - (eshell-match-command-output "unless {[ foo = bar ]} {echo no} {echo yes}" - "no\n"))) + (eshell-command-result-equal "unless {[ foo = foo ]} {echo no} {echo yes}" + "yes") + (eshell-command-result-equal "unless {[ foo = bar ]} {echo no} {echo yes}" + "no")) ;; esh-cmd-tests.el ends here -- cgit v1.2.3 From 1be925faa1065af5754fc11914b56ae98dfb2a83 Mon Sep 17 00:00:00 2001 From: Jim Porter Date: Sat, 9 Jul 2022 10:34:31 -0700 Subject: Simplify Eshell handle functions and add tests/documentation * lisp/eshell/esh-arg.el (eshell-parse-argument-hook): Explain how to use 'eshell-finish-arg'. * lisp/eshell/esh-io.el (eshell-create-handles): Only call 'eshell-get-target' for stderr if necessary. (eshell-protect-handles): Use 'dotimes'. (eshell-set-output-handle): Pass HANDLES and fix an edge case with setting a duplicate TARGET. * test/lisp/eshell/eshell-tests-helpers.el (eshell-with-temp-buffer): New macro. * test/lisp/eshell/esh-cmd-tests.el (esh-cmd-test/quoted-lisp-form) (esh-cmd-test/backquoted-lisp-form) (esh-cmd-test/backquoted-lisp-form/splice): New tests. * test/lisp/eshell/eshell-tests.el (eshell-test/redirect-buffer) (eshell-test/redirect-buffer-escaped): Move to... * test/lisp/eshell/esh-io-tests.el: ... here, and add other I/O tests. * doc/misc/eshell.texi (Arguments): Add documentation for special argument types. (Input/Output): Expand documentation for redirection and pipelines. --- doc/misc/eshell.texi | 160 ++++++++++++++++++---- lisp/eshell/esh-arg.el | 4 + lisp/eshell/esh-io.el | 55 ++++---- test/lisp/eshell/esh-cmd-tests.el | 19 +++ test/lisp/eshell/esh-io-tests.el | 220 +++++++++++++++++++++++++++++++ test/lisp/eshell/eshell-tests-helpers.el | 10 ++ test/lisp/eshell/eshell-tests.el | 19 --- 7 files changed, 413 insertions(+), 74 deletions(-) create mode 100644 test/lisp/eshell/esh-io-tests.el (limited to 'test/lisp/eshell/esh-cmd-tests.el') diff --git a/doc/misc/eshell.texi b/doc/misc/eshell.texi index 13f13163dd7..0c98d2860e9 100644 --- a/doc/misc/eshell.texi +++ b/doc/misc/eshell.texi @@ -256,7 +256,6 @@ as an argument will ``spread'' the elements into multiple arguments: @end example @subsection Quoting and escaping - As with other shells, you can escape special characters and spaces with by prefixing the character with a backslash (@code{\}), or by surrounding the string with apostrophes (@code{''}) or double quotes @@ -268,6 +267,40 @@ When using expansions (@pxref{Expansion}) in an Eshell command, the result may potentially be of any data type. To ensure that the result is always a string, the expansion can be surrounded by double quotes. +@subsection Special argument types +In addition to strings and numbers, Eshell supports a number of +special argument types. These let you refer to various other Emacs +Lisp data types, such as lists or buffers. + +@table @code + +@item #'@var{lisp-form} +This refers to the quoted Emacs Lisp form @var{lisp-form}. Though +this looks similar to the ``sharp quote'' syntax for functions +(@pxref{Special Read Syntax, , , elisp, The Emacs Lisp Reference +Manual}), it instead corresponds to @code{quote} and can be used for +any quoted form.@footnote{Eshell would interpret a bare apostrophe +(@code{'}) as the start of a single-quoted string.} + +@item `@var{lisp-form} +This refers to the backquoted Emacs Lisp form @var{lisp-form} +(@pxref{Backquote, , , elisp, The Emacs Lisp Reference Manual}). As +in Emacs Lisp, you can use @samp{,} and @samp{,@@} to refer to +non-constant values. + +@item # +@itemx #<@var{name}> +Return the buffer named @var{name}. This is equivalent to +@samp{$(get-buffer-create "@var{name}")} (@pxref{Creating Buffers, , , +elisp, The Emacs Lisp Reference Manual}). + +@item # +Return the process named @var{name}. This is equivalent to +@samp{$(get-process "@var{name}")} (@pxref{Process Information, , , +elisp, The Emacs Lisp Reference Manual}). + +@end table + @node Built-ins @section Built-in commands Several commands are built-in in Eshell. In order to call the @@ -1560,6 +1593,13 @@ Reverses the order of a list of values. Since Eshell does not communicate with a terminal like most command shells, IO is a little different. +@menu +* Visual Commands:: +* Redirection:: +* Pipelines:: +@end menu + +@node Visual Commands @section Visual Commands If you try to run programs from within Eshell that are not line-oriented, such as programs that use ncurses, you will just get @@ -1592,40 +1632,104 @@ program exits, customize the variable @code{eshell-destroy-buffer-when-process-dies} to a non-@code{nil} value; the default is @code{nil}. +@node Redirection @section Redirection -Redirection is mostly the same in Eshell as it is in other command -shells. The output redirection operators @code{>} and @code{>>} as -well as pipes are supported, but there is not yet any support for -input redirection. Output can also be redirected to buffers, using -the @code{>>>} redirection operator, and Elisp functions, using -virtual devices. - -The buffer redirection operator, @code{>>>}, expects a buffer object -on the right-hand side, into which it inserts the output of the -left-hand side. e.g., @samp{echo hello >>> #} -inserts the string @code{"hello"} into the @file{*scratch*} buffer. -The convenience shorthand variant @samp{#<@var{buffer-name}>}, as in -@samp{#<*scratch*>}, is also accepted. - -@code{eshell-virtual-targets} is a list of mappings of virtual device -names to functions. Eshell comes with two virtual devices: -@file{/dev/kill}, which sends the text to the kill ring, and -@file{/dev/clip}, which sends text to the clipboard. +Redirection in Eshell is similar to that of other command shells. You +can use the output redirection operators @code{>} and @code{>>}, but +there is not yet any support for input redirection. In the cases +below, @var{fd} specifies the file descriptor to redirect; if not +specified, file descriptor 1 (standard output) will be used by +default. + +@table @code + +@item > @var{dest} +@itemx @var{fd}> @var{dest} +Redirect output to @var{dest}, overwriting its contents with the new +output. + +@item >> @var{dest} +@itemx @var{fd}>> @var{dest} +Redirect output to @var{dest}, appending it to the existing contents +of @var{dest}. + +@item >>> @var{buffer} +@itemx @var{fd}>>> @var{buffer} +Redirect output to @var{dest}, inserting it at the current mark if +@var{dest} is a buffer, at the beginning of the file if @var{dest} is +a file, or otherwise behaving the same as @code{>>}. + +@end table + +Eshell supports redirecting output to several different types of +targets: + +@itemize @bullet + +@item +files, including virtual targets (see below); +@item +buffers (@pxref{Buffers, , , elisp, GNU Emacs Lisp Reference Manual}); + +@item +markers (@pxref{Markers, , , elisp, GNU Emacs Lisp Reference Manual}); + +@item +processes (@pxref{Processes, , , elisp, GNU Emacs Lisp Reference +Manual}); and + +@item +symbols (@pxref{Symbols, , , elisp, GNU Emacs Lisp Reference Manual}). + +@end itemize + +@subsection Virtual Targets +Virtual targets are mapping of device names to functions. Eshell +comes with four virtual devices: + +@table @file + +@item /dev/null +Does nothing with the output passed to it. + +@item /dev/eshell +Writes the text passed to it to the display. + +@item /dev/kill +Adds the text passed to it to the kill ring. + +@item /dev/clip +Adds the text passed to it to the clipboard. + +@end table + +@vindex eshell-virtual-targets You can, of course, define your own virtual targets. They are defined -by adding a list of the form @samp{("/dev/name" @var{function} @var{mode})} to -@code{eshell-virtual-targets}. The first element is the device name; -@var{function} may be either a lambda or a function name. If -@var{mode} is @code{nil}, then the function is the output function; if it is -non-@code{nil}, then the function is passed the redirection mode as a -symbol--@code{overwrite} for @code{>}, @code{append} for @code{>>}, or -@code{insert} for @code{>>>}--and the function is expected to return -the output function. +by adding a list of the form @samp{("/dev/name" @var{function} +@var{mode})} to @code{eshell-virtual-targets}. The first element is +the device name; @var{function} may be either a lambda or a function +name. If @var{mode} is @code{nil}, then the function is the output +function; if it is non-@code{nil}, then the function is passed the +redirection mode as a symbol--@code{overwrite} for @code{>}, +@code{append} for @code{>>}, or @code{insert} for @code{>>>}--and the +function is expected to return the output function. The output function is called once on each line of output until @code{nil} is passed, indicating end of output. -@section Running Shell Pipelines Natively +@node Pipelines +@section Pipelines +As with most other shells, Eshell supports pipelines to pass the +output of one command the input of the next command. You can pipe +commands to each other using the @code{|} operator. For example, + +@example +~ $ echo hello | rev +olleh +@end example + +@subsection Running Shell Pipelines Natively When constructing shell pipelines that will move a lot of data, it is a good idea to bypass Eshell's own pipelining support and use the operating system shell's instead. This is especially relevant when diff --git a/lisp/eshell/esh-arg.el b/lisp/eshell/esh-arg.el index 8e44a88459f..50fb7f5fdc6 100644 --- a/lisp/eshell/esh-arg.el +++ b/lisp/eshell/esh-arg.el @@ -147,6 +147,10 @@ return the result of the parse as a sexp. It is also responsible for moving the point forward to reflect the amount of input text that was parsed. +If the hook determines that it has reached the end of an argument, it +should call `eshell-finish-arg' to complete processing of the current +argument and proceed to the next. + If no function handles the current character at point, it will be treated as a literal character." :type 'hook diff --git a/lisp/eshell/esh-io.el b/lisp/eshell/esh-io.el index d54be55c130..f5dac2c81cd 100644 --- a/lisp/eshell/esh-io.el +++ b/lisp/eshell/esh-io.el @@ -236,22 +236,21 @@ The default location for standard output and standard error will go to STDOUT and STDERR, respectively. OUTPUT-MODE and ERROR-MODE are either `overwrite', `append' or `insert'; a nil value of mode defaults to `insert'." - (let ((handles (make-vector eshell-number-of-handles nil)) - (output-target (eshell-get-target stdout output-mode)) - (error-target (eshell-get-target stderr error-mode))) + (let* ((handles (make-vector eshell-number-of-handles nil)) + (output-target (eshell-get-target stdout output-mode)) + (error-target (if stderr + (eshell-get-target stderr error-mode) + output-target))) (aset handles eshell-output-handle (cons output-target 1)) - (aset handles eshell-error-handle - (cons (if stderr error-target output-target) 1)) + (aset handles eshell-error-handle (cons error-target 1)) handles)) (defun eshell-protect-handles (handles) "Protect the handles in HANDLES from a being closed." - (let ((idx 0)) - (while (< idx eshell-number-of-handles) - (if (aref handles idx) - (setcdr (aref handles idx) - (1+ (cdr (aref handles idx))))) - (setq idx (1+ idx)))) + (dotimes (idx eshell-number-of-handles) + (when (aref handles idx) + (setcdr (aref handles idx) + (1+ (cdr (aref handles idx)))))) handles) (defun eshell-close-handles (&optional exit-code result handles) @@ -278,6 +277,24 @@ the value already set in `eshell-last-command-result'." (eshell-close-target target (= eshell-last-command-status 0))) (setcar handle nil)))))) +(defun eshell-set-output-handle (index mode &optional target handles) + "Set handle INDEX for the current HANDLES to point to TARGET using MODE. +If HANDLES is nil, use `eshell-current-handles'." + (when target + (let ((handles (or handles eshell-current-handles))) + (if (and (stringp target) + (string= target (null-device))) + (aset handles index nil) + (let ((where (eshell-get-target target mode)) + (current (car (aref handles index)))) + (if (listp current) + (unless (member where current) + (setq current (append current (list where)))) + (setq current (list where))) + (if (not (aref handles index)) + (aset handles index (cons nil 1))) + (setcar (aref handles index) current)))))) + (defun eshell-close-target (target status) "Close an output TARGET, passing STATUS as the result. STATUS should be non-nil on successful termination of the output." @@ -390,22 +407,6 @@ it defaults to `insert'." (error "Invalid redirection target: %s" (eshell-stringify target))))) -(defun eshell-set-output-handle (index mode &optional target) - "Set handle INDEX, using MODE, to point to TARGET." - (when target - (if (and (stringp target) - (string= target (null-device))) - (aset eshell-current-handles index nil) - (let ((where (eshell-get-target target mode)) - (current (car (aref eshell-current-handles index)))) - (if (and (listp current) - (not (member where current))) - (setq current (append current (list where))) - (setq current (list where))) - (if (not (aref eshell-current-handles index)) - (aset eshell-current-handles index (cons nil 1))) - (setcar (aref eshell-current-handles index) current))))) - (defun eshell-interactive-output-p () "Return non-nil if current handles are bound for interactive display." (and (eq (car (aref eshell-current-handles diff --git a/test/lisp/eshell/esh-cmd-tests.el b/test/lisp/eshell/esh-cmd-tests.el index 3a582965d62..92d785d7fdf 100644 --- a/test/lisp/eshell/esh-cmd-tests.el +++ b/test/lisp/eshell/esh-cmd-tests.el @@ -73,6 +73,25 @@ Test that trailing arguments outside the subcommand are ignored. e.g. \"{(+ 1 2)} 3\" => 3" (eshell-command-result-equal "{(+ 1 2)} 3" 3)) + +;; Lisp forms + +(ert-deftest esh-cmd-test/quoted-lisp-form () + "Test parsing of a quoted Lisp form." + (eshell-command-result-equal "echo #'(1 2)" '(1 2))) + +(ert-deftest esh-cmd-test/backquoted-lisp-form () + "Test parsing of a backquoted Lisp form." + (let ((eshell-test-value 42)) + (eshell-command-result-equal "echo `(answer ,eshell-test-value)" + '(answer 42)))) + +(ert-deftest esh-cmd-test/backquoted-lisp-form/splice () + "Test parsing of a backquoted Lisp form using splicing." + (let ((eshell-test-value '(2 3))) + (eshell-command-result-equal "echo `(1 ,@eshell-test-value)" + '(1 2 3)))) + ;; Logical operators diff --git a/test/lisp/eshell/esh-io-tests.el b/test/lisp/eshell/esh-io-tests.el new file mode 100644 index 00000000000..6cd2dff1c13 --- /dev/null +++ b/test/lisp/eshell/esh-io-tests.el @@ -0,0 +1,220 @@ +;;; esh-io-tests.el --- esh-io test suite -*- lexical-binding:t -*- + +;; Copyright (C) 2022 Free Software Foundation, Inc. + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Code: + +(require 'ert) +(require 'ert-x) +(require 'esh-mode) +(require 'eshell) + +(require 'eshell-tests-helpers + (expand-file-name "eshell-tests-helpers" + (file-name-directory (or load-file-name + default-directory)))) + +(defvar eshell-test-value nil) + +(defun eshell-test-file-string (file) + "Return the contents of FILE as a string." + (with-temp-buffer + (insert-file-contents file) + (buffer-string))) + +(defun eshell/test-output () + "Write some test output separately to stdout and stderr." + (eshell-printn "stdout") + (eshell-errorn "stderr")) + +;;; Tests: + + +;; Basic redirection + +(ert-deftest esh-io-test/redirect-file/overwrite () + "Check that redirecting to a file in overwrite mode works." + (ert-with-temp-file temp-file + :text "old" + (with-temp-eshell + (eshell-insert-command (format "echo new > %s" temp-file))) + (should (equal (eshell-test-file-string temp-file) "new")))) + +(ert-deftest esh-io-test/redirect-file/append () + "Check that redirecting to a file in append mode works." + (ert-with-temp-file temp-file + :text "old" + (with-temp-eshell + (eshell-insert-command (format "echo new >> %s" temp-file))) + (should (equal (eshell-test-file-string temp-file) "oldnew")))) + +(ert-deftest esh-io-test/redirect-file/insert () + "Check that redirecting to a file in insert works." + (ert-with-temp-file temp-file + :text "old" + (with-temp-eshell + (eshell-insert-command (format "echo new >>> %s" temp-file))) + (should (equal (eshell-test-file-string temp-file) "newold")))) + +(ert-deftest esh-io-test/redirect-buffer/overwrite () + "Check that redirecting to a buffer in overwrite mode works." + (eshell-with-temp-buffer bufname "old" + (with-temp-eshell + (eshell-insert-command (format "echo new > #<%s>" bufname))) + (should (equal (buffer-string) "new")))) + +(ert-deftest esh-io-test/redirect-buffer/append () + "Check that redirecting to a buffer in append mode works." + (eshell-with-temp-buffer bufname "old" + (with-temp-eshell + (eshell-insert-command (format "echo new >> #<%s>" bufname))) + (should (equal (buffer-string) "oldnew")))) + +(ert-deftest esh-io-test/redirect-buffer/insert () + "Check that redirecting to a buffer in insert mode works." + (eshell-with-temp-buffer bufname "old" + (goto-char (point-min)) + (with-temp-eshell + (eshell-insert-command (format "echo new >>> #<%s>" bufname))) + (should (equal (buffer-string) "newold")))) + +(ert-deftest esh-io-test/redirect-buffer/escaped () + "Check that redirecting to a buffer with escaped characters works." + (with-temp-buffer + (rename-buffer "eshell\\temp\\buffer" t) + (let ((bufname (buffer-name))) + (with-temp-eshell + (eshell-insert-command (format "echo hi > #<%s>" + (string-replace "\\" "\\\\" bufname)))) + (should (equal (buffer-string) "hi"))))) + +(ert-deftest esh-io-test/redirect-symbol/overwrite () + "Check that redirecting to a symbol in overwrite mode works." + (let ((eshell-test-value "old")) + (with-temp-eshell + (eshell-insert-command "echo new > #'eshell-test-value")) + (should (equal eshell-test-value "new")))) + +(ert-deftest esh-io-test/redirect-symbol/append () + "Check that redirecting to a symbol in append mode works." + (let ((eshell-test-value "old")) + (with-temp-eshell + (eshell-insert-command "echo new >> #'eshell-test-value")) + (should (equal eshell-test-value "oldnew")))) + +(ert-deftest esh-io-test/redirect-marker () + "Check that redirecting to a marker works." + (with-temp-buffer + (let ((eshell-test-value (point-marker))) + (with-temp-eshell + (eshell-insert-command "echo hi > $eshell-test-value")) + (should (equal (buffer-string) "hi"))))) + +(ert-deftest esh-io-test/redirect-multiple () + "Check that redirecting to multiple targets works." + (let ((eshell-test-value "old")) + (eshell-with-temp-buffer bufname "old" + (with-temp-eshell + (eshell-insert-command (format "echo new > #<%s> > #'eshell-test-value" + bufname))) + (should (equal (buffer-string) "new")) + (should (equal eshell-test-value "new"))))) + +(ert-deftest esh-io-test/redirect-multiple/repeat () + "Check that redirecting to multiple targets works when repeating a target." + (let ((eshell-test-value "old")) + (eshell-with-temp-buffer bufname "old" + (with-temp-eshell + (eshell-insert-command + (format "echo new > #<%s> > #'eshell-test-value > #<%s>" + bufname bufname))) + (should (equal (buffer-string) "new")) + (should (equal eshell-test-value "new"))))) + + +;; Redirecting specific handles + +(ert-deftest esh-io-test/redirect-stdout () + "Check that redirecting to stdout doesn't redirect stderr." + (eshell-with-temp-buffer bufname "old" + (with-temp-eshell + (eshell-match-command-output (format "test-output > #<%s>" bufname) + "stderr\n")) + (should (equal (buffer-string) "stdout\n"))) + ;; Also check explicitly specifying the stdout fd. + (eshell-with-temp-buffer bufname "old" + (with-temp-eshell + (eshell-match-command-output (format "test-output 1> #<%s>" bufname) + "stderr\n")) + (should (equal (buffer-string) "stdout\n")))) + +(ert-deftest esh-io-test/redirect-stderr/overwrite () + "Check that redirecting to stderr doesn't redirect stdout." + (eshell-with-temp-buffer bufname "old" + (with-temp-eshell + (eshell-match-command-output (format "test-output 2> #<%s>" bufname) + "stdout\n")) + (should (equal (buffer-string) "stderr\n")))) + +(ert-deftest esh-io-test/redirect-stderr/append () + "Check that redirecting to stderr doesn't redirect stdout." + (eshell-with-temp-buffer bufname "old" + (with-temp-eshell + (eshell-match-command-output (format "test-output 2>> #<%s>" bufname) + "stdout\n")) + (should (equal (buffer-string) "oldstderr\n")))) + +(ert-deftest esh-io-test/redirect-stderr/insert () + "Check that redirecting to stderr doesn't redirect stdout." + (eshell-with-temp-buffer bufname "old" + (goto-char (point-min)) + (with-temp-eshell + (eshell-match-command-output (format "test-output 2>>> #<%s>" bufname) + "stdout\n")) + (should (equal (buffer-string) "stderr\nold")))) + +(ert-deftest esh-io-test/redirect-stdout-and-stderr () + "Check that redirecting to both stdout and stderr works." + (eshell-with-temp-buffer bufname-1 "old" + (eshell-with-temp-buffer bufname-2 "old" + (with-temp-eshell + (eshell-match-command-output (format "test-output > #<%s> 2> #<%s>" + bufname-1 bufname-2) + "\\`\\'")) + (should (equal (buffer-string) "stderr\n"))) + (should (equal (buffer-string) "stdout\n")))) + + +;; Virtual targets + +(ert-deftest esh-io-test/virtual-dev-eshell () + "Check that redirecting to /dev/eshell works." + (with-temp-eshell + (eshell-match-command-output "echo hi > /dev/eshell" "hi"))) + +(ert-deftest esh-io-test/virtual-dev-kill () + "Check that redirecting to /dev/kill works." + (with-temp-eshell + (eshell-insert-command "echo one > /dev/kill") + (should (equal (car kill-ring) "one")) + (eshell-insert-command "echo two > /dev/kill") + (should (equal (car kill-ring) "two")) + (eshell-insert-command "echo three >> /dev/kill") + (should (equal (car kill-ring) "twothree")))) + +;;; esh-io-tests.el ends here diff --git a/test/lisp/eshell/eshell-tests-helpers.el b/test/lisp/eshell/eshell-tests-helpers.el index 8f0f993447f..73abfcbb557 100644 --- a/test/lisp/eshell/eshell-tests-helpers.el +++ b/test/lisp/eshell/eshell-tests-helpers.el @@ -51,6 +51,16 @@ See `eshell-wait-for-subprocess'.") (let (kill-buffer-query-functions) (kill-buffer eshell-buffer))))))) +(defmacro eshell-with-temp-buffer (bufname text &rest body) + "Create a temporary buffer containing TEXT and evaluate BODY there. +BUFNAME will be set to the name of the temporary buffer." + (declare (indent 2)) + `(with-temp-buffer + (insert ,text) + (rename-buffer "eshell-temp-buffer" t) + (let ((,bufname (buffer-name))) + ,@body))) + (defun eshell-wait-for-subprocess (&optional all) "Wait until there is no interactive subprocess running in Eshell. If ALL is non-nil, wait until there are no Eshell subprocesses at diff --git a/test/lisp/eshell/eshell-tests.el b/test/lisp/eshell/eshell-tests.el index 1845dba2809..d5112146c2d 100644 --- a/test/lisp/eshell/eshell-tests.el +++ b/test/lisp/eshell/eshell-tests.el @@ -105,25 +105,6 @@ (format template "format \"%s\" eshell-in-pipeline-p") "nil"))) -(ert-deftest eshell-test/redirect-buffer () - "Check that piping to a buffer works" - (with-temp-buffer - (rename-buffer "eshell-temp-buffer" t) - (let ((bufname (buffer-name))) - (with-temp-eshell - (eshell-insert-command (format "echo hi > #<%s>" bufname))) - (should (equal (buffer-string) "hi"))))) - -(ert-deftest eshell-test/redirect-buffer-escaped () - "Check that piping to a buffer with escaped characters works" - (with-temp-buffer - (rename-buffer "eshell\\temp\\buffer" t) - (let ((bufname (buffer-name))) - (with-temp-eshell - (eshell-insert-command (format "echo hi > #<%s>" - (string-replace "\\" "\\\\" bufname)))) - (should (equal (buffer-string) "hi"))))) - (ert-deftest eshell-test/escape-nonspecial () "Test that \"\\c\" and \"c\" are equivalent when \"c\" is not a special character." -- cgit v1.2.3