-;;; esh-cmd --- command invocation
+;;; esh-cmd.el --- command invocation
-;; Copyright (C) 1999, 2000 Free Software Foundation
+;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004,
+;; 2005, 2006, 2007 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@gnu.org>
;; GNU Emacs is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
+;; the Free Software Foundation; either version 3, or (at your option)
;; any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-(provide 'esh-cmd)
-
-(eval-when-compile (require 'esh-maint))
-
-(defgroup eshell-cmd nil
- "Executing an Eshell command is as simple as typing it in and
-pressing <RET>. There are several different kinds of commands,
-however."
- :tag "Command invocation"
- :link '(info-link "(eshell)Command invocation")
- :group 'eshell)
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
;;; Commentary:
;; functions always take precedence, set
;; `eshell-prefer-lisp-functions' to t.
-(defcustom eshell-prefer-lisp-functions nil
- "*If non-nil, prefer Lisp functions to external commands."
- :type 'boolean
- :group 'eshell-cmd)
-
;;;_* Alias functions
;;
;; Whenever a command is specified using a simple name, such as 'ls',
;;
;; Lisp arguments are identified using the following regexp:
+;;;_* Command hooks
+;;
+;; There are several hooks involved with command execution, which can
+;; be used either to change or augment Eshell's behavior.
+
+
+;;; Code:
+
+(require 'esh-util)
+(unless (featurep 'xemacs)
+ (require 'eldoc))
+(require 'esh-arg)
+(require 'esh-proc)
+(require 'esh-ext)
+
+(eval-when-compile
+ (require 'pcomplete))
+
+
+(defgroup eshell-cmd nil
+ "Executing an Eshell command is as simple as typing it in and
+pressing <RET>. There are several different kinds of commands,
+however."
+ :tag "Command invocation"
+ ;; :link '(info-link "(eshell)Command invocation")
+ :group 'eshell)
+
+(defcustom eshell-prefer-lisp-functions nil
+ "*If non-nil, prefer Lisp functions to external commands."
+ :type 'boolean
+ :group 'eshell-cmd)
+
(defcustom eshell-lisp-regexp "\\([(`]\\|#'\\)"
"*A regexp which, if matched at beginning of an argument, means Lisp.
Such arguments will be passed to `read', and then evaluated."
:type 'regexp
:group 'eshell-cmd)
-;;;_* Command hooks
-;;
-;; There are several hooks involved with command execution, which can
-;; be used either to change or augment Eshell's behavior.
-
(defcustom eshell-pre-command-hook nil
"*A hook run before each interactive command is invoked."
:type 'hook
:type 'hook
:group 'eshell-cmd)
-(defcustom eshell-complex-commands nil
+(defcustom eshell-complex-commands '("ls")
"*A list of commands names or functions, that determine complexity.
That is, if a command is defined by a function named eshell/NAME,
and NAME is part of this list, it is invoked as a complex command.
(function :tag "Predicate")))
:group 'eshell-cmd)
-;;; Code:
-
-(require 'esh-util)
-(unless (eshell-under-xemacs-p)
- (require 'eldoc))
-(require 'esh-arg)
-(require 'esh-proc)
-(require 'esh-ext)
-
;;; User Variables:
(defcustom eshell-cmd-load-hook '(eshell-cmd-initialize)
(set (make-local-variable 'eshell-last-command-name) nil)
(set (make-local-variable 'eshell-last-async-proc) nil)
- (make-local-hook 'eshell-kill-hook)
(add-hook 'eshell-kill-hook 'eshell-resume-command nil t)
;; make sure that if a command is over, and no process is being
;; waited for, that `eshell-current-command' is set to nil. This
;; situation can occur, for example, if a Lisp function results in
;; `debug' being called, and the user then types \\[top-level]
- (make-local-hook 'eshell-post-command-hook)
(add-hook 'eshell-post-command-hook
(function
(lambda ()
(setq eshell-current-command nil
eshell-last-async-proc nil))) nil t)
- (make-local-hook 'eshell-parse-argument-hook)
(add-hook 'eshell-parse-argument-hook
'eshell-parse-subcommand-argument nil t)
(add-hook 'eshell-parse-argument-hook
'eshell-parse-lisp-argument nil t)
(when (eshell-using-module 'eshell-cmpl)
- (make-local-hook 'pcomplete-try-first-hook)
(add-hook 'pcomplete-try-first-hook
'eshell-complete-lisp-symbols nil t)))
(list 'eshell-commands commands)
commands)))
+(defun eshell-debug-command (tag subform)
+ "Output a debugging message to '*eshell last cmd*'."
+ (let ((buf (get-buffer-create "*eshell last cmd*"))
+ (text (eshell-stringify eshell-current-command)))
+ (save-excursion
+ (set-buffer buf)
+ (if (not tag)
+ (erase-buffer)
+ (insert "\n\C-l\n" tag "\n\n" text
+ (if subform
+ (concat "\n\n" (eshell-stringify subform)) ""))))))
+
(defun eshell-debug-show-parsed-args (terms)
"Display parsed arguments in the debug buffer."
(ignore
(defun eshell-rewrite-named-command (terms)
"If no other rewriting rule transforms TERMS, assume a named command."
- (list (if eshell-in-pipeline-p
- 'eshell-named-command*
- 'eshell-named-command)
- (car terms)
- (and (cdr terms)
- (append (list 'list) (cdr terms)))))
+ (let ((sym (if eshell-in-pipeline-p
+ 'eshell-named-command*
+ 'eshell-named-command))
+ (cmd (car terms))
+ (args (cdr terms)))
+ (if args
+ (list sym cmd (append (list 'list) (cdr terms)))
+ (list sym cmd))))
(eshell-deftest cmd named-command
"Execute named command"
(defun eshell-rewrite-for-command (terms)
"Rewrite a `for' command into its equivalent Eshell command form.
Because the implementation of `for' relies upon conditional evaluation
-of its argumbent (i.e., use of a Lisp special form), it must be
+of its argument (i.e., use of a Lisp special form), it must be
implemented via rewriting, rather than as a function."
(if (and (stringp (car terms))
(string= (car terms) "for")
(eshell-invokify-arg (cadr terms) nil t)
(list 'eshell-protect
(eshell-invokify-arg
- (if (= (length terms) 5)
- (car (last terms 3))
+ (if (= (length terms) 4)
+ (car (last terms 2))
(car (last terms))) t))
- (if (= (length terms) 5)
+ (if (= (length terms) 4)
(list 'eshell-protect
(eshell-invokify-arg
(car (last terms)))) t))))
"Return non-nil if the last command was \"successful\".
For a bit of Lisp code, this means a return value of non-nil.
For an external command, it means an exit code of 0."
- (if (string= eshell-last-command-name "#<Lisp>")
+ (if (save-match-data
+ (string-match "#<\\(Lisp object\\|function .*\\)>"
+ eshell-last-command-name))
eshell-last-command-result
(= eshell-last-command-status 0)))
reversed last-terms-sym)
"Separate TERMS using SEPARATOR.
If REVERSED is non-nil, the list of separated term groups will be
-returned in reverse order. If LAST-TERMS-SYM is a symbol, it's value
+returned in reverse order. If LAST-TERMS-SYM is a symbol, its value
will be set to a list of all the separator operators found (or '(list
nil)' if none)."
(let ((sub-terms (list t))
(defmacro eshell-do-subjob (object)
"Evaluate a command OBJECT as a subjob.
-We indicate thet the process was run in the background by returned it
+We indicate that the process was run in the background by returning it
ensconced in a list."
`(let ((eshell-current-subjob-p t))
,object))
"Completion for the `debug' command."
(while (pcomplete-here '("errors" "commands"))))
-(defun eshell-debug-command (tag subform)
- "Output a debugging message to '*eshell last cmd*'."
- (let ((buf (get-buffer-create "*eshell last cmd*"))
- (text (eshell-stringify eshell-current-command)))
- (save-excursion
- (set-buffer buf)
- (if (not tag)
- (erase-buffer)
- (insert "\n\C-l\n" tag "\n\n" text
- (if subform
- (concat "\n\n" (eshell-stringify subform)) ""))))))
-
(defun eshell-invoke-directly (command input)
(let ((base (cadr (nth 2 (nth 2 (cadr command))))) name)
(if (and (eq (car base) 'eshell-trap-errors)
(setq eshell-current-command command)
(let ((delim (catch 'eshell-incomplete
(eshell-resume-eval))))
- (if delim
- (error "Unmatched delimiter: %c"
- (if (listp delim)
- (car delim)
- delim))))))
+ ;; On systems that don't support async subprocesses, eshell-resume
+ ;; can return t. Don't treat that as an error.
+ (if (listp delim)
+ (setq delim (car delim)))
+ (if (and delim (not (eq delim t)))
+ (error "Unmatched delimiter: %c" delim)))))
(defun eshell-resume-command (proc status)
"Resume the current command when a process ends."
object)
(defconst function-p-func
- (if (eshell-under-xemacs-p)
+ (if (fboundp 'compiled-function-p)
'compiled-function-p
'byte-code-function-p))
"Identify the COMMAND, and where it is located."
(eshell-for name (cons command names)
(let (program alias direct)
- (if (eq (aref name 0) ?*)
+ (if (eq (aref name 0) eshell-explicit-command-char)
(setq name (substring name 1)
direct t))
(if (and (not direct)
(setq program (eshell-search-path name))
(let* ((esym (eshell-find-alias-function name))
(sym (or esym (intern-soft name))))
- (if (and sym (fboundp sym)
- (or esym eshell-prefer-lisp-functions
- (not program)))
+ (if (and (or esym (and sym (fboundp sym)))
+ (or eshell-prefer-lisp-functions (not direct)))
(let ((desc (let ((inhibit-redisplay t))
(save-window-excursion
(prog1
name (getenv "PATH")))
(eshell-printn program)))))
+(put 'eshell/which 'eshell-no-numeric-conversions t)
+
(defun eshell-named-command (command &optional args)
"Insert output from a plain COMMAND, using ARGS.
COMMAND may result in an alias being executed, or a plain command."
(defun eshell-find-alias-function (name)
"Check whether a function called `eshell/NAME' exists."
(let* ((sym (intern-soft (concat "eshell/" name)))
- (file (symbol-file sym)))
+ (file (symbol-file sym 'defun)))
;; If the function exists, but is defined in an eshell module
;; that's not currently enabled, don't report it as found
(if (and file
(intern (file-name-sans-extension
(file-name-nondirectory
(concat "eshell-" (match-string 2 file)))))))
- (if (and (eshell-using-module module-sym)
- (memq module-sym (eshell-subgroups 'eshell)))
+ (if (and (functionp sym)
+ (or (null module-sym)
+ (eshell-using-module module-sym)
+ (memq module-sym (eshell-subgroups 'eshell))))
sym))
;; Otherwise, if it's bound, return it.
(if (functionp sym)
(defun eshell-lisp-command (object &optional args)
"Insert Lisp OBJECT, using ARGS if a function."
- (setq eshell-last-arguments args
- eshell-last-command-name "#<Lisp>")
(catch 'eshell-external ; deferred to an external command
(let* ((eshell-ensure-newline-p (eshell-interactive-output-p))
(result
(if (functionp object)
- (eshell-apply object args)
+ (progn
+ (setq eshell-last-arguments args
+ eshell-last-command-name
+ (concat "#<function " (symbol-name object) ">"))
+ ;; if any of the arguments are flagged as numbers
+ ;; waiting for conversion, convert them now
+ (unless (get object 'eshell-no-numeric-conversions)
+ (while args
+ (let ((arg (car args)))
+ (if (and (stringp arg)
+ (> (length arg) 0)
+ (not (text-property-not-all
+ 0 (length arg) 'number t arg)))
+ (setcar args (string-to-number arg))))
+ (setq args (cdr args))))
+ (eshell-apply object eshell-last-arguments))
+ (setq eshell-last-arguments args
+ eshell-last-command-name "#<Lisp object>")
(eshell-eval object))))
(if (and eshell-ensure-newline-p
(save-excursion
(defalias 'eshell-lisp-command* 'eshell-lisp-command)
+(provide 'esh-cmd)
+
+;;; arch-tag: 8e4f3867-a0c5-441f-96ba-ddd142d94366
;;; esh-cmd.el ends here