Source

auctex / tex-fold.el

Diff from to

tex-fold.el

 ;;; tex-fold.el --- Fold TeX macros.
 
-;; Copyright (C) 2004 Free Software Foundation, Inc.
+;; Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
 
-;; Author: Ralf Angeli <angeli@iwi.uni-sb.de>
+;; Author: Ralf Angeli <angeli@caeruleus.net>
 ;; Maintainer: auctex-devel@gnu.org
 ;; Created: 2004-07-04
 ;; Keywords: tex, wp
 
 ;; You should have received a copy of the GNU General Public License
 ;; along with AUCTeX; see the file COPYING.  If not, write to the Free
-;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-;; 02111-1307, USA.
+;; Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+;; 02110-1301, USA.
 
 ;;; Commentary:
 
 ;; The display string of content which should display part of itself
 ;; is made by copying the text from the buffer together with its text
 ;; properties.  If fontification has not happened when this is done
-;; (e.g. because of lazy font locking) the intended fontification will
-;; not show up.  Maybe this could be improved by using some sort of
-;; "lazy folding" or refreshing the window upon scrolling.  As a
-;; workaround you can leave Emacs idle a few seconds and wait for
-;; stealth font locking to finish before you fold the buffer.
+;; (e.g. because of lazy or just-in-time font locking) the intended
+;; fontification will not show up.  Maybe this could be improved by
+;; using some sort of "lazy folding" or refreshing the window upon
+;; scrolling.  As a workaround fontification of the whole buffer
+;; currently is forced before folding it.
 
 ;;; Code:
 
   "Fold TeX macros."
   :group 'AUCTeX)
 
