emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 1be925faa1 1/5: Simplify Eshell handle functions and add tests/do


From: Jim Porter
Subject: master 1be925faa1 1/5: Simplify Eshell handle functions and add tests/documentation
Date: Sun, 4 Sep 2022 19:04:13 -0400 (EDT)

branch: master
commit 1be925faa1065af5754fc11914b56ae98dfb2a83
Author: Jim Porter <jporterbugs@gmail.com>
Commit: Jim Porter <jporterbugs@gmail.com>

    Simplify Eshell handle functions and add tests/documentation
    
    * lisp/eshell/esh-arg.el (eshell-parse-argument-hook): Explain how to
    use 'eshell-finish-arg'.
    
    * lisp/eshell/esh-io.el (eshell-create-handles): Only call
    'eshell-get-target' for stderr if necessary.
    (eshell-protect-handles): Use 'dotimes'.
    (eshell-set-output-handle): Pass HANDLES and fix an edge case with
    setting a duplicate TARGET.
    
    * test/lisp/eshell/eshell-tests-helpers.el (eshell-with-temp-buffer):
    New macro.
    
    * test/lisp/eshell/esh-cmd-tests.el (esh-cmd-test/quoted-lisp-form)
    (esh-cmd-test/backquoted-lisp-form)
    (esh-cmd-test/backquoted-lisp-form/splice): New tests.
    
    * test/lisp/eshell/eshell-tests.el (eshell-test/redirect-buffer)
    (eshell-test/redirect-buffer-escaped): Move to...
    * test/lisp/eshell/esh-io-tests.el: ... here, and add other I/O tests.
    
    * doc/misc/eshell.texi (Arguments): Add documentation for special
    argument types.
    (Input/Output): Expand documentation for redirection and pipelines.
---
 doc/misc/eshell.texi                     | 160 ++++++++++++++++++----
 lisp/eshell/esh-arg.el                   |   4 +
 lisp/eshell/esh-io.el                    |  55 ++++----
 test/lisp/eshell/esh-cmd-tests.el        |  19 +++
 test/lisp/eshell/esh-io-tests.el         | 220 +++++++++++++++++++++++++++++++
 test/lisp/eshell/eshell-tests-helpers.el |  10 ++
 test/lisp/eshell/eshell-tests.el         |  19 ---
 7 files changed, 413 insertions(+), 74 deletions(-)

diff --git a/doc/misc/eshell.texi b/doc/misc/eshell.texi
index 13f13163dd..0c98d2860e 100644
--- a/doc/misc/eshell.texi
+++ b/doc/misc/eshell.texi
@@ -256,7 +256,6 @@ as an argument will ``spread'' the elements into multiple 
arguments:
 @end example
 
 @subsection Quoting and escaping
-
 As with other shells, you can escape special characters and spaces
 with by prefixing the character with a backslash (@code{\}), or by
 surrounding the string with apostrophes (@code{''}) or double quotes
@@ -268,6 +267,40 @@ When using expansions (@pxref{Expansion}) in an Eshell 
command, the
 result may potentially be of any data type.  To ensure that the result
 is always a string, the expansion can be surrounded by double quotes.
 
