Only set Eshell execution result metavariables when non-nil
This simplifies usage of 'eshell-close-handles' in several places and
makes it work more like the docstring indicated it would.
* lisp/eshell/esh-io.el (eshell-close-handles): Only store EXIT-CODE
and RESULT if they're non-nil. Also, use 'dotimes' and 'dolist' to
simplify the implementation.
* lisp/eshell/em-alias.el (eshell-write-aliases-list):
* lisp/eshell/esh-cmd.el (eshell-rewrite-for-command)
(eshell-structure-basic-command): Adapt calls to
'eshell-close-handles'.
* test/lisp/eshell/eshell-tests.el (eshell-test/simple-command-result)
(eshell-test/lisp-command, eshell-test/lisp-command-with-quote)
(eshell-test/for-loop, eshell-test/for-name-loop)
(eshell-test/for-name-shadow-loop, eshell-test/lisp-command-args)
(eshell-test/subcommand, eshell-test/subcommand-args)
(eshell-test/subcommand-lisp): Move from here...
* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/simple-command-result, esh-cmd-test/lisp-command)
(esh-cmd-test/lisp-command-with-quote, esh-cmd-test/for-loop)
(esh-cmd-test/for-name-loop, esh-cmd-test/for-name-shadow-loop)
(esh-cmd-test/lisp-command-args, esh-cmd-test/subcommand)
(esh-cmd-test/subcommand-args, esh-cmd-test/subcommand-lisp): ... to
here.
(esh-cmd-test/and-operator, esh-cmd-test/or-operator)
(esh-cmd-test/for-loop-list, esh-cmd-test/for-loop-multiple-args)
(esh-cmd-test/while-loop, esh-cmd-test/until-loop)
(esh-cmd-test/if-statement, esh-cmd-test/if-else-statement)
(esh-cmd-test/unless-statement, esh-cmd-test/unless-else-statement):
New tests.
* doc/misc/eshell.texi (Invocation): Explain '&&' and '||'.
(for loop): Move from here...
(Control Flow): ... to here, and add documentation for other control
flow forms.
2022-08-06 13:37:28 -07:00
|
|
|
|
;;; esh-cmd-tests.el --- esh-cmd test suite -*- lexical-binding:t -*-
|
|
|
|
|
|
2024-01-02 09:47:10 +08:00
|
|
|
|
;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
|
Only set Eshell execution result metavariables when non-nil
This simplifies usage of 'eshell-close-handles' in several places and
makes it work more like the docstring indicated it would.
* lisp/eshell/esh-io.el (eshell-close-handles): Only store EXIT-CODE
and RESULT if they're non-nil. Also, use 'dotimes' and 'dolist' to
simplify the implementation.
* lisp/eshell/em-alias.el (eshell-write-aliases-list):
* lisp/eshell/esh-cmd.el (eshell-rewrite-for-command)
(eshell-structure-basic-command): Adapt calls to
'eshell-close-handles'.
* test/lisp/eshell/eshell-tests.el (eshell-test/simple-command-result)
(eshell-test/lisp-command, eshell-test/lisp-command-with-quote)
(eshell-test/for-loop, eshell-test/for-name-loop)
(eshell-test/for-name-shadow-loop, eshell-test/lisp-command-args)
(eshell-test/subcommand, eshell-test/subcommand-args)
(eshell-test/subcommand-lisp): Move from here...
* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/simple-command-result, esh-cmd-test/lisp-command)
(esh-cmd-test/lisp-command-with-quote, esh-cmd-test/for-loop)
(esh-cmd-test/for-name-loop, esh-cmd-test/for-name-shadow-loop)
(esh-cmd-test/lisp-command-args, esh-cmd-test/subcommand)
(esh-cmd-test/subcommand-args, esh-cmd-test/subcommand-lisp): ... to
here.
(esh-cmd-test/and-operator, esh-cmd-test/or-operator)
(esh-cmd-test/for-loop-list, esh-cmd-test/for-loop-multiple-args)
(esh-cmd-test/while-loop, esh-cmd-test/until-loop)
(esh-cmd-test/if-statement, esh-cmd-test/if-else-statement)
(esh-cmd-test/unless-statement, esh-cmd-test/unless-else-statement):
New tests.
* doc/misc/eshell.texi (Invocation): Explain '&&' and '||'.
(for loop): Move from here...
(Control Flow): ... to here, and add documentation for other control
flow forms.
2022-08-06 13:37:28 -07:00
|
|
|
|
|
|
|
|
|
;; 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 <https://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
|
|
;;; 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."
|
2022-08-14 13:44:04 -07:00
|
|
|
|
(eshell-command-result-equal "+ 1 2" 3))
|
Only set Eshell execution result metavariables when non-nil
This simplifies usage of 'eshell-close-handles' in several places and
makes it work more like the docstring indicated it would.
* lisp/eshell/esh-io.el (eshell-close-handles): Only store EXIT-CODE
and RESULT if they're non-nil. Also, use 'dotimes' and 'dolist' to
simplify the implementation.
* lisp/eshell/em-alias.el (eshell-write-aliases-list):
* lisp/eshell/esh-cmd.el (eshell-rewrite-for-command)
(eshell-structure-basic-command): Adapt calls to
'eshell-close-handles'.
* test/lisp/eshell/eshell-tests.el (eshell-test/simple-command-result)
(eshell-test/lisp-command, eshell-test/lisp-command-with-quote)
(eshell-test/for-loop, eshell-test/for-name-loop)
(eshell-test/for-name-shadow-loop, eshell-test/lisp-command-args)
(eshell-test/subcommand, eshell-test/subcommand-args)
(eshell-test/subcommand-lisp): Move from here...
* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/simple-command-result, esh-cmd-test/lisp-command)
(esh-cmd-test/lisp-command-with-quote, esh-cmd-test/for-loop)
(esh-cmd-test/for-name-loop, esh-cmd-test/for-name-shadow-loop)
(esh-cmd-test/lisp-command-args, esh-cmd-test/subcommand)
(esh-cmd-test/subcommand-args, esh-cmd-test/subcommand-lisp): ... to
here.
(esh-cmd-test/and-operator, esh-cmd-test/or-operator)
(esh-cmd-test/for-loop-list, esh-cmd-test/for-loop-multiple-args)
(esh-cmd-test/while-loop, esh-cmd-test/until-loop)
(esh-cmd-test/if-statement, esh-cmd-test/if-else-statement)
(esh-cmd-test/unless-statement, esh-cmd-test/unless-else-statement):
New tests.
* doc/misc/eshell.texi (Invocation): Explain '&&' and '||'.
(for loop): Move from here...
(Control Flow): ... to here, and add documentation for other control
flow forms.
2022-08-06 13:37:28 -07:00
|
|
|
|
|
|
|
|
|
(ert-deftest esh-cmd-test/lisp-command ()
|
|
|
|
|
"Test invocation with an elisp command."
|
2022-08-14 13:44:04 -07:00
|
|
|
|
(eshell-command-result-equal "(+ 1 2)" 3))
|
Only set Eshell execution result metavariables when non-nil
This simplifies usage of 'eshell-close-handles' in several places and
makes it work more like the docstring indicated it would.
* lisp/eshell/esh-io.el (eshell-close-handles): Only store EXIT-CODE
and RESULT if they're non-nil. Also, use 'dotimes' and 'dolist' to
simplify the implementation.
* lisp/eshell/em-alias.el (eshell-write-aliases-list):
* lisp/eshell/esh-cmd.el (eshell-rewrite-for-command)
(eshell-structure-basic-command): Adapt calls to
'eshell-close-handles'.
* test/lisp/eshell/eshell-tests.el (eshell-test/simple-command-result)
(eshell-test/lisp-command, eshell-test/lisp-command-with-quote)
(eshell-test/for-loop, eshell-test/for-name-loop)
(eshell-test/for-name-shadow-loop, eshell-test/lisp-command-args)
(eshell-test/subcommand, eshell-test/subcommand-args)
(eshell-test/subcommand-lisp): Move from here...
* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/simple-command-result, esh-cmd-test/lisp-command)
(esh-cmd-test/lisp-command-with-quote, esh-cmd-test/for-loop)
(esh-cmd-test/for-name-loop, esh-cmd-test/for-name-shadow-loop)
(esh-cmd-test/lisp-command-args, esh-cmd-test/subcommand)
(esh-cmd-test/subcommand-args, esh-cmd-test/subcommand-lisp): ... to
here.
(esh-cmd-test/and-operator, esh-cmd-test/or-operator)
(esh-cmd-test/for-loop-list, esh-cmd-test/for-loop-multiple-args)
(esh-cmd-test/while-loop, esh-cmd-test/until-loop)
(esh-cmd-test/if-statement, esh-cmd-test/if-else-statement)
(esh-cmd-test/unless-statement, esh-cmd-test/unless-else-statement):
New tests.
* doc/misc/eshell.texi (Invocation): Explain '&&' and '||'.
(for loop): Move from here...
(Control Flow): ... to here, and add documentation for other control
flow forms.
2022-08-06 13:37:28 -07:00
|
|
|
|
|
|
|
|
|
(ert-deftest esh-cmd-test/lisp-command-with-quote ()
|
|
|
|
|
"Test invocation with an elisp command containing a quote."
|
2022-08-14 13:44:04 -07:00
|
|
|
|
(eshell-command-result-equal "(eq 'foo nil)" nil))
|
Only set Eshell execution result metavariables when non-nil
This simplifies usage of 'eshell-close-handles' in several places and
makes it work more like the docstring indicated it would.
* lisp/eshell/esh-io.el (eshell-close-handles): Only store EXIT-CODE
and RESULT if they're non-nil. Also, use 'dotimes' and 'dolist' to
simplify the implementation.
* lisp/eshell/em-alias.el (eshell-write-aliases-list):
* lisp/eshell/esh-cmd.el (eshell-rewrite-for-command)
(eshell-structure-basic-command): Adapt calls to
'eshell-close-handles'.
* test/lisp/eshell/eshell-tests.el (eshell-test/simple-command-result)
(eshell-test/lisp-command, eshell-test/lisp-command-with-quote)
(eshell-test/for-loop, eshell-test/for-name-loop)
(eshell-test/for-name-shadow-loop, eshell-test/lisp-command-args)
(eshell-test/subcommand, eshell-test/subcommand-args)
(eshell-test/subcommand-lisp): Move from here...
* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/simple-command-result, esh-cmd-test/lisp-command)
(esh-cmd-test/lisp-command-with-quote, esh-cmd-test/for-loop)
(esh-cmd-test/for-name-loop, esh-cmd-test/for-name-shadow-loop)
(esh-cmd-test/lisp-command-args, esh-cmd-test/subcommand)
(esh-cmd-test/subcommand-args, esh-cmd-test/subcommand-lisp): ... to
here.
(esh-cmd-test/and-operator, esh-cmd-test/or-operator)
(esh-cmd-test/for-loop-list, esh-cmd-test/for-loop-multiple-args)
(esh-cmd-test/while-loop, esh-cmd-test/until-loop)
(esh-cmd-test/if-statement, esh-cmd-test/if-else-statement)
(esh-cmd-test/unless-statement, esh-cmd-test/unless-else-statement):
New tests.
* doc/misc/eshell.texi (Invocation): Explain '&&' and '||'.
(for loop): Move from here...
(Control Flow): ... to here, and add documentation for other control
flow forms.
2022-08-06 13:37:28 -07:00
|
|
|
|
|
|
|
|
|
(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"
|
2022-08-14 13:44:04 -07:00
|
|
|
|
(eshell-command-result-equal "(+ 1 2) 3" 3))
|
Only set Eshell execution result metavariables when non-nil
This simplifies usage of 'eshell-close-handles' in several places and
makes it work more like the docstring indicated it would.
* lisp/eshell/esh-io.el (eshell-close-handles): Only store EXIT-CODE
and RESULT if they're non-nil. Also, use 'dotimes' and 'dolist' to
simplify the implementation.
* lisp/eshell/em-alias.el (eshell-write-aliases-list):
* lisp/eshell/esh-cmd.el (eshell-rewrite-for-command)
(eshell-structure-basic-command): Adapt calls to
'eshell-close-handles'.
* test/lisp/eshell/eshell-tests.el (eshell-test/simple-command-result)
(eshell-test/lisp-command, eshell-test/lisp-command-with-quote)
(eshell-test/for-loop, eshell-test/for-name-loop)
(eshell-test/for-name-shadow-loop, eshell-test/lisp-command-args)
(eshell-test/subcommand, eshell-test/subcommand-args)
(eshell-test/subcommand-lisp): Move from here...
* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/simple-command-result, esh-cmd-test/lisp-command)
(esh-cmd-test/lisp-command-with-quote, esh-cmd-test/for-loop)
(esh-cmd-test/for-name-loop, esh-cmd-test/for-name-shadow-loop)
(esh-cmd-test/lisp-command-args, esh-cmd-test/subcommand)
(esh-cmd-test/subcommand-args, esh-cmd-test/subcommand-lisp): ... to
here.
(esh-cmd-test/and-operator, esh-cmd-test/or-operator)
(esh-cmd-test/for-loop-list, esh-cmd-test/for-loop-multiple-args)
(esh-cmd-test/while-loop, esh-cmd-test/until-loop)
(esh-cmd-test/if-statement, esh-cmd-test/if-else-statement)
(esh-cmd-test/unless-statement, esh-cmd-test/unless-else-statement):
New tests.
* doc/misc/eshell.texi (Invocation): Explain '&&' and '||'.
(for loop): Move from here...
(Control Flow): ... to here, and add documentation for other control
flow forms.
2022-08-06 13:37:28 -07:00
|
|
|
|
|
|
|
|
|
(ert-deftest esh-cmd-test/subcommand ()
|
|
|
|
|
"Test invocation with a simple subcommand."
|
2022-08-14 13:44:04 -07:00
|
|
|
|
(eshell-command-result-equal "{+ 1 2}" 3))
|
Only set Eshell execution result metavariables when non-nil
This simplifies usage of 'eshell-close-handles' in several places and
makes it work more like the docstring indicated it would.
* lisp/eshell/esh-io.el (eshell-close-handles): Only store EXIT-CODE
and RESULT if they're non-nil. Also, use 'dotimes' and 'dolist' to
simplify the implementation.
* lisp/eshell/em-alias.el (eshell-write-aliases-list):
* lisp/eshell/esh-cmd.el (eshell-rewrite-for-command)
(eshell-structure-basic-command): Adapt calls to
'eshell-close-handles'.
* test/lisp/eshell/eshell-tests.el (eshell-test/simple-command-result)
(eshell-test/lisp-command, eshell-test/lisp-command-with-quote)
(eshell-test/for-loop, eshell-test/for-name-loop)
(eshell-test/for-name-shadow-loop, eshell-test/lisp-command-args)
(eshell-test/subcommand, eshell-test/subcommand-args)
(eshell-test/subcommand-lisp): Move from here...
* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/simple-command-result, esh-cmd-test/lisp-command)
(esh-cmd-test/lisp-command-with-quote, esh-cmd-test/for-loop)
(esh-cmd-test/for-name-loop, esh-cmd-test/for-name-shadow-loop)
(esh-cmd-test/lisp-command-args, esh-cmd-test/subcommand)
(esh-cmd-test/subcommand-args, esh-cmd-test/subcommand-lisp): ... to
here.
(esh-cmd-test/and-operator, esh-cmd-test/or-operator)
(esh-cmd-test/for-loop-list, esh-cmd-test/for-loop-multiple-args)
(esh-cmd-test/while-loop, esh-cmd-test/until-loop)
(esh-cmd-test/if-statement, esh-cmd-test/if-else-statement)
(esh-cmd-test/unless-statement, esh-cmd-test/unless-else-statement):
New tests.
* doc/misc/eshell.texi (Invocation): Explain '&&' and '||'.
(for loop): Move from here...
(Control Flow): ... to here, and add documentation for other control
flow forms.
2022-08-06 13:37:28 -07:00
|
|
|
|
|
|
|
|
|
(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"
|
2022-08-14 13:44:04 -07:00
|
|
|
|
(eshell-command-result-equal "{+ 1 2} 3" 3))
|
Only set Eshell execution result metavariables when non-nil
This simplifies usage of 'eshell-close-handles' in several places and
makes it work more like the docstring indicated it would.
* lisp/eshell/esh-io.el (eshell-close-handles): Only store EXIT-CODE
and RESULT if they're non-nil. Also, use 'dotimes' and 'dolist' to
simplify the implementation.
* lisp/eshell/em-alias.el (eshell-write-aliases-list):
* lisp/eshell/esh-cmd.el (eshell-rewrite-for-command)
(eshell-structure-basic-command): Adapt calls to
'eshell-close-handles'.
* test/lisp/eshell/eshell-tests.el (eshell-test/simple-command-result)
(eshell-test/lisp-command, eshell-test/lisp-command-with-quote)
(eshell-test/for-loop, eshell-test/for-name-loop)
(eshell-test/for-name-shadow-loop, eshell-test/lisp-command-args)
(eshell-test/subcommand, eshell-test/subcommand-args)
(eshell-test/subcommand-lisp): Move from here...
* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/simple-command-result, esh-cmd-test/lisp-command)
(esh-cmd-test/lisp-command-with-quote, esh-cmd-test/for-loop)
(esh-cmd-test/for-name-loop, esh-cmd-test/for-name-shadow-loop)
(esh-cmd-test/lisp-command-args, esh-cmd-test/subcommand)
(esh-cmd-test/subcommand-args, esh-cmd-test/subcommand-lisp): ... to
here.
(esh-cmd-test/and-operator, esh-cmd-test/or-operator)
(esh-cmd-test/for-loop-list, esh-cmd-test/for-loop-multiple-args)
(esh-cmd-test/while-loop, esh-cmd-test/until-loop)
(esh-cmd-test/if-statement, esh-cmd-test/if-else-statement)
(esh-cmd-test/unless-statement, esh-cmd-test/unless-else-statement):
New tests.
* doc/misc/eshell.texi (Invocation): Explain '&&' and '||'.
(for loop): Move from here...
(Control Flow): ... to here, and add documentation for other control
flow forms.
2022-08-06 13:37:28 -07:00
|
|
|
|
|
|
|
|
|
(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"
|
2022-08-14 13:44:04 -07:00
|
|
|
|
(eshell-command-result-equal "{(+ 1 2)} 3" 3))
|
Only set Eshell execution result metavariables when non-nil
This simplifies usage of 'eshell-close-handles' in several places and
makes it work more like the docstring indicated it would.
* lisp/eshell/esh-io.el (eshell-close-handles): Only store EXIT-CODE
and RESULT if they're non-nil. Also, use 'dotimes' and 'dolist' to
simplify the implementation.
* lisp/eshell/em-alias.el (eshell-write-aliases-list):
* lisp/eshell/esh-cmd.el (eshell-rewrite-for-command)
(eshell-structure-basic-command): Adapt calls to
'eshell-close-handles'.
* test/lisp/eshell/eshell-tests.el (eshell-test/simple-command-result)
(eshell-test/lisp-command, eshell-test/lisp-command-with-quote)
(eshell-test/for-loop, eshell-test/for-name-loop)
(eshell-test/for-name-shadow-loop, eshell-test/lisp-command-args)
(eshell-test/subcommand, eshell-test/subcommand-args)
(eshell-test/subcommand-lisp): Move from here...
* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/simple-command-result, esh-cmd-test/lisp-command)
(esh-cmd-test/lisp-command-with-quote, esh-cmd-test/for-loop)
(esh-cmd-test/for-name-loop, esh-cmd-test/for-name-shadow-loop)
(esh-cmd-test/lisp-command-args, esh-cmd-test/subcommand)
(esh-cmd-test/subcommand-args, esh-cmd-test/subcommand-lisp): ... to
here.
(esh-cmd-test/and-operator, esh-cmd-test/or-operator)
(esh-cmd-test/for-loop-list, esh-cmd-test/for-loop-multiple-args)
(esh-cmd-test/while-loop, esh-cmd-test/until-loop)
(esh-cmd-test/if-statement, esh-cmd-test/if-else-statement)
(esh-cmd-test/unless-statement, esh-cmd-test/unless-else-statement):
New tests.
* doc/misc/eshell.texi (Invocation): Explain '&&' and '||'.
(for loop): Move from here...
(Control Flow): ... to here, and add documentation for other control
flow forms.
2022-08-06 13:37:28 -07:00
|
|
|
|
|
2023-03-18 19:18:28 -07:00
|
|
|
|
(ert-deftest esh-cmd-test/subcommand-shadow-value ()
|
|
|
|
|
"Test that the variable `value' isn't shadowed inside subcommands."
|
|
|
|
|
(with-temp-eshell
|
|
|
|
|
(with-no-warnings (setq-local value "hello"))
|
|
|
|
|
(eshell-match-command-output "echo ${echo $value}"
|
|
|
|
|
"hello\n")))
|
|
|
|
|
|
2023-09-15 13:40:37 -07:00
|
|
|
|
(ert-deftest esh-cmd-test/skip-leading-nils ()
|
|
|
|
|
"Test that Eshell skips leading nil arguments for named commands."
|
|
|
|
|
(eshell-command-result-equal "$eshell-test-value echo hello" "hello")
|
|
|
|
|
(eshell-command-result-equal
|
|
|
|
|
"$eshell-test-value $eshell-test-value echo hello" "hello"))
|
|
|
|
|
|
2023-01-24 17:14:54 -08:00
|
|
|
|
(ert-deftest esh-cmd-test/let-rebinds-after-defer ()
|
|
|
|
|
"Test that let-bound values are properly updated after `eshell-defer'.
|
|
|
|
|
When inside a `let' block in an Eshell command form, we need to
|
|
|
|
|
ensure that deferred commands update any let-bound variables so
|
|
|
|
|
they have the correct values when resuming evaluation. See
|
|
|
|
|
bug#59469."
|
|
|
|
|
(skip-unless (executable-find "echo"))
|
|
|
|
|
(with-temp-eshell
|
|
|
|
|
(eshell-match-command-output
|
|
|
|
|
(concat "{"
|
|
|
|
|
" export LOCAL=value; "
|
|
|
|
|
" echo \"$LOCAL\"; "
|
|
|
|
|
" *echo external; " ; This will throw `eshell-defer'.
|
|
|
|
|
" echo \"$LOCAL\"; "
|
|
|
|
|
"}")
|
|
|
|
|
"value\nexternal\nvalue\n")))
|
|
|
|
|
|
2023-09-23 11:36:11 -07:00
|
|
|
|
|
|
|
|
|
;; Background command invocation
|
|
|
|
|
|
|
|
|
|
(ert-deftest esh-cmd-test/background/simple-command ()
|
|
|
|
|
"Test invocation with a simple background command."
|
|
|
|
|
(skip-unless (executable-find "echo"))
|
|
|
|
|
(eshell-with-temp-buffer bufname ""
|
|
|
|
|
(with-temp-eshell
|
|
|
|
|
(eshell-match-command-output
|
|
|
|
|
(format "*echo hi > #<%s> &" bufname)
|
2024-07-09 10:45:35 -07:00
|
|
|
|
(rx bos "[echo" (? ".exe") "] " (+ digit) "\n"))
|
2023-09-23 11:36:11 -07:00
|
|
|
|
(eshell-wait-for-subprocess t))
|
|
|
|
|
(should (equal (buffer-string) "hi\n"))))
|
|
|
|
|
|
|
|
|
|
(ert-deftest esh-cmd-test/background/subcommand ()
|
|
|
|
|
"Test invocation with a background command containing subcommands."
|
|
|
|
|
(skip-unless (and (executable-find "echo")
|
|
|
|
|
(executable-find "rev")))
|
|
|
|
|
(eshell-with-temp-buffer bufname ""
|
|
|
|
|
(with-temp-eshell
|
|
|
|
|
(eshell-match-command-output
|
|
|
|
|
(format "*echo ${*echo hello | rev} > #<%s> &" bufname)
|
|
|
|
|
(rx "[echo" (? ".exe") "] " (+ digit) "\n"))
|
|
|
|
|
(eshell-wait-for-subprocess t))
|
|
|
|
|
(should (equal (buffer-string) "olleh\n"))))
|
|
|
|
|
|
2024-07-09 10:45:35 -07:00
|
|
|
|
(ert-deftest esh-cmd-test/background/kill ()
|
|
|
|
|
"Make sure that a background command that gets killed doesn't emit a prompt."
|
|
|
|
|
(skip-unless (executable-find "sleep"))
|
|
|
|
|
(let ((background-message (rx bos "[sleep" (? ".exe") "] " (+ digit) "\n")))
|
|
|
|
|
(with-temp-eshell
|
|
|
|
|
(eshell-match-command-output "*sleep 10 &" background-message)
|
|
|
|
|
(kill-process (caar eshell-process-list))
|
|
|
|
|
(eshell-wait-for-subprocess t)
|
|
|
|
|
;; Ensure we didn't emit another prompt after killing the
|
|
|
|
|
;; background process.
|
|
|
|
|
(should (eshell-match-output background-message)))))
|
|
|
|
|
|
2022-07-09 10:34:31 -07:00
|
|
|
|
|
|
|
|
|
;; 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))))
|
|
|
|
|
|
Only set Eshell execution result metavariables when non-nil
This simplifies usage of 'eshell-close-handles' in several places and
makes it work more like the docstring indicated it would.
* lisp/eshell/esh-io.el (eshell-close-handles): Only store EXIT-CODE
and RESULT if they're non-nil. Also, use 'dotimes' and 'dolist' to
simplify the implementation.
* lisp/eshell/em-alias.el (eshell-write-aliases-list):
* lisp/eshell/esh-cmd.el (eshell-rewrite-for-command)
(eshell-structure-basic-command): Adapt calls to
'eshell-close-handles'.
* test/lisp/eshell/eshell-tests.el (eshell-test/simple-command-result)
(eshell-test/lisp-command, eshell-test/lisp-command-with-quote)
(eshell-test/for-loop, eshell-test/for-name-loop)
(eshell-test/for-name-shadow-loop, eshell-test/lisp-command-args)
(eshell-test/subcommand, eshell-test/subcommand-args)
(eshell-test/subcommand-lisp): Move from here...
* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/simple-command-result, esh-cmd-test/lisp-command)
(esh-cmd-test/lisp-command-with-quote, esh-cmd-test/for-loop)
(esh-cmd-test/for-name-loop, esh-cmd-test/for-name-shadow-loop)
(esh-cmd-test/lisp-command-args, esh-cmd-test/subcommand)
(esh-cmd-test/subcommand-args, esh-cmd-test/subcommand-lisp): ... to
here.
(esh-cmd-test/and-operator, esh-cmd-test/or-operator)
(esh-cmd-test/for-loop-list, esh-cmd-test/for-loop-multiple-args)
(esh-cmd-test/while-loop, esh-cmd-test/until-loop)
(esh-cmd-test/if-statement, esh-cmd-test/if-else-statement)
(esh-cmd-test/unless-statement, esh-cmd-test/unless-else-statement):
New tests.
* doc/misc/eshell.texi (Invocation): Explain '&&' and '||'.
(for loop): Move from here...
(Control Flow): ... to here, and add documentation for other control
flow forms.
2022-08-06 13:37:28 -07:00
|
|
|
|
|
|
|
|
|
;; Logical operators
|
|
|
|
|
|
|
|
|
|
(ert-deftest esh-cmd-test/and-operator ()
|
|
|
|
|
"Test logical && operator."
|
|
|
|
|
(skip-unless (executable-find "["))
|
|
|
|
|
(with-temp-eshell
|
2022-08-13 20:31:11 -07:00
|
|
|
|
(eshell-match-command-output "[ foo = foo ] && echo hi"
|
|
|
|
|
"hi\n")
|
|
|
|
|
(eshell-match-command-output "[ foo = bar ] && echo hi"
|
|
|
|
|
"\\`\\'")))
|
Only set Eshell execution result metavariables when non-nil
This simplifies usage of 'eshell-close-handles' in several places and
makes it work more like the docstring indicated it would.
* lisp/eshell/esh-io.el (eshell-close-handles): Only store EXIT-CODE
and RESULT if they're non-nil. Also, use 'dotimes' and 'dolist' to
simplify the implementation.
* lisp/eshell/em-alias.el (eshell-write-aliases-list):
* lisp/eshell/esh-cmd.el (eshell-rewrite-for-command)
(eshell-structure-basic-command): Adapt calls to
'eshell-close-handles'.
* test/lisp/eshell/eshell-tests.el (eshell-test/simple-command-result)
(eshell-test/lisp-command, eshell-test/lisp-command-with-quote)
(eshell-test/for-loop, eshell-test/for-name-loop)
(eshell-test/for-name-shadow-loop, eshell-test/lisp-command-args)
(eshell-test/subcommand, eshell-test/subcommand-args)
(eshell-test/subcommand-lisp): Move from here...
* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/simple-command-result, esh-cmd-test/lisp-command)
(esh-cmd-test/lisp-command-with-quote, esh-cmd-test/for-loop)
(esh-cmd-test/for-name-loop, esh-cmd-test/for-name-shadow-loop)
(esh-cmd-test/lisp-command-args, esh-cmd-test/subcommand)
(esh-cmd-test/subcommand-args, esh-cmd-test/subcommand-lisp): ... to
here.
(esh-cmd-test/and-operator, esh-cmd-test/or-operator)
(esh-cmd-test/for-loop-list, esh-cmd-test/for-loop-multiple-args)
(esh-cmd-test/while-loop, esh-cmd-test/until-loop)
(esh-cmd-test/if-statement, esh-cmd-test/if-else-statement)
(esh-cmd-test/unless-statement, esh-cmd-test/unless-else-statement):
New tests.
* doc/misc/eshell.texi (Invocation): Explain '&&' and '||'.
(for loop): Move from here...
(Control Flow): ... to here, and add documentation for other control
flow forms.
2022-08-06 13:37:28 -07:00
|
|
|
|
|
|
|
|
|
(ert-deftest esh-cmd-test/or-operator ()
|
|
|
|
|
"Test logical || operator."
|
|
|
|
|
(skip-unless (executable-find "["))
|
|
|
|
|
(with-temp-eshell
|
2022-08-13 20:31:11 -07:00
|
|
|
|
(eshell-match-command-output "[ foo = foo ] || echo hi"
|
|
|
|
|
"\\`\\'")
|
|
|
|
|
(eshell-match-command-output "[ foo = bar ] || echo hi"
|
|
|
|
|
"hi\n")))
|
Only set Eshell execution result metavariables when non-nil
This simplifies usage of 'eshell-close-handles' in several places and
makes it work more like the docstring indicated it would.
* lisp/eshell/esh-io.el (eshell-close-handles): Only store EXIT-CODE
and RESULT if they're non-nil. Also, use 'dotimes' and 'dolist' to
simplify the implementation.
* lisp/eshell/em-alias.el (eshell-write-aliases-list):
* lisp/eshell/esh-cmd.el (eshell-rewrite-for-command)
(eshell-structure-basic-command): Adapt calls to
'eshell-close-handles'.
* test/lisp/eshell/eshell-tests.el (eshell-test/simple-command-result)
(eshell-test/lisp-command, eshell-test/lisp-command-with-quote)
(eshell-test/for-loop, eshell-test/for-name-loop)
(eshell-test/for-name-shadow-loop, eshell-test/lisp-command-args)
(eshell-test/subcommand, eshell-test/subcommand-args)
(eshell-test/subcommand-lisp): Move from here...
* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/simple-command-result, esh-cmd-test/lisp-command)
(esh-cmd-test/lisp-command-with-quote, esh-cmd-test/for-loop)
(esh-cmd-test/for-name-loop, esh-cmd-test/for-name-shadow-loop)
(esh-cmd-test/lisp-command-args, esh-cmd-test/subcommand)
(esh-cmd-test/subcommand-args, esh-cmd-test/subcommand-lisp): ... to
here.
(esh-cmd-test/and-operator, esh-cmd-test/or-operator)
(esh-cmd-test/for-loop-list, esh-cmd-test/for-loop-multiple-args)
(esh-cmd-test/while-loop, esh-cmd-test/until-loop)
(esh-cmd-test/if-statement, esh-cmd-test/if-else-statement)
(esh-cmd-test/unless-statement, esh-cmd-test/unless-else-statement):
New tests.
* doc/misc/eshell.texi (Invocation): Explain '&&' and '||'.
(for loop): Move from here...
(Control Flow): ... to here, and add documentation for other control
flow forms.
2022-08-06 13:37:28 -07:00
|
|
|
|
|
2023-09-06 17:00:59 -07:00
|
|
|
|
|
|
|
|
|
;; Pipelines
|
|
|
|
|
|
|
|
|
|
(ert-deftest esh-cmd-test/pipeline-wait/head-proc ()
|
|
|
|
|
"Check that piping a non-process to a process command waits for the process."
|
|
|
|
|
(skip-unless (executable-find "cat"))
|
|
|
|
|
(with-temp-eshell
|
|
|
|
|
(eshell-match-command-output "echo hi | *cat"
|
|
|
|
|
"hi")))
|
|
|
|
|
|
|
|
|
|
(ert-deftest esh-cmd-test/pipeline-wait/tail-proc ()
|
|
|
|
|
"Check that piping a process to a non-process command waits for the process."
|
|
|
|
|
(skip-unless (executable-find "echo"))
|
|
|
|
|
(with-temp-eshell
|
|
|
|
|
(eshell-match-command-output "*echo hi | echo bye"
|
|
|
|
|
"bye\nhi\n")))
|
|
|
|
|
|
2023-09-06 17:01:06 -07:00
|
|
|
|
(ert-deftest esh-cmd-test/pipeline-wait/multi-proc ()
|
|
|
|
|
"Check that a pipeline waits for all its processes before returning."
|
|
|
|
|
(skip-unless (and (executable-find "echo")
|
|
|
|
|
(executable-find "sh")
|
|
|
|
|
(executable-find "rev")))
|
|
|
|
|
(with-temp-eshell
|
|
|
|
|
(eshell-match-command-output
|
|
|
|
|
"*echo hello | sh -c 'sleep 1; rev' 1>&2 | *echo goodbye"
|
|
|
|
|
"goodbye\nolleh\n")))
|
|
|
|
|
|
2023-09-06 17:00:59 -07:00
|
|
|
|
(ert-deftest esh-cmd-test/pipeline-wait/subcommand ()
|
|
|
|
|
"Check that piping with an asynchronous subcommand waits for the subcommand."
|
|
|
|
|
(skip-unless (and (executable-find "echo")
|
|
|
|
|
(executable-find "cat")))
|
|
|
|
|
(with-temp-eshell
|
|
|
|
|
(eshell-match-command-output "echo ${*echo hi} | *cat"
|
|
|
|
|
"hi")))
|
|
|
|
|
|
|
|
|
|
(ert-deftest esh-cmd-test/pipeline-wait/subcommand-with-pipe ()
|
|
|
|
|
"Check that piping with an asynchronous subcommand with its own pipe works.
|
|
|
|
|
This should also wait for the subcommand."
|
|
|
|
|
(skip-unless (and (executable-find "echo")
|
|
|
|
|
(executable-find "cat")))
|
|
|
|
|
(with-temp-eshell
|
|
|
|
|
(eshell-match-command-output "echo ${*echo hi | *cat} | *cat"
|
|
|
|
|
"hi")))
|
|
|
|
|
|
2024-05-25 13:46:24 -07:00
|
|
|
|
(ert-deftest esh-cmd-test/pipeline-wait/nested-pipes ()
|
|
|
|
|
"Check that piping a subcommand with its own pipe works.
|
|
|
|
|
This should also wait for the subcommand."
|
|
|
|
|
(skip-unless (and (executable-find "echo")
|
|
|
|
|
(executable-find "cat")
|
|
|
|
|
(executable-find "sh")
|
|
|
|
|
(executable-find "sleep")))
|
|
|
|
|
(with-temp-eshell
|
|
|
|
|
(eshell-match-command-output
|
|
|
|
|
"{ sh -c 'sleep 1; echo goodbye 1>&2' | *echo hello } | *cat"
|
|
|
|
|
"hello\ngoodbye\n")))
|
|
|
|
|
|
2023-09-06 17:00:59 -07:00
|
|
|
|
(ert-deftest esh-cmd-test/reset-in-pipeline/subcommand ()
|
|
|
|
|
"Check that subcommands reset `eshell-in-pipeline-p'."
|
|
|
|
|
(skip-unless (executable-find "cat"))
|
|
|
|
|
(dolist (template '("echo {%s} | *cat"
|
|
|
|
|
"echo ${%s} | *cat"
|
|
|
|
|
"*cat $<%s> | *cat"))
|
|
|
|
|
(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 esh-cmd-test/reset-in-pipeline/lisp ()
|
|
|
|
|
"Check that interpolated Lisp forms reset `eshell-in-pipeline-p'."
|
|
|
|
|
(skip-unless (executable-find "cat"))
|
|
|
|
|
(dolist (template '("echo (%s) | *cat"
|
|
|
|
|
"echo $(%s) | *cat"))
|
|
|
|
|
(eshell-command-result-equal
|
|
|
|
|
(format template "format \"%s\" eshell-in-pipeline-p")
|
|
|
|
|
"nil")))
|
|
|
|
|
|
Only set Eshell execution result metavariables when non-nil
This simplifies usage of 'eshell-close-handles' in several places and
makes it work more like the docstring indicated it would.
* lisp/eshell/esh-io.el (eshell-close-handles): Only store EXIT-CODE
and RESULT if they're non-nil. Also, use 'dotimes' and 'dolist' to
simplify the implementation.
* lisp/eshell/em-alias.el (eshell-write-aliases-list):
* lisp/eshell/esh-cmd.el (eshell-rewrite-for-command)
(eshell-structure-basic-command): Adapt calls to
'eshell-close-handles'.
* test/lisp/eshell/eshell-tests.el (eshell-test/simple-command-result)
(eshell-test/lisp-command, eshell-test/lisp-command-with-quote)
(eshell-test/for-loop, eshell-test/for-name-loop)
(eshell-test/for-name-shadow-loop, eshell-test/lisp-command-args)
(eshell-test/subcommand, eshell-test/subcommand-args)
(eshell-test/subcommand-lisp): Move from here...
* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/simple-command-result, esh-cmd-test/lisp-command)
(esh-cmd-test/lisp-command-with-quote, esh-cmd-test/for-loop)
(esh-cmd-test/for-name-loop, esh-cmd-test/for-name-shadow-loop)
(esh-cmd-test/lisp-command-args, esh-cmd-test/subcommand)
(esh-cmd-test/subcommand-args, esh-cmd-test/subcommand-lisp): ... to
here.
(esh-cmd-test/and-operator, esh-cmd-test/or-operator)
(esh-cmd-test/for-loop-list, esh-cmd-test/for-loop-multiple-args)
(esh-cmd-test/while-loop, esh-cmd-test/until-loop)
(esh-cmd-test/if-statement, esh-cmd-test/if-else-statement)
(esh-cmd-test/unless-statement, esh-cmd-test/unless-else-statement):
New tests.
* doc/misc/eshell.texi (Invocation): Explain '&&' and '||'.
(for loop): Move from here...
(Control Flow): ... to here, and add documentation for other control
flow forms.
2022-08-06 13:37:28 -07:00
|
|
|
|
|
|
|
|
|
;; Control flow statements
|
|
|
|
|
|
|
|
|
|
(ert-deftest esh-cmd-test/for-loop ()
|
|
|
|
|
"Test invocation of a for loop."
|
|
|
|
|
(with-temp-eshell
|
2022-08-13 20:31:11 -07:00
|
|
|
|
(eshell-match-command-output "for i in 5 { echo $i }"
|
|
|
|
|
"5\n")))
|
Only set Eshell execution result metavariables when non-nil
This simplifies usage of 'eshell-close-handles' in several places and
makes it work more like the docstring indicated it would.
* lisp/eshell/esh-io.el (eshell-close-handles): Only store EXIT-CODE
and RESULT if they're non-nil. Also, use 'dotimes' and 'dolist' to
simplify the implementation.
* lisp/eshell/em-alias.el (eshell-write-aliases-list):
* lisp/eshell/esh-cmd.el (eshell-rewrite-for-command)
(eshell-structure-basic-command): Adapt calls to
'eshell-close-handles'.
* test/lisp/eshell/eshell-tests.el (eshell-test/simple-command-result)
(eshell-test/lisp-command, eshell-test/lisp-command-with-quote)
(eshell-test/for-loop, eshell-test/for-name-loop)
(eshell-test/for-name-shadow-loop, eshell-test/lisp-command-args)
(eshell-test/subcommand, eshell-test/subcommand-args)
(eshell-test/subcommand-lisp): Move from here...
* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/simple-command-result, esh-cmd-test/lisp-command)
(esh-cmd-test/lisp-command-with-quote, esh-cmd-test/for-loop)
(esh-cmd-test/for-name-loop, esh-cmd-test/for-name-shadow-loop)
(esh-cmd-test/lisp-command-args, esh-cmd-test/subcommand)
(esh-cmd-test/subcommand-args, esh-cmd-test/subcommand-lisp): ... to
here.
(esh-cmd-test/and-operator, esh-cmd-test/or-operator)
(esh-cmd-test/for-loop-list, esh-cmd-test/for-loop-multiple-args)
(esh-cmd-test/while-loop, esh-cmd-test/until-loop)
(esh-cmd-test/if-statement, esh-cmd-test/if-else-statement)
(esh-cmd-test/unless-statement, esh-cmd-test/unless-else-statement):
New tests.
* doc/misc/eshell.texi (Invocation): Explain '&&' and '||'.
(for loop): Move from here...
(Control Flow): ... to here, and add documentation for other control
flow forms.
2022-08-06 13:37:28 -07:00
|
|
|
|
|
|
|
|
|
(ert-deftest esh-cmd-test/for-loop-list ()
|
|
|
|
|
"Test invocation of a for loop iterating over a list."
|
|
|
|
|
(with-temp-eshell
|
2022-08-13 20:31:11 -07:00
|
|
|
|
(eshell-match-command-output "for i in (list 1 2 (list 3 4)) { echo $i }"
|
|
|
|
|
"1\n2\n(3 4)\n")))
|
Only set Eshell execution result metavariables when non-nil
This simplifies usage of 'eshell-close-handles' in several places and
makes it work more like the docstring indicated it would.
* lisp/eshell/esh-io.el (eshell-close-handles): Only store EXIT-CODE
and RESULT if they're non-nil. Also, use 'dotimes' and 'dolist' to
simplify the implementation.
* lisp/eshell/em-alias.el (eshell-write-aliases-list):
* lisp/eshell/esh-cmd.el (eshell-rewrite-for-command)
(eshell-structure-basic-command): Adapt calls to
'eshell-close-handles'.
* test/lisp/eshell/eshell-tests.el (eshell-test/simple-command-result)
(eshell-test/lisp-command, eshell-test/lisp-command-with-quote)
(eshell-test/for-loop, eshell-test/for-name-loop)
(eshell-test/for-name-shadow-loop, eshell-test/lisp-command-args)
(eshell-test/subcommand, eshell-test/subcommand-args)
(eshell-test/subcommand-lisp): Move from here...
* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/simple-command-result, esh-cmd-test/lisp-command)
(esh-cmd-test/lisp-command-with-quote, esh-cmd-test/for-loop)
(esh-cmd-test/for-name-loop, esh-cmd-test/for-name-shadow-loop)
(esh-cmd-test/lisp-command-args, esh-cmd-test/subcommand)
(esh-cmd-test/subcommand-args, esh-cmd-test/subcommand-lisp): ... to
here.
(esh-cmd-test/and-operator, esh-cmd-test/or-operator)
(esh-cmd-test/for-loop-list, esh-cmd-test/for-loop-multiple-args)
(esh-cmd-test/while-loop, esh-cmd-test/until-loop)
(esh-cmd-test/if-statement, esh-cmd-test/if-else-statement)
(esh-cmd-test/unless-statement, esh-cmd-test/unless-else-statement):
New tests.
* doc/misc/eshell.texi (Invocation): Explain '&&' and '||'.
(for loop): Move from here...
(Control Flow): ... to here, and add documentation for other control
flow forms.
2022-08-06 13:37:28 -07:00
|
|
|
|
|
|
|
|
|
(ert-deftest esh-cmd-test/for-loop-multiple-args ()
|
|
|
|
|
"Test invocation of a for loop iterating over multiple arguments."
|
|
|
|
|
(with-temp-eshell
|
2022-08-13 20:31:11 -07:00
|
|
|
|
(eshell-match-command-output "for i in 1 2 (list 3 4) { echo $i }"
|
|
|
|
|
"1\n2\n3\n4\n")))
|
Only set Eshell execution result metavariables when non-nil
This simplifies usage of 'eshell-close-handles' in several places and
makes it work more like the docstring indicated it would.
* lisp/eshell/esh-io.el (eshell-close-handles): Only store EXIT-CODE
and RESULT if they're non-nil. Also, use 'dotimes' and 'dolist' to
simplify the implementation.
* lisp/eshell/em-alias.el (eshell-write-aliases-list):
* lisp/eshell/esh-cmd.el (eshell-rewrite-for-command)
(eshell-structure-basic-command): Adapt calls to
'eshell-close-handles'.
* test/lisp/eshell/eshell-tests.el (eshell-test/simple-command-result)
(eshell-test/lisp-command, eshell-test/lisp-command-with-quote)
(eshell-test/for-loop, eshell-test/for-name-loop)
(eshell-test/for-name-shadow-loop, eshell-test/lisp-command-args)
(eshell-test/subcommand, eshell-test/subcommand-args)
(eshell-test/subcommand-lisp): Move from here...
* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/simple-command-result, esh-cmd-test/lisp-command)
(esh-cmd-test/lisp-command-with-quote, esh-cmd-test/for-loop)
(esh-cmd-test/for-name-loop, esh-cmd-test/for-name-shadow-loop)
(esh-cmd-test/lisp-command-args, esh-cmd-test/subcommand)
(esh-cmd-test/subcommand-args, esh-cmd-test/subcommand-lisp): ... to
here.
(esh-cmd-test/and-operator, esh-cmd-test/or-operator)
(esh-cmd-test/for-loop-list, esh-cmd-test/for-loop-multiple-args)
(esh-cmd-test/while-loop, esh-cmd-test/until-loop)
(esh-cmd-test/if-statement, esh-cmd-test/if-else-statement)
(esh-cmd-test/unless-statement, esh-cmd-test/unless-else-statement):
New tests.
* doc/misc/eshell.texi (Invocation): Explain '&&' and '||'.
(for loop): Move from here...
(Control Flow): ... to here, and add documentation for other control
flow forms.
2022-08-06 13:37:28 -07:00
|
|
|
|
|
2023-03-18 19:18:28 -07:00
|
|
|
|
(ert-deftest esh-cmd-test/for-loop-name () ; bug#15231
|
Only set Eshell execution result metavariables when non-nil
This simplifies usage of 'eshell-close-handles' in several places and
makes it work more like the docstring indicated it would.
* lisp/eshell/esh-io.el (eshell-close-handles): Only store EXIT-CODE
and RESULT if they're non-nil. Also, use 'dotimes' and 'dolist' to
simplify the implementation.
* lisp/eshell/em-alias.el (eshell-write-aliases-list):
* lisp/eshell/esh-cmd.el (eshell-rewrite-for-command)
(eshell-structure-basic-command): Adapt calls to
'eshell-close-handles'.
* test/lisp/eshell/eshell-tests.el (eshell-test/simple-command-result)
(eshell-test/lisp-command, eshell-test/lisp-command-with-quote)
(eshell-test/for-loop, eshell-test/for-name-loop)
(eshell-test/for-name-shadow-loop, eshell-test/lisp-command-args)
(eshell-test/subcommand, eshell-test/subcommand-args)
(eshell-test/subcommand-lisp): Move from here...
* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/simple-command-result, esh-cmd-test/lisp-command)
(esh-cmd-test/lisp-command-with-quote, esh-cmd-test/for-loop)
(esh-cmd-test/for-name-loop, esh-cmd-test/for-name-shadow-loop)
(esh-cmd-test/lisp-command-args, esh-cmd-test/subcommand)
(esh-cmd-test/subcommand-args, esh-cmd-test/subcommand-lisp): ... to
here.
(esh-cmd-test/and-operator, esh-cmd-test/or-operator)
(esh-cmd-test/for-loop-list, esh-cmd-test/for-loop-multiple-args)
(esh-cmd-test/while-loop, esh-cmd-test/until-loop)
(esh-cmd-test/if-statement, esh-cmd-test/if-else-statement)
(esh-cmd-test/unless-statement, esh-cmd-test/unless-else-statement):
New tests.
* doc/misc/eshell.texi (Invocation): Explain '&&' and '||'.
(for loop): Move from here...
(Control Flow): ... to here, and add documentation for other control
flow forms.
2022-08-06 13:37:28 -07:00
|
|
|
|
"Test invocation of a for loop using `name'."
|
|
|
|
|
(let ((process-environment (cons "name" process-environment)))
|
2022-08-14 13:44:04 -07:00
|
|
|
|
(eshell-command-result-equal "for name in 3 { echo $name }"
|
|
|
|
|
3)))
|
Only set Eshell execution result metavariables when non-nil
This simplifies usage of 'eshell-close-handles' in several places and
makes it work more like the docstring indicated it would.
* lisp/eshell/esh-io.el (eshell-close-handles): Only store EXIT-CODE
and RESULT if they're non-nil. Also, use 'dotimes' and 'dolist' to
simplify the implementation.
* lisp/eshell/em-alias.el (eshell-write-aliases-list):
* lisp/eshell/esh-cmd.el (eshell-rewrite-for-command)
(eshell-structure-basic-command): Adapt calls to
'eshell-close-handles'.
* test/lisp/eshell/eshell-tests.el (eshell-test/simple-command-result)
(eshell-test/lisp-command, eshell-test/lisp-command-with-quote)
(eshell-test/for-loop, eshell-test/for-name-loop)
(eshell-test/for-name-shadow-loop, eshell-test/lisp-command-args)
(eshell-test/subcommand, eshell-test/subcommand-args)
(eshell-test/subcommand-lisp): Move from here...
* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/simple-command-result, esh-cmd-test/lisp-command)
(esh-cmd-test/lisp-command-with-quote, esh-cmd-test/for-loop)
(esh-cmd-test/for-name-loop, esh-cmd-test/for-name-shadow-loop)
(esh-cmd-test/lisp-command-args, esh-cmd-test/subcommand)
(esh-cmd-test/subcommand-args, esh-cmd-test/subcommand-lisp): ... to
here.
(esh-cmd-test/and-operator, esh-cmd-test/or-operator)
(esh-cmd-test/for-loop-list, esh-cmd-test/for-loop-multiple-args)
(esh-cmd-test/while-loop, esh-cmd-test/until-loop)
(esh-cmd-test/if-statement, esh-cmd-test/if-else-statement)
(esh-cmd-test/unless-statement, esh-cmd-test/unless-else-statement):
New tests.
* doc/misc/eshell.texi (Invocation): Explain '&&' and '||'.
(for loop): Move from here...
(Control Flow): ... to here, and add documentation for other control
flow forms.
2022-08-06 13:37:28 -07:00
|
|
|
|
|
2023-03-18 19:18:28 -07:00
|
|
|
|
(ert-deftest esh-cmd-test/for-loop-name-shadow () ; bug#15372
|
Only set Eshell execution result metavariables when non-nil
This simplifies usage of 'eshell-close-handles' in several places and
makes it work more like the docstring indicated it would.
* lisp/eshell/esh-io.el (eshell-close-handles): Only store EXIT-CODE
and RESULT if they're non-nil. Also, use 'dotimes' and 'dolist' to
simplify the implementation.
* lisp/eshell/em-alias.el (eshell-write-aliases-list):
* lisp/eshell/esh-cmd.el (eshell-rewrite-for-command)
(eshell-structure-basic-command): Adapt calls to
'eshell-close-handles'.
* test/lisp/eshell/eshell-tests.el (eshell-test/simple-command-result)
(eshell-test/lisp-command, eshell-test/lisp-command-with-quote)
(eshell-test/for-loop, eshell-test/for-name-loop)
(eshell-test/for-name-shadow-loop, eshell-test/lisp-command-args)
(eshell-test/subcommand, eshell-test/subcommand-args)
(eshell-test/subcommand-lisp): Move from here...
* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/simple-command-result, esh-cmd-test/lisp-command)
(esh-cmd-test/lisp-command-with-quote, esh-cmd-test/for-loop)
(esh-cmd-test/for-name-loop, esh-cmd-test/for-name-shadow-loop)
(esh-cmd-test/lisp-command-args, esh-cmd-test/subcommand)
(esh-cmd-test/subcommand-args, esh-cmd-test/subcommand-lisp): ... to
here.
(esh-cmd-test/and-operator, esh-cmd-test/or-operator)
(esh-cmd-test/for-loop-list, esh-cmd-test/for-loop-multiple-args)
(esh-cmd-test/while-loop, esh-cmd-test/until-loop)
(esh-cmd-test/if-statement, esh-cmd-test/if-else-statement)
(esh-cmd-test/unless-statement, esh-cmd-test/unless-else-statement):
New tests.
* doc/misc/eshell.texi (Invocation): Explain '&&' and '||'.
(for loop): Move from here...
(Control Flow): ... to here, and add documentation for other control
flow forms.
2022-08-06 13:37:28 -07:00
|
|
|
|
"Test invocation of a for loop using an env-var."
|
|
|
|
|
(let ((process-environment (cons "name=env-value" process-environment)))
|
|
|
|
|
(with-temp-eshell
|
2022-08-13 20:31:11 -07:00
|
|
|
|
(eshell-match-command-output
|
Only set Eshell execution result metavariables when non-nil
This simplifies usage of 'eshell-close-handles' in several places and
makes it work more like the docstring indicated it would.
* lisp/eshell/esh-io.el (eshell-close-handles): Only store EXIT-CODE
and RESULT if they're non-nil. Also, use 'dotimes' and 'dolist' to
simplify the implementation.
* lisp/eshell/em-alias.el (eshell-write-aliases-list):
* lisp/eshell/esh-cmd.el (eshell-rewrite-for-command)
(eshell-structure-basic-command): Adapt calls to
'eshell-close-handles'.
* test/lisp/eshell/eshell-tests.el (eshell-test/simple-command-result)
(eshell-test/lisp-command, eshell-test/lisp-command-with-quote)
(eshell-test/for-loop, eshell-test/for-name-loop)
(eshell-test/for-name-shadow-loop, eshell-test/lisp-command-args)
(eshell-test/subcommand, eshell-test/subcommand-args)
(eshell-test/subcommand-lisp): Move from here...
* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/simple-command-result, esh-cmd-test/lisp-command)
(esh-cmd-test/lisp-command-with-quote, esh-cmd-test/for-loop)
(esh-cmd-test/for-name-loop, esh-cmd-test/for-name-shadow-loop)
(esh-cmd-test/lisp-command-args, esh-cmd-test/subcommand)
(esh-cmd-test/subcommand-args, esh-cmd-test/subcommand-lisp): ... to
here.
(esh-cmd-test/and-operator, esh-cmd-test/or-operator)
(esh-cmd-test/for-loop-list, esh-cmd-test/for-loop-multiple-args)
(esh-cmd-test/while-loop, esh-cmd-test/until-loop)
(esh-cmd-test/if-statement, esh-cmd-test/if-else-statement)
(esh-cmd-test/unless-statement, esh-cmd-test/unless-else-statement):
New tests.
* doc/misc/eshell.texi (Invocation): Explain '&&' and '||'.
(for loop): Move from here...
(Control Flow): ... to here, and add documentation for other control
flow forms.
2022-08-06 13:37:28 -07:00
|
|
|
|
"echo $name; for name in 3 { echo $name }; echo $name"
|
|
|
|
|
"env-value\n3\nenv-value\n"))))
|
|
|
|
|
|
2023-03-18 19:18:28 -07:00
|
|
|
|
(ert-deftest esh-cmd-test/for-loop-for-items-shadow ()
|
|
|
|
|
"Test that the variable `for-items' isn't shadowed inside for loops."
|
|
|
|
|
(with-temp-eshell
|
|
|
|
|
(with-no-warnings (setq-local for-items "hello"))
|
|
|
|
|
(eshell-match-command-output "for i in 1 { echo $for-items }"
|
|
|
|
|
"hello\n")))
|
|
|
|
|
|
Fix reference-counting of Eshell I/O handles
This ensures that output targets in Eshell are only closed when Eshell
is actually done with them. In particular, this means that
"{ echo foo; echo bar } | rev" prints "raboof" as expected
(bug#59545).
* lisp/eshell/esh-io.el (eshell-create-handles): Structure the handles
differently so the targets and their ref-count can be shared.
(eshell-duplicate-handles): Reimplement this to share targets between
the original and new handle sets. Add STEAL-P argument.
(eshell-protect-handles, eshell-copy-output-handle)
(eshell-interactive-output-p, eshell-output-object): Account for
changes to the handle structure.
(eshell-close-handle): New function...
(eshell-close-handles, eshell-set-output-handle): ... use it.
(eshell-get-targets): Remove. This only existed to make the previous
implementation of 'eshell-duplicate-handles' work.
* lisp/eshell/esh-cmd.el (eshell-with-copied-handles): New argument
STEAL-P.
(eshell-do-pipelines): Use STEAL-P for the last item in the pipeline.
(eshell-parse-command): Don't copy handles for the last command in the
list; explain why we can't use STEAL-P here.
(eshell-eval-command): When queuing input, set 'eshell-command-body'
and 'eshell-test-body' for the 'if' conditional (see
'eshell-do-eval').
* test/lisp/eshell/esh-io-tests.el (esh-io-test/redirect-pipe): Split
into...
(esh-io-test/pipeline/default, esh-io-test/pipeline/all): ... these.
(esh-io-test/pipeline/subcommands): New test.
* test/lisp/eshell/esh-cmd-tests.el (esh-cmd-test/for-loop-pipe)
(esh-cmd-test/while-loop-pipe, esh-cmd-test/if-statement-pipe)
esh-cmd-test/if-else-statement-pipe): New tests.
(esh-cmd-test/while-loop): Use 'pop' to simplify the test a bit.
* test/lisp/eshell/eshell-test-helpers.el
(eshell-test--max-subprocess-time): Rename to...
(eshell-test--max-wait-time): ... this.
(eshell-wait-for): New function...
(eshell-wait-for-subprocess): ... use it.
* test/lisp/eshell/eshell-tests.el (eshell-test/queue-input): Fix this
test. Previously, it didn't correctly verify that the original
command completed.
* test/lisp/eshell/em-tramp-tests.el
(em-tramp-test/should-replace-command): New macro...
(em-tramp-test/su-default, em-tramp-test/su-user)
(em-tramp-test/su-login, em-tramp-test/sudo-shell)
(em-tramp-test/sudo-user-shell, em-tramp-test/doas-shell)
(em-tramp-test/doas-user-shell): ... use it.
2022-12-24 14:31:50 -08:00
|
|
|
|
(ert-deftest esh-cmd-test/for-loop-pipe ()
|
|
|
|
|
"Test invocation of a for loop piped to another command."
|
|
|
|
|
(skip-unless (executable-find "rev"))
|
|
|
|
|
(with-temp-eshell
|
|
|
|
|
(eshell-match-command-output "for i in foo bar baz { echo $i } | rev"
|
|
|
|
|
"zabraboof")))
|
|
|
|
|
|
Only set Eshell execution result metavariables when non-nil
This simplifies usage of 'eshell-close-handles' in several places and
makes it work more like the docstring indicated it would.
* lisp/eshell/esh-io.el (eshell-close-handles): Only store EXIT-CODE
and RESULT if they're non-nil. Also, use 'dotimes' and 'dolist' to
simplify the implementation.
* lisp/eshell/em-alias.el (eshell-write-aliases-list):
* lisp/eshell/esh-cmd.el (eshell-rewrite-for-command)
(eshell-structure-basic-command): Adapt calls to
'eshell-close-handles'.
* test/lisp/eshell/eshell-tests.el (eshell-test/simple-command-result)
(eshell-test/lisp-command, eshell-test/lisp-command-with-quote)
(eshell-test/for-loop, eshell-test/for-name-loop)
(eshell-test/for-name-shadow-loop, eshell-test/lisp-command-args)
(eshell-test/subcommand, eshell-test/subcommand-args)
(eshell-test/subcommand-lisp): Move from here...
* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/simple-command-result, esh-cmd-test/lisp-command)
(esh-cmd-test/lisp-command-with-quote, esh-cmd-test/for-loop)
(esh-cmd-test/for-name-loop, esh-cmd-test/for-name-shadow-loop)
(esh-cmd-test/lisp-command-args, esh-cmd-test/subcommand)
(esh-cmd-test/subcommand-args, esh-cmd-test/subcommand-lisp): ... to
here.
(esh-cmd-test/and-operator, esh-cmd-test/or-operator)
(esh-cmd-test/for-loop-list, esh-cmd-test/for-loop-multiple-args)
(esh-cmd-test/while-loop, esh-cmd-test/until-loop)
(esh-cmd-test/if-statement, esh-cmd-test/if-else-statement)
(esh-cmd-test/unless-statement, esh-cmd-test/unless-else-statement):
New tests.
* doc/misc/eshell.texi (Invocation): Explain '&&' and '||'.
(for loop): Move from here...
(Control Flow): ... to here, and add documentation for other control
flow forms.
2022-08-06 13:37:28 -07:00
|
|
|
|
(ert-deftest esh-cmd-test/while-loop ()
|
|
|
|
|
"Test invocation of a while loop."
|
2022-08-08 21:24:27 -07:00
|
|
|
|
(with-temp-eshell
|
|
|
|
|
(let ((eshell-test-value '(0 1 2)))
|
2022-08-13 20:31:11 -07:00
|
|
|
|
(eshell-match-command-output
|
2022-08-08 21:24:27 -07:00
|
|
|
|
(concat "while $eshell-test-value "
|
Fix reference-counting of Eshell I/O handles
This ensures that output targets in Eshell are only closed when Eshell
is actually done with them. In particular, this means that
"{ echo foo; echo bar } | rev" prints "raboof" as expected
(bug#59545).
* lisp/eshell/esh-io.el (eshell-create-handles): Structure the handles
differently so the targets and their ref-count can be shared.
(eshell-duplicate-handles): Reimplement this to share targets between
the original and new handle sets. Add STEAL-P argument.
(eshell-protect-handles, eshell-copy-output-handle)
(eshell-interactive-output-p, eshell-output-object): Account for
changes to the handle structure.
(eshell-close-handle): New function...
(eshell-close-handles, eshell-set-output-handle): ... use it.
(eshell-get-targets): Remove. This only existed to make the previous
implementation of 'eshell-duplicate-handles' work.
* lisp/eshell/esh-cmd.el (eshell-with-copied-handles): New argument
STEAL-P.
(eshell-do-pipelines): Use STEAL-P for the last item in the pipeline.
(eshell-parse-command): Don't copy handles for the last command in the
list; explain why we can't use STEAL-P here.
(eshell-eval-command): When queuing input, set 'eshell-command-body'
and 'eshell-test-body' for the 'if' conditional (see
'eshell-do-eval').
* test/lisp/eshell/esh-io-tests.el (esh-io-test/redirect-pipe): Split
into...
(esh-io-test/pipeline/default, esh-io-test/pipeline/all): ... these.
(esh-io-test/pipeline/subcommands): New test.
* test/lisp/eshell/esh-cmd-tests.el (esh-cmd-test/for-loop-pipe)
(esh-cmd-test/while-loop-pipe, esh-cmd-test/if-statement-pipe)
esh-cmd-test/if-else-statement-pipe): New tests.
(esh-cmd-test/while-loop): Use 'pop' to simplify the test a bit.
* test/lisp/eshell/eshell-test-helpers.el
(eshell-test--max-subprocess-time): Rename to...
(eshell-test--max-wait-time): ... this.
(eshell-wait-for): New function...
(eshell-wait-for-subprocess): ... use it.
* test/lisp/eshell/eshell-tests.el (eshell-test/queue-input): Fix this
test. Previously, it didn't correctly verify that the original
command completed.
* test/lisp/eshell/em-tramp-tests.el
(em-tramp-test/should-replace-command): New macro...
(em-tramp-test/su-default, em-tramp-test/su-user)
(em-tramp-test/su-login, em-tramp-test/sudo-shell)
(em-tramp-test/sudo-user-shell, em-tramp-test/doas-shell)
(em-tramp-test/doas-user-shell): ... use it.
2022-12-24 14:31:50 -08:00
|
|
|
|
"{ (pop eshell-test-value) }")
|
|
|
|
|
"0\n1\n2\n"))))
|
2022-08-08 21:24:27 -07:00
|
|
|
|
|
2022-08-09 20:09:57 -07:00
|
|
|
|
(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))
|
2022-08-13 20:31:11 -07:00
|
|
|
|
(eshell-match-command-output
|
2022-08-09 20:09:57 -07:00
|
|
|
|
(concat "while (/= eshell-test-value 3) "
|
|
|
|
|
"{ setq eshell-test-value (1+ eshell-test-value) }")
|
|
|
|
|
"1\n2\n3\n"))))
|
|
|
|
|
|
2022-08-08 21:24:27 -07:00
|
|
|
|
(ert-deftest esh-cmd-test/while-loop-ext-cmd ()
|
|
|
|
|
"Test invocation of a while loop using an external command."
|
Only set Eshell execution result metavariables when non-nil
This simplifies usage of 'eshell-close-handles' in several places and
makes it work more like the docstring indicated it would.
* lisp/eshell/esh-io.el (eshell-close-handles): Only store EXIT-CODE
and RESULT if they're non-nil. Also, use 'dotimes' and 'dolist' to
simplify the implementation.
* lisp/eshell/em-alias.el (eshell-write-aliases-list):
* lisp/eshell/esh-cmd.el (eshell-rewrite-for-command)
(eshell-structure-basic-command): Adapt calls to
'eshell-close-handles'.
* test/lisp/eshell/eshell-tests.el (eshell-test/simple-command-result)
(eshell-test/lisp-command, eshell-test/lisp-command-with-quote)
(eshell-test/for-loop, eshell-test/for-name-loop)
(eshell-test/for-name-shadow-loop, eshell-test/lisp-command-args)
(eshell-test/subcommand, eshell-test/subcommand-args)
(eshell-test/subcommand-lisp): Move from here...
* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/simple-command-result, esh-cmd-test/lisp-command)
(esh-cmd-test/lisp-command-with-quote, esh-cmd-test/for-loop)
(esh-cmd-test/for-name-loop, esh-cmd-test/for-name-shadow-loop)
(esh-cmd-test/lisp-command-args, esh-cmd-test/subcommand)
(esh-cmd-test/subcommand-args, esh-cmd-test/subcommand-lisp): ... to
here.
(esh-cmd-test/and-operator, esh-cmd-test/or-operator)
(esh-cmd-test/for-loop-list, esh-cmd-test/for-loop-multiple-args)
(esh-cmd-test/while-loop, esh-cmd-test/until-loop)
(esh-cmd-test/if-statement, esh-cmd-test/if-else-statement)
(esh-cmd-test/unless-statement, esh-cmd-test/unless-else-statement):
New tests.
* doc/misc/eshell.texi (Invocation): Explain '&&' and '||'.
(for loop): Move from here...
(Control Flow): ... to here, and add documentation for other control
flow forms.
2022-08-06 13:37:28 -07:00
|
|
|
|
(skip-unless (executable-find "["))
|
|
|
|
|
(with-temp-eshell
|
|
|
|
|
(let ((eshell-test-value 0))
|
2022-08-13 20:31:11 -07:00
|
|
|
|
(eshell-match-command-output
|
Only set Eshell execution result metavariables when non-nil
This simplifies usage of 'eshell-close-handles' in several places and
makes it work more like the docstring indicated it would.
* lisp/eshell/esh-io.el (eshell-close-handles): Only store EXIT-CODE
and RESULT if they're non-nil. Also, use 'dotimes' and 'dolist' to
simplify the implementation.
* lisp/eshell/em-alias.el (eshell-write-aliases-list):
* lisp/eshell/esh-cmd.el (eshell-rewrite-for-command)
(eshell-structure-basic-command): Adapt calls to
'eshell-close-handles'.
* test/lisp/eshell/eshell-tests.el (eshell-test/simple-command-result)
(eshell-test/lisp-command, eshell-test/lisp-command-with-quote)
(eshell-test/for-loop, eshell-test/for-name-loop)
(eshell-test/for-name-shadow-loop, eshell-test/lisp-command-args)
(eshell-test/subcommand, eshell-test/subcommand-args)
(eshell-test/subcommand-lisp): Move from here...
* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/simple-command-result, esh-cmd-test/lisp-command)
(esh-cmd-test/lisp-command-with-quote, esh-cmd-test/for-loop)
(esh-cmd-test/for-name-loop, esh-cmd-test/for-name-shadow-loop)
(esh-cmd-test/lisp-command-args, esh-cmd-test/subcommand)
(esh-cmd-test/subcommand-args, esh-cmd-test/subcommand-lisp): ... to
here.
(esh-cmd-test/and-operator, esh-cmd-test/or-operator)
(esh-cmd-test/for-loop-list, esh-cmd-test/for-loop-multiple-args)
(esh-cmd-test/while-loop, esh-cmd-test/until-loop)
(esh-cmd-test/if-statement, esh-cmd-test/if-else-statement)
(esh-cmd-test/unless-statement, esh-cmd-test/unless-else-statement):
New tests.
* doc/misc/eshell.texi (Invocation): Explain '&&' and '||'.
(for loop): Move from here...
(Control Flow): ... to here, and add documentation for other control
flow forms.
2022-08-06 13:37:28 -07:00
|
|
|
|
(concat "while {[ $eshell-test-value -ne 3 ]} "
|
|
|
|
|
"{ setq eshell-test-value (1+ eshell-test-value) }")
|
|
|
|
|
"1\n2\n3\n"))))
|
|
|
|
|
|
Fix reference-counting of Eshell I/O handles
This ensures that output targets in Eshell are only closed when Eshell
is actually done with them. In particular, this means that
"{ echo foo; echo bar } | rev" prints "raboof" as expected
(bug#59545).
* lisp/eshell/esh-io.el (eshell-create-handles): Structure the handles
differently so the targets and their ref-count can be shared.
(eshell-duplicate-handles): Reimplement this to share targets between
the original and new handle sets. Add STEAL-P argument.
(eshell-protect-handles, eshell-copy-output-handle)
(eshell-interactive-output-p, eshell-output-object): Account for
changes to the handle structure.
(eshell-close-handle): New function...
(eshell-close-handles, eshell-set-output-handle): ... use it.
(eshell-get-targets): Remove. This only existed to make the previous
implementation of 'eshell-duplicate-handles' work.
* lisp/eshell/esh-cmd.el (eshell-with-copied-handles): New argument
STEAL-P.
(eshell-do-pipelines): Use STEAL-P for the last item in the pipeline.
(eshell-parse-command): Don't copy handles for the last command in the
list; explain why we can't use STEAL-P here.
(eshell-eval-command): When queuing input, set 'eshell-command-body'
and 'eshell-test-body' for the 'if' conditional (see
'eshell-do-eval').
* test/lisp/eshell/esh-io-tests.el (esh-io-test/redirect-pipe): Split
into...
(esh-io-test/pipeline/default, esh-io-test/pipeline/all): ... these.
(esh-io-test/pipeline/subcommands): New test.
* test/lisp/eshell/esh-cmd-tests.el (esh-cmd-test/for-loop-pipe)
(esh-cmd-test/while-loop-pipe, esh-cmd-test/if-statement-pipe)
esh-cmd-test/if-else-statement-pipe): New tests.
(esh-cmd-test/while-loop): Use 'pop' to simplify the test a bit.
* test/lisp/eshell/eshell-test-helpers.el
(eshell-test--max-subprocess-time): Rename to...
(eshell-test--max-wait-time): ... this.
(eshell-wait-for): New function...
(eshell-wait-for-subprocess): ... use it.
* test/lisp/eshell/eshell-tests.el (eshell-test/queue-input): Fix this
test. Previously, it didn't correctly verify that the original
command completed.
* test/lisp/eshell/em-tramp-tests.el
(em-tramp-test/should-replace-command): New macro...
(em-tramp-test/su-default, em-tramp-test/su-user)
(em-tramp-test/su-login, em-tramp-test/sudo-shell)
(em-tramp-test/sudo-user-shell, em-tramp-test/doas-shell)
(em-tramp-test/doas-user-shell): ... use it.
2022-12-24 14:31:50 -08:00
|
|
|
|
(ert-deftest esh-cmd-test/while-loop-pipe ()
|
|
|
|
|
"Test invocation of a while loop piped to another command."
|
|
|
|
|
(skip-unless (executable-find "rev"))
|
|
|
|
|
(with-temp-eshell
|
|
|
|
|
(let ((eshell-test-value '("foo" "bar" "baz")))
|
|
|
|
|
(eshell-match-command-output
|
|
|
|
|
(concat "while $eshell-test-value "
|
|
|
|
|
"{ (pop eshell-test-value) }"
|
|
|
|
|
" | rev")
|
|
|
|
|
"zabraboof"))))
|
|
|
|
|
|
Only set Eshell execution result metavariables when non-nil
This simplifies usage of 'eshell-close-handles' in several places and
makes it work more like the docstring indicated it would.
* lisp/eshell/esh-io.el (eshell-close-handles): Only store EXIT-CODE
and RESULT if they're non-nil. Also, use 'dotimes' and 'dolist' to
simplify the implementation.
* lisp/eshell/em-alias.el (eshell-write-aliases-list):
* lisp/eshell/esh-cmd.el (eshell-rewrite-for-command)
(eshell-structure-basic-command): Adapt calls to
'eshell-close-handles'.
* test/lisp/eshell/eshell-tests.el (eshell-test/simple-command-result)
(eshell-test/lisp-command, eshell-test/lisp-command-with-quote)
(eshell-test/for-loop, eshell-test/for-name-loop)
(eshell-test/for-name-shadow-loop, eshell-test/lisp-command-args)
(eshell-test/subcommand, eshell-test/subcommand-args)
(eshell-test/subcommand-lisp): Move from here...
* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/simple-command-result, esh-cmd-test/lisp-command)
(esh-cmd-test/lisp-command-with-quote, esh-cmd-test/for-loop)
(esh-cmd-test/for-name-loop, esh-cmd-test/for-name-shadow-loop)
(esh-cmd-test/lisp-command-args, esh-cmd-test/subcommand)
(esh-cmd-test/subcommand-args, esh-cmd-test/subcommand-lisp): ... to
here.
(esh-cmd-test/and-operator, esh-cmd-test/or-operator)
(esh-cmd-test/for-loop-list, esh-cmd-test/for-loop-multiple-args)
(esh-cmd-test/while-loop, esh-cmd-test/until-loop)
(esh-cmd-test/if-statement, esh-cmd-test/if-else-statement)
(esh-cmd-test/unless-statement, esh-cmd-test/unless-else-statement):
New tests.
* doc/misc/eshell.texi (Invocation): Explain '&&' and '||'.
(for loop): Move from here...
(Control Flow): ... to here, and add documentation for other control
flow forms.
2022-08-06 13:37:28 -07:00
|
|
|
|
(ert-deftest esh-cmd-test/until-loop ()
|
|
|
|
|
"Test invocation of an until loop."
|
2022-08-08 21:24:27 -07:00
|
|
|
|
(with-temp-eshell
|
|
|
|
|
(let ((eshell-test-value nil))
|
2022-08-13 20:31:11 -07:00
|
|
|
|
(eshell-match-command-output
|
2022-08-08 21:24:27 -07:00
|
|
|
|
(concat "until $eshell-test-value "
|
|
|
|
|
"{ setq eshell-test-value t }")
|
|
|
|
|
"t\n"))))
|
|
|
|
|
|
2022-08-09 20:09:57 -07:00
|
|
|
|
(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))
|
2022-08-13 20:31:11 -07:00
|
|
|
|
(eshell-match-command-output
|
2022-08-09 20:09:57 -07:00
|
|
|
|
(concat "until (= eshell-test-value 3) "
|
|
|
|
|
"{ setq eshell-test-value (1+ eshell-test-value) }")
|
|
|
|
|
"1\n2\n3\n"))))
|
|
|
|
|
|
2022-08-08 21:24:27 -07:00
|
|
|
|
(ert-deftest esh-cmd-test/until-loop-ext-cmd ()
|
|
|
|
|
"Test invocation of an until loop using an external command."
|
Only set Eshell execution result metavariables when non-nil
This simplifies usage of 'eshell-close-handles' in several places and
makes it work more like the docstring indicated it would.
* lisp/eshell/esh-io.el (eshell-close-handles): Only store EXIT-CODE
and RESULT if they're non-nil. Also, use 'dotimes' and 'dolist' to
simplify the implementation.
* lisp/eshell/em-alias.el (eshell-write-aliases-list):
* lisp/eshell/esh-cmd.el (eshell-rewrite-for-command)
(eshell-structure-basic-command): Adapt calls to
'eshell-close-handles'.
* test/lisp/eshell/eshell-tests.el (eshell-test/simple-command-result)
(eshell-test/lisp-command, eshell-test/lisp-command-with-quote)
(eshell-test/for-loop, eshell-test/for-name-loop)
(eshell-test/for-name-shadow-loop, eshell-test/lisp-command-args)
(eshell-test/subcommand, eshell-test/subcommand-args)
(eshell-test/subcommand-lisp): Move from here...
* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/simple-command-result, esh-cmd-test/lisp-command)
(esh-cmd-test/lisp-command-with-quote, esh-cmd-test/for-loop)
(esh-cmd-test/for-name-loop, esh-cmd-test/for-name-shadow-loop)
(esh-cmd-test/lisp-command-args, esh-cmd-test/subcommand)
(esh-cmd-test/subcommand-args, esh-cmd-test/subcommand-lisp): ... to
here.
(esh-cmd-test/and-operator, esh-cmd-test/or-operator)
(esh-cmd-test/for-loop-list, esh-cmd-test/for-loop-multiple-args)
(esh-cmd-test/while-loop, esh-cmd-test/until-loop)
(esh-cmd-test/if-statement, esh-cmd-test/if-else-statement)
(esh-cmd-test/unless-statement, esh-cmd-test/unless-else-statement):
New tests.
* doc/misc/eshell.texi (Invocation): Explain '&&' and '||'.
(for loop): Move from here...
(Control Flow): ... to here, and add documentation for other control
flow forms.
2022-08-06 13:37:28 -07:00
|
|
|
|
(skip-unless (executable-find "["))
|
|
|
|
|
(with-temp-eshell
|
|
|
|
|
(let ((eshell-test-value 0))
|
2022-08-13 20:31:11 -07:00
|
|
|
|
(eshell-match-command-output
|
Only set Eshell execution result metavariables when non-nil
This simplifies usage of 'eshell-close-handles' in several places and
makes it work more like the docstring indicated it would.
* lisp/eshell/esh-io.el (eshell-close-handles): Only store EXIT-CODE
and RESULT if they're non-nil. Also, use 'dotimes' and 'dolist' to
simplify the implementation.
* lisp/eshell/em-alias.el (eshell-write-aliases-list):
* lisp/eshell/esh-cmd.el (eshell-rewrite-for-command)
(eshell-structure-basic-command): Adapt calls to
'eshell-close-handles'.
* test/lisp/eshell/eshell-tests.el (eshell-test/simple-command-result)
(eshell-test/lisp-command, eshell-test/lisp-command-with-quote)
(eshell-test/for-loop, eshell-test/for-name-loop)
(eshell-test/for-name-shadow-loop, eshell-test/lisp-command-args)
(eshell-test/subcommand, eshell-test/subcommand-args)
(eshell-test/subcommand-lisp): Move from here...
* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/simple-command-result, esh-cmd-test/lisp-command)
(esh-cmd-test/lisp-command-with-quote, esh-cmd-test/for-loop)
(esh-cmd-test/for-name-loop, esh-cmd-test/for-name-shadow-loop)
(esh-cmd-test/lisp-command-args, esh-cmd-test/subcommand)
(esh-cmd-test/subcommand-args, esh-cmd-test/subcommand-lisp): ... to
here.
(esh-cmd-test/and-operator, esh-cmd-test/or-operator)
(esh-cmd-test/for-loop-list, esh-cmd-test/for-loop-multiple-args)
(esh-cmd-test/while-loop, esh-cmd-test/until-loop)
(esh-cmd-test/if-statement, esh-cmd-test/if-else-statement)
(esh-cmd-test/unless-statement, esh-cmd-test/unless-else-statement):
New tests.
* doc/misc/eshell.texi (Invocation): Explain '&&' and '||'.
(for loop): Move from here...
(Control Flow): ... to here, and add documentation for other control
flow forms.
2022-08-06 13:37:28 -07:00
|
|
|
|
(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."
|
2022-08-14 13:48:22 -07:00
|
|
|
|
(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)))
|
Only set Eshell execution result metavariables when non-nil
This simplifies usage of 'eshell-close-handles' in several places and
makes it work more like the docstring indicated it would.
* lisp/eshell/esh-io.el (eshell-close-handles): Only store EXIT-CODE
and RESULT if they're non-nil. Also, use 'dotimes' and 'dolist' to
simplify the implementation.
* lisp/eshell/em-alias.el (eshell-write-aliases-list):
* lisp/eshell/esh-cmd.el (eshell-rewrite-for-command)
(eshell-structure-basic-command): Adapt calls to
'eshell-close-handles'.
* test/lisp/eshell/eshell-tests.el (eshell-test/simple-command-result)
(eshell-test/lisp-command, eshell-test/lisp-command-with-quote)
(eshell-test/for-loop, eshell-test/for-name-loop)
(eshell-test/for-name-shadow-loop, eshell-test/lisp-command-args)
(eshell-test/subcommand, eshell-test/subcommand-args)
(eshell-test/subcommand-lisp): Move from here...
* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/simple-command-result, esh-cmd-test/lisp-command)
(esh-cmd-test/lisp-command-with-quote, esh-cmd-test/for-loop)
(esh-cmd-test/for-name-loop, esh-cmd-test/for-name-shadow-loop)
(esh-cmd-test/lisp-command-args, esh-cmd-test/subcommand)
(esh-cmd-test/subcommand-args, esh-cmd-test/subcommand-lisp): ... to
here.
(esh-cmd-test/and-operator, esh-cmd-test/or-operator)
(esh-cmd-test/for-loop-list, esh-cmd-test/for-loop-multiple-args)
(esh-cmd-test/while-loop, esh-cmd-test/until-loop)
(esh-cmd-test/if-statement, esh-cmd-test/if-else-statement)
(esh-cmd-test/unless-statement, esh-cmd-test/unless-else-statement):
New tests.
* doc/misc/eshell.texi (Invocation): Explain '&&' and '||'.
(for loop): Move from here...
(Control Flow): ... to here, and add documentation for other control
flow forms.
2022-08-06 13:37:28 -07:00
|
|
|
|
|
|
|
|
|
(ert-deftest esh-cmd-test/if-else-statement ()
|
|
|
|
|
"Test invocation of an if/else statement."
|
2022-08-14 13:48:22 -07:00
|
|
|
|
(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")))
|
2022-08-08 21:24:27 -07:00
|
|
|
|
|
2022-08-09 20:09:57 -07:00
|
|
|
|
(ert-deftest esh-cmd-test/if-else-statement-lisp-form ()
|
|
|
|
|
"Test invocation of an if/else statement using a Lisp form."
|
2022-08-14 13:48:22 -07:00
|
|
|
|
(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")))
|
2022-08-09 20:09:57 -07:00
|
|
|
|
|
|
|
|
|
(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))
|
2022-08-14 13:48:22 -07:00
|
|
|
|
(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"))))
|
2022-08-09 20:09:57 -07:00
|
|
|
|
|
2022-08-08 21:24:27 -07:00
|
|
|
|
(ert-deftest esh-cmd-test/if-else-statement-ext-cmd ()
|
|
|
|
|
"Test invocation of an if/else statement using an external command."
|
Only set Eshell execution result metavariables when non-nil
This simplifies usage of 'eshell-close-handles' in several places and
makes it work more like the docstring indicated it would.
* lisp/eshell/esh-io.el (eshell-close-handles): Only store EXIT-CODE
and RESULT if they're non-nil. Also, use 'dotimes' and 'dolist' to
simplify the implementation.
* lisp/eshell/em-alias.el (eshell-write-aliases-list):
* lisp/eshell/esh-cmd.el (eshell-rewrite-for-command)
(eshell-structure-basic-command): Adapt calls to
'eshell-close-handles'.
* test/lisp/eshell/eshell-tests.el (eshell-test/simple-command-result)
(eshell-test/lisp-command, eshell-test/lisp-command-with-quote)
(eshell-test/for-loop, eshell-test/for-name-loop)
(eshell-test/for-name-shadow-loop, eshell-test/lisp-command-args)
(eshell-test/subcommand, eshell-test/subcommand-args)
(eshell-test/subcommand-lisp): Move from here...
* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/simple-command-result, esh-cmd-test/lisp-command)
(esh-cmd-test/lisp-command-with-quote, esh-cmd-test/for-loop)
(esh-cmd-test/for-name-loop, esh-cmd-test/for-name-shadow-loop)
(esh-cmd-test/lisp-command-args, esh-cmd-test/subcommand)
(esh-cmd-test/subcommand-args, esh-cmd-test/subcommand-lisp): ... to
here.
(esh-cmd-test/and-operator, esh-cmd-test/or-operator)
(esh-cmd-test/for-loop-list, esh-cmd-test/for-loop-multiple-args)
(esh-cmd-test/while-loop, esh-cmd-test/until-loop)
(esh-cmd-test/if-statement, esh-cmd-test/if-else-statement)
(esh-cmd-test/unless-statement, esh-cmd-test/unless-else-statement):
New tests.
* doc/misc/eshell.texi (Invocation): Explain '&&' and '||'.
(for loop): Move from here...
(Control Flow): ... to here, and add documentation for other control
flow forms.
2022-08-06 13:37:28 -07:00
|
|
|
|
(skip-unless (executable-find "["))
|
2022-08-14 13:48:22 -07:00
|
|
|
|
(eshell-command-result-equal "if {[ foo = foo ]} {echo yes} {echo no}"
|
|
|
|
|
"yes")
|
|
|
|
|
(eshell-command-result-equal "if {[ foo = bar ]} {echo yes} {echo no}"
|
|
|
|
|
"no"))
|
Only set Eshell execution result metavariables when non-nil
This simplifies usage of 'eshell-close-handles' in several places and
makes it work more like the docstring indicated it would.
* lisp/eshell/esh-io.el (eshell-close-handles): Only store EXIT-CODE
and RESULT if they're non-nil. Also, use 'dotimes' and 'dolist' to
simplify the implementation.
* lisp/eshell/em-alias.el (eshell-write-aliases-list):
* lisp/eshell/esh-cmd.el (eshell-rewrite-for-command)
(eshell-structure-basic-command): Adapt calls to
'eshell-close-handles'.
* test/lisp/eshell/eshell-tests.el (eshell-test/simple-command-result)
(eshell-test/lisp-command, eshell-test/lisp-command-with-quote)
(eshell-test/for-loop, eshell-test/for-name-loop)
(eshell-test/for-name-shadow-loop, eshell-test/lisp-command-args)
(eshell-test/subcommand, eshell-test/subcommand-args)
(eshell-test/subcommand-lisp): Move from here...
* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/simple-command-result, esh-cmd-test/lisp-command)
(esh-cmd-test/lisp-command-with-quote, esh-cmd-test/for-loop)
(esh-cmd-test/for-name-loop, esh-cmd-test/for-name-shadow-loop)
(esh-cmd-test/lisp-command-args, esh-cmd-test/subcommand)
(esh-cmd-test/subcommand-args, esh-cmd-test/subcommand-lisp): ... to
here.
(esh-cmd-test/and-operator, esh-cmd-test/or-operator)
(esh-cmd-test/for-loop-list, esh-cmd-test/for-loop-multiple-args)
(esh-cmd-test/while-loop, esh-cmd-test/until-loop)
(esh-cmd-test/if-statement, esh-cmd-test/if-else-statement)
(esh-cmd-test/unless-statement, esh-cmd-test/unless-else-statement):
New tests.
* doc/misc/eshell.texi (Invocation): Explain '&&' and '||'.
(for loop): Move from here...
(Control Flow): ... to here, and add documentation for other control
flow forms.
2022-08-06 13:37:28 -07:00
|
|
|
|
|
Fix reference-counting of Eshell I/O handles
This ensures that output targets in Eshell are only closed when Eshell
is actually done with them. In particular, this means that
"{ echo foo; echo bar } | rev" prints "raboof" as expected
(bug#59545).
* lisp/eshell/esh-io.el (eshell-create-handles): Structure the handles
differently so the targets and their ref-count can be shared.
(eshell-duplicate-handles): Reimplement this to share targets between
the original and new handle sets. Add STEAL-P argument.
(eshell-protect-handles, eshell-copy-output-handle)
(eshell-interactive-output-p, eshell-output-object): Account for
changes to the handle structure.
(eshell-close-handle): New function...
(eshell-close-handles, eshell-set-output-handle): ... use it.
(eshell-get-targets): Remove. This only existed to make the previous
implementation of 'eshell-duplicate-handles' work.
* lisp/eshell/esh-cmd.el (eshell-with-copied-handles): New argument
STEAL-P.
(eshell-do-pipelines): Use STEAL-P for the last item in the pipeline.
(eshell-parse-command): Don't copy handles for the last command in the
list; explain why we can't use STEAL-P here.
(eshell-eval-command): When queuing input, set 'eshell-command-body'
and 'eshell-test-body' for the 'if' conditional (see
'eshell-do-eval').
* test/lisp/eshell/esh-io-tests.el (esh-io-test/redirect-pipe): Split
into...
(esh-io-test/pipeline/default, esh-io-test/pipeline/all): ... these.
(esh-io-test/pipeline/subcommands): New test.
* test/lisp/eshell/esh-cmd-tests.el (esh-cmd-test/for-loop-pipe)
(esh-cmd-test/while-loop-pipe, esh-cmd-test/if-statement-pipe)
esh-cmd-test/if-else-statement-pipe): New tests.
(esh-cmd-test/while-loop): Use 'pop' to simplify the test a bit.
* test/lisp/eshell/eshell-test-helpers.el
(eshell-test--max-subprocess-time): Rename to...
(eshell-test--max-wait-time): ... this.
(eshell-wait-for): New function...
(eshell-wait-for-subprocess): ... use it.
* test/lisp/eshell/eshell-tests.el (eshell-test/queue-input): Fix this
test. Previously, it didn't correctly verify that the original
command completed.
* test/lisp/eshell/em-tramp-tests.el
(em-tramp-test/should-replace-command): New macro...
(em-tramp-test/su-default, em-tramp-test/su-user)
(em-tramp-test/su-login, em-tramp-test/sudo-shell)
(em-tramp-test/sudo-user-shell, em-tramp-test/doas-shell)
(em-tramp-test/doas-user-shell): ... use it.
2022-12-24 14:31:50 -08:00
|
|
|
|
(ert-deftest esh-cmd-test/if-statement-pipe ()
|
|
|
|
|
"Test invocation of an if statement piped to another command."
|
|
|
|
|
(skip-unless (executable-find "rev"))
|
2022-12-30 10:40:08 -08:00
|
|
|
|
(with-temp-eshell
|
|
|
|
|
(let ((eshell-test-value t))
|
|
|
|
|
(eshell-match-command-output "if $eshell-test-value {echo yes} | rev"
|
|
|
|
|
"\\`sey\n?"))
|
|
|
|
|
(let ((eshell-test-value nil))
|
|
|
|
|
(eshell-match-command-output "if $eshell-test-value {echo yes} | rev"
|
|
|
|
|
"\\`\n?"))))
|
Fix reference-counting of Eshell I/O handles
This ensures that output targets in Eshell are only closed when Eshell
is actually done with them. In particular, this means that
"{ echo foo; echo bar } | rev" prints "raboof" as expected
(bug#59545).
* lisp/eshell/esh-io.el (eshell-create-handles): Structure the handles
differently so the targets and their ref-count can be shared.
(eshell-duplicate-handles): Reimplement this to share targets between
the original and new handle sets. Add STEAL-P argument.
(eshell-protect-handles, eshell-copy-output-handle)
(eshell-interactive-output-p, eshell-output-object): Account for
changes to the handle structure.
(eshell-close-handle): New function...
(eshell-close-handles, eshell-set-output-handle): ... use it.
(eshell-get-targets): Remove. This only existed to make the previous
implementation of 'eshell-duplicate-handles' work.
* lisp/eshell/esh-cmd.el (eshell-with-copied-handles): New argument
STEAL-P.
(eshell-do-pipelines): Use STEAL-P for the last item in the pipeline.
(eshell-parse-command): Don't copy handles for the last command in the
list; explain why we can't use STEAL-P here.
(eshell-eval-command): When queuing input, set 'eshell-command-body'
and 'eshell-test-body' for the 'if' conditional (see
'eshell-do-eval').
* test/lisp/eshell/esh-io-tests.el (esh-io-test/redirect-pipe): Split
into...
(esh-io-test/pipeline/default, esh-io-test/pipeline/all): ... these.
(esh-io-test/pipeline/subcommands): New test.
* test/lisp/eshell/esh-cmd-tests.el (esh-cmd-test/for-loop-pipe)
(esh-cmd-test/while-loop-pipe, esh-cmd-test/if-statement-pipe)
esh-cmd-test/if-else-statement-pipe): New tests.
(esh-cmd-test/while-loop): Use 'pop' to simplify the test a bit.
* test/lisp/eshell/eshell-test-helpers.el
(eshell-test--max-subprocess-time): Rename to...
(eshell-test--max-wait-time): ... this.
(eshell-wait-for): New function...
(eshell-wait-for-subprocess): ... use it.
* test/lisp/eshell/eshell-tests.el (eshell-test/queue-input): Fix this
test. Previously, it didn't correctly verify that the original
command completed.
* test/lisp/eshell/em-tramp-tests.el
(em-tramp-test/should-replace-command): New macro...
(em-tramp-test/su-default, em-tramp-test/su-user)
(em-tramp-test/su-login, em-tramp-test/sudo-shell)
(em-tramp-test/sudo-user-shell, em-tramp-test/doas-shell)
(em-tramp-test/doas-user-shell): ... use it.
2022-12-24 14:31:50 -08:00
|
|
|
|
|
|
|
|
|
(ert-deftest esh-cmd-test/if-else-statement-pipe ()
|
|
|
|
|
"Test invocation of an if/else statement piped to another command."
|
|
|
|
|
(skip-unless (executable-find "rev"))
|
2022-12-30 10:40:08 -08:00
|
|
|
|
(with-temp-eshell
|
|
|
|
|
(let ((eshell-test-value t))
|
|
|
|
|
(eshell-match-command-output
|
|
|
|
|
"if $eshell-test-value {echo yes} {echo no} | rev"
|
|
|
|
|
"\\`sey\n?"))
|
|
|
|
|
(let ((eshell-test-value nil))
|
|
|
|
|
(eshell-match-command-output
|
|
|
|
|
"if $eshell-test-value {echo yes} {echo no} | rev"
|
|
|
|
|
"\\`on\n?"))))
|
Fix reference-counting of Eshell I/O handles
This ensures that output targets in Eshell are only closed when Eshell
is actually done with them. In particular, this means that
"{ echo foo; echo bar } | rev" prints "raboof" as expected
(bug#59545).
* lisp/eshell/esh-io.el (eshell-create-handles): Structure the handles
differently so the targets and their ref-count can be shared.
(eshell-duplicate-handles): Reimplement this to share targets between
the original and new handle sets. Add STEAL-P argument.
(eshell-protect-handles, eshell-copy-output-handle)
(eshell-interactive-output-p, eshell-output-object): Account for
changes to the handle structure.
(eshell-close-handle): New function...
(eshell-close-handles, eshell-set-output-handle): ... use it.
(eshell-get-targets): Remove. This only existed to make the previous
implementation of 'eshell-duplicate-handles' work.
* lisp/eshell/esh-cmd.el (eshell-with-copied-handles): New argument
STEAL-P.
(eshell-do-pipelines): Use STEAL-P for the last item in the pipeline.
(eshell-parse-command): Don't copy handles for the last command in the
list; explain why we can't use STEAL-P here.
(eshell-eval-command): When queuing input, set 'eshell-command-body'
and 'eshell-test-body' for the 'if' conditional (see
'eshell-do-eval').
* test/lisp/eshell/esh-io-tests.el (esh-io-test/redirect-pipe): Split
into...
(esh-io-test/pipeline/default, esh-io-test/pipeline/all): ... these.
(esh-io-test/pipeline/subcommands): New test.
* test/lisp/eshell/esh-cmd-tests.el (esh-cmd-test/for-loop-pipe)
(esh-cmd-test/while-loop-pipe, esh-cmd-test/if-statement-pipe)
esh-cmd-test/if-else-statement-pipe): New tests.
(esh-cmd-test/while-loop): Use 'pop' to simplify the test a bit.
* test/lisp/eshell/eshell-test-helpers.el
(eshell-test--max-subprocess-time): Rename to...
(eshell-test--max-wait-time): ... this.
(eshell-wait-for): New function...
(eshell-wait-for-subprocess): ... use it.
* test/lisp/eshell/eshell-tests.el (eshell-test/queue-input): Fix this
test. Previously, it didn't correctly verify that the original
command completed.
* test/lisp/eshell/em-tramp-tests.el
(em-tramp-test/should-replace-command): New macro...
(em-tramp-test/su-default, em-tramp-test/su-user)
(em-tramp-test/su-login, em-tramp-test/sudo-shell)
(em-tramp-test/sudo-user-shell, em-tramp-test/doas-shell)
(em-tramp-test/doas-user-shell): ... use it.
2022-12-24 14:31:50 -08:00
|
|
|
|
|
Only set Eshell execution result metavariables when non-nil
This simplifies usage of 'eshell-close-handles' in several places and
makes it work more like the docstring indicated it would.
* lisp/eshell/esh-io.el (eshell-close-handles): Only store EXIT-CODE
and RESULT if they're non-nil. Also, use 'dotimes' and 'dolist' to
simplify the implementation.
* lisp/eshell/em-alias.el (eshell-write-aliases-list):
* lisp/eshell/esh-cmd.el (eshell-rewrite-for-command)
(eshell-structure-basic-command): Adapt calls to
'eshell-close-handles'.
* test/lisp/eshell/eshell-tests.el (eshell-test/simple-command-result)
(eshell-test/lisp-command, eshell-test/lisp-command-with-quote)
(eshell-test/for-loop, eshell-test/for-name-loop)
(eshell-test/for-name-shadow-loop, eshell-test/lisp-command-args)
(eshell-test/subcommand, eshell-test/subcommand-args)
(eshell-test/subcommand-lisp): Move from here...
* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/simple-command-result, esh-cmd-test/lisp-command)
(esh-cmd-test/lisp-command-with-quote, esh-cmd-test/for-loop)
(esh-cmd-test/for-name-loop, esh-cmd-test/for-name-shadow-loop)
(esh-cmd-test/lisp-command-args, esh-cmd-test/subcommand)
(esh-cmd-test/subcommand-args, esh-cmd-test/subcommand-lisp): ... to
here.
(esh-cmd-test/and-operator, esh-cmd-test/or-operator)
(esh-cmd-test/for-loop-list, esh-cmd-test/for-loop-multiple-args)
(esh-cmd-test/while-loop, esh-cmd-test/until-loop)
(esh-cmd-test/if-statement, esh-cmd-test/if-else-statement)
(esh-cmd-test/unless-statement, esh-cmd-test/unless-else-statement):
New tests.
* doc/misc/eshell.texi (Invocation): Explain '&&' and '||'.
(for loop): Move from here...
(Control Flow): ... to here, and add documentation for other control
flow forms.
2022-08-06 13:37:28 -07:00
|
|
|
|
(ert-deftest esh-cmd-test/unless-statement ()
|
|
|
|
|
"Test invocation of an unless statement."
|
2022-08-14 13:48:22 -07:00
|
|
|
|
(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")))
|
Only set Eshell execution result metavariables when non-nil
This simplifies usage of 'eshell-close-handles' in several places and
makes it work more like the docstring indicated it would.
* lisp/eshell/esh-io.el (eshell-close-handles): Only store EXIT-CODE
and RESULT if they're non-nil. Also, use 'dotimes' and 'dolist' to
simplify the implementation.
* lisp/eshell/em-alias.el (eshell-write-aliases-list):
* lisp/eshell/esh-cmd.el (eshell-rewrite-for-command)
(eshell-structure-basic-command): Adapt calls to
'eshell-close-handles'.
* test/lisp/eshell/eshell-tests.el (eshell-test/simple-command-result)
(eshell-test/lisp-command, eshell-test/lisp-command-with-quote)
(eshell-test/for-loop, eshell-test/for-name-loop)
(eshell-test/for-name-shadow-loop, eshell-test/lisp-command-args)
(eshell-test/subcommand, eshell-test/subcommand-args)
(eshell-test/subcommand-lisp): Move from here...
* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/simple-command-result, esh-cmd-test/lisp-command)
(esh-cmd-test/lisp-command-with-quote, esh-cmd-test/for-loop)
(esh-cmd-test/for-name-loop, esh-cmd-test/for-name-shadow-loop)
(esh-cmd-test/lisp-command-args, esh-cmd-test/subcommand)
(esh-cmd-test/subcommand-args, esh-cmd-test/subcommand-lisp): ... to
here.
(esh-cmd-test/and-operator, esh-cmd-test/or-operator)
(esh-cmd-test/for-loop-list, esh-cmd-test/for-loop-multiple-args)
(esh-cmd-test/while-loop, esh-cmd-test/until-loop)
(esh-cmd-test/if-statement, esh-cmd-test/if-else-statement)
(esh-cmd-test/unless-statement, esh-cmd-test/unless-else-statement):
New tests.
* doc/misc/eshell.texi (Invocation): Explain '&&' and '||'.
(for loop): Move from here...
(Control Flow): ... to here, and add documentation for other control
flow forms.
2022-08-06 13:37:28 -07:00
|
|
|
|
|
|
|
|
|
(ert-deftest esh-cmd-test/unless-else-statement ()
|
|
|
|
|
"Test invocation of an unless/else statement."
|
2022-08-14 13:48:22 -07:00
|
|
|
|
(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")))
|
2022-08-08 21:24:27 -07:00
|
|
|
|
|
2022-08-09 20:09:57 -07:00
|
|
|
|
(ert-deftest esh-cmd-test/unless-else-statement-lisp-form ()
|
|
|
|
|
"Test invocation of an unless/else statement using a Lisp form."
|
2022-08-14 13:48:22 -07:00
|
|
|
|
(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")))
|
2022-08-09 20:09:57 -07:00
|
|
|
|
|
2022-08-08 21:24:27 -07:00
|
|
|
|
(ert-deftest esh-cmd-test/unless-else-statement-ext-cmd ()
|
|
|
|
|
"Test invocation of an unless/else statement using an external command."
|
Only set Eshell execution result metavariables when non-nil
This simplifies usage of 'eshell-close-handles' in several places and
makes it work more like the docstring indicated it would.
* lisp/eshell/esh-io.el (eshell-close-handles): Only store EXIT-CODE
and RESULT if they're non-nil. Also, use 'dotimes' and 'dolist' to
simplify the implementation.
* lisp/eshell/em-alias.el (eshell-write-aliases-list):
* lisp/eshell/esh-cmd.el (eshell-rewrite-for-command)
(eshell-structure-basic-command): Adapt calls to
'eshell-close-handles'.
* test/lisp/eshell/eshell-tests.el (eshell-test/simple-command-result)
(eshell-test/lisp-command, eshell-test/lisp-command-with-quote)
(eshell-test/for-loop, eshell-test/for-name-loop)
(eshell-test/for-name-shadow-loop, eshell-test/lisp-command-args)
(eshell-test/subcommand, eshell-test/subcommand-args)
(eshell-test/subcommand-lisp): Move from here...
* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/simple-command-result, esh-cmd-test/lisp-command)
(esh-cmd-test/lisp-command-with-quote, esh-cmd-test/for-loop)
(esh-cmd-test/for-name-loop, esh-cmd-test/for-name-shadow-loop)
(esh-cmd-test/lisp-command-args, esh-cmd-test/subcommand)
(esh-cmd-test/subcommand-args, esh-cmd-test/subcommand-lisp): ... to
here.
(esh-cmd-test/and-operator, esh-cmd-test/or-operator)
(esh-cmd-test/for-loop-list, esh-cmd-test/for-loop-multiple-args)
(esh-cmd-test/while-loop, esh-cmd-test/until-loop)
(esh-cmd-test/if-statement, esh-cmd-test/if-else-statement)
(esh-cmd-test/unless-statement, esh-cmd-test/unless-else-statement):
New tests.
* doc/misc/eshell.texi (Invocation): Explain '&&' and '||'.
(for loop): Move from here...
(Control Flow): ... to here, and add documentation for other control
flow forms.
2022-08-06 13:37:28 -07:00
|
|
|
|
(skip-unless (executable-find "["))
|
2022-08-14 13:48:22 -07:00
|
|
|
|
(eshell-command-result-equal "unless {[ foo = foo ]} {echo no} {echo yes}"
|
|
|
|
|
"yes")
|
|
|
|
|
(eshell-command-result-equal "unless {[ foo = bar ]} {echo no} {echo yes}"
|
|
|
|
|
"no"))
|
Only set Eshell execution result metavariables when non-nil
This simplifies usage of 'eshell-close-handles' in several places and
makes it work more like the docstring indicated it would.
* lisp/eshell/esh-io.el (eshell-close-handles): Only store EXIT-CODE
and RESULT if they're non-nil. Also, use 'dotimes' and 'dolist' to
simplify the implementation.
* lisp/eshell/em-alias.el (eshell-write-aliases-list):
* lisp/eshell/esh-cmd.el (eshell-rewrite-for-command)
(eshell-structure-basic-command): Adapt calls to
'eshell-close-handles'.
* test/lisp/eshell/eshell-tests.el (eshell-test/simple-command-result)
(eshell-test/lisp-command, eshell-test/lisp-command-with-quote)
(eshell-test/for-loop, eshell-test/for-name-loop)
(eshell-test/for-name-shadow-loop, eshell-test/lisp-command-args)
(eshell-test/subcommand, eshell-test/subcommand-args)
(eshell-test/subcommand-lisp): Move from here...
* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/simple-command-result, esh-cmd-test/lisp-command)
(esh-cmd-test/lisp-command-with-quote, esh-cmd-test/for-loop)
(esh-cmd-test/for-name-loop, esh-cmd-test/for-name-shadow-loop)
(esh-cmd-test/lisp-command-args, esh-cmd-test/subcommand)
(esh-cmd-test/subcommand-args, esh-cmd-test/subcommand-lisp): ... to
here.
(esh-cmd-test/and-operator, esh-cmd-test/or-operator)
(esh-cmd-test/for-loop-list, esh-cmd-test/for-loop-multiple-args)
(esh-cmd-test/while-loop, esh-cmd-test/until-loop)
(esh-cmd-test/if-statement, esh-cmd-test/if-else-statement)
(esh-cmd-test/unless-statement, esh-cmd-test/unless-else-statement):
New tests.
* doc/misc/eshell.texi (Invocation): Explain '&&' and '||'.
(for loop): Move from here...
(Control Flow): ... to here, and add documentation for other control
flow forms.
2022-08-06 13:37:28 -07:00
|
|
|
|
|
2024-01-26 10:17:19 -08:00
|
|
|
|
|
|
|
|
|
;; Direct invocation
|
|
|
|
|
|
|
|
|
|
(defmacro esh-cmd-test--deftest-invoke-directly (name command expected)
|
2024-01-26 11:56:47 -08:00
|
|
|
|
"Test `eshell-invoke-directly-p' returns EXPECTED for COMMAND.
|
|
|
|
|
NAME is the name of the test case."
|
2024-01-26 10:17:19 -08:00
|
|
|
|
(declare (indent 2))
|
|
|
|
|
`(ert-deftest ,(intern (concat "esh-cmd-test/invoke-directly/"
|
2024-01-26 10:26:57 -08:00
|
|
|
|
(symbol-name name)))
|
|
|
|
|
()
|
2024-01-26 10:17:19 -08:00
|
|
|
|
(with-temp-eshell
|
2024-01-26 10:26:57 -08:00
|
|
|
|
(should (equal (eshell-invoke-directly-p
|
2024-01-26 10:17:19 -08:00
|
|
|
|
(eshell-parse-command ,command nil t))
|
|
|
|
|
,expected)))))
|
|
|
|
|
|
|
|
|
|
(esh-cmd-test--deftest-invoke-directly no-args "echo" t)
|
|
|
|
|
(esh-cmd-test--deftest-invoke-directly with-args "echo hi" t)
|
|
|
|
|
(esh-cmd-test--deftest-invoke-directly multiple-cmds "echo hi; echo bye" nil)
|
|
|
|
|
(esh-cmd-test--deftest-invoke-directly subcmd "echo ${echo hi}" t)
|
|
|
|
|
(esh-cmd-test--deftest-invoke-directly complex "ls ." nil)
|
|
|
|
|
(esh-cmd-test--deftest-invoke-directly complex-subcmd "echo {ls .}" nil)
|
|
|
|
|
|
2023-09-22 18:22:34 -07:00
|
|
|
|
|
|
|
|
|
;; Error handling
|
|
|
|
|
|
2024-06-09 13:17:53 -07:00
|
|
|
|
(ert-deftest esh-cmd-test/empty-background-command ()
|
|
|
|
|
"Test that Eshell reports an error when trying to background a nil command."
|
2024-06-10 22:17:35 +02:00
|
|
|
|
(let ((text-quoting-style 'grave))
|
|
|
|
|
(with-temp-eshell
|
|
|
|
|
(eshell-match-command-output "echo hi & &"
|
|
|
|
|
"\\`Empty command before `&'\n")
|
|
|
|
|
;; Make sure the next Eshell prompt has the original input so the
|
|
|
|
|
;; user can fix it.
|
|
|
|
|
(should (equal (buffer-substring eshell-last-output-end (point))
|
|
|
|
|
"echo hi & &")))))
|
2024-06-09 13:17:53 -07:00
|
|
|
|
|
2023-09-22 18:22:34 -07:00
|
|
|
|
(ert-deftest esh-cmd-test/throw ()
|
|
|
|
|
"Test that calling `throw' as an Eshell command unwinds everything properly."
|
|
|
|
|
(with-temp-eshell
|
|
|
|
|
(should (= (catch 'tag
|
|
|
|
|
(eshell-insert-command
|
|
|
|
|
"echo hi; (throw 'tag 42); echo bye"))
|
|
|
|
|
42))
|
|
|
|
|
(should (eshell-match-output "\\`hi\n\\'"))
|
2023-09-23 11:36:11 -07:00
|
|
|
|
(should-not eshell-foreground-command)
|
2023-09-22 18:22:34 -07:00
|
|
|
|
;; Make sure we can call another command after throwing.
|
|
|
|
|
(eshell-match-command-output "echo again" "\\`again\n")))
|
|
|
|
|
|
2024-05-29 19:21:09 -07:00
|
|
|
|
|
|
|
|
|
;; `which' command
|
|
|
|
|
|
|
|
|
|
(ert-deftest esh-cmd-test/which/plain/eshell-builtin ()
|
|
|
|
|
"Check that `which' finds Eshell built-in functions."
|
|
|
|
|
(eshell-command-result-match "which cat" "\\`eshell/cat"))
|
|
|
|
|
|
|
|
|
|
(ert-deftest esh-cmd-test/which/plain/external-program ()
|
|
|
|
|
"Check that `which' finds external programs."
|
|
|
|
|
(skip-unless (executable-find "sh"))
|
2024-06-15 16:59:11 -07:00
|
|
|
|
(ert-info (#'eshell-get-debug-logs :prefix "Command logs: ")
|
|
|
|
|
(let ((actual (eshell-test-command-result "which sh"))
|
|
|
|
|
(expected (concat (executable-find "sh") "\n")))
|
|
|
|
|
;; Eshell handles the casing of the PATH differently from
|
|
|
|
|
;; `executable-find'. This means that the results may not match
|
|
|
|
|
;; exactly on case-insensitive file systems (e.g. when using
|
|
|
|
|
;; MS-Windows), so compare case-insensitively there.
|
|
|
|
|
(should (if (file-name-case-insensitive-p actual)
|
|
|
|
|
(string-equal-ignore-case actual expected)
|
|
|
|
|
(string-equal actual expected))))))
|
2024-05-29 19:21:09 -07:00
|
|
|
|
|
|
|
|
|
(ert-deftest esh-cmd-test/which/plain/not-found ()
|
|
|
|
|
"Check that `which' reports an error for not-found commands."
|
|
|
|
|
(skip-when (executable-find "nonexist"))
|
|
|
|
|
(eshell-command-result-match "which nonexist" "\\`which: no nonexist in"))
|
|
|
|
|
|
|
|
|
|
(ert-deftest esh-cmd-test/which/alias ()
|
|
|
|
|
"Check that `which' finds aliases."
|
|
|
|
|
(with-temp-eshell
|
|
|
|
|
(eshell-insert-command "alias cat '*cat $@*'")
|
|
|
|
|
(eshell-match-command-output "which cat" "\\`cat is an alias")))
|
|
|
|
|
|
|
|
|
|
(ert-deftest esh-cmd-test/which/explicit ()
|
|
|
|
|
"Check that `which' finds explicitly-external programs."
|
|
|
|
|
(skip-unless (executable-find "cat"))
|
|
|
|
|
(eshell-command-result-match "which *cat"
|
|
|
|
|
(concat (executable-find "cat") "\n")))
|
|
|
|
|
|
|
|
|
|
(ert-deftest esh-cmd-test/which/explicit/not-found ()
|
|
|
|
|
"Check that `which' reports an error for not-found explicit commands."
|
|
|
|
|
(skip-when (executable-find "nonexist"))
|
|
|
|
|
(eshell-command-result-match "which *nonexist" "\\`which: no nonexist in"))
|
|
|
|
|
|
|
|
|
|
(ert-deftest esh-cmd-test/which/quoted-file ()
|
|
|
|
|
"Check that `which' finds programs with quoted file names."
|
|
|
|
|
(skip-unless (executable-find "cat"))
|
|
|
|
|
(eshell-command-result-match "which /:cat"
|
|
|
|
|
(concat (executable-find "cat") "\n")))
|
|
|
|
|
|
|
|
|
|
(ert-deftest esh-cmd-test/which/quoted-file/not-found ()
|
|
|
|
|
"Check that `which' reports an error for not-found quoted commands."
|
|
|
|
|
(skip-when (executable-find "nonexist"))
|
|
|
|
|
(eshell-command-result-match "which /:nonexist" "\\`which: no nonexist in"))
|
|
|
|
|
|
Only set Eshell execution result metavariables when non-nil
This simplifies usage of 'eshell-close-handles' in several places and
makes it work more like the docstring indicated it would.
* lisp/eshell/esh-io.el (eshell-close-handles): Only store EXIT-CODE
and RESULT if they're non-nil. Also, use 'dotimes' and 'dolist' to
simplify the implementation.
* lisp/eshell/em-alias.el (eshell-write-aliases-list):
* lisp/eshell/esh-cmd.el (eshell-rewrite-for-command)
(eshell-structure-basic-command): Adapt calls to
'eshell-close-handles'.
* test/lisp/eshell/eshell-tests.el (eshell-test/simple-command-result)
(eshell-test/lisp-command, eshell-test/lisp-command-with-quote)
(eshell-test/for-loop, eshell-test/for-name-loop)
(eshell-test/for-name-shadow-loop, eshell-test/lisp-command-args)
(eshell-test/subcommand, eshell-test/subcommand-args)
(eshell-test/subcommand-lisp): Move from here...
* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/simple-command-result, esh-cmd-test/lisp-command)
(esh-cmd-test/lisp-command-with-quote, esh-cmd-test/for-loop)
(esh-cmd-test/for-name-loop, esh-cmd-test/for-name-shadow-loop)
(esh-cmd-test/lisp-command-args, esh-cmd-test/subcommand)
(esh-cmd-test/subcommand-args, esh-cmd-test/subcommand-lisp): ... to
here.
(esh-cmd-test/and-operator, esh-cmd-test/or-operator)
(esh-cmd-test/for-loop-list, esh-cmd-test/for-loop-multiple-args)
(esh-cmd-test/while-loop, esh-cmd-test/until-loop)
(esh-cmd-test/if-statement, esh-cmd-test/if-else-statement)
(esh-cmd-test/unless-statement, esh-cmd-test/unless-else-statement):
New tests.
* doc/misc/eshell.texi (Invocation): Explain '&&' and '||'.
(for loop): Move from here...
(Control Flow): ... to here, and add documentation for other control
flow forms.
2022-08-06 13:37:28 -07:00
|
|
|
|
;; esh-cmd-tests.el ends here
|