+(defcustom TeX-fold-type-list '(env macro)
+  "List of item types to consider when folding.
+Valid items are the symbols 'env for environments, 'macro for
+macros and 'comment for comments."
+  :type '(set (const :tag "Environments" env)
+	      (const :tag "Macros" macro)
+	      (const :tag "Comments" comment))
+  :group 'TeX-fold)
+
 (defcustom TeX-fold-macro-spec-list
   '(("[f]" ("footnote"))
     ("[c]" ("cite"))
     ("[l]" ("label"))
-    ("[r]" ("ref"))
+    ("[r]" ("ref" "pageref"))
     ("[i]" ("index"))
     ("*" ("item"))
     ("..." ("dots"))
   :type 'boolean
   :group 'TeX-fold)
 
+(defcustom TeX-fold-help-echo-max-length 70
+  "Maximum length of help echo message for folded overlays.
+Set it to zero in order to disable help echos."
+  :type 'integer
+  :group 'TeX-fold)
+
+(defcustom TeX-fold-force-fontify t
+  "Force the buffer to be fully fontified by folding it."
+  :group 'TeX-fold
+  :type 'boolean)
+
 (defface TeX-fold-folded-face
   '((((class color) (background light))
      (:foreground "SlateBlue"))
 (defvar TeX-fold-unfolded-face 'TeX-fold-unfolded-face
   "Face for folded content when it is temporarily opened.")
 
+(defvar TeX-fold-ellipsis "..."
+  "String used as display string for overlays instead of a zero-length string.")
+
 (defvar TeX-fold-open-spots nil)
 (make-variable-buffer-local 'TeX-fold-open-spots)
 
     (define-key map "\C-c\C-o\C-p" 'TeX-fold-paragraph)
     (define-key map "\C-c\C-o\C-m" 'TeX-fold-macro)
     (define-key map "\C-c\C-o\C-e" 'TeX-fold-env)
+    (define-key map "\C-c\C-o\C-c" 'TeX-fold-comment)
     (define-key map "\C-c\C-ob"    'TeX-fold-clearout-buffer)
     (define-key map "\C-c\C-or"    'TeX-fold-clearout-region)
     (define-key map "\C-c\C-op"    'TeX-fold-clearout-paragraph)
     (define-key map "\C-c\C-oi"    'TeX-fold-clearout-item)
-    ;; To be removed
-    (define-key map "\C-c\C-o\C-x" 'TeX-fold-clearout-buffer)
-    (define-key map "\C-c\C-o\C-c" 'TeX-fold-clearout-item)
     map))
 
 
   (cond ((TeX-fold-clearout-item))
 	((TeX-active-mark) (TeX-fold-region (mark) (point)))
 	((TeX-fold-item 'macro))
-	((TeX-fold-item 'env))))
+	((TeX-fold-item 'env))
+	((TeX-fold-comment))))
 
 (defun TeX-fold-buffer ()
   "Hide all configured macros and environments in the current buffer.
 and environments in `TeX-fold-env-spec-list'."
   (interactive)
   (TeX-fold-clearout-region (point-min) (point-max))
+  (when (and TeX-fold-force-fontify
+	     (boundp 'jit-lock-mode)
+	     jit-lock-mode
+	     (fboundp 'jit-lock-fontify-now))
+    ;; We force fontification here only because it should rarely be
+    ;; needed for the other folding commands.
+    (jit-lock-fontify-now))
   (TeX-fold-region (point-min) (point-max)))
 
 (defun TeX-fold-paragraph ()
       (TeX-fold-clearout-region start end)
       (TeX-fold-region start end))))
 
-(defun TeX-fold-region (start end &optional type)
-  "Fold all items in region starting at position START and ending at END.
-If optional parameter TYPE is given, fold only items of the
-specified type.  TYPE can be one of the symbols 'env for
-environments or 'macro for macros."
+(defun TeX-fold-region (start end)
+  "Fold all items in region from START to END."
   (interactive "r")
-  (if (null type)
-      (progn
-	(TeX-fold-region start end 'env)
-	(TeX-fold-region start end 'macro))
-    (when (or (and (eq type 'env)
-		   (not (eq major-mode 'plain-tex-mode)))
-	      (eq type 'macro))
-      (save-excursion
-	(let (fold-list item-list regexp)
-	  (dolist (item (if (eq type 'env)
-			    TeX-fold-env-spec-list
-			  TeX-fold-macro-spec-list))
-	    (dolist (i (cadr item))
-	      (add-to-list 'fold-list (list i (car item)))
-	      (add-to-list 'item-list i)))
-	  (setq regexp (cond ((and (eq type 'env)
-				   (eq major-mode 'context-mode))
-			      (concat (regexp-quote TeX-esc)
-				      "start" (regexp-opt item-list t)))
-			     ((and (eq type 'env)
-				   (eq major-mode 'texinfo-mode))
-			      (concat (regexp-quote TeX-esc)
-				      (regexp-opt item-list t)))
-			     ((eq type 'env)
-			      (concat (regexp-quote TeX-esc)
-				      "begin[ \t]*{"
-				      (regexp-opt item-list t) "}"))
-			     (t
-			      ;; "\\_>" is only available with Emacs
-			      ;; 21.4 or later (checked into CVS Emacs
-			      ;; on 2004-05-19). (This could be used in
-			      ;; font-latex as well for
-			      ;; `font-latex-match-variable-make' and
-			      ;; friends instead of "\\>" and would fix
-			      ;; issues with starred macros.)
-			      (concat (regexp-quote TeX-esc)
-				      (regexp-opt item-list t)
-				      (if (string-match "\\_>" "X")
-					  "\\_>"
-					"[^A-Za-z@*]")))))
-	  (save-restriction
-	    (narrow-to-region start end)
-	    ;; Start from the bottom so that it is easier to prioritize
-	    ;; nested macros.
-	    (goto-char (point-max))
-	    (let ((case-fold-search nil))
-	      (while (re-search-backward regexp nil t)
-		(when (not (and TeX-fold-preserve-comments
-				(TeX-in-commented-line)))
-		  (let* ((item-start (match-beginning 0))
-			 (display-string-spec (cadr (assoc (match-string 1)
-							   fold-list)))
-			 (item-end (cond ((and (eq type 'env)
-					       (eq major-mode 'context-mode))
-					  (save-excursion
-					    (goto-char (match-end 0))
-					    (ConTeXt-find-matching-stop)
-					    (point)))
-					 ((and (eq type 'env)
-					       (eq major-mode 'texinfo-mode))
-					  (save-excursion
-					    (goto-char (match-end 0))
-					    (Texinfo-find-env-end)
-					    (point)))
-					 ((eq type 'env)
-					  (save-excursion
-					    (goto-char (match-end 0))
-					    (LaTeX-find-matching-end)
-					    (point)))
-					 (t
-					  (save-excursion
-					    (goto-char item-start)
-					    (TeX-find-macro-end)))))
-			 (display-string (if (integerp display-string-spec)
-					     (or (TeX-fold-macro-nth-arg
-						  display-string-spec
-						  item-start
-						  (when (eq type 'macro)
-						    item-end))
-						 "[Error: No content found]")
-					   display-string-spec))
-			 (ov (TeX-fold-make-overlay item-start item-end type
-						    display-string-spec
-						    display-string)))
-		    (TeX-fold-hide-item ov)))))))))))
+  (when (and (memq 'env TeX-fold-type-list)
+	     (not (eq major-mode 'plain-tex-mode)))
+    (TeX-fold-region-macro-or-env start end 'env))
+  (when (memq 'macro TeX-fold-type-list)
+    (TeX-fold-region-macro-or-env start end 'macro))
+  (when (memq 'comment TeX-fold-type-list)
+    (TeX-fold-region-comment start end)))
+
+(defun TeX-fold-region-macro-or-env (start end type)
+  "Fold all items of type TYPE in region from START to END.
+TYPE can be one of the symbols 'env for environments and 'macro
+for macros."
+  (save-excursion
+    (let (fold-list item-list regexp)
+      (dolist (item (if (eq type 'env)
+			TeX-fold-env-spec-list
+		      TeX-fold-macro-spec-list))
+	(dolist (i (cadr item))
+	  (add-to-list 'fold-list (list i (car item)))
+	  (add-to-list 'item-list i)))
+      (setq regexp (cond ((and (eq type 'env)
+			       (eq major-mode 'context-mode))
+			  (concat (regexp-quote TeX-esc)
+				  "start" (regexp-opt item-list t)))
+			 ((and (eq type 'env)
+			       (eq major-mode 'texinfo-mode))
+			  (concat (regexp-quote TeX-esc)
+				  (regexp-opt item-list t)))
+			 ((eq type 'env)
+			  (concat (regexp-quote TeX-esc)
+				  "begin[ \t]*{"
+				  (regexp-opt item-list t) "}"))
+			 (t
+			  (concat (regexp-quote TeX-esc)
+				  (regexp-opt item-list t)))))
+      (save-restriction
+	(narrow-to-region start end)
+	;; Start from the bottom so that it is easier to prioritize
+	;; nested macros.
+	(goto-char (point-max))
+	(let ((case-fold-search nil)
+	      item-name)
+	  (while (re-search-backward regexp nil t)
+	    (setq item-name (match-string 1))
+	    (unless (or (and TeX-fold-preserve-comments
+			     (TeX-in-commented-line))
+			;; Make sure no partially matched macros are
+			;; folded.  For macros consisting of letters
+			;; this means there should be none of the
+			;; characters [A-Za-z@*] after the matched
+			;; string.  Single-char non-letter macros like
+			;; \, don't have this requirement.
+			(and (eq type 'macro)
+			     (save-match-data
+			       (string-match "[A-Za-z]" item-name))
+			     (save-match-data
+			       (string-match "[A-Za-z@*]"
+					     (string (char-after
+						      (match-end 0)))))))
+	      (let* ((item-start (match-beginning 0))
+		     (display-string-spec (cadr (assoc item-name
+						       fold-list)))
+		     (item-end (TeX-fold-item-end item-start type))
+		     (ov (TeX-fold-make-overlay item-start item-end type
+						display-string-spec)))
+		(TeX-fold-hide-item ov)))))))))
+
+(defun TeX-fold-region-comment (start end)
+  "Fold all comments in region from START to END."
+  (save-excursion
+    (goto-char start)
+    (let (beg)
+      (while (setq beg (TeX-search-forward-comment-start end))
+	(goto-char beg)
+	;; Determine the start of the region to be folded just behind
+	;; the comment starter.
+	(looking-at TeX-comment-start-regexp)
+	(setq beg (match-end 0))
+	;; Search for the end of the comment.
+	(while (TeX-comment-forward))
+	(end-of-line 0)
+	;; Hide the whole region.
+	(TeX-fold-hide-item (TeX-fold-make-overlay beg (point) 'comment
+						   TeX-fold-ellipsis))))))
 
 (defun TeX-fold-macro ()
   "Hide the macro on which point currently is located."
   (interactive)
   (unless (TeX-fold-item 'macro)
-    (message "No macro found.")))
+    (message "No macro found")))
 
 (defun TeX-fold-env ()
   "Hide the environment on which point currently is located."
   (interactive)
   (unless (TeX-fold-item 'env)
-    (message "No environment found.")))
+    (message "No environment found")))
+
+(defun TeX-fold-comment ()
+  "Hide the comment on which point currently is located."
+  (interactive)
+  (unless (TeX-fold-comment-do)
+    (message "No comment found")))
 
 (defun TeX-fold-item (type)
   "Hide the item on which point currently is located.
 		      (if (eq type 'env)
 			  TeX-fold-unspec-env-display-string
 			TeX-fold-unspec-macro-display-string))))
-	       (item-end (cond ((and (eq type 'env)
-				     (eq major-mode 'context-mode))
-				(save-excursion
-				  (goto-char (match-end 0))
-				  (ConTeXt-find-matching-stop)
-				  (point)))
-			       ((and (eq type 'env)
-				     (eq major-mode 'texinfo-mode))
-				(save-excursion
-				  (goto-char (match-end 0))
-				  (Texinfo-find-env-end)
-				  (point)))
-			       ((eq type 'env)
-				(save-excursion
-				  (goto-char (match-end 0))
-				  (LaTeX-find-matching-end)
-				  (point)))
-			       (t
-				(save-excursion
-				  (goto-char item-start)
-				  (TeX-find-macro-end)))))
-	       (display-string (if (integerp display-string-spec)
-				   (or (TeX-fold-macro-nth-arg
-					display-string-spec
-					item-start (when (eq type 'macro)
-						     item-end))
-				       "[Error: No content found]")
-				 display-string-spec))
+	       (item-end (TeX-fold-item-end item-start type))
 	       (ov (TeX-fold-make-overlay item-start item-end type
-					  display-string-spec
-					  display-string)))
+					  display-string-spec)))
 	  (TeX-fold-hide-item ov))))))
 
+(defun TeX-fold-comment-do ()
+  "Hide the comment on which point currently is located.
+This is the function doing the work for `TeX-fold-comment'.  It
+is an internal function communication with return values rather
+than with messages for the user.
+Return non-nil if a comment was found and folded, nil otherwise."
+  (if (and (not (TeX-in-comment)) (not (TeX-in-line-comment)))
+      nil
+    (let (beg)
+      (save-excursion
+	(while (progn
+		 (beginning-of-line 0)
+		 (TeX-in-line-comment)))
+	(goto-char (TeX-search-forward-comment-start (line-end-position 2)))
+	(looking-at TeX-comment-start-regexp)
+	(setq beg (match-end 0))
+	(while (TeX-comment-forward))
+	(end-of-line 0)
+	(TeX-fold-hide-item (TeX-fold-make-overlay beg (point) 'comment
+						   TeX-fold-ellipsis))))))
 
-;;; Utilities for folding
 
-(defun TeX-fold-make-overlay (ov-start ov-end type
-				       display-string-spec display-string)
-  "Make an overlay to cover the item.
-The overlay will reach from OV-START to OV-END and will display
-the string part of DISPLAY-STRING which has to be a string or a
-list where the first item is a string and the second a face or
-nil.  DISPLAY-STRING-SPEC is the original specification of the
-display string in the variables `TeX-fold-macro-spec-list' or
-`TeX-fold-env-spec-list' and may be a string or an integer.  TYPE
-is a symbol which is used to describe the content to hide and may
-be 'macro for macros and 'env for environments.
+;;; Utilities
 
-The position of the end of the overlay and its display string may
-be altered to prevent overfull lines."
-  (let* ((face (when (listp display-string)
-		 (cadr display-string)))
-	 (display-string (if (listp display-string)
-			     (car display-string)
-			   display-string))
-	 (overfull (and (not (featurep 'xemacs)) ; Linebreaks in glyphs don't
-						 ; work in XEmacs anyway.
-			(save-excursion
-			  (goto-char ov-end)
-			  (search-backward "\n" ov-start t))
-			(not (string-match "\n" display-string))
-			(> (+ (- ov-start
-				 (save-excursion
-				   (goto-char ov-start)
-				   (line-beginning-position)))
-			      (length display-string)
-			      (- (save-excursion
-				   (goto-char ov-end)
-				   (line-end-position))
-				 ov-end))
-			   (current-fill-column))))
-	 (ov-end (if overfull
-		     (save-excursion
-		       (goto-char ov-end)
-		       (skip-chars-forward " \t")
-		       (point))
-		   ov-end))
-	 (display-string (concat display-string (when overfull "\n")))
-	 (priority (TeX-fold-prioritize ov-start ov-end))
-	 (ov (make-overlay ov-start ov-end (current-buffer) t nil)))
+(defun TeX-fold-make-overlay (ov-start ov-end type display-string-spec)
+  "Make a TeX-fold overlay extending from OV-START to OV-END.
+TYPE is a symbol which is used to describe the content to hide
+and may be 'macro for macros and 'env for environments.
+DISPLAY-STRING-SPEC is the original specification of the display
+string in the variables `TeX-fold-macro-spec-list' or
+`TeX-fold-env-spec-list' and may be a string or an integer."
+  ;; Calculate priority before the overlay is instantiated.  We don't
+  ;; want `TeX-overlay-prioritize' to pick up a non-prioritized one.
+  (let ((priority (TeX-overlay-prioritize ov-start ov-end))
+	(ov (make-overlay ov-start ov-end (current-buffer) t nil)))
     (overlay-put ov 'category 'TeX-fold)
     (overlay-put ov 'priority priority)
     (overlay-put ov 'evaporate t)
-    (when font-lock-mode
-      (overlay-put ov 'TeX-fold-face face))
     (overlay-put ov 'TeX-fold-type type)
     (overlay-put ov 'TeX-fold-display-string-spec display-string-spec)
-    (overlay-put ov 'TeX-fold-display-string display-string)
     ov))
 
+(defun TeX-fold-item-end (start type)
+  "Return the end of an item of type TYPE starting at START.
+TYPE can be either 'env for environments or 'macro for macros."
+  (save-excursion
+    (cond ((and (eq type 'env)
+		(eq major-mode 'context-mode))
+	   (goto-char start)
+	   (ConTeXt-find-matching-stop)
+	   (point))
+	  ((and (eq type 'env)
+		(eq major-mode 'texinfo-mode))
+	   (goto-char (1+ start))
+	   (Texinfo-find-env-end)
+	   (point))
+	  ((eq type 'env)
+	   (goto-char (1+ start))
+	   (LaTeX-find-matching-end)
+	   (point))
+	  (t
+	   (goto-char start)
+	   (TeX-find-macro-end)))))
+
+(defun TeX-fold-overfull-p (ov-start ov-end display-string)
+  "Return t if an overfull line will result after adding an overlay.
+The overlay extends from OV-START to OV-END and will display the
+string DISPLAY-STRING."
+  (and (not (featurep 'xemacs)) ; Linebreaks in glyphs don't
+				; work in XEmacs anyway.
+       (save-excursion
+	 (goto-char ov-end)
+	 (search-backward "\n" ov-start t))
+       (not (string-match "\n" display-string))
+       (> (+ (- ov-start
+		(save-excursion
+		  (goto-char ov-start)
+		  (line-beginning-position)))
+	     (length display-string)
+	     (- (save-excursion
+		  (goto-char ov-end)
+		  (line-end-position))
+		ov-end))
+	  (current-fill-column))))
+
 (defun TeX-fold-macro-nth-arg (n macro-start &optional macro-end)
-  "Return a property list of the nth argument of a macro.
-The first item in the list is the string specified in the
-argument, the second item may be a face if the argument string
-was fontified.  In Emacs the string holds text properties as
-well, so the second item is always nil.  In XEmacs the string
+  "Return a property list of the argument number N of a macro.
+The start of the macro to examine is given by MACRO-START, its
+end optionally by MACRO-END.
+
+The first item in the returned list is the string specified in
+the argument, the second item may be a face if the argument
+string was fontified.  In Emacs the string holds text properties
+as well, so the second item is always nil.  In XEmacs the string
 does not enclose any faces, so these are given in the second item
 of the resulting list."
   (save-excursion
 					(point)))
 		  (goto-char (TeX-find-closing-brace))
 		  (setq content-end (save-excursion
-				      (skip-chars-backward "} \t")
+				      (backward-char)
+				      (skip-chars-backward " \t")
 				      (point)))
 		  (setq n (1- n)))
 		t)
 	    (error nil))
-	  (list (buffer-substring content-start content-end)
+	  (list (TeX-fold-buffer-substring content-start content-end)
 		(when (and (featurep 'xemacs)
 			   (extent-at content-start))
 		  ;; A glyph in XEmacs does not seem to be able to hold more
 		  (car (extent-property (extent-at content-start) 'face))))
 	nil))))
 
-(defvar TeX-fold-priority-step 16
-  "Numerical difference of priorities between nested overlays.
-The step should be big enough to allow setting a priority for new
-overlays between two existing ones.")
+(defun TeX-fold-buffer-substring (start end)
+  "Return the contents of buffer from START to END as a string.
+Like `buffer-substring' but copy overlay display strings as well."
+  ;; Swap values of `start' and `end' if necessary.
+  (when (> start end) (let ((tmp start)) (setq start end end tmp)))
+  (let ((overlays (overlays-in start end))
+	result)
+    ;; Get rid of overlays not under our control or not completely
+    ;; inside the specified region.
+    (dolist (ov overlays)
+      (when (or (not (eq (overlay-get ov 'category) 'TeX-fold))
+		(< (overlay-start ov) start)
+		(> (overlay-end ov) end))
+	(setq overlays (remove ov overlays))))
+    (if (null overlays)
+	(buffer-substring start end)
+      ;; Sort list according to ascending starts.
+      (setq overlays (sort (copy-sequence overlays)
+			   (lambda (a b)
+			     (< (overlay-start a) (overlay-start b)))))
+      ;; Get the string from the start of the region up to the first overlay.
+      (setq result (buffer-substring start (overlay-start (car overlays))))
+      (let (ov)
+	(while overlays
+	  (setq ov (car overlays)
+		overlays (cdr overlays))
+	  ;; Add the display string of the overlay.
+	  (setq result (concat result (overlay-get ov 'display)))
+	  ;; Remove overlays contained in the current one.
+	  (dolist (elt overlays)
+	    (when (< (overlay-start elt) (overlay-end ov))
+	      (setq overlays (remove elt overlays))))
+	  ;; Add the string from the end of the current overlay up to
+	  ;; the next overlay or the end of the specified region.
+	  (setq result (concat result (buffer-substring (overlay-end ov)
+							(if overlays
+							    (overlay-start
+							     (car overlays))
+							  end))))))
+      result)))
 
-(defun TeX-fold-prioritize (start end)
-  "Calculate a priority for an overlay.
-The calculated priority is lower than the minimum of priorities
-of surrounding overlays and higher than the maximum of enclosed
-overlays."
-  (let (outer-priority inner-priority)
-    (dolist (ov (overlays-in start end))
-      (when (eq (overlay-get ov 'category) 'TeX-fold)
-	(let ((ov-priority (overlay-get ov 'priority)))
-	  (if (>= (overlay-start ov) start)
-	      (setq inner-priority (max ov-priority (or inner-priority
-							ov-priority)))
-	    (setq outer-priority (min ov-priority (or outer-priority
-						      ov-priority)))))))
-    (cond ((and inner-priority (not outer-priority))
-	   (+ inner-priority TeX-fold-priority-step))
-	  ((and (not inner-priority) outer-priority)
-	   (/ outer-priority 2))
-	  ((and inner-priority outer-priority)
-	   (/ (- outer-priority inner-priority) 2))
-	  (t TeX-fold-priority-step))))
+(defun TeX-fold-make-help-echo (start end)
+  "Return a string to be used as the help echo of folded overlays.
+The text between START and END will be used for this but cropped
+to the length defined by `TeX-fold-help-echo-max-length'.  Line
+breaks will be replaced by spaces."
+  (let* ((spill (+ start TeX-fold-help-echo-max-length))
+	 (lines (split-string (buffer-substring start (min end spill)) "\n"))
+	 (result (pop lines)))
+    (dolist (line lines)
+      ;; Strip leading whitespace
+      (when (string-match "^[ \t]+" line)
+	(setq line (replace-match "" nil nil line)))
+      ;; Strip trailing whitespace
+      (when (string-match "[ \t]+$" line)
+	(setq line (replace-match "" nil nil line)))
+      (setq result (concat result " " line)))
+    (when (> end spill) (setq result (concat result "...")))
+    result))
+
+(defun TeX-fold-update-at-point ()
+  "Update all TeX-fold overlays at point displaying computed content."
+  (let (overlays)
+    ;; Get all overlays at point under our control.
+    (dolist (ov (overlays-at (point)))
+      (when (and (eq (overlay-get ov 'category) 'TeX-fold)
+		 (numberp (overlay-get ov 'TeX-fold-display-string-spec)))
+	(add-to-list 'overlays ov)))
+    (when overlays
+      ;; Sort list according to descending starts.
+      (setq overlays (sort (copy-sequence overlays)
+			   (lambda (a b)
+			     (> (overlay-start a) (overlay-start b)))))
+      (dolist (ov overlays)
+	(TeX-fold-hide-item ov)))))
 
 
 ;;; Removal
 (defun TeX-fold-hide-item (ov)
   "Hide a single macro or environment.
 That means, put respective properties onto overlay OV."
-  (let* ((display-string-spec (overlay-get ov 'TeX-fold-display-string-spec))
-	 (display-string (if (stringp display-string-spec)
-			     (overlay-get ov 'TeX-fold-display-string)
-			   ;; If the display string specification is
-			   ;; an integer, recompute the display string
-			   ;; in order to have an up-to-date string if
-			   ;; the content has changed.
-			   (or (TeX-fold-macro-nth-arg
-				display-string-spec (overlay-start ov)
-				(when (eq (overlay-get ov 'TeX-fold-type)
-					  'macro)
-				  (overlay-end ov)))
-			       "[Error: No content found]"))))
+  (let* ((ov-start (overlay-start ov))
+	 (ov-end (overlay-end ov))
+	 (spec (overlay-get ov 'TeX-fold-display-string-spec))
+	 (computed (if (stringp spec)
+		       spec
+		     (or (TeX-fold-macro-nth-arg spec ov-start ov-end)
+			 "[Error: No content found]")))
+	 (display-string (if (listp computed) (car computed) computed))
+	 (face (when (listp computed) (cadr computed))))
+    ;; Cater for zero-length display strings.
+    (when (string= display-string "") (setq display-string TeX-fold-ellipsis))
+    ;; Add a linebreak to the display string and adjust the overlay end
+    ;; in case of an overfull line.
+    (when (TeX-fold-overfull-p ov-start ov-end display-string)
+      (setq display-string (concat display-string "\n"))
+      (move-overlay ov ov-start (save-excursion
+				  (goto-char ov-end)
+				  (skip-chars-forward " \t")
+				  (point))))
     (overlay-put ov 'mouse-face 'highlight)
+    (overlay-put ov 'display display-string)
     (if (featurep 'xemacs)
 	(let ((glyph (make-glyph (if (listp display-string)
 				     (car display-string)
-				   display-string)))
-	      (face (overlay-get ov 'TeX-fold-face)))
+				   display-string))))
 	  (overlay-put ov 'invisible t)
 	  (when font-lock-mode
 	    (if face
 	  (set-extent-property ov 'end-glyph glyph))
       (when font-lock-mode
 	(overlay-put ov 'face TeX-fold-folded-face))
-      (overlay-put ov 'display display-string))))
+      (unless (zerop TeX-fold-help-echo-max-length)
+	(overlay-put ov 'help-echo (TeX-fold-make-help-echo
+				    (overlay-start ov) (overlay-end ov)))))))
 
 (defun TeX-fold-show-item (ov)
   "Show a single LaTeX macro or environment.
 	(set-extent-property ov 'end-glyph nil)
 	(overlay-put ov 'invisible nil))
     (overlay-put ov 'display nil)
+    (overlay-put ov 'help-echo nil)
     (when font-lock-mode
       (overlay-put ov 'face TeX-fold-unfolded-face))))
 
 
 ;;; The mode
 
+;; This autoload cookie had to be changed because of XEmacs.  This is
+;; very dissatisfactory, because we now don't have the full doc string
+;; available to tell people what to expect when using this mode before
+;; loading it.
+
+;;;###autoload (autoload 'TeX-fold-mode "tex-fold" "Minor mode for hiding and revealing macros and environments." t)
 (define-minor-mode TeX-fold-mode
-  "Toggle TeX-fold-mode on or off.
-TeX-fold-mode lets you hide and unhide LaTeX macros.
+  "Minor mode for hiding and revealing macros and environments.
 
-Interactively, with no prefix argument, toggle the mode.
+Called 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."
   nil nil TeX-fold-keymap
   (if TeX-fold-mode
       (progn
 	(set (make-local-variable 'search-invisible) t)
-	(add-hook 'post-command-hook 'TeX-fold-post-command nil t))
+	(add-hook 'post-command-hook 'TeX-fold-post-command nil t)
+	(add-hook 'LaTeX-fill-newline-hook 'TeX-fold-update-at-point nil t))
     (kill-local-variable 'search-invisible)
     (remove-hook 'post-command-hook 'TeX-fold-post-command t)
+    (remove-hook 'LaTeX-fill-newline-hook 'TeX-fold-update-at-point t)
     (TeX-fold-clearout-buffer))
   (TeX-set-mode-name))
+
+;;;###autoload
 (defalias 'tex-fold-mode 'TeX-fold-mode)
 
 (provide 'tex-fold)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.