aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/eshell
diff options
context:
space:
mode:
authorAlan Mackenzie2011-11-03 22:03:18 +0000
committerAlan Mackenzie2011-11-03 22:03:18 +0000
commit85ba4cded3ef5a834c880edfdb6cf7ec3a747e9b (patch)
tree2a207d6e9e906119087ad357c892414db01211cb /lisp/eshell
parenta6ba2ab9277496b66f6939766a3470c1f0a84287 (diff)
parent14e1d9eab9f4b7341f92397a0a9a2706f7b26ee9 (diff)
downloademacs-85ba4cded3ef5a834c880edfdb6cf7ec3a747e9b.tar.gz
emacs-85ba4cded3ef5a834c880edfdb6cf7ec3a747e9b.zip
Merge.
Diffstat (limited to 'lisp/eshell')
-rw-r--r--lisp/eshell/esh-cmd.el317
1 files changed, 133 insertions, 184 deletions
diff --git a/lisp/eshell/esh-cmd.el b/lisp/eshell/esh-cmd.el
index bdcdc453272..52c8c2ddc20 100644
--- a/lisp/eshell/esh-cmd.el
+++ b/lisp/eshell/esh-cmd.el
@@ -356,35 +356,32 @@ hooks should be run before and after the command."
356 (mapcar 356 (mapcar
357 (function 357 (function
358 (lambda (cmd) 358 (lambda (cmd)
359 (if (or (not (car sep-terms)) 359 (setq cmd
360 (string= (car sep-terms) ";")) 360 (if (or (not (car sep-terms))
361 (setq cmd 361 (string= (car sep-terms) ";"))
362 (eshell-parse-pipeline cmd (not (car sep-terms)))) 362 (eshell-parse-pipeline cmd (not (car sep-terms)))
363 (setq cmd 363 `(eshell-do-subjob
364 (list 'eshell-do-subjob 364 (list ,(eshell-parse-pipeline cmd)))))
365 (list 'list (eshell-parse-pipeline cmd)))))
366 (setq sep-terms (cdr sep-terms)) 365 (setq sep-terms (cdr sep-terms))
367 (if eshell-in-pipeline-p 366 (if eshell-in-pipeline-p
368 cmd 367 cmd
369 (list 'eshell-trap-errors cmd)))) 368 `(eshell-trap-errors ,cmd))))
370 (eshell-separate-commands terms "[&;]" nil 'sep-terms)))) 369 (eshell-separate-commands terms "[&;]" nil 'sep-terms))))
371 (let ((cmd commands)) 370 (let ((cmd commands))
372 (while cmd 371 (while cmd
373 (if (cdr cmd) 372 (if (cdr cmd)
374 (setcar cmd (list 'eshell-commands (car cmd)))) 373 (setcar cmd `(eshell-commands ,(car cmd))))
375 (setq cmd (cdr cmd)))) 374 (setq cmd (cdr cmd))))
376 (setq commands 375 (setq commands
377 (append (list 'progn) 376 `(progn
378 (if top-level 377 ,@(if top-level
379 (list '(run-hooks 'eshell-pre-command-hook))) 378 '((run-hooks 'eshell-pre-command-hook)))
380 (if (not top-level) 379 ,@(if (not top-level)
381 commands 380 commands
382 (list 381 `((catch 'top-level (progn ,@commands))
383 (list 'catch (quote 'top-level) 382 (run-hooks 'eshell-post-command-hook)))))
384 (append (list 'progn) commands))
385 '(run-hooks 'eshell-post-command-hook)))))
386 (if top-level 383 (if top-level
387 (list 'eshell-commands commands) 384 `(eshell-commands ,commands)
388 commands))) 385 commands)))
389 386
390(defun eshell-debug-command (tag subform) 387(defun eshell-debug-command (tag subform)
@@ -417,9 +414,8 @@ hooks should be run before and after the command."
417 (while terms 414 (while terms
418 (if (and (listp (car terms)) 415 (if (and (listp (car terms))
419 (eq (caar terms) 'eshell-as-subcommand)) 416 (eq (caar terms) 'eshell-as-subcommand))
420 (setcar terms (list 'eshell-convert 417 (setcar terms `(eshell-convert
421 (list 'eshell-command-to-value 418 (eshell-command-to-value ,(car terms)))))
422 (car terms)))))
423 (setq terms (cdr terms)))) 419 (setq terms (cdr terms))))
424 420
425(defun eshell-rewrite-sexp-command (terms) 421(defun eshell-rewrite-sexp-command (terms)
@@ -443,7 +439,7 @@ hooks should be run before and after the command."
443 (cmd (car terms)) 439 (cmd (car terms))
444 (args (cdr terms))) 440 (args (cdr terms)))
445 (if args 441 (if args
446 (list sym cmd (append (list 'list) (cdr terms))) 442 (list sym cmd `(list ,@(cdr terms)))
447 (list sym cmd)))) 443 (list sym cmd))))
448 444
449(defvar eshell-command-body) 445(defvar eshell-command-body)
@@ -469,62 +465,43 @@ the second is ignored."
469 (eq (car (cadr arg)) 'eshell-command-to-value)) 465 (eq (car (cadr arg)) 'eshell-command-to-value))
470 (if share-output 466 (if share-output
471 (cadr (cadr arg)) 467 (cadr (cadr arg))
472 (list 'eshell-commands (cadr (cadr arg)) 468 `(eshell-commands ,(cadr (cadr arg)) ,silent))
473 silent))
474 arg)) 469 arg))
475 470
471(defvar eshell-last-command-status) ;Define in esh-io.el.
472
476(defun eshell-rewrite-for-command (terms) 473(defun eshell-rewrite-for-command (terms)
477 "Rewrite a `for' command into its equivalent Eshell command form. 474 "Rewrite a `for' command into its equivalent Eshell command form.
478Because the implementation of `for' relies upon conditional evaluation 475Because the implementation of `for' relies upon conditional evaluation
479of its argument (i.e., use of a Lisp special form), it must be 476of its argument (i.e., use of a Lisp special form), it must be
480implemented via rewriting, rather than as a function." 477implemented via rewriting, rather than as a function."
481 (if (and (stringp (car terms)) 478 (if (and (equal (car terms) "for")
482 (string= (car terms) "for") 479 (equal (nth 2 terms) "in"))
483 (stringp (nth 2 terms))
484 (string= (nth 2 terms) "in"))
485 (let ((body (car (last terms)))) 480 (let ((body (car (last terms))))
486 (setcdr (last terms 2) nil) 481 (setcdr (last terms 2) nil)
487 (list 482 `(let ((for-items
488 'let (list (list 'for-items 483 ;; Apparently, eshell-do-eval only works for immutable
489 (append 484 ;; let-bindings, i.e. we cannot use `setq' on `for-items'.
490 (list 'append) 485 ;; Instead we store the list in the car of a cons-cell (which
491 (mapcar 486 ;; acts as a ref-cell) so we can setcar instead of setq.
492 (function 487 (list
493 (lambda (elem) 488 (append
494 (if (listp elem) 489 ,@(mapcar
495 elem 490 (lambda (elem)
496 (list 'list elem)))) 491 (if (listp elem)
497 (cdr (cddr terms))))) 492 elem
498 (list 'eshell-command-body 493 `(list ,elem)))
499 (list 'quote (list nil))) 494 (cdr (cddr terms))))))
500 (list 'eshell-test-body 495 (eshell-command-body '(nil))
501 (list 'quote (list nil)))) 496 (eshell-test-body '(nil)))
502 (list 497 (while (consp (car for-items))
503 'progn 498 (let ((,(intern (cadr terms)) (caar for-items)))
504 (list 499 (eshell-protect
505 'while (list 'car (list 'symbol-value 500 ,(eshell-invokify-arg body t)))
506 (list 'quote 'for-items))) 501 (setcar for-items (cdar for-items)))
507 (list 502 (eshell-close-handles
508 'progn 503 eshell-last-command-status
509 (list 'let 504 (list 'quote eshell-last-command-result))))))
510 (list (list (intern (cadr terms))
511 (list 'car
512 (list 'symbol-value
513 (list 'quote 'for-items)))))
514 (list 'eshell-protect
515 (eshell-invokify-arg body t)))
516 (list 'setcar 'for-items
517 (list 'cadr
518 (list 'symbol-value
519 (list 'quote 'for-items))))
520 (list 'setcdr 'for-items
521 (list 'cddr
522 (list 'symbol-value
523 (list 'quote 'for-items))))))
524 (list 'eshell-close-handles
525 'eshell-last-command-status
526 (list 'list (quote 'quote)
527 'eshell-last-command-result)))))))
528 505
529(defun eshell-structure-basic-command (func names keyword test body 506(defun eshell-structure-basic-command (func names keyword test body
530 &optional else vocal-test) 507 &optional else vocal-test)
@@ -540,8 +517,8 @@ shown, as well as output from the body."
540 ;; that determine the truth of the statement. 517 ;; that determine the truth of the statement.
541 (unless (eq (car test) 'eshell-convert) 518 (unless (eq (car test) 'eshell-convert)
542 (setq test 519 (setq test
543 (list 'progn test 520 `(progn ,test
544 (list 'eshell-exit-success-p)))) 521 (eshell-exit-success-p))))
545 522
546 ;; should we reverse the sense of the test? This depends 523 ;; should we reverse the sense of the test? This depends
547 ;; on the `names' parameter. If it's the symbol nil, yes. 524 ;; on the `names' parameter. If it's the symbol nil, yes.
@@ -551,20 +528,16 @@ shown, as well as output from the body."
551 (if (or (eq names nil) 528 (if (or (eq names nil)
552 (and (listp names) 529 (and (listp names)
553 (string= keyword (cadr names)))) 530 (string= keyword (cadr names))))
554 (setq test (list 'not test))) 531 (setq test `(not ,test)))
555 532
556 ;; finally, create the form that represents this structured 533 ;; finally, create the form that represents this structured
557 ;; command 534 ;; command
558 (list 535 `(let ((eshell-command-body '(nil))
559 'let (list (list 'eshell-command-body 536 (eshell-test-body '(nil)))
560 (list 'quote (list nil))) 537 (,func ,test ,body ,else)
561 (list 'eshell-test-body 538 (eshell-close-handles
562 (list 'quote (list nil)))) 539 eshell-last-command-status
563 (list func test body else) 540 (list 'quote eshell-last-command-result))))
564 (list 'eshell-close-handles
565 'eshell-last-command-status
566 (list 'list (quote 'quote)
567 'eshell-last-command-result))))
568 541
569(defun eshell-rewrite-while-command (terms) 542(defun eshell-rewrite-while-command (terms)
570 "Rewrite a `while' command into its equivalent Eshell command form. 543 "Rewrite a `while' command into its equivalent Eshell command form.
@@ -576,8 +549,8 @@ must be implemented via rewriting, rather than as a function."
576 (eshell-structure-basic-command 549 (eshell-structure-basic-command
577 'while '("while" "until") (car terms) 550 'while '("while" "until") (car terms)
578 (eshell-invokify-arg (cadr terms) nil t) 551 (eshell-invokify-arg (cadr terms) nil t)
579 (list 'eshell-protect 552 `(eshell-protect
580 (eshell-invokify-arg (car (last terms)) t))))) 553 ,(eshell-invokify-arg (car (last terms)) t)))))
581 554
582(defun eshell-rewrite-if-command (terms) 555(defun eshell-rewrite-if-command (terms)
583 "Rewrite an `if' command into its equivalent Eshell command form. 556 "Rewrite an `if' command into its equivalent Eshell command form.
@@ -589,15 +562,14 @@ must be implemented via rewriting, rather than as a function."
589 (eshell-structure-basic-command 562 (eshell-structure-basic-command
590 'if '("if" "unless") (car terms) 563 'if '("if" "unless") (car terms)
591 (eshell-invokify-arg (cadr terms) nil t) 564 (eshell-invokify-arg (cadr terms) nil t)
592 (list 'eshell-protect 565 `(eshell-protect
593 (eshell-invokify-arg 566 ,(eshell-invokify-arg (car (last terms (if (= (length terms) 4) 2)))
594 (if (= (length terms) 4) 567 t))
595 (car (last terms 2))
596 (car (last terms))) t))
597 (if (= (length terms) 4) 568 (if (= (length terms) 4)
598 (list 'eshell-protect 569 `(eshell-protect
599 (eshell-invokify-arg 570 ,(eshell-invokify-arg (car (last terms)))) t))))
600 (car (last terms)))) t)))) 571
572(defvar eshell-last-command-result) ;Defined in esh-io.el.
601 573
602(defun eshell-exit-success-p () 574(defun eshell-exit-success-p ()
603 "Return non-nil if the last command was \"successful\". 575 "Return non-nil if the last command was \"successful\".
@@ -634,8 +606,7 @@ For an external command, it means an exit code of 0."
634 (if (<= (length pieces) 1) 606 (if (<= (length pieces) 1)
635 (car pieces) 607 (car pieces)
636 (assert (not eshell-in-pipeline-p)) 608 (assert (not eshell-in-pipeline-p))
637 (list 'eshell-execute-pipeline 609 `(eshell-execute-pipeline (quote ,pieces))))))
638 (list 'quote pieces))))))
639 (setq bp (cdr bp)))) 610 (setq bp (cdr bp))))
640 ;; `results' might be empty; this happens in the case of 611 ;; `results' might be empty; this happens in the case of
641 ;; multi-line input 612 ;; multi-line input
@@ -648,8 +619,8 @@ For an external command, it means an exit code of 0."
648 (assert (car sep-terms)) 619 (assert (car sep-terms))
649 (setq final (eshell-structure-basic-command 620 (setq final (eshell-structure-basic-command
650 'if (string= (car sep-terms) "&&") "if" 621 'if (string= (car sep-terms) "&&") "if"
651 (list 'eshell-protect (car results)) 622 `(eshell-protect ,(car results))
652 (list 'eshell-protect final) 623 `(eshell-protect ,final)
653 nil t) 624 nil t)
654 results (cdr results) 625 results (cdr results)
655 sep-terms (cdr sep-terms))) 626 sep-terms (cdr sep-terms)))
@@ -667,8 +638,8 @@ For an external command, it means an exit code of 0."
667 (throw 'eshell-incomplete ?\{) 638 (throw 'eshell-incomplete ?\{)
668 (when (eshell-arg-delimiter (1+ end)) 639 (when (eshell-arg-delimiter (1+ end))
669 (prog1 640 (prog1
670 (list 'eshell-as-subcommand 641 `(eshell-as-subcommand
671 (eshell-parse-command (cons (1+ (point)) end))) 642 ,(eshell-parse-command (cons (1+ (point)) end)))
672 (goto-char (1+ end)))))))) 643 (goto-char (1+ end))))))))
673 644
674(defun eshell-parse-lisp-argument () 645(defun eshell-parse-lisp-argument ()
@@ -683,8 +654,8 @@ For an external command, it means an exit code of 0."
683 (end-of-file 654 (end-of-file
684 (throw 'eshell-incomplete ?\())))) 655 (throw 'eshell-incomplete ?\()))))
685 (if (eshell-arg-delimiter) 656 (if (eshell-arg-delimiter)
686 (list 'eshell-command-to-value 657 `(eshell-command-to-value
687 (list 'eshell-lisp-command (list 'quote obj))) 658 (eshell-lisp-command (quote ,obj)))
688 (ignore (goto-char here)))))) 659 (ignore (goto-char here))))))
689 660
690(defun eshell-separate-commands (terms separator &optional 661(defun eshell-separate-commands (terms separator &optional
@@ -759,7 +730,7 @@ to this hook using `nconc', and *not* `add-hook'.
759 730
760Someday, when Scheme will become the dominant Emacs language, all of 731Someday, when Scheme will become the dominant Emacs language, all of
761this grossness will be made to disappear by using `call/cc'..." 732this grossness will be made to disappear by using `call/cc'..."
762 `(let ((eshell-this-command-hook (list 'ignore))) 733 `(let ((eshell-this-command-hook '(ignore)))
763 (eshell-condition-case err 734 (eshell-condition-case err
764 (prog1 735 (prog1
765 ,object 736 ,object
@@ -769,6 +740,9 @@ this grossness will be made to disappear by using `call/cc'..."
769 (eshell-errorn (error-message-string err)) 740 (eshell-errorn (error-message-string err))
770 (eshell-close-handles 1))))) 741 (eshell-close-handles 1)))))
771 742
743(defvar eshell-output-handle) ;Defined in esh-io.el.
744(defvar eshell-error-handle) ;Defined in esh-io.el.
745
772(defmacro eshell-copy-handles (object) 746(defmacro eshell-copy-handles (object)
773 "Duplicate current I/O handles, so OBJECT works with its own copy." 747 "Duplicate current I/O handles, so OBJECT works with its own copy."
774 `(let ((eshell-current-handles 748 `(let ((eshell-current-handles
@@ -793,14 +767,13 @@ This macro calls itself recursively, with NOTFIRST non-nil."
793 (progn 767 (progn
794 ,(when (cdr pipeline) 768 ,(when (cdr pipeline)
795 `(let (nextproc) 769 `(let (nextproc)
796 (progn 770 (setq nextproc
797 (set 'nextproc 771 (eshell-do-pipelines (quote ,(cdr pipeline)) t))
798 (eshell-do-pipelines (quote ,(cdr pipeline)) t)) 772 (eshell-set-output-handle ,eshell-output-handle
799 (eshell-set-output-handle ,eshell-output-handle 773 'append nextproc)
800 'append nextproc) 774 (eshell-set-output-handle ,eshell-error-handle
801 (eshell-set-output-handle ,eshell-error-handle 775 'append nextproc)
802 'append nextproc) 776 (setq tailproc (or tailproc nextproc))))
803 (set 'tailproc (or tailproc nextproc)))))
804 ,(let ((head (car pipeline))) 777 ,(let ((head (car pipeline)))
805 (if (memq (car head) '(let progn)) 778 (if (memq (car head) '(let progn))
806 (setq head (car (last head)))) 779 (setq head (car (last head))))
@@ -824,37 +797,35 @@ Output of each command is passed as input to the next one in the pipeline.
824This is used on systems where `start-process' is not supported." 797This is used on systems where `start-process' is not supported."
825 (when (setq pipeline (cadr pipeline)) 798 (when (setq pipeline (cadr pipeline))
826 `(let (result) 799 `(let (result)
827 (progn 800 ,(when (cdr pipeline)
828 ,(when (cdr pipeline) 801 `(let (output-marker)
829 `(let (output-marker) 802 (setq output-marker ,(point-marker))
830 (progn 803 (eshell-set-output-handle ,eshell-output-handle
831 (set 'output-marker ,(point-marker)) 804 'append output-marker)
832 (eshell-set-output-handle ,eshell-output-handle 805 (eshell-set-output-handle ,eshell-error-handle
833 'append output-marker) 806 'append output-marker)))
834 (eshell-set-output-handle ,eshell-error-handle 807 ,(let ((head (car pipeline)))
835 'append output-marker)))) 808 (if (memq (car head) '(let progn))
836 ,(let ((head (car pipeline))) 809 (setq head (car (last head))))
837 (if (memq (car head) '(let progn)) 810 ;; FIXME: is deferrable significant here?
838 (setq head (car (last head)))) 811 (when (memq (car head) eshell-deferrable-commands)
839 ;;; FIXME: is deferrable significant here? 812 (ignore
840 (when (memq (car head) eshell-deferrable-commands) 813 (setcar head
841 (ignore
842 (setcar head
843 (intern-soft 814 (intern-soft
844 (concat (symbol-name (car head)) "*")))))) 815 (concat (symbol-name (car head)) "*"))))))
845 ;; The last process in the pipe should get its handles 816 ;; The last process in the pipe should get its handles
846 ;; redirected as we found them before running the pipe. 817 ;; redirected as we found them before running the pipe.
847 ,(if (null (cdr pipeline)) 818 ,(if (null (cdr pipeline))
848 `(progn 819 `(progn
849 (set 'eshell-current-handles tail-handles) 820 (setq eshell-current-handles tail-handles)
850 (set 'eshell-in-pipeline-p nil))) 821 (setq eshell-in-pipeline-p nil)))
851 (set 'result ,(car pipeline)) 822 (setq result ,(car pipeline))
852 ;; tailproc gets the result of the last successful process in 823 ;; tailproc gets the result of the last successful process in
853 ;; the pipeline. 824 ;; the pipeline.
854 (set 'tailproc (or result tailproc)) 825 (setq tailproc (or result tailproc))
855 ,(if (cdr pipeline) 826 ,(if (cdr pipeline)
856 `(eshell-do-pipelines-synchronously (quote ,(cdr pipeline)))) 827 `(eshell-do-pipelines-synchronously (quote ,(cdr pipeline))))
857 result)))) 828 result)))
858 829
859(defalias 'eshell-process-identity 'identity) 830(defalias 'eshell-process-identity 'identity)
860 831
@@ -965,14 +936,12 @@ at the moment are:
965 ;; we can just stick the new command at the end of the current 936 ;; we can just stick the new command at the end of the current
966 ;; one, and everything will happen as it should 937 ;; one, and everything will happen as it should
967 (setcdr (last (cdr eshell-current-command)) 938 (setcdr (last (cdr eshell-current-command))
968 (list (list 'let '((here (and (eobp) (point)))) 939 (list `(let ((here (and (eobp) (point))))
969 (and input 940 ,(and input
970 (list 'insert-and-inherit 941 `(insert-and-inherit ,(concat input "\n")))
971 (concat input "\n"))) 942 (if here
972 '(if here 943 (eshell-update-markers here))
973 (eshell-update-markers here)) 944 (eshell-do-eval ',command))))
974 (list 'eshell-do-eval
975 (list 'quote command)))))
976 (and eshell-debug-command 945 (and eshell-debug-command
977 (with-current-buffer (get-buffer-create "*eshell last cmd*") 946 (with-current-buffer (get-buffer-create "*eshell last cmd*")
978 (erase-buffer) 947 (erase-buffer)
@@ -1016,6 +985,7 @@ at the moment are:
1016 985
1017(defmacro eshell-manipulate (tag &rest commands) 986(defmacro eshell-manipulate (tag &rest commands)
1018 "Manipulate a COMMAND form, with TAG as a debug identifier." 987 "Manipulate a COMMAND form, with TAG as a debug identifier."
988 (declare (indent 1))
1019 ;; Check `bound'ness since at compile time the code until here has not 989 ;; Check `bound'ness since at compile time the code until here has not
1020 ;; executed yet. 990 ;; executed yet.
1021 (if (not (and (boundp 'eshell-debug-command) eshell-debug-command)) 991 (if (not (and (boundp 'eshell-debug-command) eshell-debug-command))
@@ -1025,39 +995,13 @@ at the moment are:
1025 ,@commands 995 ,@commands
1026 (eshell-debug-command ,(concat "done " (eval tag)) form)))) 996 (eshell-debug-command ,(concat "done " (eval tag)) form))))
1027 997
1028(put 'eshell-manipulate 'lisp-indent-function 1)
1029
1030;; eshell-lookup-function, eshell-functionp, and eshell-macrop taken
1031;; from edebug
1032
1033(defsubst eshell-lookup-function (object)
1034 "Return the ultimate function definition of OBJECT."
1035 (while (and (symbolp object) (fboundp object))
1036 (setq object (symbol-function object)))
1037 object)
1038
1039(defconst function-p-func
1040 (if (fboundp 'compiled-function-p)
1041 'compiled-function-p
1042 'byte-code-function-p))
1043
1044(defsubst eshell-functionp (object)
1045 "Returns the function named by OBJECT, or nil if it is not a function."
1046 (setq object (eshell-lookup-function object))
1047 (if (or (subrp object)
1048 (funcall function-p-func object)
1049 (and (listp object)
1050 (eq (car object) 'lambda)
1051 (listp (car (cdr object)))))
1052 object))
1053
1054(defsubst eshell-macrop (object) 998(defsubst eshell-macrop (object)
1055 "Return t if OBJECT is a macro or nil otherwise." 999 "Return t if OBJECT is a macro or nil otherwise."
1056 (setq object (eshell-lookup-function object)) 1000 (and (symbolp object) (fboundp object)
1057 (if (and (listp object) 1001 (setq object (indirect-function object))
1058 (eq 'macro (car object)) 1002 (listp object)
1059 (eshell-functionp (cdr object))) 1003 (eq 'macro (car object))
1060 t)) 1004 (functionp (cdr object))))
1061 1005
1062(defun eshell-do-eval (form &optional synchronous-p) 1006(defun eshell-do-eval (form &optional synchronous-p)
1063 "Evaluate form, simplifying it as we go. 1007 "Evaluate form, simplifying it as we go.
@@ -1093,7 +1037,10 @@ be finished later after the completion of an asynchronous subprocess."
1093 (unless (car eshell-test-body) 1037 (unless (car eshell-test-body)
1094 (setcar eshell-test-body (eshell-copy-tree (car args)))) 1038 (setcar eshell-test-body (eshell-copy-tree (car args))))
1095 (while (cadr (eshell-do-eval (car eshell-test-body))) 1039 (while (cadr (eshell-do-eval (car eshell-test-body)))
1096 (setcar eshell-command-body (eshell-copy-tree (cadr args))) 1040 (setcar eshell-command-body
1041 (if (cddr args)
1042 `(progn ,@(eshell-copy-tree (cdr args)))
1043 (eshell-copy-tree (cadr args))))
1097 (eshell-do-eval (car eshell-command-body) synchronous-p) 1044 (eshell-do-eval (car eshell-command-body) synchronous-p)
1098 (setcar eshell-command-body nil) 1045 (setcar eshell-command-body nil)
1099 (setcar eshell-test-body (eshell-copy-tree (car args)))) 1046 (setcar eshell-test-body (eshell-copy-tree (car args))))
@@ -1107,9 +1054,11 @@ be finished later after the completion of an asynchronous subprocess."
1107 (eshell-do-eval (car eshell-command-body))) 1054 (eshell-do-eval (car eshell-command-body)))
1108 (unless (car eshell-test-body) 1055 (unless (car eshell-test-body)
1109 (setcar eshell-test-body (eshell-copy-tree (car args)))) 1056 (setcar eshell-test-body (eshell-copy-tree (car args))))
1110 (if (cadr (eshell-do-eval (car eshell-test-body))) 1057 (setcar eshell-command-body
1111 (setcar eshell-command-body (eshell-copy-tree (cadr args))) 1058 (eshell-copy-tree
1112 (setcar eshell-command-body (eshell-copy-tree (car (cddr args))))) 1059 (if (cadr (eshell-do-eval (car eshell-test-body)))
1060 (cadr args)
1061 (car (cddr args)))))
1113 (eshell-do-eval (car eshell-command-body) synchronous-p)) 1062 (eshell-do-eval (car eshell-command-body) synchronous-p))
1114 (setcar eshell-command-body nil) 1063 (setcar eshell-command-body nil)
1115 (setcar eshell-test-body nil)) 1064 (setcar eshell-test-body nil))
@@ -1140,9 +1089,7 @@ be finished later after the completion of an asynchronous subprocess."
1140 (setq args (cdr args))) 1089 (setq args (cdr args)))
1141 (unless (eq (caar args) 'eshell-do-eval) 1090 (unless (eq (caar args) 'eshell-do-eval)
1142 (eshell-manipulate "handling special form" 1091 (eshell-manipulate "handling special form"
1143 (setcar args (list 'eshell-do-eval 1092 (setcar args `(eshell-do-eval ',(car args) ,synchronous-p))))
1144 (list 'quote (car args))
1145 synchronous-p))))
1146 (eval form)) 1093 (eval form))
1147 (t 1094 (t
1148 (if (and args (not (memq (car form) '(run-hooks)))) 1095 (if (and args (not (memq (car form) '(run-hooks))))
@@ -1362,6 +1309,8 @@ messages, and errors."
1362 "Evaluate FORM, trapping errors and returning them." 1309 "Evaluate FORM, trapping errors and returning them."
1363 (eshell-eval* 'eshell-printn 'eshell-errorn form)) 1310 (eshell-eval* 'eshell-printn 'eshell-errorn form))
1364 1311
1312(defvar eshell-last-output-end) ;Defined in esh-mode.el.
1313
1365(defun eshell-lisp-command (object &optional args) 1314(defun eshell-lisp-command (object &optional args)
1366 "Insert Lisp OBJECT, using ARGS if a function." 1315 "Insert Lisp OBJECT, using ARGS if a function."
1367 (catch 'eshell-external ; deferred to an external command 1316 (catch 'eshell-external ; deferred to an external command