aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Monnier2011-10-29 23:58:48 -0400
committerStefan Monnier2011-10-29 23:58:48 -0400
commit1bc4c3aeb94bac3ff93a1e1a57d93d0d65824f59 (patch)
tree04f9a2b4115cc1ca9f5eec7743e9a4ec1327dd50
parent30b65d9ce6d45ee306d090a6c23467f3e7075a4c (diff)
downloademacs-1bc4c3aeb94bac3ff93a1e1a57d93d0d65824f59.tar.gz
emacs-1bc4c3aeb94bac3ff93a1e1a57d93d0d65824f59.zip
* lisp/eshell/esh-cmd.el (eshell-rewrite-for-command): Don't modify the list
in place. (eshell-subcommand-arg-values, eshell-rewrite-named-command) (eshell-rewrite-if-command, eshell-rewrite-for-command) (eshell-structure-basic-command, eshell-rewrite-while-command) (eshell-invokify-arg, eshell-parse-pipeline, eshell-parse-command) (eshell-parse-subcommand-argument, eshell-parse-lisp-argument) (eshell-trap-errors, eshell-do-pipelines, eshell-do-eval) (eshell-do-pipelines-synchronously, eshell-eval-command): Use backquotes and prefer setq to set. (eshell-lookup-function, function-p-func, eshell-functionp): Remove. (eshell-macrop): Use functionp. Fixes: debbugs:9907
-rw-r--r--lisp/ChangeLog15
-rw-r--r--lisp/eshell/esh-cmd.el312
2 files changed, 141 insertions, 186 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 7f189e01550..65378251efa 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,18 @@
12011-10-30 Stefan Monnier <monnier@iro.umontreal.ca>
2
3 * eshell/esh-cmd.el (eshell-rewrite-for-command): Don't modify the list
4 in place (bug#9907).
5 (eshell-subcommand-arg-values, eshell-rewrite-named-command)
6 (eshell-rewrite-if-command, eshell-rewrite-for-command)
7 (eshell-structure-basic-command, eshell-rewrite-while-command)
8 (eshell-invokify-arg, eshell-parse-pipeline, eshell-parse-command)
9 (eshell-parse-subcommand-argument, eshell-parse-lisp-argument)
10 (eshell-trap-errors, eshell-do-pipelines, eshell-do-eval)
11 (eshell-do-pipelines-synchronously, eshell-eval-command):
12 Use backquotes and prefer setq to set.
13 (eshell-lookup-function, function-p-func, eshell-functionp): Remove.
14 (eshell-macrop): Use functionp.
15
12011-10-30 Chong Yidong <cyd@gnu.org> 162011-10-30 Chong Yidong <cyd@gnu.org>
2 17
3 * emulation/viper-cmd.el (viper-exec-change): Use push-mark 18 * emulation/viper-cmd.el (viper-exec-change): Use push-mark
diff --git a/lisp/eshell/esh-cmd.el b/lisp/eshell/esh-cmd.el
index bdcdc453272..cac33f130f1 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,37 @@ 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 (append
489 (append 484 ,@(mapcar
490 (list 'append) 485 (lambda (elem)
491 (mapcar 486 (if (listp elem)
492 (function 487 elem
493 (lambda (elem) 488 `(list ,elem)))
494 (if (listp elem) 489 (cdr (cddr terms)))))
495 elem 490 (eshell-command-body '(nil))
496 (list 'list elem)))) 491 (eshell-test-body '(nil)))
497 (cdr (cddr terms))))) 492 (while (consp for-items)
498 (list 'eshell-command-body 493 (let ((,(intern (cadr terms)) (car for-items)))
499 (list 'quote (list nil))) 494 (eshell-protect ,(eshell-invokify-arg body t)))
500 (list 'eshell-test-body 495 (setq for-items (cdr for-items)))
501 (list 'quote (list nil)))) 496 (eshell-close-handles
502 (list 497 eshell-last-command-status
503 'progn 498 (list 'quote eshell-last-command-result))))))
504 (list
505 'while (list 'car (list 'symbol-value
506 (list 'quote 'for-items)))
507 (list
508 'progn
509 (list 'let
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 499
529(defun eshell-structure-basic-command (func names keyword test body 500(defun eshell-structure-basic-command (func names keyword test body
530 &optional else vocal-test) 501 &optional else vocal-test)
@@ -540,8 +511,8 @@ shown, as well as output from the body."
540 ;; that determine the truth of the statement. 511 ;; that determine the truth of the statement.
541 (unless (eq (car test) 'eshell-convert) 512 (unless (eq (car test) 'eshell-convert)
542 (setq test 513 (setq test
543 (list 'progn test 514 `(progn ,test
544 (list 'eshell-exit-success-p)))) 515 (eshell-exit-success-p))))
545 516
546 ;; should we reverse the sense of the test? This depends 517 ;; should we reverse the sense of the test? This depends
547 ;; on the `names' parameter. If it's the symbol nil, yes. 518 ;; on the `names' parameter. If it's the symbol nil, yes.
@@ -551,20 +522,16 @@ shown, as well as output from the body."
551 (if (or (eq names nil) 522 (if (or (eq names nil)
552 (and (listp names) 523 (and (listp names)
553 (string= keyword (cadr names)))) 524 (string= keyword (cadr names))))
554 (setq test (list 'not test))) 525 (setq test `(not ,test)))
555 526
556 ;; finally, create the form that represents this structured 527 ;; finally, create the form that represents this structured
557 ;; command 528 ;; command
558 (list 529 `(let ((eshell-command-body '(nil))
559 'let (list (list 'eshell-command-body 530 (eshell-test-body '(nil)))
560 (list 'quote (list nil))) 531 (,func ,test ,body ,else)
561 (list 'eshell-test-body 532 (eshell-close-handles
562 (list 'quote (list nil)))) 533 eshell-last-command-status
563 (list func test body else) 534 (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 535
569(defun eshell-rewrite-while-command (terms) 536(defun eshell-rewrite-while-command (terms)
570 "Rewrite a `while' command into its equivalent Eshell command form. 537 "Rewrite a `while' command into its equivalent Eshell command form.
@@ -576,8 +543,8 @@ must be implemented via rewriting, rather than as a function."
576 (eshell-structure-basic-command 543 (eshell-structure-basic-command
577 'while '("while" "until") (car terms) 544 'while '("while" "until") (car terms)
578 (eshell-invokify-arg (cadr terms) nil t) 545 (eshell-invokify-arg (cadr terms) nil t)
579 (list 'eshell-protect 546 `(eshell-protect
580 (eshell-invokify-arg (car (last terms)) t))))) 547 ,(eshell-invokify-arg (car (last terms)) t)))))
581 548
582(defun eshell-rewrite-if-command (terms) 549(defun eshell-rewrite-if-command (terms)
583 "Rewrite an `if' command into its equivalent Eshell command form. 550 "Rewrite an `if' command into its equivalent Eshell command form.
@@ -589,15 +556,14 @@ must be implemented via rewriting, rather than as a function."
589 (eshell-structure-basic-command 556 (eshell-structure-basic-command
590 'if '("if" "unless") (car terms) 557 'if '("if" "unless") (car terms)
591 (eshell-invokify-arg (cadr terms) nil t) 558 (eshell-invokify-arg (cadr terms) nil t)
592 (list 'eshell-protect 559 `(eshell-protect
593 (eshell-invokify-arg 560 ,(eshell-invokify-arg (car (last terms (if (= (length terms) 4) 2)))
594 (if (= (length terms) 4) 561 t))
595 (car (last terms 2))
596 (car (last terms))) t))
597 (if (= (length terms) 4) 562 (if (= (length terms) 4)
598 (list 'eshell-protect 563 `(eshell-protect
599 (eshell-invokify-arg 564 ,(eshell-invokify-arg (car (last terms)))) t))))
600 (car (last terms)))) t)))) 565
566(defvar eshell-last-command-result) ;Defined in esh-io.el.
601 567
602(defun eshell-exit-success-p () 568(defun eshell-exit-success-p ()
603 "Return non-nil if the last command was \"successful\". 569 "Return non-nil if the last command was \"successful\".
@@ -634,8 +600,7 @@ For an external command, it means an exit code of 0."
634 (if (<= (length pieces) 1) 600 (if (<= (length pieces) 1)
635 (car pieces) 601 (car pieces)
636 (assert (not eshell-in-pipeline-p)) 602 (assert (not eshell-in-pipeline-p))
637 (list 'eshell-execute-pipeline 603 `(eshell-execute-pipeline (quote ,pieces))))))
638 (list 'quote pieces))))))
639 (setq bp (cdr bp)))) 604 (setq bp (cdr bp))))
640 ;; `results' might be empty; this happens in the case of 605 ;; `results' might be empty; this happens in the case of
641 ;; multi-line input 606 ;; multi-line input
@@ -648,8 +613,8 @@ For an external command, it means an exit code of 0."
648 (assert (car sep-terms)) 613 (assert (car sep-terms))
649 (setq final (eshell-structure-basic-command 614 (setq final (eshell-structure-basic-command
650 'if (string= (car sep-terms) "&&") "if" 615 'if (string= (car sep-terms) "&&") "if"
651 (list 'eshell-protect (car results)) 616 `(eshell-protect ,(car results))
652 (list 'eshell-protect final) 617 `(eshell-protect ,final)
653 nil t) 618 nil t)
654 results (cdr results) 619 results (cdr results)
655 sep-terms (cdr sep-terms))) 620 sep-terms (cdr sep-terms)))
@@ -667,8 +632,8 @@ For an external command, it means an exit code of 0."
667 (throw 'eshell-incomplete ?\{) 632 (throw 'eshell-incomplete ?\{)
668 (when (eshell-arg-delimiter (1+ end)) 633 (when (eshell-arg-delimiter (1+ end))
669 (prog1 634 (prog1
670 (list 'eshell-as-subcommand 635 `(eshell-as-subcommand
671 (eshell-parse-command (cons (1+ (point)) end))) 636 ,(eshell-parse-command (cons (1+ (point)) end)))
672 (goto-char (1+ end)))))))) 637 (goto-char (1+ end))))))))
673 638
674(defun eshell-parse-lisp-argument () 639(defun eshell-parse-lisp-argument ()
@@ -683,8 +648,8 @@ For an external command, it means an exit code of 0."
683 (end-of-file 648 (end-of-file
684 (throw 'eshell-incomplete ?\())))) 649 (throw 'eshell-incomplete ?\()))))
685 (if (eshell-arg-delimiter) 650 (if (eshell-arg-delimiter)
686 (list 'eshell-command-to-value 651 `(eshell-command-to-value
687 (list 'eshell-lisp-command (list 'quote obj))) 652 (eshell-lisp-command (quote ,obj)))
688 (ignore (goto-char here)))))) 653 (ignore (goto-char here))))))
689 654
690(defun eshell-separate-commands (terms separator &optional 655(defun eshell-separate-commands (terms separator &optional
@@ -759,7 +724,7 @@ to this hook using `nconc', and *not* `add-hook'.
759 724
760Someday, when Scheme will become the dominant Emacs language, all of 725Someday, when Scheme will become the dominant Emacs language, all of
761this grossness will be made to disappear by using `call/cc'..." 726this grossness will be made to disappear by using `call/cc'..."
762 `(let ((eshell-this-command-hook (list 'ignore))) 727 `(let ((eshell-this-command-hook '(ignore)))
763 (eshell-condition-case err 728 (eshell-condition-case err
764 (prog1 729 (prog1
765 ,object 730 ,object
@@ -769,6 +734,9 @@ this grossness will be made to disappear by using `call/cc'..."
769 (eshell-errorn (error-message-string err)) 734 (eshell-errorn (error-message-string err))
770 (eshell-close-handles 1))))) 735 (eshell-close-handles 1)))))
771 736
737(defvar eshell-output-handle) ;Defined in esh-io.el.
738(defvar eshell-error-handle) ;Defined in esh-io.el.
739
772(defmacro eshell-copy-handles (object) 740(defmacro eshell-copy-handles (object)
773 "Duplicate current I/O handles, so OBJECT works with its own copy." 741 "Duplicate current I/O handles, so OBJECT works with its own copy."
774 `(let ((eshell-current-handles 742 `(let ((eshell-current-handles
@@ -793,14 +761,13 @@ This macro calls itself recursively, with NOTFIRST non-nil."
793 (progn 761 (progn
794 ,(when (cdr pipeline) 762 ,(when (cdr pipeline)
795 `(let (nextproc) 763 `(let (nextproc)
796 (progn 764 (setq nextproc
797 (set 'nextproc 765 (eshell-do-pipelines (quote ,(cdr pipeline)) t))
798 (eshell-do-pipelines (quote ,(cdr pipeline)) t)) 766 (eshell-set-output-handle ,eshell-output-handle
799 (eshell-set-output-handle ,eshell-output-handle 767 'append nextproc)
800 'append nextproc) 768 (eshell-set-output-handle ,eshell-error-handle
801 (eshell-set-output-handle ,eshell-error-handle 769 'append nextproc)
802 'append nextproc) 770 (setq tailproc (or tailproc nextproc))))
803 (set 'tailproc (or tailproc nextproc)))))
804 ,(let ((head (car pipeline))) 771 ,(let ((head (car pipeline)))
805 (if (memq (car head) '(let progn)) 772 (if (memq (car head) '(let progn))
806 (setq head (car (last head)))) 773 (setq head (car (last head))))
@@ -824,37 +791,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." 791This is used on systems where `start-process' is not supported."
825 (when (setq pipeline (cadr pipeline)) 792 (when (setq pipeline (cadr pipeline))
826 `(let (result) 793 `(let (result)
827 (progn 794 ,(when (cdr pipeline)
828 ,(when (cdr pipeline) 795 `(let (output-marker)
829 `(let (output-marker) 796 (setq output-marker ,(point-marker))
830 (progn 797 (eshell-set-output-handle ,eshell-output-handle
831 (set 'output-marker ,(point-marker)) 798 'append output-marker)
832 (eshell-set-output-handle ,eshell-output-handle 799 (eshell-set-output-handle ,eshell-error-handle
833 'append output-marker) 800 'append output-marker)))
834 (eshell-set-output-handle ,eshell-error-handle 801 ,(let ((head (car pipeline)))
835 'append output-marker)))) 802 (if (memq (car head) '(let progn))
836 ,(let ((head (car pipeline))) 803 (setq head (car (last head))))
837 (if (memq (car head) '(let progn)) 804 ;; FIXME: is deferrable significant here?
838 (setq head (car (last head)))) 805 (when (memq (car head) eshell-deferrable-commands)
839 ;;; FIXME: is deferrable significant here? 806 (ignore
840 (when (memq (car head) eshell-deferrable-commands) 807 (setcar head
841 (ignore 808 (intern-soft
842 (setcar head 809 (concat (symbol-name (car head)) "*"))))))
843 (intern-soft 810 ;; The last process in the pipe should get its handles
844 (concat (symbol-name (car head)) "*")))))) 811 ;; redirected as we found them before running the pipe.
845 ;; The last process in the pipe should get its handles 812 ,(if (null (cdr pipeline))
846 ;; redirected as we found them before running the pipe. 813 `(progn
847 ,(if (null (cdr pipeline)) 814 (setq eshell-current-handles tail-handles)
848 `(progn 815 (setq eshell-in-pipeline-p nil)))
849 (set 'eshell-current-handles tail-handles) 816 (setq result ,(car pipeline))
850 (set 'eshell-in-pipeline-p nil))) 817 ;; tailproc gets the result of the last successful process in
851 (set 'result ,(car pipeline)) 818 ;; the pipeline.
852 ;; tailproc gets the result of the last successful process in 819 (setq tailproc (or result tailproc))
853 ;; the pipeline. 820 ,(if (cdr pipeline)
854 (set 'tailproc (or result tailproc)) 821 `(eshell-do-pipelines-synchronously (quote ,(cdr pipeline))))
855 ,(if (cdr pipeline) 822 result)))
856 `(eshell-do-pipelines-synchronously (quote ,(cdr pipeline))))
857 result))))
858 823
859(defalias 'eshell-process-identity 'identity) 824(defalias 'eshell-process-identity 'identity)
860 825
@@ -965,14 +930,12 @@ at the moment are:
965 ;; we can just stick the new command at the end of the current 930 ;; we can just stick the new command at the end of the current
966 ;; one, and everything will happen as it should 931 ;; one, and everything will happen as it should
967 (setcdr (last (cdr eshell-current-command)) 932 (setcdr (last (cdr eshell-current-command))
968 (list (list 'let '((here (and (eobp) (point)))) 933 (list `(let ((here (and (eobp) (point))))
969 (and input 934 ,(and input
970 (list 'insert-and-inherit 935 `(insert-and-inherit ,(concat input "\n")))
971 (concat input "\n"))) 936 (if here
972 '(if here 937 (eshell-update-markers here))
973 (eshell-update-markers here)) 938 (eshell-do-eval ',command))))
974 (list 'eshell-do-eval
975 (list 'quote command)))))
976 (and eshell-debug-command 939 (and eshell-debug-command
977 (with-current-buffer (get-buffer-create "*eshell last cmd*") 940 (with-current-buffer (get-buffer-create "*eshell last cmd*")
978 (erase-buffer) 941 (erase-buffer)
@@ -1016,6 +979,7 @@ at the moment are:
1016 979
1017(defmacro eshell-manipulate (tag &rest commands) 980(defmacro eshell-manipulate (tag &rest commands)
1018 "Manipulate a COMMAND form, with TAG as a debug identifier." 981 "Manipulate a COMMAND form, with TAG as a debug identifier."
982 (declare (indent 1))
1019 ;; Check `bound'ness since at compile time the code until here has not 983 ;; Check `bound'ness since at compile time the code until here has not
1020 ;; executed yet. 984 ;; executed yet.
1021 (if (not (and (boundp 'eshell-debug-command) eshell-debug-command)) 985 (if (not (and (boundp 'eshell-debug-command) eshell-debug-command))
@@ -1025,39 +989,13 @@ at the moment are:
1025 ,@commands 989 ,@commands
1026 (eshell-debug-command ,(concat "done " (eval tag)) form)))) 990 (eshell-debug-command ,(concat "done " (eval tag)) form))))
1027 991
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) 992(defsubst eshell-macrop (object)
1055 "Return t if OBJECT is a macro or nil otherwise." 993 "Return t if OBJECT is a macro or nil otherwise."
1056 (setq object (eshell-lookup-function object)) 994 (and (symbolp object) (fboundp object)
1057 (if (and (listp object) 995 (setq object (indirect-function object))
1058 (eq 'macro (car object)) 996 (listp object)
1059 (eshell-functionp (cdr object))) 997 (eq 'macro (car object))
1060 t)) 998 (functionp (cdr object))))
1061 999
1062(defun eshell-do-eval (form &optional synchronous-p) 1000(defun eshell-do-eval (form &optional synchronous-p)
1063 "Evaluate form, simplifying it as we go. 1001 "Evaluate form, simplifying it as we go.
@@ -1107,9 +1045,11 @@ be finished later after the completion of an asynchronous subprocess."
1107 (eshell-do-eval (car eshell-command-body))) 1045 (eshell-do-eval (car eshell-command-body)))
1108 (unless (car eshell-test-body) 1046 (unless (car eshell-test-body)
1109 (setcar eshell-test-body (eshell-copy-tree (car args)))) 1047 (setcar eshell-test-body (eshell-copy-tree (car args))))
1110 (if (cadr (eshell-do-eval (car eshell-test-body))) 1048 (setcar eshell-command-body
1111 (setcar eshell-command-body (eshell-copy-tree (cadr args))) 1049 (eshell-copy-tree
1112 (setcar eshell-command-body (eshell-copy-tree (car (cddr args))))) 1050 (if (cadr (eshell-do-eval (car eshell-test-body)))
1051 (cadr args)
1052 (car (cddr args)))))
1113 (eshell-do-eval (car eshell-command-body) synchronous-p)) 1053 (eshell-do-eval (car eshell-command-body) synchronous-p))
1114 (setcar eshell-command-body nil) 1054 (setcar eshell-command-body nil)
1115 (setcar eshell-test-body nil)) 1055 (setcar eshell-test-body nil))
@@ -1140,9 +1080,7 @@ be finished later after the completion of an asynchronous subprocess."
1140 (setq args (cdr args))) 1080 (setq args (cdr args)))
1141 (unless (eq (caar args) 'eshell-do-eval) 1081 (unless (eq (caar args) 'eshell-do-eval)
1142 (eshell-manipulate "handling special form" 1082 (eshell-manipulate "handling special form"
1143 (setcar args (list 'eshell-do-eval 1083 (setcar args `(eshell-do-eval ',(car args) ,synchronous-p))))
1144 (list 'quote (car args))
1145 synchronous-p))))
1146 (eval form)) 1084 (eval form))
1147 (t 1085 (t
1148 (if (and args (not (memq (car form) '(run-hooks)))) 1086 (if (and args (not (memq (car form) '(run-hooks))))
@@ -1362,6 +1300,8 @@ messages, and errors."
1362 "Evaluate FORM, trapping errors and returning them." 1300 "Evaluate FORM, trapping errors and returning them."
1363 (eshell-eval* 'eshell-printn 'eshell-errorn form)) 1301 (eshell-eval* 'eshell-printn 'eshell-errorn form))
1364 1302
1303(defvar eshell-last-output-end) ;Defined in esh-mode.el.
1304
1365(defun eshell-lisp-command (object &optional args) 1305(defun eshell-lisp-command (object &optional args)
1366 "Insert Lisp OBJECT, using ARGS if a function." 1306 "Insert Lisp OBJECT, using ARGS if a function."
1367 (catch 'eshell-external ; deferred to an external command 1307 (catch 'eshell-external ; deferred to an external command