Add arch taglines
[bpt/emacs.git] / lisp / eshell / em-smart.el
index ac2545b..6725f96 100644 (file)
@@ -1,6 +1,8 @@
-;;; em-smart --- smart display of output
+;;; em-smart.el --- smart display of output
 
-;; Copyright (C) 1999, 2000 Free Sofware Foundation
+;; Copyright (C) 1999, 2000 Free Software Foundation
+
+;; Author: John Wiegley <johnw@gnu.org>
 
 ;; This file is part of GNU Emacs.
 
@@ -31,7 +33,7 @@ some of the edit/review concepts inherent in the design of Plan 9's
 Most likely you will have to turn this option on and play around with
 it to get a real sense of how it works."
   :tag "Smart display of output"
-  :link '(info-link "(eshell.info)Smart display of output")
+  :link '(info-link "(eshell)Smart display of output")
   :group 'eshell-module)
 
 ;;; Commentary:
@@ -75,6 +77,11 @@ it to get a real sense of how it works."
 ;;   scroll, etc.
 ;;
 ;; @ Like I said, it's not really comprehensible until you try it! ;)
+;;
+;; One disadvantage of this module is that it increases Eshell's
+;; memory consumption by a factor of two or more.  With small commands
+;; (such as pwd), where the screen is mostly full, consumption can
+;; increase by orders of magnitude.
 
 ;;; User Variables:
 
