1;;; esh-cmd.el --- command invocation 2 3;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 4;; 2005, 2006, 2007 Free Software Foundation, Inc. 5 6;; Author: John Wiegley <johnw@gnu.org> 7 8;; This file is part of GNU Emacs. 9 10;; GNU Emacs is free software; you can redistribute it and/or modify 11;; it under the terms of the GNU General Public License as published by 12;; the Free Software Foundation; either version 2, or (at your option) 13;; any later version. 14 15;; GNU Emacs is distributed in the hope that it will be useful, 16;; but WITHOUT ANY WARRANTY; without even the implied warranty of 17;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18;; GNU General Public License for more details. 19 20;; You should have received a copy of the GNU General Public License 21;; along with GNU Emacs; see the file COPYING. If not, write to the 22;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 23;; Boston, MA 02110-1301, USA. 24 25(provide 'esh-cmd) 26 27(eval-when-compile (require 'esh-maint)) 28 29(defgroup eshell-cmd nil 30 "Executing an Eshell command is as simple as typing it in and 31pressing <RET>. There are several different kinds of commands, 32however." 33 :tag "Command invocation" 34 ;; :link '(info-link "(eshell)Command invocation") 35 :group 'eshell) 36 37;;; Commentary: 38 39;;;_* Invoking external commands 40;; 41;; External commands cause processes to be created, by loading 42;; external executables into memory. This is what most normal shells 43;; do, most of the time. For more information, see [External commands]. 44;; 45;;;_* Invoking Lisp functions 46;; 47;; A Lisp function can be invoked using Lisp syntax, or command shell 48;; syntax. For example, to run `dired' to edit the current directory: 49;; 50;; /tmp $ (dired ".") 51;; 52;; Or: 53;; 54;; /tmp $ dired . 55;; 56;; The latter form is preferable, but the former is more precise, 57;; since it involves no translations. See [Argument parsing], to 58;; learn more about how arguments are transformed before passing them 59;; to commands. 60;; 61;; Ordinarily, if 'dired' were also available as an external command, 62;; the external version would be called in preference to any Lisp 63;; function of the same name. To change this behavior so that Lisp 64;; functions always take precedence, set 65;; `eshell-prefer-lisp-functions' to t. 66 67(defcustom eshell-prefer-lisp-functions nil 68 "*If non-nil, prefer Lisp functions to external commands." 69 :type 'boolean 70 :group 'eshell-cmd) 71 72;;;_* Alias functions 73;; 74;; Whenever a command is specified using a simple name, such as 'ls', 75;; Eshell will first look for a Lisp function of the name `eshell/ls'. 76;; If it exists, it will be called in preference to any other command 77;; which might have matched the name 'ls' (such as command aliases, 78;; external commands, Lisp functions of that name, etc). 79;; 80;; This is the most flexible mechanism for creating new commands, 81;; since it does not pollute the global namespace, yet allows you to 82;; use all of Lisp's facilities to define that piece of functionality. 83;; Most of Eshell's "builtin" commands are defined as alias functions. 84;; 85;;;_* Lisp arguments 86;; 87;; It is possible to invoke a Lisp form as an argument. This can be 88;; done either by specifying the form as you might in Lisp, or by 89;; using the '$' character to introduce a value-interpolation: 90;; 91;; echo (+ 1 2) 92;; 93;; Or 94;; 95;; echo $(+ 1 2) 96;; 97;; The two forms are equivalent. The second is required only if the 98;; form being interpolated is within a string, or is a subexpression 99;; of a larger argument: 100;; 101;; echo x$(+ 1 2) "String $(+ 1 2)" 102;; 103;; To pass a Lisp symbol as a argument, use the alternate quoting 104;; syntax, since the single quote character is far too overused in 105;; shell syntax: 106;; 107;; echo #'lisp-symbol 108;; 109;; Backquote can also be used: 110;; 111;; echo `(list ,lisp-symbol) 112;; 113;; Lisp arguments are identified using the following regexp: 114 115(defcustom eshell-lisp-regexp "\\([(`]\\|#'\\)" 116 "*A regexp which, if matched at beginning of an argument, means Lisp. 117Such arguments will be passed to `read', and then evaluated." 118 :type 'regexp 119 :group 'eshell-cmd) 120 121;;;_* Command hooks 122;; 123;; There are several hooks involved with command execution, which can 124;; be used either to change or augment Eshell's behavior. 125 126(defcustom eshell-pre-command-hook nil 127 "*A hook run before each interactive command is invoked." 128 :type 'hook 129 :group 'eshell-cmd) 130 131(defcustom eshell-post-command-hook nil 132 "*A hook run after each interactive command is invoked." 133 :type 'hook 134 :group 'eshell-cmd) 135 136(defcustom eshell-prepare-command-hook nil 137 "*A set of functions called to prepare a named command. 138The command name and its argument are in `eshell-last-command-name' 139and `eshell-last-arguments'. The functions on this hook can change 140the value of these symbols if necessary. 141 142To prevent a command from executing at all, set 143`eshell-last-command-name' to nil." 144 :type 'hook 145 :group 'eshell-cmd) 146 147(defcustom eshell-named-command-hook nil 148 "*A set of functions called before a named command is invoked. 149Each function will be passed the command name and arguments that were 150passed to `eshell-named-command'. 151 152If any of the functions returns a non-nil value, the named command 153will not be invoked, and that value will be returned from 154`eshell-named-command'. 155 156In order to substitute an alternate command form for execution, the 157hook function should throw it using the tag `eshell-replace-command'. 158For example: 159 160 (add-hook 'eshell-named-command-hook 'subst-with-cd) 161 (defun subst-with-cd (command args) 162 (throw 'eshell-replace-command 163 (eshell-parse-command \"cd\" args))) 164 165Although useless, the above code will cause any non-glob, non-Lisp 166command (i.e., 'ls' as opposed to '*ls' or '(ls)') to be replaced by a 167call to `cd' using the arguments that were passed to the function." 168 :type 'hook 169 :group 'eshell-cmd) 170 171(defcustom eshell-pre-rewrite-command-hook 172 '(eshell-no-command-conversion 173 eshell-subcommand-arg-values) 174 "*A hook run before command rewriting begins. 175The terms of the command to be rewritten is passed as arguments, and 176may be modified in place. Any return value is ignored." 177 :type 'hook 178 :group 'eshell-cmd) 179 180(defcustom eshell-rewrite-command-hook 181 '(eshell-rewrite-for-command 182 eshell-rewrite-while-command 183 eshell-rewrite-if-command 184 eshell-rewrite-sexp-command 185 eshell-rewrite-initial-subcommand 186 eshell-rewrite-named-command) 187 "*A set of functions used to rewrite the command argument. 188Once parsing of a command line is completed, the next step is to 189rewrite the initial argument into something runnable. 190 191A module may wish to associate special behavior with certain argument 192syntaxes at the beginning of a command line. They are welcome to do 193so by adding a function to this hook. The first function to return a 194substitute command form is the one used. Each function is passed the 195command's full argument list, which is a list of sexps (typically 196forms or strings)." 197 :type 'hook 198 :group 'eshell-cmd) 199 200(defcustom eshell-post-rewrite-command-hook nil 201 "*A hook run after command rewriting is finished. 202Each function is passed the symbol containing the rewritten command, 203which may be modified directly. Any return value is ignored." 204 :type 'hook 205 :group 'eshell-cmd) 206 207(defcustom eshell-complex-commands nil 208 "*A list of commands names or functions, that determine complexity. 209That is, if a command is defined by a function named eshell/NAME, 210and NAME is part of this list, it is invoked as a complex command. 211Complex commands are always correct, but run much slower. If a 212command works fine without being part of this list, then it doesn't 213need to be. 214 215If an entry is a function, it will be called with the name, and should 216return non-nil if the command is complex." 217 :type '(repeat :tag "Commands" 218 (choice (string :tag "Name") 219 (function :tag "Predicate"))) 220 :group 'eshell-cmd) 221 222;;; Code: 223 224(require 'esh-util) 225(unless (eshell-under-xemacs-p) 226 (require 'eldoc)) 227(require 'esh-arg) 228(require 'esh-proc) 229(require 'esh-ext) 230 231;;; User Variables: 232 233(defcustom eshell-cmd-load-hook '(eshell-cmd-initialize) 234 "*A hook that gets run when `eshell-cmd' is loaded." 235 :type 'hook 236 :group 'eshell-cmd) 237 238(defcustom eshell-debug-command nil 239 "*If non-nil, enable debugging code. SSLLOOWW. 240This option is only useful for reporting bugs. If you enable it, you 241will have to visit the file 'eshell-cmd.el' and run the command 242\\[eval-buffer]." 243 :type 'boolean 244 :group 'eshell-cmd) 245 246(defcustom eshell-deferrable-commands 247 '(eshell-named-command 248 eshell-lisp-command 249 eshell-process-identity) 250 "*A list of functions which might return an ansychronous process. 251If they return a process object, execution of the calling Eshell 252command will wait for completion (in the background) before finishing 253the command." 254 :type '(repeat function) 255 :group 'eshell-cmd) 256 257(defcustom eshell-subcommand-bindings 258 '((eshell-in-subcommand-p t) 259 (default-directory default-directory) 260 (process-environment (eshell-copy-environment))) 261 "*A list of `let' bindings for subcommand environments." 262 :type 'sexp 263 :group 'eshell-cmd) 264 265(put 'risky-local-variable 'eshell-subcommand-bindings t) 266 267(defvar eshell-ensure-newline-p nil 268 "If non-nil, ensure that a newline is emitted after a Lisp form. 269This can be changed by Lisp forms that are evaluated from the Eshell 270command line.") 271 272;;; Internal Variables: 273 274(defvar eshell-current-command nil) 275(defvar eshell-command-name nil) 276(defvar eshell-command-arguments nil) 277(defvar eshell-in-pipeline-p nil) 278(defvar eshell-in-subcommand-p nil) 279(defvar eshell-last-arguments nil) 280(defvar eshell-last-command-name nil) 281(defvar eshell-last-async-proc nil 282 "When this foreground process completes, resume command evaluation.") 283 284;;; Functions: 285 286(defsubst eshell-interactive-process () 287 "Return currently running command process, if non-Lisp." 288 eshell-last-async-proc) 289 290(defun eshell-cmd-initialize () 291 "Initialize the Eshell command processing module." 292 (set (make-local-variable 'eshell-current-command) nil) 293 (set (make-local-variable 'eshell-command-name) nil) 294 (set (make-local-variable 'eshell-command-arguments) nil) 295 (set (make-local-variable 'eshell-last-arguments) nil) 296 (set (make-local-variable 'eshell-last-command-name) nil) 297 (set (make-local-variable 'eshell-last-async-proc) nil) 298 299 (add-hook 'eshell-kill-hook 'eshell-resume-command nil t) 300 301 ;; make sure that if a command is over, and no process is being 302 ;; waited for, that `eshell-current-command' is set to nil. This 303 ;; situation can occur, for example, if a Lisp function results in 304 ;; `debug' being called, and the user then types \\[top-level] 305 (add-hook 'eshell-post-command-hook 306 (function 307 (lambda () 308 (setq eshell-current-command nil 309 eshell-last-async-proc nil))) nil t) 310 311 (add-hook 'eshell-parse-argument-hook 312 'eshell-parse-subcommand-argument nil t) 313 (add-hook 'eshell-parse-argument-hook 314 'eshell-parse-lisp-argument nil t) 315 316 (when (eshell-using-module 'eshell-cmpl) 317 (add-hook 'pcomplete-try-first-hook 318 'eshell-complete-lisp-symbols nil t))) 319 320(eshell-deftest var last-result-var 321 "\"last result\" variable" 322 (eshell-command-result-p "+ 1 2; + $$ 2" "3\n5\n")) 323 324(eshell-deftest var last-result-var2 325 "\"last result\" variable" 326 (eshell-command-result-p "+ 1 2; + $$ $$" "3\n6\n")) 327 328(eshell-deftest var last-arg-var 329 "\"last arg\" variable" 330 (eshell-command-result-p "+ 1 2; + $_ 4" "3\n6\n")) 331 332(defun eshell-complete-lisp-symbols () 333 "If there is a user reference, complete it." 334 (let ((arg (pcomplete-actual-arg))) 335 (when (string-match (concat "\\`" eshell-lisp-regexp) arg) 336 (setq pcomplete-stub (substring arg (match-end 0)) 337 pcomplete-last-completion-raw t) 338 (throw 'pcomplete-completions 339 (all-completions pcomplete-stub obarray 'boundp))))) 340 341;; Command parsing 342 343(defun eshell-parse-command (command &optional args top-level) 344 "Parse the COMMAND, adding ARGS if given. 345COMMAND can either be a string, or a cons cell demarcating a buffer 346region. TOP-LEVEL, if non-nil, means that the outermost command (the 347user's input command) is being parsed, and that pre and post command 348hooks should be run before and after the command." 349 (let* (sep-terms 350 (terms 351 (append 352 (if (consp command) 353 (eshell-parse-arguments (car command) (cdr command)) 354 (let ((here (point)) 355 (inhibit-point-motion-hooks t) 356 after-change-functions) 357 (insert command) 358 (prog1 359 (eshell-parse-arguments here (point)) 360 (delete-region here (point))))) 361 args)) 362 (commands 363 (mapcar 364 (function 365 (lambda (cmd) 366 (if (or (not (car sep-terms)) 367 (string= (car sep-terms) ";")) 368 (setq cmd 369 (eshell-parse-pipeline cmd (not (car sep-terms)))) 370 (setq cmd 371 (list 'eshell-do-subjob 372 (list 'list (eshell-parse-pipeline cmd))))) 373 (setq sep-terms (cdr sep-terms)) 374 (if eshell-in-pipeline-p 375 cmd 376 (list 'eshell-trap-errors cmd)))) 377 (eshell-separate-commands terms "[&;]" nil 'sep-terms)))) 378 (let ((cmd commands)) 379 (while cmd 380 (if (cdr cmd) 381 (setcar cmd (list 'eshell-commands (car cmd)))) 382 (setq cmd (cdr cmd)))) 383 (setq commands 384 (append (list 'progn) 385 (if top-level 386 (list '(run-hooks 'eshell-pre-command-hook))) 387 (if (not top-level) 388 commands 389 (list 390 (list 'catch (quote 'top-level) 391 (append (list 'progn) commands)) 392 '(run-hooks 'eshell-post-command-hook))))) 393 (if top-level 394 (list 'eshell-commands commands) 395 commands))) 396 397(defun eshell-debug-show-parsed-args (terms) 398 "Display parsed arguments in the debug buffer." 399 (ignore 400 (if eshell-debug-command 401 (eshell-debug-command "parsed arguments" terms)))) 402 403(defun eshell-no-command-conversion (terms) 404 "Don't convert the command argument." 405 (ignore 406 (if (and (listp (car terms)) 407 (eq (caar terms) 'eshell-convert)) 408 (setcar terms (cadr (car terms)))))) 409 410(defun eshell-subcommand-arg-values (terms) 411 "Convert subcommand arguments {x} to ${x}, in order to take their values." 412 (setq terms (cdr terms)) ; skip command argument 413 (while terms 414 (if (and (listp (car terms)) 415 (eq (caar terms) 'eshell-as-subcommand)) 416 (setcar terms (list 'eshell-convert 417 (list 'eshell-command-to-value 418 (car terms))))) 419 (setq terms (cdr terms)))) 420 421(defun eshell-rewrite-sexp-command (terms) 422 "Rewrite a sexp in initial position, such as '(+ 1 2)'." 423 ;; this occurs when a Lisp expression is in first position 424 (if (and (listp (car terms)) 425 (eq (caar terms) 'eshell-command-to-value)) 426 (car (cdar terms)))) 427 428(eshell-deftest cmd lisp-command 429 "Evaluate Lisp command" 430 (eshell-command-result-p "(+ 1 2)" "3")) 431 432(eshell-deftest cmd lisp-command-args 433 "Evaluate Lisp command (ignore args)" 434 (eshell-command-result-p "(+ 1 2) 3" "3")) 435 436(defun eshell-rewrite-initial-subcommand (terms) 437 "Rewrite a subcommand in initial position, such as '{+ 1 2}'." 438 (if (and (listp (car terms)) 439 (eq (caar terms) 'eshell-as-subcommand)) 440 (car terms))) 441 442(eshell-deftest cmd subcommand 443 "Run subcommand" 444 (eshell-command-result-p "{+ 1 2}" "3\n")) 445 446(eshell-deftest cmd subcommand-args 447 "Run subcommand (ignore args)" 448 (eshell-command-result-p "{+ 1 2} 3" "3\n")) 449 450(eshell-deftest cmd subcommand-lisp 451 "Run subcommand + Lisp form" 452 (eshell-command-result-p "{(+ 1 2)}" "3\n")) 453 454(defun eshell-rewrite-named-command (terms) 455 "If no other rewriting rule transforms TERMS, assume a named command." 456 (let ((sym (if eshell-in-pipeline-p 457 'eshell-named-command* 458 'eshell-named-command)) 459 (cmd (car terms)) 460 (args (cdr terms))) 461 (if args 462 (list sym cmd (append (list 'list) (cdr terms))) 463 (list sym cmd)))) 464 465(eshell-deftest cmd named-command 466 "Execute named command" 467 (eshell-command-result-p "+ 1 2" "3\n")) 468 469(eval-when-compile 470 (defvar eshell-command-body) 471 (defvar eshell-test-body)) 472 473(defsubst eshell-invokify-arg (arg &optional share-output silent) 474 "Change ARG so it can be invoked from a structured command. 475 476SHARE-OUTPUT, if non-nil, means this invocation should share the 477current output stream, which is separately redirectable. SILENT 478means the user and/or any redirections shouldn't see any output 479from this command. If both SHARE-OUTPUT and SILENT are non-nil, 480the second is ignored." 481 ;; something that begins with `eshell-convert' means that it 482 ;; intends to return a Lisp value. We want to get past this, 483 ;; but if it's not _actually_ a value interpolation -- in which 484 ;; we leave it alone. In fact, the only time we muck with it 485 ;; is in the case of a {subcommand} that has been turned into 486 ;; the interpolation, ${subcommand}, by the parser because it 487 ;; didn't know better. 488 (if (and (listp arg) 489 (eq (car arg) 'eshell-convert) 490 (eq (car (cadr arg)) 'eshell-command-to-value)) 491 (if share-output 492 (cadr (cadr arg)) 493 (list 'eshell-commands (cadr (cadr arg)) 494 silent)) 495 arg)) 496 497(defun eshell-rewrite-for-command (terms) 498 "Rewrite a `for' command into its equivalent Eshell command form. 499Because the implementation of `for' relies upon conditional evaluation 500of its argument (i.e., use of a Lisp special form), it must be 501implemented via rewriting, rather than as a function." 502 (if (and (stringp (car terms)) 503 (string= (car terms) "for") 504 (stringp (nth 2 terms)) 505 (string= (nth 2 terms) "in")) 506 (let ((body (car (last terms)))) 507 (setcdr (last terms 2) nil) 508 (list 509 'let (list (list 'for-items 510 (append 511 (list 'append) 512 (mapcar 513 (function 514 (lambda (elem) 515 (if (listp elem) 516 elem 517 (list 'list elem)))) 518 (cdr (cddr terms))))) 519 (list 'eshell-command-body 520 (list 'quote (list nil))) 521 (list 'eshell-test-body 522 (list 'quote (list nil)))) 523 (list 524 'progn 525 (list 526 'while (list 'car (list 'symbol-value 527 (list 'quote 'for-items))) 528 (list 529 'progn 530 (list 'let 531 (list (list (intern (cadr terms)) 532 (list 'car 533 (list 'symbol-value 534 (list 'quote 'for-items))))) 535 (list 'eshell-protect 536 (eshell-invokify-arg body t))) 537 (list 'setcar 'for-items 538 (list 'cadr 539 (list 'symbol-value 540 (list 'quote 'for-items)))) 541 (list 'setcdr 'for-items 542 (list 'cddr 543 (list 'symbol-value 544 (list 'quote 'for-items)))))) 545 (list 'eshell-close-handles 546 'eshell-last-command-status 547 (list 'list (quote 'quote) 548 'eshell-last-command-result))))))) 549 550(defun eshell-structure-basic-command (func names keyword test body 551 &optional else vocal-test) 552 "With TERMS, KEYWORD, and two NAMES, structure a basic command. 553The first of NAMES should be the positive form, and the second the 554negative. It's not likely that users should ever need to call this 555function. 556 557If VOCAL-TEST is non-nil, it means output from the test should be 558shown, as well as output from the body." 559 ;; If the test form begins with `eshell-convert', it means 560 ;; something data-wise will be returned, and we should let 561 ;; that determine the truth of the statement. 562 (unless (eq (car test) 'eshell-convert) 563 (setq test 564 (list 'progn test 565 (list 'eshell-exit-success-p)))) 566 567 ;; should we reverse the sense of the test? This depends 568 ;; on the `names' parameter. If it's the symbol nil, yes. 569 ;; Otherwise, it can be a pair of strings; if the keyword 570 ;; we're using matches the second member of that pair (a 571 ;; list), we should reverse it. 572 (if (or (eq names nil) 573 (and (listp names) 574 (string= keyword (cadr names)))) 575 (setq test (list 'not test))) 576 577 ;; finally, create the form that represents this structured 578 ;; command 579 (list 580 'let (list (list 'eshell-command-body 581 (list 'quote (list nil))) 582 (list 'eshell-test-body 583 (list 'quote (list nil)))) 584 (list func test body else) 585 (list 'eshell-close-handles 586 'eshell-last-command-status 587 (list 'list (quote 'quote) 588 'eshell-last-command-result)))) 589 590(defun eshell-rewrite-while-command (terms) 591 "Rewrite a `while' command into its equivalent Eshell command form. 592Because the implementation of `while' relies upon conditional 593evaluation of its argument (i.e., use of a Lisp special form), it 594must be implemented via rewriting, rather than as a function." 595 (if (and (stringp (car terms)) 596 (member (car terms) '("while" "until"))) 597 (eshell-structure-basic-command 598 'while '("while" "until") (car terms) 599 (eshell-invokify-arg (cadr terms) nil t) 600 (list 'eshell-protect 601 (eshell-invokify-arg (car (last terms)) t))))) 602 603(defun eshell-rewrite-if-command (terms) 604 "Rewrite an `if' command into its equivalent Eshell command form. 605Because the implementation of `if' relies upon conditional 606evaluation of its argument (i.e., use of a Lisp special form), it 607must be implemented via rewriting, rather than as a function." 608 (if (and (stringp (car terms)) 609 (member (car terms) '("if" "unless"))) 610 (eshell-structure-basic-command 611 'if '("if" "unless") (car terms) 612 (eshell-invokify-arg (cadr terms) nil t) 613 (list 'eshell-protect 614 (eshell-invokify-arg 615 (if (= (length terms) 4) 616 (car (last terms 2)) 617 (car (last terms))) t)) 618 (if (= (length terms) 4) 619 (list 'eshell-protect 620 (eshell-invokify-arg 621 (car (last terms)))) t)))) 622 623(defun eshell-exit-success-p () 624 "Return non-nil if the last command was \"successful\". 625For a bit of Lisp code, this means a return value of non-nil. 626For an external command, it means an exit code of 0." 627 (if (save-match-data 628 (string-match "#<\\(Lisp object\\|function .*\\)>" 629 eshell-last-command-name)) 630 eshell-last-command-result 631 (= eshell-last-command-status 0))) 632 633(defun eshell-parse-pipeline (terms &optional final-p) 634 "Parse a pipeline from TERMS, return the appropriate Lisp forms." 635 (let* (sep-terms 636 (bigpieces (eshell-separate-commands terms "\\(&&\\|||\\)" 637 nil 'sep-terms)) 638 (bp bigpieces) 639 (results (list t)) 640 final) 641 (while bp 642 (let ((subterms (car bp))) 643 (let* ((pieces (eshell-separate-commands subterms "|")) 644 (p pieces)) 645 (while p 646 (let ((cmd (car p))) 647 (run-hook-with-args 'eshell-pre-rewrite-command-hook cmd) 648 (setq cmd (run-hook-with-args-until-success 649 'eshell-rewrite-command-hook cmd)) 650 (run-hook-with-args 'eshell-post-rewrite-command-hook 'cmd) 651 (setcar p cmd)) 652 (setq p (cdr p))) 653 (nconc results 654 (list 655 (if (<= (length pieces) 1) 656 (car pieces) 657 (assert (not eshell-in-pipeline-p)) 658 (list 'eshell-execute-pipeline 659 (list 'quote pieces)))))) 660 (setq bp (cdr bp)))) 661 ;; `results' might be empty; this happens in the case of 662 ;; multi-line input 663 (setq results (cdr results) 664 results (nreverse results) 665 final (car results) 666 results (cdr results) 667 sep-terms (nreverse sep-terms)) 668 (while results 669 (assert (car sep-terms)) 670 (setq final (eshell-structure-basic-command 671 'if (string= (car sep-terms) "&&") "if" 672 (list 'eshell-protect (car results)) 673 (list 'eshell-protect final) 674 nil t) 675 results (cdr results) 676 sep-terms (cdr sep-terms))) 677 final)) 678 679(defun eshell-parse-subcommand-argument () 680 "Parse a subcommand argument of the form '{command}'." 681 (if (and (not eshell-current-argument) 682 (not eshell-current-quoted) 683 (eq (char-after) ?\{) 684 (or (= (point-max) (1+ (point))) 685 (not (eq (char-after (1+ (point))) ?\})))) 686 (let ((end (eshell-find-delimiter ?\{ ?\}))) 687 (if (not end) 688 (throw 'eshell-incomplete ?\{) 689 (when (eshell-arg-delimiter (1+ end)) 690 (prog1 691 (list 'eshell-as-subcommand 692 (eshell-parse-command (cons (1+ (point)) end))) 693 (goto-char (1+ end)))))))) 694 695(defun eshell-parse-lisp-argument () 696 "Parse a Lisp expression which is specified as an argument." 697 (if (and (not eshell-current-argument) 698 (not eshell-current-quoted) 699 (looking-at eshell-lisp-regexp)) 700 (let* ((here (point)) 701 (obj 702 (condition-case err 703 (read (current-buffer)) 704 (end-of-file 705 (throw 'eshell-incomplete ?\())))) 706 (if (eshell-arg-delimiter) 707 (list 'eshell-command-to-value 708 (list 'eshell-lisp-command (list 'quote obj))) 709 (ignore (goto-char here)))))) 710 711(defun eshell-separate-commands (terms separator &optional 712 reversed last-terms-sym) 713 "Separate TERMS using SEPARATOR. 714If REVERSED is non-nil, the list of separated term groups will be 715returned in reverse order. If LAST-TERMS-SYM is a symbol, its value 716will be set to a list of all the separator operators found (or '(list 717nil)' if none)." 718 (let ((sub-terms (list t)) 719 (eshell-sep-terms (list t)) 720 subchains) 721 (while terms 722 (if (and (consp (car terms)) 723 (eq (caar terms) 'eshell-operator) 724 (string-match (concat "^" separator "$") 725 (nth 1 (car terms)))) 726 (progn 727 (nconc eshell-sep-terms (list (nth 1 (car terms)))) 728 (setq subchains (cons (cdr sub-terms) subchains) 729 sub-terms (list t))) 730 (nconc sub-terms (list (car terms)))) 731 (setq terms (cdr terms))) 732 (if (> (length sub-terms) 1) 733 (setq subchains (cons (cdr sub-terms) subchains))) 734 (if reversed 735 (progn 736 (if last-terms-sym 737 (set last-terms-sym (reverse (cdr eshell-sep-terms)))) 738 subchains) ; already reversed 739 (if last-terms-sym 740 (set last-terms-sym (cdr eshell-sep-terms))) 741 (nreverse subchains)))) 742 743;;_* Command evaluation macros 744;; 745;; The structure of the following macros is very important to 746;; `eshell-do-eval' [Iterative evaluation]: 747;; 748;; @ Don't use forms that conditionally evaluate their arguments, such 749;; as `setq', `if', `while', `let*', etc. The only special forms 750;; that can be used are `let', `condition-case' and 751;; `unwind-protect'. 752;; 753;; @ The main body of a `let' can contain only one form. Use `progn' 754;; if necessary. 755;; 756;; @ The two `special' variables are `eshell-current-handles' and 757;; `eshell-current-subjob-p'. Bind them locally with a `let' if you 758;; need to change them. Change them directly only if your intention 759;; is to change the calling environment. 760 761(defmacro eshell-do-subjob (object) 762 "Evaluate a command OBJECT as a subjob. 763We indicate that the process was run in the background by returning it 764ensconced in a list." 765 `(let ((eshell-current-subjob-p t)) 766 ,object)) 767 768(defmacro eshell-commands (object &optional silent) 769 "Place a valid set of handles, and context, around command OBJECT." 770 `(let ((eshell-current-handles 771 (eshell-create-handles ,(not silent) 'append)) 772 eshell-current-subjob-p) 773 ,object)) 774 775(defmacro eshell-trap-errors (object) 776 "Trap any errors that occur, so they are not entirely fatal. 777Also, the variable `eshell-this-command-hook' is available for the 778duration of OBJECT's evaluation. Note that functions should be added 779to this hook using `nconc', and *not* `add-hook'. 780 781Someday, when Scheme will become the dominant Emacs language, all of 782this grossness will be made to disappear by using `call/cc'..." 783 `(let ((eshell-this-command-hook (list 'ignore))) 784 (eshell-condition-case err 785 (prog1 786 ,object 787 (run-hooks 'eshell-this-command-hook)) 788 (error 789 (run-hooks 'eshell-this-command-hook) 790 (eshell-errorn (error-message-string err)) 791 (eshell-close-handles 1))))) 792 793(defmacro eshell-copy-handles (object) 794 "Duplicate current I/O handles, so OBJECT works with its own copy." 795 `(let ((eshell-current-handles 796 (eshell-create-handles 797 (car (aref eshell-current-handles 798 eshell-output-handle)) nil 799 (car (aref eshell-current-handles 800 eshell-error-handle)) nil))) 801 ,object)) 802 803(defmacro eshell-protect (object) 804 "Protect I/O handles, so they aren't get closed after eval'ing OBJECT." 805 `(progn 806 (eshell-protect-handles eshell-current-handles) 807 ,object)) 808 809(defmacro eshell-do-pipelines (pipeline) 810 "Execute the commands in PIPELINE, connecting each to one another." 811 (when (setq pipeline (cadr pipeline)) 812 `(eshell-copy-handles 813 (progn 814 ,(when (cdr pipeline) 815 `(let (nextproc) 816 (progn 817 (set 'nextproc 818 (eshell-do-pipelines (quote ,(cdr pipeline)))) 819 (eshell-set-output-handle ,eshell-output-handle 820 'append nextproc) 821 (eshell-set-output-handle ,eshell-error-handle 822 'append nextproc) 823 (set 'tailproc (or tailproc nextproc))))) 824 ,(let ((head (car pipeline))) 825 (if (memq (car head) '(let progn)) 826 (setq head (car (last head)))) 827 (when (memq (car head) eshell-deferrable-commands) 828 (ignore 829 (setcar head 830 (intern-soft 831 (concat (symbol-name (car head)) "*")))))) 832 ,(car pipeline))))) 833 834(defmacro eshell-do-pipelines-synchronously (pipeline) 835 "Execute the commands in PIPELINE in sequence synchronously. 836Output of each command is passed as input to the next one in the pipeline. 837This is used on systems where `start-process' is not supported." 838 (when (setq pipeline (cadr pipeline)) 839 `(let (result) 840 (progn 841 ,(when (cdr pipeline) 842 `(let (output-marker) 843 (progn 844 (set 'output-marker ,(point-marker)) 845 (eshell-set-output-handle ,eshell-output-handle 846 'append output-marker) 847 (eshell-set-output-handle ,eshell-error-handle 848 'append output-marker)))) 849 ,(let ((head (car pipeline))) 850 (if (memq (car head) '(let progn)) 851 (setq head (car (last head)))) 852 ;;; FIXME: is deferrable significant here? 853 (when (memq (car head) eshell-deferrable-commands) 854 (ignore 855 (setcar head 856 (intern-soft 857 (concat (symbol-name (car head)) "*")))))) 858 ;; The last process in the pipe should get its handles 859 ;; redirected as we found them before running the pipe. 860 ,(if (null (cdr pipeline)) 861 `(progn 862 (set 'eshell-current-handles tail-handles) 863 (set 'eshell-in-pipeline-p nil))) 864 (set 'result ,(car pipeline)) 865 ;; tailproc gets the result of the last successful process in 866 ;; the pipeline. 867 (set 'tailproc (or result tailproc)) 868 ,(if (cdr pipeline) 869 `(eshell-do-pipelines-synchronously (quote ,(cdr pipeline)))) 870 result)))) 871 872(defalias 'eshell-process-identity 'identity) 873 874(defmacro eshell-execute-pipeline (pipeline) 875 "Execute the commands in PIPELINE, connecting each to one another." 876 `(let ((eshell-in-pipeline-p t) tailproc) 877 (progn 878 ,(if (fboundp 'start-process) 879 `(eshell-do-pipelines ,pipeline) 880 `(let ((tail-handles (eshell-create-handles 881 (car (aref eshell-current-handles 882 ,eshell-output-handle)) nil 883 (car (aref eshell-current-handles 884 ,eshell-error-handle)) nil))) 885 (eshell-do-pipelines-synchronously ,pipeline))) 886 (eshell-process-identity tailproc)))) 887 888(defmacro eshell-as-subcommand (command) 889 "Execute COMMAND using a temp buffer. 890This is used so that certain Lisp commands, such as `cd', when 891executed in a subshell, do not disturb the environment of the main 892Eshell buffer." 893 `(let ,eshell-subcommand-bindings 894 ,command)) 895 896(defmacro eshell-do-command-to-value (object) 897 "Run a subcommand prepared by `eshell-command-to-value'. 898This avoids the need to use `let*'." 899 `(let ((eshell-current-handles 900 (eshell-create-handles value 'overwrite))) 901 (progn 902 ,object 903 (symbol-value value)))) 904 905(defmacro eshell-command-to-value (object) 906 "Run OBJECT synchronously, returning its result as a string. 907Returns a string comprising the output from the command." 908 `(let ((value (make-symbol "eshell-temp"))) 909 (eshell-do-command-to-value ,object))) 910 911;;;_* Iterative evaluation 912;; 913;; Eshell runs all of its external commands asynchronously, so that 914;; Emacs is not blocked while the operation is being performed. 915;; However, this introduces certain synchronization difficulties, 916;; since the Lisp code, once it returns, will not "go back" to finish 917;; executing the commands which haven't yet been started. 918;; 919;; What Eshell does to work around this problem (basically, the lack 920;; of threads in Lisp), is that it evaluates the command sequence 921;; iteratively. Whenever an asynchronous process is begun, evaluation 922;; terminates and control is given back to Emacs. When that process 923;; finishes, it will resume the evaluation using the remainder of the 924;; command tree. 925 926(defun eshell/eshell-debug (&rest args) 927 "A command for toggling certain debug variables." 928 (ignore 929 (cond 930 ((not args) 931 (if eshell-handle-errors 932 (eshell-print "errors\n")) 933 (if eshell-debug-command 934 (eshell-print "commands\n"))) 935 ((or (string= (car args) "-h") 936 (string= (car args) "--help")) 937 (eshell-print "usage: eshell-debug [kinds] 938 939This command is used to aid in debugging problems related to Eshell 940itself. It is not useful for anything else. The recognized `kinds' 941at the moment are: 942 943 errors stops Eshell from trapping errors 944 commands shows command execution progress in `*eshell last cmd*' 945")) 946 (t 947 (while args 948 (cond 949 ((string= (car args) "errors") 950 (setq eshell-handle-errors (not eshell-handle-errors))) 951 ((string= (car args) "commands") 952 (setq eshell-debug-command (not eshell-debug-command)))) 953 (setq args (cdr args))))))) 954 955(defun pcomplete/eshell-mode/eshell-debug () 956 "Completion for the `debug' command." 957 (while (pcomplete-here '("errors" "commands")))) 958 959(defun eshell-debug-command (tag subform) 960 "Output a debugging message to '*eshell last cmd*'." 961 (let ((buf (get-buffer-create "*eshell last cmd*")) 962 (text (eshell-stringify eshell-current-command))) 963 (save-excursion 964 (set-buffer buf) 965 (if (not tag) 966 (erase-buffer) 967 (insert "\n\C-l\n" tag "\n\n" text 968 (if subform 969 (concat "\n\n" (eshell-stringify subform)) "")))))) 970 971(defun eshell-invoke-directly (command input) 972 (let ((base (cadr (nth 2 (nth 2 (cadr command))))) name) 973 (if (and (eq (car base) 'eshell-trap-errors) 974 (eq (car (cadr base)) 'eshell-named-command)) 975 (setq name (cadr (cadr base)))) 976 (and name (stringp name) 977 (not (member name eshell-complex-commands)) 978 (catch 'simple 979 (progn 980 (eshell-for pred eshell-complex-commands 981 (if (and (functionp pred) 982 (funcall pred name)) 983 (throw 'simple nil))) 984 t)) 985 (fboundp (intern-soft (concat "eshell/" name)))))) 986 987(defun eshell-eval-command (command &optional input) 988 "Evaluate the given COMMAND iteratively." 989 (if eshell-current-command 990 ;; we can just stick the new command at the end of the current 991 ;; one, and everything will happen as it should 992 (setcdr (last (cdr eshell-current-command)) 993 (list (list 'let '((here (and (eobp) (point)))) 994 (and input 995 (list 'insert-and-inherit 996 (concat input "\n"))) 997 '(if here 998 (eshell-update-markers here)) 999 (list 'eshell-do-eval 1000 (list 'quote command))))) 1001 (and eshell-debug-command 1002 (save-excursion 1003 (let ((buf (get-buffer-create "*eshell last cmd*"))) 1004 (set-buffer buf) 1005 (erase-buffer) 1006 (insert "command: \"" input "\"\n")))) 1007 (setq eshell-current-command command) 1008 (let ((delim (catch 'eshell-incomplete 1009 (eshell-resume-eval)))) 1010 ;; On systems that don't support async subprocesses, eshell-resume 1011 ;; can return t. Don't treat that as an error. 1012 (if (listp delim) 1013 (setq delim (car delim))) 1014 (if (and delim (not (eq delim t))) 1015 (error "Unmatched delimiter: %c" delim))))) 1016 1017(defun eshell-resume-command (proc status) 1018 "Resume the current command when a process ends." 1019 (when proc 1020 (unless (or (not (stringp status)) 1021 (string= "stopped" status) 1022 (string-match eshell-reset-signals status)) 1023 (if (eq proc (eshell-interactive-process)) 1024 (eshell-resume-eval))))) 1025 1026(defun eshell-resume-eval () 1027 "Destructively evaluate a form which may need to be deferred." 1028 (eshell-condition-case err 1029 (progn 1030 (setq eshell-last-async-proc nil) 1031 (when eshell-current-command 1032 (let* (retval 1033 (proc (catch 'eshell-defer 1034 (ignore 1035 (setq retval 1036 (eshell-do-eval 1037 eshell-current-command)))))) 1038 (if (eshell-processp proc) 1039 (ignore (setq eshell-last-async-proc proc)) 1040 (cadr retval))))) 1041 (error 1042 (error (error-message-string err))))) 1043 1044(defmacro eshell-manipulate (tag &rest commands) 1045 "Manipulate a COMMAND form, with TAG as a debug identifier." 1046 (if (not eshell-debug-command) 1047 `(progn ,@commands) 1048 `(progn 1049 (eshell-debug-command ,(eval tag) form) 1050 ,@commands 1051 (eshell-debug-command ,(concat "done " (eval tag)) form)))) 1052 1053(put 'eshell-manipulate 'lisp-indent-function 1) 1054 1055;; eshell-lookup-function, eshell-functionp, and eshell-macrop taken 1056;; from edebug 1057 1058(defsubst eshell-lookup-function (object) 1059 "Return the ultimate function definition of OBJECT." 1060 (while (and (symbolp object) (fboundp object)) 1061 (setq object (symbol-function object))) 1062 object) 1063 1064(defconst function-p-func 1065 (if (fboundp 'compiled-function-p) 1066 'compiled-function-p 1067 'byte-code-function-p)) 1068 1069(defsubst eshell-functionp (object) 1070 "Returns the function named by OBJECT, or nil if it is not a function." 1071 (setq object (eshell-lookup-function object)) 1072 (if (or (subrp object) 1073 (funcall function-p-func object) 1074 (and (listp object) 1075 (eq (car object) 'lambda) 1076 (listp (car (cdr object))))) 1077 object)) 1078 1079(defsubst eshell-macrop (object) 1080 "Return t if OBJECT is a macro or nil otherwise." 1081 (setq object (eshell-lookup-function object)) 1082 (if (and (listp object) 1083 (eq 'macro (car object)) 1084 (eshell-functionp (cdr object))) 1085 t)) 1086 1087(defun eshell-do-eval (form &optional synchronous-p) 1088 "Evaluate form, simplifying it as we go. 1089Unless SYNCHRONOUS-P is non-nil, throws `eshell-defer' if it needs to 1090be finished later after the completion of an asynchronous subprocess." 1091 (cond 1092 ((not (listp form)) 1093 (list 'quote (eval form))) 1094 ((memq (car form) '(quote function)) 1095 form) 1096 (t 1097 ;; skip past the call to `eshell-do-eval' 1098 (when (eq (car form) 'eshell-do-eval) 1099 (setq form (cadr (cadr form)))) 1100 ;; expand any macros directly into the form. This is done so that 1101 ;; we can modify any `let' forms to evaluate only once. 1102 (if (eshell-macrop (car form)) 1103 (let ((exp (eshell-copy-tree (macroexpand form)))) 1104 (eshell-manipulate (format "expanding macro `%s'" 1105 (symbol-name (car form))) 1106 (setcar form (car exp)) 1107 (setcdr form (cdr exp))))) 1108 (let ((args (cdr form))) 1109 (cond 1110 ((eq (car form) 'while) 1111 ;; `eshell-copy-tree' is needed here so that the test argument 1112 ;; doesn't get modified and thus always yield the same result. 1113 (when (car eshell-command-body) 1114 (assert (not synchronous-p)) 1115 (eshell-do-eval (car eshell-command-body)) 1116 (setcar eshell-command-body nil) 1117 (setcar eshell-test-body nil)) 1118 (unless (car eshell-test-body) 1119 (setcar eshell-test-body (eshell-copy-tree (car args)))) 1120 (while (cadr (eshell-do-eval (car eshell-test-body))) 1121 (setcar eshell-command-body (eshell-copy-tree (cadr args))) 1122 (eshell-do-eval (car eshell-command-body) synchronous-p) 1123 (setcar eshell-command-body nil) 1124 (setcar eshell-test-body (eshell-copy-tree (car args)))) 1125 (setcar eshell-command-body nil)) 1126 ((eq (car form) 'if) 1127 ;; `eshell-copy-tree' is needed here so that the test argument 1128 ;; doesn't get modified and thus always yield the same result. 1129 (if (car eshell-command-body) 1130 (progn 1131 (assert (not synchronous-p)) 1132 (eshell-do-eval (car eshell-command-body))) 1133 (unless (car eshell-test-body) 1134 (setcar eshell-test-body (eshell-copy-tree (car args)))) 1135 (if (cadr (eshell-do-eval (car eshell-test-body))) 1136 (setcar eshell-command-body (eshell-copy-tree (cadr args))) 1137 (setcar eshell-command-body (eshell-copy-tree (car (cddr args))))) 1138 (eshell-do-eval (car eshell-command-body) synchronous-p)) 1139 (setcar eshell-command-body nil) 1140 (setcar eshell-test-body nil)) 1141 ((eq (car form) 'setcar) 1142 (setcar (cdr args) (eshell-do-eval (cadr args) synchronous-p)) 1143 (eval form)) 1144 ((eq (car form) 'setcdr) 1145 (setcar (cdr args) (eshell-do-eval (cadr args) synchronous-p)) 1146 (eval form)) 1147 ((memq (car form) '(let catch condition-case unwind-protect)) 1148 ;; `let', `condition-case' and `unwind-protect' have to be 1149 ;; handled specially, because we only want to call 1150 ;; `eshell-do-eval' on their first form. 1151 ;; 1152 ;; NOTE: This requires obedience by all forms which this 1153 ;; function might encounter, that they do not contain 1154 ;; other special forms. 1155 (if (and (eq (car form) 'let) 1156 (not (eq (car (cadr args)) 'eshell-do-eval))) 1157 (eshell-manipulate "evaluating let args" 1158 (eshell-for letarg (car args) 1159 (if (and (listp letarg) 1160 (not (eq (cadr letarg) 'quote))) 1161 (setcdr letarg 1162 (list (eshell-do-eval 1163 (cadr letarg) synchronous-p))))))) 1164 (unless (eq (car form) 'unwind-protect) 1165 (setq args (cdr args))) 1166 (unless (eq (caar args) 'eshell-do-eval) 1167 (eshell-manipulate "handling special form" 1168 (setcar args (list 'eshell-do-eval 1169 (list 'quote (car args)) 1170 synchronous-p)))) 1171 (eval form)) 1172 (t 1173 (if (and args (not (memq (car form) '(run-hooks)))) 1174 (eshell-manipulate 1175 (format "evaluating arguments to `%s'" 1176 (symbol-name (car form))) 1177 (while args 1178 (setcar args (eshell-do-eval (car args) synchronous-p)) 1179 (setq args (cdr args))))) 1180 (cond 1181 ((eq (car form) 'progn) 1182 (car (last form))) 1183 ((eq (car form) 'prog1) 1184 (cadr form)) 1185 (t 1186 ;; If a command desire to replace its execution form with 1187 ;; another command form, all it needs to do is throw the new 1188 ;; form using the exception tag `eshell-replace-command'. 1189 ;; For example, let's say that the form currently being 1190 ;; eval'd is: 1191 ;; 1192 ;; (eshell-named-command "hello") 1193 ;; 1194 ;; Now, let's assume the 'hello' command is an Eshell alias, 1195 ;; the definition of which yields the command: 1196 ;; 1197 ;; (eshell-named-command "echo" (list "Hello" "world")) 1198 ;; 1199 ;; What the alias code would like to do is simply substitute 1200 ;; the alias form for the original form. To accomplish 1201 ;; this, all it needs to do is to throw the substitution 1202 ;; form with the `eshell-replace-command' tag, and the form 1203 ;; will be replaced within the current command, and 1204 ;; execution will then resume (iteratively) as before. 1205 ;; Thus, aliases can even contain references to asynchronous 1206 ;; sub-commands, and things will still work out as they 1207 ;; should. 1208 (let (result new-form) 1209 (if (setq new-form 1210 (catch 'eshell-replace-command 1211 (ignore 1212 (setq result (eval form))))) 1213 (progn 1214 (eshell-manipulate "substituting replacement form" 1215 (setcar form (car new-form)) 1216 (setcdr form (cdr new-form))) 1217 (eshell-do-eval form synchronous-p)) 1218 (if (and (memq (car form) eshell-deferrable-commands) 1219 (not eshell-current-subjob-p) 1220 result 1221 (eshell-processp result)) 1222 (if synchronous-p 1223 (eshell/wait result) 1224 (eshell-manipulate "inserting ignore form" 1225 (setcar form 'ignore) 1226 (setcdr form nil)) 1227 (throw 'eshell-defer result)) 1228 (list 'quote result)))))))))))) 1229 1230;; command invocation 1231 1232(defun eshell/which (command &rest names) 1233 "Identify the COMMAND, and where it is located." 1234 (eshell-for name (cons command names) 1235 (let (program alias direct) 1236 (if (eq (aref name 0) eshell-explicit-command-char) 1237 (setq name (substring name 1) 1238 direct t)) 1239 (if (and (not direct) 1240 (eshell-using-module 'eshell-alias) 1241 (setq alias 1242 (funcall (symbol-function 'eshell-lookup-alias) 1243 name))) 1244 (setq program 1245 (concat name " is an alias, defined as \"" 1246 (cadr alias) "\""))) 1247 (unless program 1248 (setq program (eshell-search-path name)) 1249 (let* ((esym (eshell-find-alias-function name)) 1250 (sym (or esym (intern-soft name)))) 1251 (if (and (or esym (and sym (fboundp sym))) 1252 (or eshell-prefer-lisp-functions (not direct))) 1253 (let ((desc (let ((inhibit-redisplay t)) 1254 (save-window-excursion 1255 (prog1 1256 (describe-function sym) 1257 (message nil)))))) 1258 (setq desc (substring desc 0 1259 (1- (or (string-match "\n" desc) 1260 (length desc))))) 1261 (if (buffer-live-p (get-buffer "*Help*")) 1262 (kill-buffer "*Help*")) 1263 (setq program (or desc name)))))) 1264 (if (not program) 1265 (eshell-error (format "which: no %s in (%s)\n" 1266 name (getenv "PATH"))) 1267 (eshell-printn program))))) 1268 1269(put 'eshell/which 'eshell-no-numeric-conversions t) 1270 1271(defun eshell-named-command (command &optional args) 1272 "Insert output from a plain COMMAND, using ARGS. 1273COMMAND may result in an alias being executed, or a plain command." 1274 (setq eshell-last-arguments args 1275 eshell-last-command-name (eshell-stringify command)) 1276 (run-hook-with-args 'eshell-prepare-command-hook) 1277 (assert (stringp eshell-last-command-name)) 1278 (if eshell-last-command-name 1279 (or (run-hook-with-args-until-success 1280 'eshell-named-command-hook eshell-last-command-name 1281 eshell-last-arguments) 1282 (eshell-plain-command eshell-last-command-name 1283 eshell-last-arguments)))) 1284 1285(defalias 'eshell-named-command* 'eshell-named-command) 1286 1287(defun eshell-find-alias-function (name) 1288 "Check whether a function called `eshell/NAME' exists." 1289 (let* ((sym (intern-soft (concat "eshell/" name))) 1290 (file (symbol-file sym 'defun))) 1291 ;; If the function exists, but is defined in an eshell module 1292 ;; that's not currently enabled, don't report it as found 1293 (if (and file 1294 (string-match "\\(em\\|esh\\)-\\(.*\\)\\(\\.el\\)?\\'" file)) 1295 (let ((module-sym 1296 (intern (file-name-sans-extension 1297 (file-name-nondirectory 1298 (concat "eshell-" (match-string 2 file))))))) 1299 (if (and (functionp sym) 1300 (or (null module-sym) 1301 (eshell-using-module module-sym) 1302 (memq module-sym (eshell-subgroups 'eshell)))) 1303 sym)) 1304 ;; Otherwise, if it's bound, return it. 1305 (if (functionp sym) 1306 sym)))) 1307 1308(defun eshell-plain-command (command args) 1309 "Insert output from a plain COMMAND, using ARGS. 1310COMMAND may result in either a Lisp function being executed by name, 1311or an external command." 1312 (let* ((esym (eshell-find-alias-function command)) 1313 (sym (or esym (intern-soft command)))) 1314 (if (and sym (fboundp sym) 1315 (or esym eshell-prefer-lisp-functions 1316 (not (eshell-search-path command)))) 1317 (eshell-lisp-command sym args) 1318 (eshell-external-command command args)))) 1319 1320(defun eshell-exec-lisp (printer errprint func-or-form args form-p) 1321 "Execute a lisp FUNC-OR-FORM, maybe passing ARGS. 1322PRINTER and ERRPRINT are functions to use for printing regular 1323messages, and errors. FORM-P should be non-nil if FUNC-OR-FORM 1324represent a lisp form; ARGS will be ignored in that case." 1325 (let (result) 1326 (eshell-condition-case err 1327 (progn 1328 (setq result 1329 (save-current-buffer 1330 (if form-p 1331 (eval func-or-form) 1332 (apply func-or-form args)))) 1333 (and result (funcall printer result)) 1334 result) 1335 (error 1336 (let ((msg (error-message-string err))) 1337 (if (and (not form-p) 1338 (string-match "^Wrong number of arguments" msg) 1339 (fboundp 'eldoc-get-fnsym-args-string)) 1340 (let ((func-doc (eldoc-get-fnsym-args-string func-or-form))) 1341 (setq msg (format "usage: %s" func-doc)))) 1342 (funcall errprint msg)) 1343 nil)))) 1344 1345(defsubst eshell-apply* (printer errprint func args) 1346 "Call FUNC, with ARGS, trapping errors and return them as output. 1347PRINTER and ERRPRINT are functions to use for printing regular 1348messages, and errors." 1349 (eshell-exec-lisp printer errprint func args nil)) 1350 1351(defsubst eshell-funcall* (printer errprint func &rest args) 1352 "Call FUNC, with ARGS, trapping errors and return them as output." 1353 (eshell-apply* printer errprint func args)) 1354 1355(defsubst eshell-eval* (printer errprint form) 1356 "Evaluate FORM, trapping errors and returning them." 1357 (eshell-exec-lisp printer errprint form nil t)) 1358 1359(defsubst eshell-apply (func args) 1360 "Call FUNC, with ARGS, trapping errors and return them as output. 1361PRINTER and ERRPRINT are functions to use for printing regular 1362messages, and errors." 1363 (eshell-apply* 'eshell-print 'eshell-error func args)) 1364 1365(defsubst eshell-funcall (func &rest args) 1366 "Call FUNC, with ARGS, trapping errors and return them as output." 1367 (eshell-apply func args)) 1368 1369(defsubst eshell-eval (form) 1370 "Evaluate FORM, trapping errors and returning them." 1371 (eshell-eval* 'eshell-print 'eshell-error form)) 1372 1373(defsubst eshell-applyn (func args) 1374 "Call FUNC, with ARGS, trapping errors and return them as output. 1375PRINTER and ERRPRINT are functions to use for printing regular 1376messages, and errors." 1377 (eshell-apply* 'eshell-printn 'eshell-errorn func args)) 1378 1379(defsubst eshell-funcalln (func &rest args) 1380 "Call FUNC, with ARGS, trapping errors and return them as output." 1381 (eshell-applyn func args)) 1382 1383(defsubst eshell-evaln (form) 1384 "Evaluate FORM, trapping errors and returning them." 1385 (eshell-eval* 'eshell-printn 'eshell-errorn form)) 1386 1387(defun eshell-lisp-command (object &optional args) 1388 "Insert Lisp OBJECT, using ARGS if a function." 1389 (catch 'eshell-external ; deferred to an external command 1390 (let* ((eshell-ensure-newline-p (eshell-interactive-output-p)) 1391 (result 1392 (if (functionp object) 1393 (progn 1394 (setq eshell-last-arguments args 1395 eshell-last-command-name 1396 (concat "#<function " (symbol-name object) ">")) 1397 ;; if any of the arguments are flagged as numbers 1398 ;; waiting for conversion, convert them now 1399 (unless (get object 'eshell-no-numeric-conversions) 1400 (while args 1401 (let ((arg (car args))) 1402 (if (and (stringp arg) 1403 (> (length arg) 0) 1404 (not (text-property-not-all 1405 0 (length arg) 'number t arg))) 1406 (setcar args (string-to-number arg)))) 1407 (setq args (cdr args)))) 1408 (eshell-apply object eshell-last-arguments)) 1409 (setq eshell-last-arguments args 1410 eshell-last-command-name "#<Lisp object>") 1411 (eshell-eval object)))) 1412 (if (and eshell-ensure-newline-p 1413 (save-excursion 1414 (goto-char eshell-last-output-end) 1415 (not (bolp)))) 1416 (eshell-print "\n")) 1417 (eshell-close-handles 0 (list 'quote result))))) 1418 1419(defalias 'eshell-lisp-command* 'eshell-lisp-command) 1420 1421;;; arch-tag: 8e4f3867-a0c5-441f-96ba-ddd142d94366 1422;;; esh-cmd.el ends here 1423