]> code.delx.au - gnu-emacs/blobdiff - lisp/reveal.el
2005-10-01 Roland Winkler <Roland.Winkler@physik.uni-erlangen.de>
[gnu-emacs] / lisp / reveal.el
index 11f8c11c936e33dfe650f6b6e7cf2d5fb7535b4e..41b7c4268c27de713de93954a1f12675fe8b5bfd 100644 (file)
@@ -1,6 +1,7 @@
 ;;; reveal.el --- Automatically reveal hidden text at point
 
-;; Copyright (C) 2000, 2001  Free Software Foundation, Inc.
+;; Copyright (C) 2000, 2001, 2002, 2003, 2004,
+;;   2005 Free Software Foundation, Inc.
 
 ;; Author: Stefan Monnier <monnier@cs.yale.edu>
 ;; Keywords: outlines
@@ -19,8 +20,8 @@
 
 ;; 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.
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
 
 ;;; Commentary:
 
 
 (defcustom reveal-around-mark t
   "Reveal text around the mark, if active."
-  :type 'boolean)
+  :type 'boolean
+  :group 'reveal)
 
 (defvar reveal-open-spots nil)
 (make-variable-buffer-local 'reveal-open-spots)
 
+(defvar reveal-last-tick nil)
+(make-variable-buffer-local 'reveal-last-tick)
+
 ;; Actual code
 
 (defun reveal-post-command ()
                          (overlays-at (point))))
         (push (cons (selected-window) ol) reveal-open-spots)
         (setq old-ols (delq ol old-ols))
-        (let ((open (overlay-get ol 'reveal-toggle-invisible)))
-          (when (or open
-                    (let ((inv (overlay-get ol 'invisible)))
-                      (and inv (symbolp inv)
-                           (or (setq open (or (get inv 'reveal-toggle-invisible)
-                                              (overlay-get ol 'isearch-open-invisible-temporary)))
-                               (overlay-get ol 'isearch-open-invisible)
-                               (and (consp buffer-invisibility-spec)
-                                    (assq inv buffer-invisibility-spec)))
-                           (overlay-put ol 'reveal-invisible inv))))
+        (let ((inv (overlay-get ol 'invisible)) open)
+          (when (and inv
+                     ;; There's an `invisible' property.  Make sure it's
+                     ;; actually invisible.
+                     (or (not (listp buffer-invisibility-spec))
+                         (memq inv buffer-invisibility-spec)
+                         (assq inv buffer-invisibility-spec))
+                     (or (setq open
+                               (or (overlay-get ol 'reveal-toggle-invisible)
+                                   (and (symbolp inv)
+                                        (get inv 'reveal-toggle-invisible))
+                                   (overlay-get ol 'isearch-open-invisible-temporary)))
+                         (overlay-get ol 'isearch-open-invisible)
+                         (and (consp buffer-invisibility-spec)
+                              (cdr (assq inv buffer-invisibility-spec))))
+                     (overlay-put ol 'reveal-invisible inv))
             (if (null open)
                 (overlay-put ol 'invisible nil)
               ;; Use the provided opening function and repeat (since the
               (setq repeat t)
               (condition-case err
                   (funcall open ol nil)
-                (error (message "!!Reveal-show: %s !!" err)
+                (error (message "!!Reveal-show (funcall %s %s nil): %s !!"
+                                open ol err)
                        ;; Let's default to a meaningful behavior to avoid
                        ;; getting stuck in an infinite loop.
                        (setq repeat nil)
                        (overlay-put ol 'invisible nil))))))))
      ;; Close old overlays.
-     (dolist (ol old-ols)
-       (when (and (eq (current-buffer) (overlay-buffer ol))
-                 (not (rassq ol reveal-open-spots)))
-        (if (and (>= (point) (save-excursion
-                               (goto-char (overlay-start ol))
-                               (line-beginning-position 1)))
-                 (<= (point) (save-excursion
-                               (goto-char (overlay-end ol))
-                               (line-beginning-position 2))))
-            ;; Still near the overlay: keep it open.
-            (push (cons (selected-window) ol) reveal-open-spots)
-          ;; Really close it.
-          (let ((open (overlay-get ol 'reveal-toggle-invisible)) inv)
-            (if (or open
-                    (and (setq inv (overlay-get ol 'reveal-invisible))
-                         (setq open (or (get inv 'reveal-toggle-invisible)
-                                        (overlay-get ol 'isearch-open-invisible-temporary)))))
-                (condition-case err
-                    (funcall open ol t)
-                  (error (message "!!Reveal-hide: %s !!" err)))
-              (overlay-put ol 'invisible inv)))))))
+     (if (not (eq reveal-last-tick
+                 (setq reveal-last-tick (buffer-modified-tick))))
+        ;; The buffer was modified since last command: let's refrain from
+        ;; closing any overlay because it tends to behave poorly when
+        ;; inserting text at the end of an overlay (basically the overlay
+        ;; should be rear-advance when it's open, but things like
+        ;; outline-minor-mode make it non-rear-advance because it's
+        ;; a better choice when it's closed).
+        (dolist (ol old-ols)
+          (push (cons (selected-window) ol) reveal-open-spots))
+       ;; The last command was only a point motion or some such
+       ;; non-buffer-modifying command.  Let's close whatever can be closed.
+       (dolist (ol old-ols)
+        (when (and (eq (current-buffer) (overlay-buffer ol))
+                   (not (rassq ol reveal-open-spots)))
+          (if (and (>= (point) (save-excursion
+                                 (goto-char (overlay-start ol))
+                                 (line-beginning-position 1)))
+                   (<= (point) (save-excursion
+                                 (goto-char (overlay-end ol))
+                                 (line-beginning-position 2))))
+              ;; Still near the overlay: keep it open.
+              (push (cons (selected-window) ol) reveal-open-spots)
+            ;; Really close it.
+            (let ((open (overlay-get ol 'reveal-toggle-invisible)) inv)
+              (if (or open
+                      (and (setq inv (overlay-get ol 'reveal-invisible))
+                           (setq open (or (get inv 'reveal-toggle-invisible)
+                                          (overlay-get ol 'isearch-open-invisible-temporary)))))
+                  (condition-case err
+                      (funcall open ol t)
+                    (error (message "!!Reveal-hide (funcall %s %s t): %s !!"
+                                    open ol err)))
+                (overlay-put ol 'invisible inv))))))))
    (error (message "Reveal: %s" err)))))
 
+(defvar reveal-mode-map
+  (let ((map (make-sparse-keymap)))
+    ;; Override the default move-beginning-of-line and move-end-of-line
+    ;; which skips valuable invisible text.
+    (define-key map [remap move-beginning-of-line] 'beginning-of-line)
+    (define-key map [remap move-end-of-line] 'end-of-line)
+    map))
+
 ;;;###autoload
 (define-minor-mode reveal-mode
   "Toggle Reveal mode on or off.
@@ -144,7 +177,9 @@ Reveal mode renders invisible text around point visible again.
 Interactively, with no prefix argument, toggle the mode.
 With universal prefix ARG (or if ARG is nil) turn mode on.
 With zero or negative ARG turn mode off."
+  :group 'reveal
   :lighter (global-reveal-mode nil " Reveal")
+  :keymap reveal-mode-map
   (if reveal-mode
       (progn
        (set (make-local-variable 'search-invisible) t)
@@ -171,4 +206,5 @@ With zero or negative ARG turn mode off."
 
 (provide 'reveal)
 
+;; arch-tag: 96ba0242-2274-4ed7-8e10-26bc0707b4d8
 ;;; reveal.el ends here