@@ -94,10 +101,20 @@ it to get a real sense of how it works."
   :group 'eshell-smart)
 
 (defcustom eshell-review-quick-commands nil
-  "*If nil, point does not stay on quick commands.
-A quick command is one that produces no output, and exits
-successfully."
-  :type 'boolean
+  "*If t, always review commands.
+Reviewing means keeping point on the text of the command that was just
+invoked, to allow corrections to be made easily.
+
+If set to nil, quick commands won't be reviewed.  A quick command is a
+command that produces no output, and exits successfully.
+
+If set to `not-even-short-output', then the definition of \"quick
+command\" is extended to include commands that produce output, iff
+that output can be presented in its entirely in the Eshell window."
+  :type '(choice (const :tag "No" nil)
+                (const :tag "Yes" t)
+                (const :tag "Not even short output"
+                       not-even-short-output))
   :group 'eshell-smart)
 
 (defcustom eshell-smart-display-navigate-list
@@ -142,6 +159,7 @@ The options are `begin', `after' or `end'."
 
 (defvar eshell-smart-displayed nil)
 (defvar eshell-smart-command-done nil)
+(defvar eshell-currently-handling-window nil)
 
 ;;; Functions:
 
@@ -154,30 +172,22 @@ The options are `begin', `after' or `end'."
     (set (make-local-variable 'eshell-scroll-to-bottom-on-input) nil)
     (set (make-local-variable 'eshell-scroll-show-maximum-output) t)
 
-    (make-local-hook 'window-scroll-functions)
     (add-hook 'window-scroll-functions 'eshell-smart-scroll-window nil t)
     (add-hook 'window-configuration-change-hook 'eshell-refresh-windows)
 
-    (make-local-hook 'eshell-output-filter-functions)
     (add-hook 'eshell-output-filter-functions 'eshell-refresh-windows t t)
 
-    (make-local-hook 'pre-command-hook)
-    (make-local-hook 'after-change-functions)
-    (add-hook 'after-change-functions
-             'eshell-disable-after-change nil t)
+    (add-hook 'after-change-functions 'eshell-disable-after-change nil t)
 
-    (make-local-hook 'eshell-input-filter-functions)
-    (add-hook 'eshell-input-filter-functions
-             'eshell-smart-display-setup nil t)
+    (add-hook 'eshell-input-filter-functions 'eshell-smart-display-setup nil t)
 
     (make-local-variable 'eshell-smart-command-done)
-    (make-local-hook 'eshell-post-command-hook)
-    (add-hook  'eshell-post-command-hook
-              (function
-               (lambda ()
-                 (setq eshell-smart-command-done t))) t t)
+    (add-hook 'eshell-post-command-hook
+             (function
+              (lambda ()
+                (setq eshell-smart-command-done t))) t t)
 
-    (unless eshell-review-quick-commands
+    (unless (eq eshell-review-quick-commands t)
       (add-hook 'eshell-post-command-hook
                'eshell-smart-maybe-jump-to-end nil t))))
 
@@ -186,10 +196,9 @@ The options are `begin', `after' or `end'."
   (unless eshell-currently-handling-window
     (let ((inhibit-point-motion-hooks t)
          (eshell-currently-handling-window t))
-      (save-current-buffer
-       (save-selected-window
-         (select-window wind)
-         (eshell-smart-redisplay))))))
+      (save-selected-window
+       (select-window wind)
+       (eshell-smart-redisplay)))))
 
 (defun eshell-refresh-windows (&optional frame)
   "Refresh all visible Eshell buffers."
@@ -198,10 +207,10 @@ The options are `begin', `after' or `end'."
      (function
       (lambda (wind)
        (with-current-buffer (window-buffer wind)
-         (when eshell-mode
-           (let (window-scroll-functions)
-             (eshell-smart-scroll-window wind (window-start))
-             (setq affected t))))))
+         (if eshell-mode
+             (let (window-scroll-functions)
+               (eshell-smart-scroll-window wind (window-start))
+               (setq affected t))))))
      0 frame)
     (if affected
        (let (window-scroll-functions)
@@ -233,27 +242,39 @@ The options are `begin', `after' or `end'."
 
 (defun eshell-smart-maybe-jump-to-end ()
   "Jump to the end of the input buffer.
-This is done whenever a command exits sucessfully that displayed no
-output."
+This is done whenever a command exits sucessfully and both the command
+and the end of the buffer are still visible."
   (when (and (= eshell-last-command-status 0)
-            (= (count-lines eshell-last-input-end
-                            eshell-last-output-end) 0))
+            (if (eq eshell-review-quick-commands 'not-even-short-output)
+                (and (pos-visible-in-window-p (point-max))
+                     (pos-visible-in-window-p eshell-last-input-start))
+              (= (count-lines eshell-last-input-end
+                              eshell-last-output-end) 0)))
     (goto-char (point-max))
     (remove-hook 'pre-command-hook 'eshell-smart-display-move t)))
 
 (defun eshell-smart-redisplay ()
   "Display as much output as possible, smartly."
   (if (eobp)
-      (recenter -1)
-    (and (memq 'eshell-smart-display-move pre-command-hook)
-        (>= (point) eshell-last-input-start)
-        (< (point) eshell-last-input-end)
-        (set-window-start (selected-window)
-                          (line-beginning-position) t))
-    (if (pos-visible-in-window-p (point-max))
-       (save-excursion
-         (goto-char (point-max))
-         (recenter -1)))))
+      (save-excursion
+       (recenter -1)
+       ;; trigger the redisplay now, so that we catch any attempted
+       ;; point motion; this is to cover for a redisplay bug
+       (eshell-redisplay))
+    (let ((top-point (point)))
+      (and (memq 'eshell-smart-display-move pre-command-hook)
+          (>= (point) eshell-last-input-start)
+          (< (point) eshell-last-input-end)
+          (set-window-start (selected-window)
+                            (line-beginning-position) t))
+      (if (pos-visible-in-window-p (point-max))
+         (save-excursion
+           (goto-char (point-max))
+           (recenter -1)
+           (unless (pos-visible-in-window-p top-point)
+             (goto-char top-point)
+             (set-window-start (selected-window)
+                               (line-beginning-position) t)))))))
 
 (defun eshell-smart-goto-end ()
   "Like `end-of-buffer', but do not push a mark."
@@ -302,4 +323,5 @@ output."
 
 ;;; Code:
 
+;;; arch-tag: 8c0112c7-379c-4d54-9a1c-204d68786a4b
 ;;; em-smart.el ends here