+@subsection Special argument types
+In addition to strings and numbers, Eshell supports a number of
+special argument types.  These let you refer to various other Emacs
+Lisp data types, such as lists or buffers.
+
+@table @code
+
+@item #'@var{lisp-form}
+This refers to the quoted Emacs Lisp form @var{lisp-form}.  Though
+this looks similar to the ``sharp quote'' syntax for functions
+(@pxref{Special Read Syntax, , , elisp, The Emacs Lisp Reference
+Manual}), it instead corresponds to @code{quote} and can be used for
+any quoted form.@footnote{Eshell would interpret a bare apostrophe
+(@code{'}) as the start of a single-quoted string.}
+
+@item `@var{lisp-form}
+This refers to the backquoted Emacs Lisp form @var{lisp-form}
+(@pxref{Backquote, , , elisp, The Emacs Lisp Reference Manual}).  As
+in Emacs Lisp, you can use @samp{,} and @samp{,@@} to refer to
+non-constant values.
+
+@item #<buffer @var{name}>
+@itemx #<@var{name}>
+Return the buffer named @var{name}.  This is equivalent to
+@samp{$(get-buffer-create "@var{name}")} (@pxref{Creating Buffers, , ,
+elisp, The Emacs Lisp Reference Manual}).
+
+@item #<process @var{name}>
+Return the process named @var{name}.  This is equivalent to
+@samp{$(get-process "@var{name}")}  (@pxref{Process Information, , ,
+elisp, The Emacs Lisp Reference Manual}).
+
+@end table
+
 @node Built-ins
 @section Built-in commands
 Several commands are built-in in Eshell.  In order to call the
@@ -1560,6 +1593,13 @@ Reverses the order of a list of values.
 Since Eshell does not communicate with a terminal like most command
 shells, IO is a little different.
 
+@menu
+* Visual Commands::
+* Redirection::
+* Pipelines::
+@end menu
+
+@node Visual Commands
 @section Visual Commands
 If you try to run programs from within Eshell that are not
 line-oriented, such as programs that use ncurses, you will just get
@@ -1592,40 +1632,104 @@ program exits, customize the variable
 @code{eshell-destroy-buffer-when-process-dies} to a non-@code{nil}
 value; the default is @code{nil}.
 
+@node Redirection
 @section Redirection
-Redirection is mostly the same in Eshell as it is in other command
-shells.  The output redirection operators @code{>} and @code{>>} as
-well as pipes are supported, but there is not yet any support for
-input redirection.  Output can also be redirected to buffers, using
-the @code{>>>} redirection operator, and Elisp functions, using
-virtual devices.
-
-The buffer redirection operator, @code{>>>}, expects a buffer object
-on the right-hand side, into which it inserts the output of the
-left-hand side.  e.g., @samp{echo hello >>> #<buffer *scratch*>}
-inserts the string @code{"hello"} into the @file{*scratch*} buffer.
-The convenience shorthand variant @samp{#<@var{buffer-name}>}, as in
-@samp{#<*scratch*>}, is also accepted.
-
-@code{eshell-virtual-targets} is a list of mappings of virtual device
-names to functions.  Eshell comes with two virtual devices:
-@file{/dev/kill}, which sends the text to the kill ring, and
-@file{/dev/clip}, which sends text to the clipboard.
+Redirection in Eshell is similar to that of other command shells.  You
+can use the output redirection operators @code{>} and @code{>>}, but
+there is not yet any support for input redirection.  In the cases
+below, @var{fd} specifies the file descriptor to redirect; if not
+specified, file descriptor 1 (standard output) will be used by
+default.
+
+@table @code
+
+@item > @var{dest}
+@itemx @var{fd}> @var{dest}
+Redirect output to @var{dest}, overwriting its contents with the new
+output.
+
+@item >> @var{dest}
+@itemx @var{fd}>> @var{dest}
+Redirect output to @var{dest}, appending it to the existing contents
+of @var{dest}.
+
+@item >>> @var{buffer}
+@itemx @var{fd}>>> @var{buffer}
+Redirect output to @var{dest}, inserting it at the current mark if
+@var{dest} is a buffer, at the beginning of the file if @var{dest} is
+a file, or otherwise behaving the same as @code{>>}.
+
+@end table
+
+Eshell supports redirecting output to several different types of
+targets:
+
+@itemize @bullet
+
+@item
+files, including virtual targets (see below);
 
+@item
+buffers (@pxref{Buffers, , , elisp, GNU Emacs Lisp Reference Manual});
+
+@item
+markers (@pxref{Markers, , , elisp, GNU Emacs Lisp Reference Manual});
+
+@item
+processes (@pxref{Processes, , , elisp, GNU Emacs Lisp Reference
+Manual}); and
+
+@item
+symbols (@pxref{Symbols, , , elisp, GNU Emacs Lisp Reference Manual}).
+
+@end itemize
+
+@subsection Virtual Targets
+Virtual targets are mapping of device names to functions.  Eshell
+comes with four virtual devices:
+
+@table @file
+
+@item /dev/null
+Does nothing with the output passed to it.
+
+@item /dev/eshell
+Writes the text passed to it to the display.
+
+@item /dev/kill
+Adds the text passed to it to the kill ring.
+
+@item /dev/clip
+Adds the text passed to it to the clipboard.
+
+@end table
+
+@vindex eshell-virtual-targets
 You can, of course, define your own virtual targets.  They are defined
-by adding a list of the form @samp{("/dev/name" @var{function} @var{mode})} to
-@code{eshell-virtual-targets}.  The first element is the device name;
-@var{function} may be either a lambda or a function name.  If
-@var{mode} is @code{nil}, then the function is the output function; if it is
-non-@code{nil}, then the function is passed the redirection mode as a
-symbol--@code{overwrite} for @code{>}, @code{append} for @code{>>}, or
-@code{insert} for @code{>>>}--and the function is expected to return
-the output function.
+by adding a list of the form @samp{("/dev/name" @var{function}
+@var{mode})} to @code{eshell-virtual-targets}.  The first element is
+the device name; @var{function} may be either a lambda or a function
+name.  If @var{mode} is @code{nil}, then the function is the output
+function; if it is non-@code{nil}, then the function is passed the
+redirection mode as a symbol--@code{overwrite} for @code{>},
+@code{append} for @code{>>}, or @code{insert} for @code{>>>}--and the
+function is expected to return the output function.
 
 The output function is called once on each line of output until
 @code{nil} is passed, indicating end of output.
 
-@section Running Shell Pipelines Natively
+@node Pipelines
+@section Pipelines
+As with most other shells, Eshell supports pipelines to pass the
+output of one command the input of the next command.  You can pipe
+commands to each other using the @code{|} operator.  For example,
+
+@example
+~ $ echo hello | rev
+olleh
+@end example
+
+@subsection Running Shell Pipelines Natively
 When constructing shell pipelines that will move a lot of data, it is
 a good idea to bypass Eshell's own pipelining support and use the
 operating system shell's instead.  This is especially relevant when
diff --git a/lisp/eshell/esh-arg.el b/lisp/eshell/esh-arg.el
index 8e44a88459..50fb7f5fdc 100644
--- a/lisp/eshell/esh-arg.el
+++ b/lisp/eshell/esh-arg.el
@@ -147,6 +147,10 @@ return the result of the parse as a sexp.  It is also 
responsible for
 moving the point forward to reflect the amount of input text that was
 parsed.
 
+If the hook determines that it has reached the end of an argument, it
+should call `eshell-finish-arg' to complete processing of the current
+argument and proceed to the next.
+
 If no function handles the current character at point, it will be
 treated as a literal character."
   :type 'hook
diff --git a/lisp/eshell/esh-io.el b/lisp/eshell/esh-io.el
index d54be55c13..f5dac2c81c 100644
--- a/lisp/eshell/esh-io.el
+++ b/lisp/eshell/esh-io.el
@@ -236,22 +236,21 @@ The default location for standard output and standard 
error will go to
 STDOUT and STDERR, respectively.
 OUTPUT-MODE and ERROR-MODE are either `overwrite', `append' or `insert';
 a nil value of mode defaults to `insert'."
-  (let ((handles (make-vector eshell-number-of-handles nil))
-       (output-target (eshell-get-target stdout output-mode))
-        (error-target (eshell-get-target stderr error-mode)))
+  (let* ((handles (make-vector eshell-number-of-handles nil))
+         (output-target (eshell-get-target stdout output-mode))
+         (error-target (if stderr
+                           (eshell-get-target stderr error-mode)
+                         output-target)))
     (aset handles eshell-output-handle (cons output-target 1))
-    (aset handles eshell-error-handle
-          (cons (if stderr error-target output-target) 1))
+    (aset handles eshell-error-handle (cons error-target 1))
     handles))
 
 (defun eshell-protect-handles (handles)
   "Protect the handles in HANDLES from a being closed."
-  (let ((idx 0))
-    (while (< idx eshell-number-of-handles)
-      (if (aref handles idx)
-         (setcdr (aref handles idx)
-                 (1+ (cdr (aref handles idx)))))
-      (setq idx (1+ idx))))
+  (dotimes (idx eshell-number-of-handles)
+    (when (aref handles idx)
+      (setcdr (aref handles idx)
+              (1+ (cdr (aref handles idx))))))
   handles)
 
 (defun eshell-close-handles (&optional exit-code result handles)
@@ -278,6 +277,24 @@ the value already set in `eshell-last-command-result'."
             (eshell-close-target target (= eshell-last-command-status 0)))
           (setcar handle nil))))))
 
