[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[AUCTeX-devel] making folding work together with previewing

From: Joe Wells
Subject: [AUCTeX-devel] making folding work together with previewing
Date: Wed, 19 Sep 2007 16:22:18 +0100
User-agent: Gnus/5.11 (Gnus v5.11) Emacs/22.1 (gnu/linux)

Dear AUCTeX gurus,

Attached to this message is a patch that makes TeX-fold display images
from preview-latex in folded material.  So you can write

  \emph{Mathematical equations like $e=mc^2$ and $e^{i\pi}=-1$ are fun.}

and then type C-c C-p C-b, wait for the images to show up, and then
type C-c C-o C-b.  You will then see the text in italic font, the
“\emph{” and “}” hidden, and all the math displayed as images.

It works by putting most (all but the last chunk of text) of the
folded material into the before-string property of the overlay used
for folding.  The images are used as display properties of substrings
of the before-string.  (By the way, my code should be redone using
after-string, because there is one fewer Emacs bug in this case: the
mouse-face will cover the entire overlay if after-string is used.)

You have to do the folding after the images are installed to get the
full benefit.  (You can always unfold and refold to see the images in
the folded display.)

There's lots of work still to be done.  I haven't carefully tested
boundary cases (e.g., what happens if the entire folded material is a
single image).  The checking for overfull lines doesn't accurately
measure how wide the folded material will display as.  It's possible
there are additional Emacs display bugs that I haven't yet triggered.
(I had to work around lots of Emacs display bugs to find this
solution.)  Someone will probably object that I used items from CL.
(Feel free to rewrite the code not to use them.)  The help-echo
property is not displayed over material to the left of the rightmost
image.  I have no idea how to make this work in Xemacs and I didn't
even try.

Anyway, here is at least a starting point for further development.  It
gets you closer to WYSIWIG LaTeX in Emacs.

By the way, the patch also makes some of the fontification show up in
the tooltips for folded material.  For example, you should see italics
correctly.  (Unfortunately, the tooltip frame gets the mono version of
all faces declared with defface.  And the tooltip-show function
installs the tooltip face, which messes up the most important face

I hope you find the ideas in this patch useful.


--- tex-fold.el-orig    2007-09-19 15:45:35.000000000 +0100
+++ tex-fold.el 2007-09-19 15:56:01.000000000 +0100
@@ -535,45 +535,49 @@
 (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."
+  "Return the contents of buffer from START to END as a list of
+display specifications (strings and other values of the display property).
+Uses the display properties of overlays in this region instead of the
+buffer substrings covered by the overlays."
   ;; 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))
-    ;; Get rid of overlays not under our control or not completely
-    ;; inside the specified region.
+    ;; Get rid of overlays not under our control (or preview-latex's)
+    ;; or not completely inside the specified region.
     (dolist (ov overlays)
-      (when (or (not (eq (overlay-get ov 'category) 'TeX-fold))
+      (when (or (not (memq (overlay-get ov 'category) '(TeX-fold 
                (< (overlay-start ov) start)
-               (> (overlay-end ov) end))
+               (> (overlay-end ov) end)
+                (null (overlay-get ov 'display)))
        (setq overlays (remove ov overlays))))
     (if (null overlays)
-       (buffer-substring start end)
+        (list (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))))
+      (setq result (list (buffer-substring start (overlay-start (car 
       (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)))
+          (push (overlay-get ov 'display) result)
          ;; 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)))
+         (push (buffer-substring (overlay-end ov)
+                                  (if overlays
+                                      (overlay-start
+                                       (car overlays))
+                                    end))
+                result)))
+      (nreverse result))))
 (defun TeX-fold-make-help-echo (start end)
   "Return a string to be used as the help echo of folded overlays.
@@ -659,38 +663,82 @@
         (ov-end (overlay-end ov))
         (spec (overlay-get ov 'TeX-fold-display-string-spec))
         (computed (if (stringp spec)
-                      spec
+                      (list (list spec))
                     (or (TeX-fold-macro-nth-arg spec ov-start ov-end)
-                        "[Error: No content found]")))
+                        (list (list "[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))
+    (when (and (every #'stringp display-string)
+               (string= (apply #'concat display-string) ""))
+      (setq display-string (list 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"))
+    (when (TeX-fold-overfull-p
+           ov-start ov-end
+           (apply #'concat
+                  (mapcar
+                   (lambda (x)
+                     (if (stringp x) x
+                       ;; Make a wild guess that the display spec
+                       ;; takes the same horizontal width as a space.
+                       " "))
+                   display-string)))
+      (setq display-string (append display-string (list "\n")))
       (move-overlay ov ov-start (save-excursion
                                  (goto-char ov-end)
                                  (skip-chars-forward " \t")
     (overlay-put ov 'mouse-face 'highlight)
-    (overlay-put ov 'display display-string)
+    (callf nreverse display-string)
+    (let* ((tl (car display-string))
+           (d (if (and (stringp tl)
+                       (< 0 (length tl)))
+                  (pop display-string)
+                ;; Kludge.  We need to make a non-empty display
+                ;; property (due to Emacs bug), and the last item in
+                ;; display-string is not suitable, so we add a space.
+                " ")))
+      (callf nreverse display-string)
+      (let ((bs (loop for i in display-string
+                      concat (if (stringp i)
+                                 i
+                               (propertize " " 'display i)))))
+        (overlay-put ov 'before-string bs))
+      (overlay-put ov 'display d))
     (if (featurep 'xemacs)
-       (let ((glyph (make-glyph (if (listp display-string)
-                                    (car display-string)
-                                  display-string))))
+       (let ((glyph (make-glyph
+                      ;; *** What to do here?  Must convert list of
+                      ;; display specs into something Xemacs's
+                      ;; make-glyph can handle. ***
+                      (if (listp display-string)
+                          (car display-string)
+                        ;; Huh?  display-string will be nil in this
+                        ;; case!
+                        display-string))))
          (overlay-put ov 'invisible t)
          (when font-lock-mode
            (if face
                (set-glyph-property glyph 'face face)
              (set-glyph-property glyph 'face TeX-fold-folded-face)))
          (set-extent-property ov 'end-glyph glyph))
+      (overlay-put ov 'face nil);;sanity
       (when font-lock-mode
-       (overlay-put ov 'face TeX-fold-folded-face))
+        (overlay-put ov 'face TeX-fold-folded-face))
+      ;;(when font-lock-mode
+      ;;  (overlay-put ov 'face 'font-latex-red-italic-face));;debugging
       (unless (zerop TeX-fold-help-echo-max-length)
-       (overlay-put ov 'help-echo (TeX-fold-make-help-echo
-                                   (overlay-start ov) (overlay-end ov)))))))
+        ;; *** ARRGH!  The help-echo property is only displayed over
+        ;; the display property, not over the before-string property!
+        (let ((s (TeX-fold-make-help-echo (overlay-start ov) (overlay-end ov)))
+              (s1 " "))
+          ;; By putting our fontified help-echo text on a display
+          ;; property, we escape the complete smashing of face
+          ;; information that tooltip-show does.  Unfortunately we
+          ;; will still inherit from face tooltip.
+          (put-text-property 0 1 'display s s1)
+          (overlay-put ov 'help-echo s1)))))
+  (setq foobar (overlay-properties ov)))
 (defun TeX-fold-show-item (ov)
   "Show a single LaTeX macro or environment.
@@ -700,6 +748,7 @@
        (set-extent-property ov 'end-glyph nil)
        (overlay-put ov 'invisible nil))
+    (overlay-put ov 'before-string nil)
     (overlay-put ov 'display nil)
     (overlay-put ov 'help-echo nil)
     (when font-lock-mode

reply via email to

[Prev in Thread] Current Thread [Next in Thread]