* lisp/eshell/esh-cmd.el (eshell-rewrite-for-command): Fix last change.
[bpt/emacs.git] / lisp / eshell / esh-cmd.el
index ed335ab..52c8c2d 100644 (file)
@@ -1,7 +1,6 @@
 ;;; esh-cmd.el --- command invocation
 
 ;;; esh-cmd.el --- command invocation
 
-;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
-;;   2008, 2009, 2010  Free Software Foundation, Inc.
+;; Copyright (C) 1999-2011  Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@gnu.org>
 
 
 ;; Author: John Wiegley <johnw@gnu.org>
 
@@ -122,28 +121,28 @@ however."
   :group 'eshell)
 
 (defcustom eshell-prefer-lisp-functions nil
   :group 'eshell)
 
 (defcustom eshell-prefer-lisp-functions nil
-  "*If non-nil, prefer Lisp functions to external commands."
+  "If non-nil, prefer Lisp functions to external commands."
   :type 'boolean
   :group 'eshell-cmd)
 
 (defcustom eshell-lisp-regexp "\\([(`]\\|#'\\)"
   :type 'boolean
   :group 'eshell-cmd)
 
 (defcustom eshell-lisp-regexp "\\([(`]\\|#'\\)"
-  "*A regexp which, if matched at beginning of an argument, means Lisp.
+  "A regexp which, if matched at beginning of an argument, means Lisp.
 Such arguments will be passed to `read', and then evaluated."
   :type 'regexp
   :group 'eshell-cmd)
 
 (defcustom eshell-pre-command-hook nil
 Such arguments will be passed to `read', and then evaluated."
   :type 'regexp
   :group 'eshell-cmd)
 
 (defcustom eshell-pre-command-hook nil
-  "*A hook run before each interactive command is invoked."
+  "A hook run before each interactive command is invoked."
   :type 'hook
   :group 'eshell-cmd)
 
 (defcustom eshell-post-command-hook nil
   :type 'hook
   :group 'eshell-cmd)
 
 (defcustom eshell-post-command-hook nil
-  "*A hook run after each interactive command is invoked."
+  "A hook run after each interactive command is invoked."
   :type 'hook
   :group 'eshell-cmd)
 
 (defcustom eshell-prepare-command-hook nil
   :type 'hook
   :group 'eshell-cmd)
 
 (defcustom eshell-prepare-command-hook nil
-  "*A set of functions called to prepare a named command.
+  "A set of functions called to prepare a named command.
 The command name and its argument are in `eshell-last-command-name'
 and `eshell-last-arguments'.  The functions on this hook can change
 the value of these symbols if necessary.
 The command name and its argument are in `eshell-last-command-name'
 and `eshell-last-arguments'.  The functions on this hook can change
 the value of these symbols if necessary.
@@ -154,7 +153,7 @@ To prevent a command from executing at all, set
   :group 'eshell-cmd)
 
 (defcustom eshell-named-command-hook nil
   :group 'eshell-cmd)
 
 (defcustom eshell-named-command-hook nil
-  "*A set of functions called before a named command is invoked.
+  "A set of functions called before a named command is invoked.
 Each function will be passed the command name and arguments that were
 passed to `eshell-named-command'.
 
 Each function will be passed the command name and arguments that were
 passed to `eshell-named-command'.
 
@@ -180,7 +179,7 @@ call to `cd' using the arguments that were passed to the function."
 (defcustom eshell-pre-rewrite-command-hook
   '(eshell-no-command-conversion
     eshell-subcommand-arg-values)
 (defcustom eshell-pre-rewrite-command-hook
   '(eshell-no-command-conversion
     eshell-subcommand-arg-values)
-  "*A hook run before command rewriting begins.
+  "A hook run before command rewriting begins.
 The terms of the command to be rewritten is passed as arguments, and
 may be modified in place.  Any return value is ignored."
   :type 'hook
 The terms of the command to be rewritten is passed as arguments, and
 may be modified in place.  Any return value is ignored."
   :type 'hook
@@ -193,7 +192,7 @@ may be modified in place.  Any return value is ignored."
     eshell-rewrite-sexp-command
     eshell-rewrite-initial-subcommand
     eshell-rewrite-named-command)
     eshell-rewrite-sexp-command
     eshell-rewrite-initial-subcommand
     eshell-rewrite-named-command)
-  "*A set of functions used to rewrite the command argument.
+  "A set of functions used to rewrite the command argument.
 Once parsing of a command line is completed, the next step is to
 rewrite the initial argument into something runnable.
 
 Once parsing of a command line is completed, the next step is to
 rewrite the initial argument into something runnable.
 
@@ -207,14 +206,14 @@ forms or strings)."
   :group 'eshell-cmd)
 
 (defcustom eshell-post-rewrite-command-hook nil
   :group 'eshell-cmd)
 
 (defcustom eshell-post-rewrite-command-hook nil
-  "*A hook run after command rewriting is finished.
+  "A hook run after command rewriting is finished.
 Each function is passed the symbol containing the rewritten command,
 which may be modified directly.  Any return value is ignored."
   :type 'hook
   :group 'eshell-cmd)
 
 (defcustom eshell-complex-commands '("ls")
 Each function is passed the symbol containing the rewritten command,
 which may be modified directly.  Any return value is ignored."
   :type 'hook
   :group 'eshell-cmd)
 
 (defcustom eshell-complex-commands '("ls")
-  "*A list of commands names or functions, that determine complexity.
+  "A list of commands names or functions, that determine complexity.
 That is, if a command is defined by a function named eshell/NAME,
 and NAME is part of this list, it is invoked as a complex command.
 Complex commands are always correct, but run much slower.  If a
 That is, if a command is defined by a function named eshell/NAME,
 and NAME is part of this list, it is invoked as a complex command.
 Complex commands are always correct, but run much slower.  If a
@@ -230,13 +229,14 @@ return non-nil if the command is complex."
 
 ;;; User Variables:
 
 
 ;;; User Variables:
 
-(defcustom eshell-cmd-load-hook '(eshell-cmd-initialize)
-  "*A hook that gets run when `eshell-cmd' is loaded."
+(defcustom eshell-cmd-load-hook nil
+  "A hook that gets run when `eshell-cmd' is loaded."
+  :version "24.1"                     ; removed eshell-cmd-initialize
   :type 'hook
   :group 'eshell-cmd)
 
 (defcustom eshell-debug-command nil
   :type 'hook
   :group 'eshell-cmd)
 
 (defcustom eshell-debug-command nil
-  "*If non-nil, enable debugging code.  SSLLOOWW.
+  "If non-nil, enable debugging code.  SSLLOOWW.
 This option is only useful for reporting bugs.  If you enable it, you
 will have to visit the file 'eshell-cmd.el' and run the command
 \\[eval-buffer]."
 This option is only useful for reporting bugs.  If you enable it, you
 will have to visit the file 'eshell-cmd.el' and run the command
 \\[eval-buffer]."
@@ -247,7 +247,7 @@ will have to visit the file 'eshell-cmd.el' and run the command
   '(eshell-named-command
     eshell-lisp-command
     eshell-process-identity)
   '(eshell-named-command
     eshell-lisp-command
     eshell-process-identity)
-  "*A list of functions which might return an ansychronous process.
+  "A list of functions which might return an ansychronous process.
 If they return a process object, execution of the calling Eshell
 command will wait for completion (in the background) before finishing
 the command."
 If they return a process object, execution of the calling Eshell
 command will wait for completion (in the background) before finishing
 the command."
@@ -258,7 +258,7 @@ the command."
   '((eshell-in-subcommand-p t)
     (default-directory default-directory)
     (process-environment (eshell-copy-environment)))
   '((eshell-in-subcommand-p t)
     (default-directory default-directory)
     (process-environment (eshell-copy-environment)))
-  "*A list of `let' bindings for subcommand environments."
+  "A list of `let' bindings for subcommand environments."
   :type 'sexp
   :group 'eshell-cmd)
 
   :type 'sexp
   :group 'eshell-cmd)
 
@@ -320,18 +320,6 @@ otherwise t.")
     (add-hook 'pcomplete-try-first-hook
              'eshell-complete-lisp-symbols nil t)))
 
     (add-hook 'pcomplete-try-first-hook
              'eshell-complete-lisp-symbols nil t)))
 
-(eshell-deftest var last-result-var
-  "\"last result\" variable"
-  (eshell-command-result-p "+ 1 2; + $$ 2" "3\n5\n"))
-
-(eshell-deftest var last-result-var2
-  "\"last result\" variable"
-  (eshell-command-result-p "+ 1 2; + $$ $$" "3\n6\n"))
-
-(eshell-deftest var last-arg-var
-  "\"last arg\" variable"
-  (eshell-command-result-p "+ 1 2; + $_ 4" "3\n6\n"))
-
 (defun eshell-complete-lisp-symbols ()
   "If there is a user reference, complete it."
   (let ((arg (pcomplete-actual-arg)))
 (defun eshell-complete-lisp-symbols ()
   "If there is a user reference, complete it."
   (let ((arg (pcomplete-actual-arg)))
@@ -355,46 +343,45 @@ hooks should be run before and after the command."
           (if (consp command)
               (eshell-parse-arguments (car command) (cdr command))
             (let ((here (point))
           (if (consp command)
               (eshell-parse-arguments (car command) (cdr command))
             (let ((here (point))
-                  (inhibit-point-motion-hooks t)
-                  after-change-functions)
-              (insert command)
-              (prog1
-                  (eshell-parse-arguments here (point))
-                (delete-region here (point)))))
+                  (inhibit-point-motion-hooks t))
+               (with-silent-modifications
+                 ;; FIXME: Why not use a temporary buffer and avoid this
+                 ;; "insert&delete" business?  --Stef
+                 (insert command)
+                 (prog1
+                     (eshell-parse-arguments here (point))
+                   (delete-region here (point))))))
           args))
         (commands
          (mapcar
           (function
            (lambda (cmd)
           args))
         (commands
          (mapcar
           (function
            (lambda (cmd)
-             (if (or (not (car sep-terms))
-                     (string= (car sep-terms) ";"))
-                 (setq cmd
-                       (eshell-parse-pipeline cmd (not (car sep-terms))))
-               (setq cmd
-                     (list 'eshell-do-subjob
-                           (list 'list (eshell-parse-pipeline cmd)))))
+              (setq cmd
+                    (if (or (not (car sep-terms))
+                            (string= (car sep-terms) ";"))
+                       (eshell-parse-pipeline cmd (not (car sep-terms)))
+                     `(eshell-do-subjob
+                        (list ,(eshell-parse-pipeline cmd)))))
              (setq sep-terms (cdr sep-terms))
              (if eshell-in-pipeline-p
                  cmd
              (setq sep-terms (cdr sep-terms))
              (if eshell-in-pipeline-p
                  cmd
-               (list 'eshell-trap-errors cmd))))
+               `(eshell-trap-errors ,cmd))))
           (eshell-separate-commands terms "[&;]" nil 'sep-terms))))
     (let ((cmd commands))
       (while cmd
        (if (cdr cmd)
           (eshell-separate-commands terms "[&;]" nil 'sep-terms))))
     (let ((cmd commands))
       (while cmd
        (if (cdr cmd)
-           (setcar cmd (list 'eshell-commands (car cmd))))
+           (setcar cmd `(eshell-commands ,(car cmd))))
        (setq cmd (cdr cmd))))
     (setq commands
        (setq cmd (cdr cmd))))
     (setq commands
-         (append (list 'progn)
-                 (if top-level
-                     (list '(run-hooks 'eshell-pre-command-hook)))
-                 (if (not top-level)
-                     commands
-                   (list
-                    (list 'catch (quote 'top-level)
-                          (append (list 'progn) commands))
-                    '(run-hooks 'eshell-post-command-hook)))))
+         `(progn
+             ,@(if top-level
+                   '((run-hooks 'eshell-pre-command-hook)))
+             ,@(if (not top-level)
+                   commands
+                 `((catch 'top-level (progn ,@commands))
+                   (run-hooks 'eshell-post-command-hook)))))
     (if top-level
     (if top-level
-       (list 'eshell-commands commands)
+       `(eshell-commands ,commands)
       commands)))
 
 (defun eshell-debug-command (tag subform)
       commands)))
 
 (defun eshell-debug-command (tag subform)
@@ -427,9 +414,8 @@ hooks should be run before and after the command."
   (while terms
     (if (and (listp (car terms))
             (eq (caar terms) 'eshell-as-subcommand))
   (while terms
     (if (and (listp (car terms))
             (eq (caar terms) 'eshell-as-subcommand))
-       (setcar terms (list 'eshell-convert
-                           (list 'eshell-command-to-value
-                                 (car terms)))))
+       (setcar terms `(eshell-convert
+                        (eshell-command-to-value ,(car terms)))))
     (setq terms (cdr terms))))
 
 (defun eshell-rewrite-sexp-command (terms)
     (setq terms (cdr terms))))
 
 (defun eshell-rewrite-sexp-command (terms)
@@ -439,32 +425,12 @@ hooks should be run before and after the command."
           (eq (caar terms) 'eshell-command-to-value))
       (car (cdar terms))))
 
           (eq (caar terms) 'eshell-command-to-value))
       (car (cdar terms))))
 
-(eshell-deftest cmd lisp-command
-  "Evaluate Lisp command"
-  (eshell-command-result-p "(+ 1 2)" "3"))
-
-(eshell-deftest cmd lisp-command-args
-  "Evaluate Lisp command (ignore args)"
-  (eshell-command-result-p "(+ 1 2) 3" "3"))
-
 (defun eshell-rewrite-initial-subcommand (terms)
   "Rewrite a subcommand in initial position, such as '{+ 1 2}'."
   (if (and (listp (car terms))
           (eq (caar terms) 'eshell-as-subcommand))
       (car terms)))
 
 (defun eshell-rewrite-initial-subcommand (terms)
   "Rewrite a subcommand in initial position, such as '{+ 1 2}'."
   (if (and (listp (car terms))
           (eq (caar terms) 'eshell-as-subcommand))
       (car terms)))
 
-(eshell-deftest cmd subcommand
-  "Run subcommand"
-  (eshell-command-result-p "{+ 1 2}" "3\n"))
-
-(eshell-deftest cmd subcommand-args
-  "Run subcommand (ignore args)"
-  (eshell-command-result-p "{+ 1 2} 3" "3\n"))
-
-(eshell-deftest cmd subcommand-lisp
-  "Run subcommand + Lisp form"
-  (eshell-command-result-p "{(+ 1 2)}" "3\n"))
-
 (defun eshell-rewrite-named-command (terms)
   "If no other rewriting rule transforms TERMS, assume a named command."
   (let ((sym (if eshell-in-pipeline-p
 (defun eshell-rewrite-named-command (terms)
   "If no other rewriting rule transforms TERMS, assume a named command."
   (let ((sym (if eshell-in-pipeline-p
@@ -473,13 +439,9 @@ hooks should be run before and after the command."
        (cmd (car terms))
        (args (cdr terms)))
     (if args
        (cmd (car terms))
        (args (cdr terms)))
     (if args
-       (list sym cmd (append (list 'list) (cdr terms)))
+       (list sym cmd `(list ,@(cdr terms)))
       (list sym cmd))))
 
       (list sym cmd))))
 
-(eshell-deftest cmd named-command
-  "Execute named command"
-  (eshell-command-result-p "+ 1 2" "3\n"))
-
 (defvar eshell-command-body)
 (defvar eshell-test-body)
 
 (defvar eshell-command-body)
 (defvar eshell-test-body)
 
@@ -503,62 +465,43 @@ the second is ignored."
           (eq (car (cadr arg)) 'eshell-command-to-value))
       (if share-output
          (cadr (cadr arg))
           (eq (car (cadr arg)) 'eshell-command-to-value))
       (if share-output
          (cadr (cadr arg))
-       (list 'eshell-commands (cadr (cadr arg))
-             silent))
+       `(eshell-commands ,(cadr (cadr arg)) ,silent))
     arg))
 
     arg))
 
+(defvar eshell-last-command-status)     ;Define in esh-io.el.
+
 (defun eshell-rewrite-for-command (terms)
   "Rewrite a `for' command into its equivalent Eshell command form.
 Because the implementation of `for' relies upon conditional evaluation
 of its argument (i.e., use of a Lisp special form), it must be
 implemented via rewriting, rather than as a function."
 (defun eshell-rewrite-for-command (terms)
   "Rewrite a `for' command into its equivalent Eshell command form.
 Because the implementation of `for' relies upon conditional evaluation
 of its argument (i.e., use of a Lisp special form), it must be
 implemented via rewriting, rather than as a function."
-  (if (and (stringp (car terms))
-          (string= (car terms) "for")
-          (stringp (nth 2 terms))
-          (string= (nth 2 terms) "in"))
+  (if (and (equal (car terms) "for")
+          (equal (nth 2 terms) "in"))
       (let ((body (car (last terms))))
        (setcdr (last terms 2) nil)
       (let ((body (car (last terms))))
        (setcdr (last terms 2) nil)
-       (list
-        'let (list (list 'for-items
-                         (append
-                          (list 'append)
-                          (mapcar
-                           (function
-                            (lambda (elem)
-                              (if (listp elem)
-                                  elem
-                                (list 'list elem))))
-                           (cdr (cddr terms)))))
-                   (list 'eshell-command-body
-                         (list 'quote (list nil)))
-                   (list 'eshell-test-body
-                         (list 'quote (list nil))))
-        (list
-         'progn
-         (list
-          'while (list 'car (list 'symbol-value
-                                  (list 'quote 'for-items)))
-          (list
-           'progn
-           (list 'let
-                 (list (list (intern (cadr terms))
-                             (list 'car
-                                   (list 'symbol-value
-                                         (list 'quote 'for-items)))))
-                 (list 'eshell-protect
-                       (eshell-invokify-arg body t)))
-           (list 'setcar 'for-items
-                 (list 'cadr
-                       (list 'symbol-value
-                             (list 'quote 'for-items))))
-           (list 'setcdr 'for-items
-                 (list 'cddr
-                       (list 'symbol-value
-                             (list 'quote 'for-items))))))
-         (list 'eshell-close-handles
-               'eshell-last-command-status
-               (list 'list (quote 'quote)
-                     'eshell-last-command-result)))))))
+       `(let ((for-items
+                ;; Apparently, eshell-do-eval only works for immutable
+                ;; let-bindings, i.e. we cannot use `setq' on `for-items'.
+                ;; Instead we store the list in the car of a cons-cell (which
+                ;; acts as a ref-cell) so we can setcar instead of setq.
+                (list
+                 (append
+                  ,@(mapcar
+                     (lambda (elem)
+                       (if (listp elem)
+                           elem
+                         `(list ,elem)))
+                     (cdr (cddr terms))))))
+               (eshell-command-body '(nil))
+               (eshell-test-body '(nil)))
+           (while (consp (car for-items))
+             (let ((,(intern (cadr terms)) (caar for-items)))
+               (eshell-protect
+                ,(eshell-invokify-arg body t)))
+             (setcar for-items (cdar for-items)))
+           (eshell-close-handles
+            eshell-last-command-status
+            (list 'quote eshell-last-command-result))))))
 
 (defun eshell-structure-basic-command (func names keyword test body
                                            &optional else vocal-test)
 
 (defun eshell-structure-basic-command (func names keyword test body
                                            &optional else vocal-test)
@@ -574,8 +517,8 @@ shown, as well as output from the body."
   ;; that determine the truth of the statement.
   (unless (eq (car test) 'eshell-convert)
     (setq test
   ;; that determine the truth of the statement.
   (unless (eq (car test) 'eshell-convert)
     (setq test
-         (list 'progn test
-               (list 'eshell-exit-success-p))))
+         `(progn ,test
+                  (eshell-exit-success-p))))
 
   ;; should we reverse the sense of the test?  This depends
   ;; on the `names' parameter.  If it's the symbol nil, yes.
 
   ;; should we reverse the sense of the test?  This depends
   ;; on the `names' parameter.  If it's the symbol nil, yes.
@@ -585,20 +528,16 @@ shown, as well as output from the body."
   (if (or (eq names nil)
          (and (listp names)
               (string= keyword (cadr names))))
   (if (or (eq names nil)
          (and (listp names)
               (string= keyword (cadr names))))
-      (setq test (list 'not test)))
+      (setq test `(not ,test)))
 
   ;; finally, create the form that represents this structured
   ;; command
 
   ;; finally, create the form that represents this structured
   ;; command
-  (list
-   'let (list (list 'eshell-command-body
-                   (list 'quote (list nil)))
-             (list 'eshell-test-body
-                   (list 'quote (list nil))))
-   (list func test body else)
-   (list 'eshell-close-handles
-        'eshell-last-command-status
-        (list 'list (quote 'quote)
-              'eshell-last-command-result))))
+  `(let ((eshell-command-body '(nil))
+         (eshell-test-body '(nil)))
+     (,func ,test ,body ,else)
+     (eshell-close-handles
+        eshell-last-command-status
+        (list 'quote eshell-last-command-result))))
 
 (defun eshell-rewrite-while-command (terms)
   "Rewrite a `while' command into its equivalent Eshell command form.
 
 (defun eshell-rewrite-while-command (terms)
   "Rewrite a `while' command into its equivalent Eshell command form.
@@ -610,8 +549,8 @@ must be implemented via rewriting, rather than as a function."
       (eshell-structure-basic-command
        'while '("while" "until") (car terms)
        (eshell-invokify-arg (cadr terms) nil t)
       (eshell-structure-basic-command
        'while '("while" "until") (car terms)
        (eshell-invokify-arg (cadr terms) nil t)
-       (list 'eshell-protect
-            (eshell-invokify-arg (car (last terms)) t)))))
+       `(eshell-protect
+         ,(eshell-invokify-arg (car (last terms)) t)))))
 
 (defun eshell-rewrite-if-command (terms)
   "Rewrite an `if' command into its equivalent Eshell command form.
 
 (defun eshell-rewrite-if-command (terms)
   "Rewrite an `if' command into its equivalent Eshell command form.
@@ -623,15 +562,14 @@ must be implemented via rewriting, rather than as a function."
       (eshell-structure-basic-command
        'if '("if" "unless") (car terms)
        (eshell-invokify-arg (cadr terms) nil t)
       (eshell-structure-basic-command
        'if '("if" "unless") (car terms)
        (eshell-invokify-arg (cadr terms) nil t)
-       (list 'eshell-protect
-            (eshell-invokify-arg
-             (if (= (length terms) 4)
-                 (car (last terms 2))
-               (car (last terms))) t))
+       `(eshell-protect
+         ,(eshell-invokify-arg (car (last terms (if (= (length terms) 4) 2)))
+                               t))
        (if (= (length terms) 4)
        (if (= (length terms) 4)
-          (list 'eshell-protect
-                (eshell-invokify-arg
-                 (car (last terms)))) t))))
+          `(eshell-protect
+             ,(eshell-invokify-arg (car (last terms)))) t))))
+
+(defvar eshell-last-command-result)     ;Defined in esh-io.el.
 
 (defun eshell-exit-success-p ()
   "Return non-nil if the last command was \"successful\".
 
 (defun eshell-exit-success-p ()
   "Return non-nil if the last command was \"successful\".
@@ -668,8 +606,7 @@ For an external command, it means an exit code of 0."
                  (if (<= (length pieces) 1)
                      (car pieces)
                    (assert (not eshell-in-pipeline-p))
                  (if (<= (length pieces) 1)
                      (car pieces)
                    (assert (not eshell-in-pipeline-p))
-                   (list 'eshell-execute-pipeline
-                         (list 'quote pieces))))))
+                   `(eshell-execute-pipeline (quote ,pieces))))))
        (setq bp (cdr bp))))
     ;; `results' might be empty; this happens in the case of
     ;; multi-line input
        (setq bp (cdr bp))))
     ;; `results' might be empty; this happens in the case of
     ;; multi-line input
@@ -682,8 +619,8 @@ For an external command, it means an exit code of 0."
       (assert (car sep-terms))
       (setq final (eshell-structure-basic-command
                   'if (string= (car sep-terms) "&&") "if"
       (assert (car sep-terms))
       (setq final (eshell-structure-basic-command
                   'if (string= (car sep-terms) "&&") "if"
-                  (list 'eshell-protect (car results))
-                  (list 'eshell-protect final)
+                  `(eshell-protect ,(car results))
+                  `(eshell-protect ,final)
                   nil t)
            results (cdr results)
            sep-terms (cdr sep-terms)))
                   nil t)
            results (cdr results)
            sep-terms (cdr sep-terms)))
@@ -701,8 +638,8 @@ For an external command, it means an exit code of 0."
            (throw 'eshell-incomplete ?\{)
          (when (eshell-arg-delimiter (1+ end))
            (prog1
            (throw 'eshell-incomplete ?\{)
          (when (eshell-arg-delimiter (1+ end))
            (prog1
-               (list 'eshell-as-subcommand
-                     (eshell-parse-command (cons (1+ (point)) end)))
+               `(eshell-as-subcommand
+                  ,(eshell-parse-command (cons (1+ (point)) end)))
              (goto-char (1+ end))))))))
 
 (defun eshell-parse-lisp-argument ()
              (goto-char (1+ end))))))))
 
 (defun eshell-parse-lisp-argument ()
@@ -717,8 +654,8 @@ For an external command, it means an exit code of 0."
                (end-of-file
                 (throw 'eshell-incomplete ?\()))))
        (if (eshell-arg-delimiter)
                (end-of-file
                 (throw 'eshell-incomplete ?\()))))
        (if (eshell-arg-delimiter)
-           (list 'eshell-command-to-value
-                 (list 'eshell-lisp-command (list 'quote obj)))
+           `(eshell-command-to-value
+              (eshell-lisp-command (quote ,obj)))
          (ignore (goto-char here))))))
 
 (defun eshell-separate-commands (terms separator &optional
          (ignore (goto-char here))))))
 
 (defun eshell-separate-commands (terms separator &optional
@@ -793,7 +730,7 @@ to this hook using `nconc', and *not* `add-hook'.
 
 Someday, when Scheme will become the dominant Emacs language, all of
 this grossness will be made to disappear by using `call/cc'..."
 
 Someday, when Scheme will become the dominant Emacs language, all of
 this grossness will be made to disappear by using `call/cc'..."
-  `(let ((eshell-this-command-hook (list 'ignore)))
+  `(let ((eshell-this-command-hook '(ignore)))
      (eshell-condition-case err
         (prog1
             ,object
      (eshell-condition-case err
         (prog1
             ,object
@@ -803,6 +740,9 @@ this grossness will be made to disappear by using `call/cc'..."
        (eshell-errorn (error-message-string err))
        (eshell-close-handles 1)))))
 
        (eshell-errorn (error-message-string err))
        (eshell-close-handles 1)))))
 
+(defvar eshell-output-handle)           ;Defined in esh-io.el.
+(defvar eshell-error-handle)            ;Defined in esh-io.el.
+
 (defmacro eshell-copy-handles (object)
   "Duplicate current I/O handles, so OBJECT works with its own copy."
   `(let ((eshell-current-handles
 (defmacro eshell-copy-handles (object)
   "Duplicate current I/O handles, so OBJECT works with its own copy."
   `(let ((eshell-current-handles
@@ -827,14 +767,13 @@ This macro calls itself recursively, with NOTFIRST non-nil."
       (progn
        ,(when (cdr pipeline)
           `(let (nextproc)
       (progn
        ,(when (cdr pipeline)
           `(let (nextproc)
-             (progn
-               (set 'nextproc
-                    (eshell-do-pipelines (quote ,(cdr pipeline)) t))
-               (eshell-set-output-handle ,eshell-output-handle
-                                         'append nextproc)
-               (eshell-set-output-handle ,eshell-error-handle
-                                         'append nextproc)
-               (set 'tailproc (or tailproc nextproc)))))
+              (setq nextproc
+                    (eshell-do-pipelines (quote ,(cdr pipeline)) t))
+              (eshell-set-output-handle ,eshell-output-handle
+                                        'append nextproc)
+              (eshell-set-output-handle ,eshell-error-handle
+                                        'append nextproc)
+              (setq tailproc (or tailproc nextproc))))
        ,(let ((head (car pipeline)))
           (if (memq (car head) '(let progn))
               (setq head (car (last head))))
        ,(let ((head (car pipeline)))
           (if (memq (car head) '(let progn))
               (setq head (car (last head))))
@@ -858,37 +797,35 @@ Output of each command is passed as input to the next one in the pipeline.
 This is used on systems where `start-process' is not supported."
   (when (setq pipeline (cadr pipeline))
     `(let (result)
 This is used on systems where `start-process' is not supported."
   (when (setq pipeline (cadr pipeline))
     `(let (result)
-       (progn
-        ,(when (cdr pipeline)
-           `(let (output-marker)
-              (progn
-                (set 'output-marker ,(point-marker))
-                (eshell-set-output-handle ,eshell-output-handle
-                                          'append output-marker)
-                (eshell-set-output-handle ,eshell-error-handle
-                                          'append output-marker))))
-        ,(let ((head (car pipeline)))
-           (if (memq (car head) '(let progn))
-               (setq head (car (last head))))
-           ;;; FIXME: is deferrable significant here?
-           (when (memq (car head) eshell-deferrable-commands)
-             (ignore
-              (setcar head
+       ,(when (cdr pipeline)
+          `(let (output-marker)
+             (setq output-marker ,(point-marker))
+             (eshell-set-output-handle ,eshell-output-handle
+                                       'append output-marker)
+             (eshell-set-output-handle ,eshell-error-handle
+                                       'append output-marker)))
+       ,(let ((head (car pipeline)))
+          (if (memq (car head) '(let progn))
+              (setq head (car (last head))))
+          ;; FIXME: is deferrable significant here?
+          (when (memq (car head) eshell-deferrable-commands)
+            (ignore
+             (setcar head
                       (intern-soft
                        (concat (symbol-name (car head)) "*"))))))
         ;; The last process in the pipe should get its handles
                       (intern-soft
                        (concat (symbol-name (car head)) "*"))))))
         ;; The last process in the pipe should get its handles
-        ;; redirected as we found them before running the pipe.
-        ,(if (null (cdr pipeline))
-             `(progn
-                (set 'eshell-current-handles tail-handles)
-                (set 'eshell-in-pipeline-p nil)))
-        (set 'result ,(car pipeline))
-        ;; tailproc gets the result of the last successful process in
-        ;; the pipeline.
-        (set 'tailproc (or result tailproc))
-        ,(if (cdr pipeline)
-             `(eshell-do-pipelines-synchronously (quote ,(cdr pipeline))))
-        result))))
+       ;; redirected as we found them before running the pipe.
+       ,(if (null (cdr pipeline))
+            `(progn
+               (setq eshell-current-handles tail-handles)
+               (setq eshell-in-pipeline-p nil)))
+       (setq result ,(car pipeline))
+       ;; tailproc gets the result of the last successful process in
+       ;; the pipeline.
+       (setq tailproc (or result tailproc))
+       ,(if (cdr pipeline)
+            `(eshell-do-pipelines-synchronously (quote ,(cdr pipeline))))
+       result)))
 
 (defalias 'eshell-process-identity 'identity)
 
 
 (defalias 'eshell-process-identity 'identity)
 
@@ -986,7 +923,7 @@ at the moment are:
         (not (member name eshell-complex-commands))
         (catch 'simple
           (progn
         (not (member name eshell-complex-commands))
         (catch 'simple
           (progn
-           (eshell-for pred eshell-complex-commands
+           (dolist (pred eshell-complex-commands)
              (if (and (functionp pred)
                       (funcall pred name))
                  (throw 'simple nil)))
              (if (and (functionp pred)
                       (funcall pred name))
                  (throw 'simple nil)))
@@ -999,14 +936,12 @@ at the moment are:
       ;; we can just stick the new command at the end of the current
       ;; one, and everything will happen as it should
       (setcdr (last (cdr eshell-current-command))
       ;; we can just stick the new command at the end of the current
       ;; one, and everything will happen as it should
       (setcdr (last (cdr eshell-current-command))
-             (list (list 'let '((here (and (eobp) (point))))
-                         (and input
-                              (list 'insert-and-inherit
-                                    (concat input "\n")))
-                         '(if here
-                              (eshell-update-markers here))
-                         (list 'eshell-do-eval
-                               (list 'quote command)))))
+             (list `(let ((here (and (eobp) (point))))
+                       ,(and input
+                             `(insert-and-inherit ,(concat input "\n")))
+                       (if here
+                           (eshell-update-markers here))
+                       (eshell-do-eval ',command))))
     (and eshell-debug-command
          (with-current-buffer (get-buffer-create "*eshell last cmd*")
            (erase-buffer)
     (and eshell-debug-command
          (with-current-buffer (get-buffer-create "*eshell last cmd*")
            (erase-buffer)
@@ -1050,6 +985,7 @@ at the moment are:
 
 (defmacro eshell-manipulate (tag &rest commands)
   "Manipulate a COMMAND form, with TAG as a debug identifier."
 
 (defmacro eshell-manipulate (tag &rest commands)
   "Manipulate a COMMAND form, with TAG as a debug identifier."
+  (declare (indent 1))
   ;; Check `bound'ness since at compile time the code until here has not
   ;; executed yet.
   (if (not (and (boundp 'eshell-debug-command) eshell-debug-command))
   ;; Check `bound'ness since at compile time the code until here has not
   ;; executed yet.
   (if (not (and (boundp 'eshell-debug-command) eshell-debug-command))
@@ -1059,39 +995,13 @@ at the moment are:
        ,@commands
        (eshell-debug-command ,(concat "done " (eval tag)) form))))
 
        ,@commands
        (eshell-debug-command ,(concat "done " (eval tag)) form))))
 
-(put 'eshell-manipulate 'lisp-indent-function 1)
-
-;; eshell-lookup-function, eshell-functionp, and eshell-macrop taken
-;; from edebug
-
-(defsubst eshell-lookup-function (object)
-  "Return the ultimate function definition of OBJECT."
-  (while (and (symbolp object) (fboundp object))
-    (setq object (symbol-function object)))
-  object)
-
-(defconst function-p-func
-  (if (fboundp 'compiled-function-p)
-      'compiled-function-p
-    'byte-code-function-p))
-
-(defsubst eshell-functionp (object)
-  "Returns the function named by OBJECT, or nil if it is not a function."
-  (setq object (eshell-lookup-function object))
-  (if (or (subrp object)
-         (funcall function-p-func object)
-         (and (listp object)
-              (eq (car object) 'lambda)
-              (listp (car (cdr object)))))
-      object))
-
 (defsubst eshell-macrop (object)
   "Return t if OBJECT is a macro or nil otherwise."
 (defsubst eshell-macrop (object)
   "Return t if OBJECT is a macro or nil otherwise."
-  (setq object (eshell-lookup-function object))
-  (if (and (listp object)
-          (eq 'macro (car object))
-          (eshell-functionp (cdr object)))
-      t))
+  (and (symbolp object) (fboundp object)
+       (setq object (indirect-function object))
+       (listp object)
+       (eq 'macro (car object))
+       (functionp (cdr object))))
 
 (defun eshell-do-eval (form &optional synchronous-p)
   "Evaluate form, simplifying it as we go.
 
 (defun eshell-do-eval (form &optional synchronous-p)
   "Evaluate form, simplifying it as we go.
@@ -1127,7 +1037,10 @@ be finished later after the completion of an asynchronous subprocess."
        (unless (car eshell-test-body)
          (setcar eshell-test-body (eshell-copy-tree (car args))))
        (while (cadr (eshell-do-eval (car eshell-test-body)))
        (unless (car eshell-test-body)
          (setcar eshell-test-body (eshell-copy-tree (car args))))
        (while (cadr (eshell-do-eval (car eshell-test-body)))
-         (setcar eshell-command-body (eshell-copy-tree (cadr args)))
+         (setcar eshell-command-body
+                  (if (cddr args)
+                      `(progn ,@(eshell-copy-tree (cdr args)))
+                    (eshell-copy-tree (cadr args))))
          (eshell-do-eval (car eshell-command-body) synchronous-p)
          (setcar eshell-command-body nil)
          (setcar eshell-test-body (eshell-copy-tree (car args))))
          (eshell-do-eval (car eshell-command-body) synchronous-p)
          (setcar eshell-command-body nil)
          (setcar eshell-test-body (eshell-copy-tree (car args))))
@@ -1141,9 +1054,11 @@ be finished later after the completion of an asynchronous subprocess."
              (eshell-do-eval (car eshell-command-body)))
          (unless (car eshell-test-body)
            (setcar eshell-test-body (eshell-copy-tree (car args))))
              (eshell-do-eval (car eshell-command-body)))
          (unless (car eshell-test-body)
            (setcar eshell-test-body (eshell-copy-tree (car args))))
-         (if (cadr (eshell-do-eval (car eshell-test-body)))
-             (setcar eshell-command-body (eshell-copy-tree (cadr args)))
-           (setcar eshell-command-body (eshell-copy-tree (car (cddr args)))))
+         (setcar eshell-command-body
+                  (eshell-copy-tree
+                   (if (cadr (eshell-do-eval (car eshell-test-body)))
+                       (cadr args)
+                     (car (cddr args)))))
          (eshell-do-eval (car eshell-command-body) synchronous-p))
        (setcar eshell-command-body nil)
        (setcar eshell-test-body nil))
          (eshell-do-eval (car eshell-command-body) synchronous-p))
        (setcar eshell-command-body nil)
        (setcar eshell-test-body nil))
@@ -1164,7 +1079,7 @@ be finished later after the completion of an asynchronous subprocess."
        (if (and (eq (car form) 'let)
                 (not (eq (car (cadr args)) 'eshell-do-eval)))
            (eshell-manipulate "evaluating let args"
        (if (and (eq (car form) 'let)
                 (not (eq (car (cadr args)) 'eshell-do-eval)))
            (eshell-manipulate "evaluating let args"
-             (eshell-for letarg (car args)
+             (dolist (letarg (car args))
                (if (and (listp letarg)
                         (not (eq (cadr letarg) 'quote)))
                    (setcdr letarg
                (if (and (listp letarg)
                         (not (eq (cadr letarg) 'quote)))
                    (setcdr letarg
@@ -1174,9 +1089,7 @@ be finished later after the completion of an asynchronous subprocess."
          (setq args (cdr args)))
        (unless (eq (caar args) 'eshell-do-eval)
          (eshell-manipulate "handling special form"
          (setq args (cdr args)))
        (unless (eq (caar args) 'eshell-do-eval)
          (eshell-manipulate "handling special form"
-           (setcar args (list 'eshell-do-eval
-                              (list 'quote (car args))
-                              synchronous-p))))
+           (setcar args `(eshell-do-eval ',(car args) ,synchronous-p))))
        (eval form))
        (t
        (if (and args (not (memq (car form) '(run-hooks))))
        (eval form))
        (t
        (if (and args (not (memq (car form) '(run-hooks))))
@@ -1240,7 +1153,7 @@ be finished later after the completion of an asynchronous subprocess."
 
 (defun eshell/which (command &rest names)
   "Identify the COMMAND, and where it is located."
 
 (defun eshell/which (command &rest names)
   "Identify the COMMAND, and where it is located."
-  (eshell-for name (cons command names)
+  (dolist (name (cons command names))
     (let (program alias direct)
       (if (eq (aref name 0) eshell-explicit-command-char)
          (setq name (substring name 1)
     (let (program alias direct)
       (if (eq (aref name 0) eshell-explicit-command-char)
          (setq name (substring name 1)
@@ -1396,6 +1309,8 @@ messages, and errors."
   "Evaluate FORM, trapping errors and returning them."
   (eshell-eval* 'eshell-printn 'eshell-errorn form))
 
   "Evaluate FORM, trapping errors and returning them."
   (eshell-eval* 'eshell-printn 'eshell-errorn form))
 
+(defvar eshell-last-output-end)         ;Defined in esh-mode.el.
+
 (defun eshell-lisp-command (object &optional args)
   "Insert Lisp OBJECT, using ARGS if a function."
   (catch 'eshell-external               ; deferred to an external command
 (defun eshell-lisp-command (object &optional args)
   "Insert Lisp OBJECT, using ARGS if a function."
   (catch 'eshell-external               ; deferred to an external command
@@ -1432,5 +1347,4 @@ messages, and errors."
 
 (provide 'esh-cmd)
 
 
 (provide 'esh-cmd)
 
-;; arch-tag: 8e4f3867-a0c5-441f-96ba-ddd142d94366
 ;;; esh-cmd.el ends here
 ;;; esh-cmd.el ends here