+(defun eshell-set-output-handle (index mode &optional target handles)
+  "Set handle INDEX for the current HANDLES to point to TARGET using MODE.
+If HANDLES is nil, use `eshell-current-handles'."
+  (when target
+    (let ((handles (or handles eshell-current-handles)))
+      (if (and (stringp target)
+               (string= target (null-device)))
+          (aset handles index nil)
+        (let ((where (eshell-get-target target mode))
+              (current (car (aref handles index))))
+          (if (listp current)
+              (unless (member where current)
+                (setq current (append current (list where))))
+            (setq current (list where)))
+          (if (not (aref handles index))
+              (aset handles index (cons nil 1)))
+          (setcar (aref handles index) current))))))
+
 (defun eshell-close-target (target status)
   "Close an output TARGET, passing STATUS as the result.
 STATUS should be non-nil on successful termination of the output."
@@ -390,22 +407,6 @@ it defaults to `insert'."
     (error "Invalid redirection target: %s"
           (eshell-stringify target)))))
 
-(defun eshell-set-output-handle (index mode &optional target)
-  "Set handle INDEX, using MODE, to point to TARGET."
-  (when target
-    (if (and (stringp target)
-             (string= target (null-device)))
-       (aset eshell-current-handles index nil)
-      (let ((where (eshell-get-target target mode))
-           (current (car (aref eshell-current-handles index))))
-       (if (and (listp current)
-                (not (member where current)))
-           (setq current (append current (list where)))
-         (setq current (list where)))
-       (if (not (aref eshell-current-handles index))
-           (aset eshell-current-handles index (cons nil 1)))
-       (setcar (aref eshell-current-handles index) current)))))
-
 (defun eshell-interactive-output-p ()
   "Return non-nil if current handles are bound for interactive display."
   (and (eq (car (aref eshell-current-handles
diff --git a/test/lisp/eshell/esh-cmd-tests.el 
b/test/lisp/eshell/esh-cmd-tests.el
index 3a582965d6..92d785d7fd 100644
--- a/test/lisp/eshell/esh-cmd-tests.el
+++ b/test/lisp/eshell/esh-cmd-tests.el
@@ -74,6 +74,25 @@ e.g. \"{(+ 1 2)} 3\" => 3"
   (eshell-command-result-equal "{(+ 1 2)} 3" 3))
 
 
+;; Lisp forms
+
+(ert-deftest esh-cmd-test/quoted-lisp-form ()
+  "Test parsing of a quoted Lisp form."
+  (eshell-command-result-equal "echo #'(1 2)" '(1 2)))
+
+(ert-deftest esh-cmd-test/backquoted-lisp-form ()
+  "Test parsing of a backquoted Lisp form."
+  (let ((eshell-test-value 42))
+    (eshell-command-result-equal "echo `(answer ,eshell-test-value)"
+                                 '(answer 42))))
+
+(ert-deftest esh-cmd-test/backquoted-lisp-form/splice ()
+  "Test parsing of a backquoted Lisp form using splicing."
+  (let ((eshell-test-value '(2 3)))
+    (eshell-command-result-equal "echo `(1 ,@eshell-test-value)"
+                                 '(1 2 3))))
+
+
 ;; Logical operators
 
 (ert-deftest esh-cmd-test/and-operator ()
diff --git a/test/lisp/eshell/esh-io-tests.el b/test/lisp/eshell/esh-io-tests.el
new file mode 100644
index 0000000000..6cd2dff1c1
--- /dev/null
+++ b/test/lisp/eshell/esh-io-tests.el
@@ -0,0 +1,220 @@
+;;; esh-io-tests.el --- esh-io test suite  -*- lexical-binding:t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'ert-x)
+(require 'esh-mode)
+(require 'eshell)
+
+(require 'eshell-tests-helpers
+         (expand-file-name "eshell-tests-helpers"
+                           (file-name-directory (or load-file-name
+                                                    default-directory))))
+
+(defvar eshell-test-value nil)
+
+(defun eshell-test-file-string (file)
+  "Return the contents of FILE as a string."
+  (with-temp-buffer
+    (insert-file-contents file)
+    (buffer-string)))
+
+(defun eshell/test-output ()
+  "Write some test output separately to stdout and stderr."
+  (eshell-printn "stdout")
+  (eshell-errorn "stderr"))
+
+;;; Tests:
+
+
+;; Basic redirection
+
+(ert-deftest esh-io-test/redirect-file/overwrite ()
+  "Check that redirecting to a file in overwrite mode works."
+  (ert-with-temp-file temp-file
+    :text "old"
+    (with-temp-eshell
+     (eshell-insert-command (format "echo new > %s" temp-file)))
+    (should (equal (eshell-test-file-string temp-file) "new"))))
+
+(ert-deftest esh-io-test/redirect-file/append ()
+  "Check that redirecting to a file in append mode works."
+  (ert-with-temp-file temp-file
+    :text "old"
+    (with-temp-eshell
+     (eshell-insert-command (format "echo new >> %s" temp-file)))
+    (should (equal (eshell-test-file-string temp-file) "oldnew"))))
+
+(ert-deftest esh-io-test/redirect-file/insert ()
+  "Check that redirecting to a file in insert works."
+  (ert-with-temp-file temp-file
+    :text "old"
+    (with-temp-eshell
+     (eshell-insert-command (format "echo new >>> %s" temp-file)))
+    (should (equal (eshell-test-file-string temp-file) "newold"))))
+
+(ert-deftest esh-io-test/redirect-buffer/overwrite ()
+  "Check that redirecting to a buffer in overwrite mode works."
+  (eshell-with-temp-buffer bufname "old"
+    (with-temp-eshell
+     (eshell-insert-command (format "echo new > #<%s>" bufname)))
+    (should (equal (buffer-string) "new"))))
+
+(ert-deftest esh-io-test/redirect-buffer/append ()
+  "Check that redirecting to a buffer in append mode works."
+  (eshell-with-temp-buffer bufname "old"
+    (with-temp-eshell
+     (eshell-insert-command (format "echo new >> #<%s>" bufname)))
+    (should (equal (buffer-string) "oldnew"))))
+
+(ert-deftest esh-io-test/redirect-buffer/insert ()
+  "Check that redirecting to a buffer in insert mode works."
+  (eshell-with-temp-buffer bufname "old"
+    (goto-char (point-min))
+    (with-temp-eshell
+     (eshell-insert-command (format "echo new >>> #<%s>" bufname)))
+    (should (equal (buffer-string) "newold"))))
+
+(ert-deftest esh-io-test/redirect-buffer/escaped ()
+  "Check that redirecting to a buffer with escaped characters works."
+  (with-temp-buffer
+    (rename-buffer "eshell\\temp\\buffer" t)
+    (let ((bufname (buffer-name)))
+      (with-temp-eshell
+       (eshell-insert-command (format "echo hi > #<%s>"
+                                      (string-replace "\\" "\\\\" bufname))))
+      (should (equal (buffer-string) "hi")))))
+
+(ert-deftest esh-io-test/redirect-symbol/overwrite ()
+  "Check that redirecting to a symbol in overwrite mode works."
+  (let ((eshell-test-value "old"))
+    (with-temp-eshell
+     (eshell-insert-command "echo new > #'eshell-test-value"))
+    (should (equal eshell-test-value "new"))))
+
+(ert-deftest esh-io-test/redirect-symbol/append ()
+  "Check that redirecting to a symbol in append mode works."
+  (let ((eshell-test-value "old"))
+    (with-temp-eshell
+     (eshell-insert-command "echo new >> #'eshell-test-value"))
+    (should (equal eshell-test-value "oldnew"))))
+
+(ert-deftest esh-io-test/redirect-marker ()
+  "Check that redirecting to a marker works."
+  (with-temp-buffer
+    (let ((eshell-test-value (point-marker)))
+      (with-temp-eshell
+       (eshell-insert-command "echo hi > $eshell-test-value"))
+      (should (equal (buffer-string) "hi")))))
+
+(ert-deftest esh-io-test/redirect-multiple ()
+  "Check that redirecting to multiple targets works."
+  (let ((eshell-test-value "old"))
+    (eshell-with-temp-buffer bufname "old"
+     (with-temp-eshell
+      (eshell-insert-command (format "echo new > #<%s> > #'eshell-test-value"
+                                     bufname)))
+     (should (equal (buffer-string) "new"))
+     (should (equal eshell-test-value "new")))))
+
+(ert-deftest esh-io-test/redirect-multiple/repeat ()
+  "Check that redirecting to multiple targets works when repeating a target."
+  (let ((eshell-test-value "old"))
+    (eshell-with-temp-buffer bufname "old"
+     (with-temp-eshell
+      (eshell-insert-command
+       (format "echo new > #<%s> > #'eshell-test-value > #<%s>"
+               bufname bufname)))
+     (should (equal (buffer-string) "new"))
+     (should (equal eshell-test-value "new")))))
+
+
+;; Redirecting specific handles
+
+(ert-deftest esh-io-test/redirect-stdout ()
+  "Check that redirecting to stdout doesn't redirect stderr."
+  (eshell-with-temp-buffer bufname "old"
+    (with-temp-eshell
+     (eshell-match-command-output (format "test-output > #<%s>" bufname)
+                                  "stderr\n"))
+    (should (equal (buffer-string) "stdout\n")))
+  ;; Also check explicitly specifying the stdout fd.
+  (eshell-with-temp-buffer bufname "old"
+    (with-temp-eshell
+     (eshell-match-command-output (format "test-output 1> #<%s>" bufname)
+                                  "stderr\n"))
+    (should (equal (buffer-string) "stdout\n"))))
+
+(ert-deftest esh-io-test/redirect-stderr/overwrite ()
+  "Check that redirecting to stderr doesn't redirect stdout."
+  (eshell-with-temp-buffer bufname "old"
+    (with-temp-eshell
+     (eshell-match-command-output (format "test-output 2> #<%s>" bufname)
+                                  "stdout\n"))
+    (should (equal (buffer-string) "stderr\n"))))
+
+(ert-deftest esh-io-test/redirect-stderr/append ()
+  "Check that redirecting to stderr doesn't redirect stdout."
+  (eshell-with-temp-buffer bufname "old"
+    (with-temp-eshell
+     (eshell-match-command-output (format "test-output 2>> #<%s>" bufname)
+                                  "stdout\n"))
+    (should (equal (buffer-string) "oldstderr\n"))))
+
+(ert-deftest esh-io-test/redirect-stderr/insert ()
+  "Check that redirecting to stderr doesn't redirect stdout."
+  (eshell-with-temp-buffer bufname "old"
+    (goto-char (point-min))
+    (with-temp-eshell
+     (eshell-match-command-output (format "test-output 2>>> #<%s>" bufname)
+                                  "stdout\n"))
+    (should (equal (buffer-string) "stderr\nold"))))
+
+(ert-deftest esh-io-test/redirect-stdout-and-stderr ()
+  "Check that redirecting to both stdout and stderr works."
+  (eshell-with-temp-buffer bufname-1 "old"
+    (eshell-with-temp-buffer bufname-2 "old"
+      (with-temp-eshell
+       (eshell-match-command-output (format "test-output > #<%s> 2> #<%s>"
+                                            bufname-1 bufname-2)
+                                    "\\`\\'"))
+      (should (equal (buffer-string) "stderr\n")))
+    (should (equal (buffer-string) "stdout\n"))))
+
+
+;; Virtual targets
+
+(ert-deftest esh-io-test/virtual-dev-eshell ()
+  "Check that redirecting to /dev/eshell works."
+  (with-temp-eshell
+   (eshell-match-command-output "echo hi > /dev/eshell" "hi")))
+
+(ert-deftest esh-io-test/virtual-dev-kill ()
+  "Check that redirecting to /dev/kill works."
+  (with-temp-eshell
+   (eshell-insert-command "echo one > /dev/kill")
+   (should (equal (car kill-ring) "one"))
+   (eshell-insert-command "echo two > /dev/kill")
+   (should (equal (car kill-ring) "two"))
+   (eshell-insert-command "echo three >> /dev/kill")
+   (should (equal (car kill-ring) "twothree"))))
+
+;;; esh-io-tests.el ends here
diff --git a/test/lisp/eshell/eshell-tests-helpers.el 
b/test/lisp/eshell/eshell-tests-helpers.el
index 8f0f993447..73abfcbb55 100644
--- a/test/lisp/eshell/eshell-tests-helpers.el
+++ b/test/lisp/eshell/eshell-tests-helpers.el
@@ -51,6 +51,16 @@ See `eshell-wait-for-subprocess'.")
            (let (kill-buffer-query-functions)
              (kill-buffer eshell-buffer)))))))
 
+(defmacro eshell-with-temp-buffer (bufname text &rest body)
+  "Create a temporary buffer containing TEXT and evaluate BODY there.
+BUFNAME will be set to the name of the temporary buffer."
+  (declare (indent 2))
+  `(with-temp-buffer
+     (insert ,text)
+     (rename-buffer "eshell-temp-buffer" t)
+     (let ((,bufname (buffer-name)))
+       ,@body)))
+
 (defun eshell-wait-for-subprocess (&optional all)
   "Wait until there is no interactive subprocess running in Eshell.
 If ALL is non-nil, wait until there are no Eshell subprocesses at
diff --git a/test/lisp/eshell/eshell-tests.el b/test/lisp/eshell/eshell-tests.el
index 1845dba280..d5112146c2 100644
--- a/test/lisp/eshell/eshell-tests.el
+++ b/test/lisp/eshell/eshell-tests.el
@@ -105,25 +105,6 @@
      (format template "format \"%s\" eshell-in-pipeline-p")
      "nil")))
 
-(ert-deftest eshell-test/redirect-buffer ()
-  "Check that piping to a buffer works"
-  (with-temp-buffer
-    (rename-buffer "eshell-temp-buffer" t)
-    (let ((bufname (buffer-name)))
-      (with-temp-eshell
-       (eshell-insert-command (format "echo hi > #<%s>" bufname)))
-      (should (equal (buffer-string) "hi")))))
-
-(ert-deftest eshell-test/redirect-buffer-escaped ()
-  "Check that piping to a buffer with escaped characters works"
-  (with-temp-buffer
-    (rename-buffer "eshell\\temp\\buffer" t)
-    (let ((bufname (buffer-name)))
-      (with-temp-eshell
-       (eshell-insert-command (format "echo hi > #<%s>"
-                                      (string-replace "\\" "\\\\" bufname))))
-      (should (equal (buffer-string) "hi")))))
-
 (ert-deftest eshell-test/escape-nonspecial ()
   "Test that \"\\c\" and \"c\" are equivalent when \"c\" is not a
 special character."



reply via email to

[Prev in Thread] Current Thread [Next in Thread]