Update copyright notices for 2013.
[bpt/emacs.git] / lisp / eshell / eshell.el
index 5829f31..a76adb1 100644 (file)
@@ -1,7 +1,6 @@
 ;;; eshell.el --- the Emacs command shell
 
-;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004,
-;;   2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2013 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@gnu.org>
 ;; Version: 2.4.2
@@ -9,10 +8,10 @@
 
 ;; This file is part of GNU Emacs.
 
-;; GNU Emacs is free software; you can redistribute it and/or modify
+;; 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 3, or (at your option)
-;; any later version.
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
 
 ;; GNU Emacs is distributed in the hope that it will be useful,
 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
 ;; GNU General Public License for more details.
 
 ;; 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., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
-
-(provide 'eshell)
-
-(eval-when-compile (require 'esh-maint))
-
-(defgroup eshell nil
-  "Eshell is a command shell implemented entirely in Emacs Lisp.  It
-invokes no external processes beyond those requested by the user.  It
-is intended to be a functional replacement for command shells such as
-bash, zsh, rc, 4dos; since Emacs itself is capable of handling most of
-the tasks accomplished by such tools."
-  :tag "The Emacs shell"
-  :link '(info-link "(eshell)Top")
-  :version "21.1"
-  :group 'applications)
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
 
 ;;; Commentary:
 
@@ -73,33 +55,9 @@ the tasks accomplished by such tools."
 ;; @ Alias functions, both Lisp and Eshell-syntax
 ;; @ Piping, sequenced commands, background jobs, etc...
 ;;
-;;;_* Eshell is free software
-;;
-;; Eshell 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 3, or (at your option)
-;; any later version.
-;;
-;; This program is distributed in the hope that it will be useful, but
-;; WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-;; General Public License for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with Eshell; see the file COPYING.  If not, write to the Free
-;; Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
-;; MA 02110-1301, USA.
-;;
 ;;;_* How to begin
 ;;
-;; To start using Eshell, add the following to your .emacs file:
-;;
-;;   (load "eshell-auto")
-;;
-;; This will define all of the necessary autoloads.
-;;
-;; Now type `M-x eshell'.  See the INSTALL file for full installation
-;; instructions.
+;; To start using Eshell, simply type `M-x eshell'.
 ;;
 ;;;_* Philosophy
 ;;
@@ -182,12 +140,12 @@ the tasks accomplished by such tools."
 ;;   paragraph wasn't discovered until two months after I wrote the
 ;;   text; it was not intentional).
 ;;
-;; @ Emacs' register and bookmarking facilities can be used for
+;; @ Emacs's register and bookmarking facilities can be used for
 ;;   remembering where you've been, and what you've seen -- to varying
 ;;   levels of persistence.  They could perhaps even be tied to
 ;;   specific "moments" during eshell execution, which would include
 ;;   the environment at that time, as well as other variables.
-;;   Although this would require functionality orthogonal to Emacs'
+;;   Although this would require functionality orthogonal to Emacs's
 ;;   own bookmarking facilities, the interface used could be made to
 ;;   operate very similarly.
 ;;
@@ -263,66 +221,58 @@ the tasks accomplished by such tools."
 ;; will only have to read in this one file, which will greatly speed
 ;; things up.
 
+(eval-when-compile
+  (require 'cl-lib)
+  (require 'esh-util))
+(require 'esh-util)
+(require 'esh-mode)
+
+(defgroup eshell nil
+  "Command shell implemented entirely in Emacs Lisp.
+It invokes no external processes beyond those requested by the
+user, and is intended to be a functional replacement for command
+shells such as bash, zsh, rc, 4dos."
+  :link '(info-link "(eshell)Top")
+  :version "21.1"
+  :group 'applications)
+
 ;;;_* User Options
 ;;
 ;; The following user options modify the behavior of Eshell overall.
+(defvar eshell-buffer-name)
 
-(unless (featurep 'esh-util)
-  (load "esh-util" nil t))
-
-(defsubst eshell-add-to-window-buffer-names ()
+(defun eshell-add-to-window-buffer-names ()
   "Add `eshell-buffer-name' to `same-window-buffer-names'."
+  (declare (obsolete nil "24.3"))
   (add-to-list 'same-window-buffer-names eshell-buffer-name))
 
-(defsubst eshell-remove-from-window-buffer-names ()
+(defun eshell-remove-from-window-buffer-names ()
   "Remove `eshell-buffer-name' from `same-window-buffer-names'."
+  (declare (obsolete nil "24.3"))
   (setq same-window-buffer-names
        (delete eshell-buffer-name same-window-buffer-names)))
 
 (defcustom eshell-load-hook nil
-  "*A hook run once Eshell has been loaded."
+  "A hook run once Eshell has been loaded."
   :type 'hook
   :group 'eshell)
 
-(defcustom eshell-unload-hook
-  '(eshell-remove-from-window-buffer-names
-    eshell-unload-all-modules)
-  "*A hook run when Eshell is unloaded from memory."
+(defcustom eshell-unload-hook '(eshell-unload-all-modules)
+  "A hook run when Eshell is unloaded from memory."
   :type 'hook
   :group 'eshell)
 
 (defcustom eshell-buffer-name "*eshell*"
-  "*The basename used for Eshell buffers."
-  :set (lambda (symbol value)
-        ;; remove the old value of `eshell-buffer-name', if present
-        (if (boundp 'eshell-buffer-name)
-            (eshell-remove-from-window-buffer-names))
-        (set symbol value)
-        ;; add the new value
-        (eshell-add-to-window-buffer-names)
-        value)
+  "The basename used for Eshell buffers."
   :type 'string
   :group 'eshell)
 
-(eshell-deftest mode same-window-buffer-names
-  "`eshell-buffer-name' is a member of `same-window-buffer-names'"
-  (member eshell-buffer-name same-window-buffer-names))
-
-(defcustom eshell-directory-name (convert-standard-filename "~/.eshell/")
-  "*The directory where Eshell control files should be kept."
+(defcustom eshell-directory-name
+  (locate-user-emacs-file "eshell/" ".eshell/")
+  "The directory where Eshell control files should be kept."
   :type 'directory
   :group 'eshell)
 
-(eshell-deftest mode eshell-directory-exists
-  "`eshell-directory-name' exists and is writable"
-  (file-writable-p eshell-directory-name))
-
-(eshell-deftest mode eshell-directory-modes
-  "`eshell-directory-name' has correct access protections"
-  (or (eshell-under-windows-p)
-      (= (file-modes eshell-directory-name)
-        eshell-private-directory-modes)))
-
 ;;;_* Running Eshell
 ;;
 ;; There are only three commands used to invoke Eshell.  The first two
@@ -340,7 +290,7 @@ switches to the session with that number, creating it if necessary.  A
 nonnumeric prefix arg means to create a new session.  Returns the
 buffer selected (or created)."
   (interactive "P")
-  (assert eshell-buffer-name)
+  (cl-assert eshell-buffer-name)
   (let ((buf (cond ((numberp arg)
                    (get-buffer-create (format "%s<%d>"
                                               eshell-buffer-name
@@ -349,17 +299,10 @@ buffer selected (or created)."
                    (generate-new-buffer eshell-buffer-name))
                   (t
                    (get-buffer-create eshell-buffer-name)))))
-    ;; Simply calling `pop-to-buffer' will not mimic the way that
-    ;; shell-mode buffers appear, since they always reuse the same
-    ;; window that that command was invoked from.  To achieve this,
-    ;; it's necessary to add `eshell-buffer-name' to the variable
-    ;; `same-window-buffer-names', which is done when Eshell is loaded
-    (assert (and buf (buffer-live-p buf)))
-    (pop-to-buffer buf)
-    (if (fboundp 'eshell-mode)
-       (unless (eq major-mode 'eshell-mode)
-         (eshell-mode))
-      (error "`eshell-auto' must be loaded before Eshell can be used"))
+    (cl-assert (and buf (buffer-live-p buf)))
+    (pop-to-buffer-same-window buf)
+    (unless (eq major-mode 'eshell-mode)
+      (eshell-mode))
     buf))
 
 (defun eshell-return-exits-minibuffer ()
@@ -383,16 +326,14 @@ With prefix ARG, insert output into the current buffer at point."
   (require 'esh-cmd)
   (unless arg
     (setq arg current-prefix-arg))
-  (unwind-protect
-      (let ((eshell-non-interactive-p t))
-       (add-hook 'minibuffer-setup-hook 'eshell-mode)
-       (add-hook 'minibuffer-exit-hook 'eshell-add-command-to-history)
-       (add-hook 'eshell-mode-hook 'eshell-return-exits-minibuffer)
-       (unless command
-         (setq command (read-from-minibuffer "Emacs shell command: "))))
-    (remove-hook 'eshell-mode-hook 'eshell-return-exits-minibuffer)
-    (remove-hook 'minibuffer-exit-hook 'eshell-add-command-to-history)
-    (remove-hook 'minibuffer-setup-hook 'eshell-mode))
+  (let ((eshell-non-interactive-p t))
+    ;; Enable `eshell-mode' only in this minibuffer.
+    (minibuffer-with-setup-hook #'(lambda ()
+                                    (eshell-mode)
+                                    (eshell-return-exits-minibuffer))
+      (unless command
+        (setq command (read-from-minibuffer "Emacs shell command: "))
+        (eshell-add-input-to-history command))))
   (unless command
     (error "No command specified!"))
   ;; redirection into the current buffer is achieved by adding an
@@ -406,7 +347,6 @@ With prefix ARG, insert output into the current buffer at point."
                    (format " >>> #<buffer %s>"
                            (buffer-name (current-buffer))))))
   (save-excursion
-    (require 'esh-mode)
     (let ((buf (set-buffer (generate-new-buffer " *eshell cmd*")))
          (eshell-non-interactive-p t))
       (eshell-mode)
@@ -427,11 +367,11 @@ With prefix ARG, insert output into the current buffer at point."
        (when intr
          (if (eshell-interactive-process)
              (eshell-wait-for-process (eshell-interactive-process)))
-         (assert (not (eshell-interactive-process)))
+         (cl-assert (not (eshell-interactive-process)))
          (goto-char (point-max))
          (while (and (bolp) (not (bobp)))
-           (delete-backward-char 1)))
-       (assert (and buf (buffer-live-p buf)))
+           (delete-char -1)))
+       (cl-assert (and buf (buffer-live-p buf)))
        (unless arg
          (let ((len (if (not intr) 2
                       (count-lines (point-min) (point-max)))))
@@ -465,58 +405,25 @@ corresponding to a successful execution."
        (if (and status-var (symbolp status-var))
           (set status-var 0)))
     (with-temp-buffer
-      (require 'esh-mode)
       (let ((eshell-non-interactive-p t))
        (eshell-mode)
        (let ((result (eshell-do-eval
                       (list 'eshell-commands
                             (list 'eshell-command-to-value
                                   (eshell-parse-command command))) t)))
-         (assert (eq (car result) 'quote))
+         (cl-assert (eq (car result) 'quote))
          (if (and status-var (symbolp status-var))
              (set status-var eshell-last-command-status))
          (cadr result))))))
 
-(eshell-deftest mode simple-command-result
-  "`eshell-command-result' works with a simple command."
-  (= (eshell-command-result "+ 1 2") 3))
-
 ;;;_* Reporting bugs
 ;;
-;; Since Eshell has not yet been in use by a wide audience, and since
-;; the number of possible configurations is quite large, it is certain
-;; that many bugs slipped past the rigors of testing it was put
-;; through.  If you do encounter a bug, on any system, please report
+;; If you do encounter a bug, on any system, please report
 ;; it -- in addition to any particular oddities in your configuration
 ;; -- so that the problem may be corrected for the benefit of others.
 
-(defconst eshell-report-bug-address "johnw@gnu.org"
-  "E-mail address to send Eshell bug reports to.")
-
 ;;;###autoload
-(defun eshell-report-bug (topic)
-  "Report a bug in Eshell.
-Prompts for the TOPIC.  Leaves you in a mail buffer.
-Please include any configuration details that might be involved."
-  (interactive "sBug Subject: ")
-  (compose-mail eshell-report-bug-address topic)
-  (goto-char (point-min))
-  (re-search-forward (concat "^" (regexp-quote mail-header-separator) "$"))
-  (forward-line 1)
-  (let ((signature (buffer-substring (point) (point-max))))
-    ;; Discourage users from writing non-English text.
-    (set-buffer-multibyte nil)
-    (delete-region (point) (point-max))
-    (insert signature)
-    (backward-char (length signature)))
-  (insert "emacs-version: " (emacs-version))
-  (insert "\n\nThere appears to be a bug in Eshell.\n\n"
-         "Please describe exactly what actions "
-         "triggered the bug and the precise\n"
-         "symptoms of the bug:\n\n")
-  ;; This is so the user has to type something in order to send
-  ;; the report easily.
-  (use-local-map (nconc (make-sparse-keymap) (current-local-map))))
+(define-obsolete-function-alias 'eshell-report-bug 'report-emacs-bug "23.1")
 
 ;;; Code:
 
@@ -529,7 +436,7 @@ Emacs."
   ;; if the user set `eshell-prefer-to-shell' to t, but never loaded
   ;; Eshell, then `eshell-subgroups' will be unbound
   (when (fboundp 'eshell-subgroups)
-    (eshell-for module (eshell-subgroups 'eshell)
+    (dolist (module (eshell-subgroups 'eshell))
       ;; this really only unloads as many modules as possible,
       ;; since other `require' references (such as by customizing
       ;; `eshell-prefer-to-shell' to a non-nil value) might make it
@@ -543,5 +450,6 @@ Emacs."
 
 (run-hooks 'eshell-load-hook)
 
-;;; arch-tag: 9d4d5214-0e4e-4e02-b349-39add640d63f
+(provide 'eshell)
+
 ;;; eshell.el ends here