Hello,

This is the last follow-up bug-report/patch from:
https://lists.gnu.org/archive/html/auctex-devel/2025-08/msg00026.html

which includes the main preview-point feature. It can be enabled by setting 
`preview-point` to `'after-string` for example.
To use `buframe`, the package needs to be installed as well (available on 
ELPA). 

Any comments/questions are welcome. I realized it's a a lot of code to review.

Best regards,
-- Al
>From 33807f005de8403499cd0dd5eb2ba2990847197c Mon Sep 17 00:00:00 2001
From: Al Haji-Ali <[email protected]>
Date: Tue, 9 Sep 2025 21:19:43 +0100
Subject: [PATCH] New feature, preview-point

* doc/preview-latex.texi: Add docs for preview-point
* preview.el (preview-silent-errors): New local variable.
(preview-point,preview-point-auto-p): New custom variables
(preview-point-disabled-face, preview-point-processing-face): New faces.
(preview-point--frame, preview-point--current-overlay): New variables.
(preview-dvipng-image-type): Update doc.
(preview-log-error,preview-reraise-error): Implement silent mode based
on `preview-silent-errors'.
(preview-gs-sentinel, preview-gs-transact): Call `preview-point-refresh'.
(preview-ascent-from-bb): Return 'center when 'preview-point' is
non-nil.
(preview-toggle): Call preview-point activation function.
(preview-disable): Control behaviour based on preview-point.
(preview-map): Add key-binding for `preview-point-toggle-mode'.
(preview-mode-setup): Control setup based on `preview-point'.
(preview-parse-messages): Restore point before calling place functions.
(preview-point-auto-delay): New custom variable.
(preview-point--buframe, preview-point-inside-overlay-p,
preview-point-activate-maybe, preview-point-move-point,
preview-point-auto, preview-point-updated, preview-point-toggle-mode,
preview-point-toggle-auto-refresh, preview-point@around@write-region,
preview-point--preview-at-point, preview-point-has-preview-p,
preview-point-buf-change): New functions.
---
 doc/preview-latex.texi |  20 ++
 preview.el             | 507 +++++++++++++++++++++++++++++++++++------
 2 files changed, 463 insertions(+), 64 deletions(-)

diff --git a/doc/preview-latex.texi b/doc/preview-latex.texi
index e9e03fd5..299a161c 100644
--- a/doc/preview-latex.texi
+++ b/doc/preview-latex.texi
@@ -480,6 +480,26 @@ math (@code{$@dots{}$}), or if your usage of @code{$} conflicts with
 @previewlatex{}'s, you can turn off inline math previews.  In the
 @samp{Preview Latex} group, remove @code{textmath} from
 @code{preview-default-option-list} by customizing this variable.
+
+@item Enable preview at point.
+
+To enable a mode where previews are shown only when the cursor is inside
+the preview area, set @code{preview-point}. Valid values are:
+
+@table @code
+@item after-string
+Show the preview after the TeX source.
+
+@item before-string
+Show the preview before the TeX source.
+
+@item buframe
+Show the preview in a separate frame next to the cursor. Requires the
+@code{buframe} package to be installed (available on ELPA).
+@end table
+
+See also @code{preview-point-auto-p} to enable automatic updating or
+generation of previews.
 @end itemize

 @node Known problems, For advanced users, Simple customization, top
diff --git a/preview.el b/preview.el
index e9339307..205d6d93 100644
--- a/preview.el
+++ b/preview.el
@@ -370,6 +370,10 @@ See also `preview-gs-command'."
   "List of overlays to convert using gs.
 Buffer-local to the appropriate TeX process buffer.")

+(defvar-local preview-silent-errors nil
+  "When non-nil, do not signal preview errors nor display output buffer.
+This variable should be set in the process buffer.")
+
 (defvar-local preview-gs-outstanding nil
   "Overlays currently processed.")

@@ -454,6 +458,53 @@ set to `postscript'."
   :group 'preview-latex
   :type 'boolean)

+;;; preview-point customizations and variables.
+(defcustom preview-point nil
+  "Specifies where to show the preview.
+If non-nil, show the preview at point.  Can be `before-string',
+`after-string' to show at before or after the TeX code or `buframe' to
+show in a separate frame (the `buframe' package must be installed).  Can
+also be \\='(buframe FN-POS FRAME-PARAMETERS BUF-PARAMETERS) where
+FN-POS is a position function (default is
+`buframe-position-right-of-overlay') and FRAME-PARAMETERS is an alist of
+additional frame parameters, default is nil and BUF-PARAMETERS is an
+alist of buffer local variables and their values.
+
+This variable must be set before opening a TeX file. Charging its value
+while a file is open will lead to previews not being displayed
+correctly. See `preview-point-toggle-mode'."
+  :type '(choice
+          (const :tag "Before string" before-string)
+          (const :tag "After string (default)" after-string)
+          (const :tag "On frame" buframe)
+          (list :tag "On frame with explicit parameters"
+                (function :tag "Position function")
+                (alist :tag "Frame parameters")
+                (alist :tag "Buffer parameters"))))
+
+(defcustom preview-point-auto-p nil
+  "Set this to enable previewing automatically.
+When non-nil, it is assumed to be a function that is is called with no
+arguments at (point) when there is not a preview already.  If the
+function return a non-nil value, a `preview-at-point' will be initiated."
+  :type 'symbol)
+
+(defface preview-point-disabled-face
+  '((t (:inherit shadow)))
+  "Face used when preview is disabled."
+  :group 'preview-point)
+
+(defface preview-point-processing-face
+  '((t (:inherit preview-point-disabled-face)))
+  "Face used when preview is processing."
+  :group 'preview-point)
+
+(defvar preview-point--frame nil
+  "The last active preview popup frame.")
+
+(defvar preview-point--current-overlay nil
+  "The overlay currently shown in the preview popup frame.")
+
 (defun preview-string-expand (arg &optional separator)
   "Expand ARG as a string.
 It can already be a string.  Or it can be a list, then it is
@@ -625,7 +676,8 @@ is to be used."
         (insert-before-markers
          (format "%s: %s\n"
                  context (error-message-string err)))
-        (display-buffer (current-buffer)))))
+        (unless preview-silent-errors
+          (display-buffer (current-buffer))))))
   (setq preview-error-condition err))

 (defun preview-reraise-error (&optional process)
@@ -634,7 +686,11 @@ Makes sure that PROCESS is removed from the \"Compilation\"
 tag in the mode line."
   (when preview-error-condition
     (unwind-protect
-        (signal (car preview-error-condition) (cdr preview-error-condition))
+        (unless (buffer-local-value 'preview-silent-errors
+                                    (or (process-buffer process)
+                                        (current-buffer)))
+          (signal (car preview-error-condition)
+                  (cdr preview-error-condition)))
       (setq preview-error-condition nil
             compilation-in-progress (delq process compilation-in-progress)))))

@@ -705,6 +761,8 @@ and tries to restart Ghostscript if necessary."
               (let* ((err (concat preview-gs-answer "\n"
                                   (process-name process) " " string))
                      (ov (preview-gs-behead-outstanding err)))
+                (when ov
+                  (preview-point-updated ov))
                 (when (and (null ov) preview-gs-queue)
                   (save-excursion
                     (goto-char (if (marker-buffer (process-mark process))
@@ -1424,16 +1482,16 @@ Try \\[ps-run-start] \\[ps-run-buffer] and \
          (ps-open
           (let ((string
                  (concat
-                (mapconcat #'shell-quote-argument
-                            (append (list
-                                     preview-gs-command
-                                     outfile)
-                                    preview-gs-command-line)
-                            " ")
-                 "\nGS>"
-                 preview-gs-init-string
-                 (aref (overlay-get ov 'queued) 1)
-                 err)))
+                  (mapconcat #'shell-quote-argument
+                             (append (list
+                                      preview-gs-command
+                                      outfile)
+                                     preview-gs-command-line)
+                             " ")
+                  "\nGS>"
+                  preview-gs-init-string
+                  (aref (overlay-get ov 'queued) 1)
+                  err)))
             (lambda () (interactive "@") (preview-mouse-open-error string))))
          (str
           (preview-make-clickable
@@ -1488,7 +1546,8 @@ given as ANSWER."
                                     (preview-ascent-from-bb
                                      bbox)
                                     (aref preview-colors 2))))
-            (overlay-put ov 'queued nil)))))
+            (overlay-put ov 'queued nil)
+            (preview-point-updated ov)))))
     (while (and (< (length preview-gs-outstanding)
                    preview-gs-outstanding-limit)
                 (setq ov (pop preview-gs-queue)))
@@ -1700,19 +1759,22 @@ icon is cached in the property list of the SYMBOL."
 (defun preview-ascent-from-bb (bb)
   "This calculates the image ascent from its bounding box.
 The bounding box BB needs to be a 4-component vector of
-numbers (can be float if available)."
+numbers (can be float if available).
+
+If `preview-point' is non-nil, this simply returns \\='center."
   ;; baseline is at 1in from the top of letter paper (11in), so it is
   ;; at 10in from the bottom precisely, which is 720 in PostScript
   ;; coordinates.  If our bounding box has its bottom not above this
   ;; line, and its top above, we can calculate a useful ascent value.
   ;; If not, something is amiss.  We just use 100 in that case.
-
-  (let ((bottom (aref bb 1))
-        (top (aref bb 3)))
-    (if (and (<= bottom 720)
-             (> top 720))
-        (round (* 100.0 (/ (- top 720.0) (- top bottom))))
-      100)))
+  (if preview-point
+      'center
+    (let ((bottom (aref bb 1))
+          (top (aref bb 3)))
+      (if (and (<= bottom 720)
+               (> top 720))
+          (round (* 100.0 (/ (- top 720.0) (- top bottom))))
+        100))))

 (defface preview-face '((((background dark))
                          (:background "dark slate gray"))
@@ -2084,26 +2146,28 @@ purposes."
              'active
            'inactive))
         (strings (overlay-get ov 'strings)))
-    (unless (eq (overlay-get ov 'preview-state) 'disabled)
-      (overlay-put ov 'preview-state preview-state)
-      (if (eq preview-state 'active)
-          (progn
-            (overlay-put ov 'category 'preview-overlay)
-            (if (eq (overlay-start ov) (overlay-end ov))
-                (overlay-put ov 'before-string (car strings))
-              (dolist (prop '(display keymap mouse-face help-echo))
-                (overlay-put ov prop
-                             (get-text-property 0 prop (car strings))))
-              (overlay-put ov 'before-string nil))
-            (overlay-put ov 'face nil))
-        (dolist (prop '(display keymap mouse-face help-echo))
-          (overlay-put ov prop nil))
-        (overlay-put ov 'face 'preview-face)
-        (unless (cdr strings)
-          (setcdr strings (preview-inactive-string ov)))
-        (overlay-put ov 'before-string (cdr strings)))
-      (if old-urgent
-          (apply #'preview-add-urgentization old-urgent))))
+    (if preview-point
+        (preview-point-activate-maybe ov arg)
+      (unless (eq (overlay-get ov 'preview-state) 'disabled)
+        (overlay-put ov 'preview-state preview-state)
+        (if (eq preview-state 'active)
+            (progn
+              (overlay-put ov 'category 'preview-overlay)
+              (if (eq (overlay-start ov) (overlay-end ov))
+                  (overlay-put ov 'before-string (car strings))
+                (dolist (prop '(display keymap mouse-face help-echo))
+                  (overlay-put ov prop
+                               (get-text-property 0 prop (car strings))))
+                (overlay-put ov 'before-string nil))
+              (overlay-put ov 'face nil))
+          (dolist (prop '(display keymap mouse-face help-echo))
+            (overlay-put ov prop nil))
+          (overlay-put ov 'face 'preview-face)
+          (unless (cdr strings)
+            (setcdr strings (preview-inactive-string ov)))
+          (overlay-put ov 'before-string (cdr strings)))
+        (if old-urgent
+            (apply #'preview-add-urgentization old-urgent)))))
   (if event
       (preview-restore-position
        ov
@@ -2334,11 +2398,21 @@ active (`transient-mark-mode'), it is run through `preview-region'."
   (unless preview-leave-open-previews-visible
     (overlay-put ovr 'preview-image nil))
   (overlay-put ovr 'timestamp nil)
-  (setcdr (overlay-get ovr 'strings) (preview-disabled-string ovr))
-  (unless preview-leave-open-previews-visible
-    (preview-toggle ovr))
+
+  (setcdr (overlay-get ovr 'strings)
+          (unless preview-point
+            ;; It will be updated later in `preview-toggle'.
+            (preview-disabled-string ovr)))
+
+  (unless preview-point
+    (unless preview-leave-open-previews-visible
+      (preview-toggle ovr)
+      ;; Only delete the files if we are not using the images
+      (preview--delete-overlay-files ovr)))
   (overlay-put ovr 'preview-state 'disabled)
-  (preview--delete-overlay-files ovr))
+  (when preview-point
+    ;; Toggle/update preview (maybe) after setting state
+    (preview-toggle ovr t)))

 (defun preview--delete-overlay-files (ovr)
   "Delete files owned by OVR."
@@ -2612,7 +2686,8 @@ Deletes the dvi file when finished."
                                     (preview-ascent-from-bb
                                      (aref queued 0))
                                     (aref preview-colors 2)))
-              (overlay-put ov 'queued nil))
+              (overlay-put ov 'queued nil)
+              (preview-point-updated ov))
           (push filename oldfiles)
           ;; Do note modify `filenames' if we are not replacing
           ;; it, to avoid orphaning files. The filenames will be
@@ -2958,6 +3033,7 @@ See description of `TeX-command-list' for details."

 (defvar preview-map
   (let ((map (make-sparse-keymap)))
+    (define-key map "\C-t" #'preview-point-toggle-mode)
     (define-key map "\C-p" #'preview-at-point)
     (define-key map "\C-r" #'preview-region)
     (define-key map "\C-b" #'preview-buffer)
@@ -3204,8 +3280,10 @@ pp")
 (defun preview-mode-setup ()
   "Setup proper buffer hooks and behavior for previews."
   (setq-local desktop-save-buffer #'desktop-buffer-preview-misc-data)
-  (add-hook 'pre-command-hook #'preview-mark-point nil t)
-  (add-hook 'post-command-hook #'preview-move-point nil t)
+  (if preview-point
+      (add-hook 'post-command-hook #'preview-point-move-point nil t)
+    (add-hook 'pre-command-hook #'preview-mark-point nil t)
+    (add-hook 'post-command-hook #'preview-move-point nil t))
   (when (TeX-buffer-file-name)
     (let* ((filename (expand-file-name (TeX-buffer-file-name)))
            format-cons)
@@ -3797,22 +3875,28 @@ name(\\([^)]+\\))\\)\\|\
                                           (funcall preview-find-end-function
                                                    region-beg)
                                         (point)))
-                                     (ovl (preview-place-preview
-                                           snippet
-                                           region-beg
-                                           region-end
-                                           (preview-TeX-bb box)
-                                           (cons lcounters counters)
-                                           tempdir
-                                           (cdr open-data))))
-                                (setq close-data (nconc ovl close-data))
-                                (when (and preview-protect-point
-                                           (<= region-beg point-current)
-                                           (< point-current region-end))
-                                  ;; Temporarily open the preview if it
-                                  ;; would bump the point.
-                                  (preview-toggle (car ovl))
-                                  (push (car ovl) preview-temporary-opened)))
+                                     ovl)
+                                (save-excursion
+                                  ;; Restore point to current one before
+                                  ;; placing preview
+                                  (goto-char point-current)
+                                  (setq ovl (preview-place-preview
+                                             snippet
+                                             region-beg
+                                             region-end
+                                             (preview-TeX-bb box)
+                                             (cons lcounters counters)
+                                             tempdir
+                                             (cdr open-data)))
+                                  (setq close-data (nconc ovl close-data))
+                                  (when (and preview-protect-point
+                                             (<= region-beg point-current)
+                                             (< point-current region-end)
+                                             (not preview-point))
+                                    ;; Temporarily open the preview if it
+                                    ;; would bump the point.
+                                    (preview-toggle (car ovl))
+                                    (push (car ovl) preview-temporary-opened))))
                             (with-current-buffer run-buffer
                               (preview-log-error
                                (list 'error
@@ -4420,6 +4504,301 @@ If not a regular release, the date of the last change.")
           (insert "\n")))
     (error nil)))

+
+;;; preview-point
+
+;; Buframe functions, it will be assumed that buframe is installed so
+;; that it can be required.
+(declare-function buframe-position-right-of-overlay "ext:buframe"
+                  (frame ov &optional location))
+(declare-function buframe-make-buffer "ext:buframe" (name &optional locals))
+(declare-function buframe-make "ext:buframe"
+                  (frame-or-name fn-pos buffer &optional
+                                 parent-buffer parent-frame parameters))
+(declare-function buframe-disable "ext:buframe" (frame-or-name &optional enable))
+
+(defun preview-point--buframe (show ov str)
+  "Show or hide a a buframe popup with STR around overlay OV."
+  (require 'buframe)
+  (if show
+      (let* ((buf (buframe-make-buffer " *preview-point-buffer*"
+                                       (car-safe (cddr (cdr-safe preview-point)))))
+             (max-image-size
+              (if (integerp max-image-size)
+                  max-image-size
+                ;; Set the size max-image-size using the current frame
+                ;; since the popup frame will be small to begin with
+                (* max-image-size (frame-width)))))
+        (with-current-buffer buf
+          (let (buffer-read-only)
+            (with-silent-modifications
+              (erase-buffer)
+              (insert (propertize str
+                                  'help-echo nil
+                                  'keymap nil
+                                  'mouse-face nil))
+              (goto-char (point-min)))))
+        (setq preview-point--frame
+              (buframe-make
+               "preview-point"
+               (lambda (frame)
+                 (when preview-point--current-overlay
+                   (funcall
+                    (or (car-safe (cdr-safe preview-point))
+                        #'buframe-position-right-of-overlay)
+                    frame preview-point--current-overlay)))
+               buf
+               (overlay-buffer ov)
+               (window-frame)
+               (car-safe (cdr (cdr-safe preview-point))))))
+    (buframe-disable preview-point--frame)))
+
+(defun preview-point-inside-overlay-p (ov &optional pt)
+  "Return PT if inside overlay OV, nil otherwise.
+If PT is nil, use point of OV's buffer."
+  (or pt
+      (setq pt (and
+                (overlay-buffer ov)
+                (with-current-buffer (overlay-buffer ov)
+                  (point)))))
+  (and
+   (eq (overlay-buffer ov) (window-buffer))
+   (>= pt (overlay-start ov))
+   (< pt (overlay-end ov))
+   pt))
+
+(defun preview-point-activate-maybe (ov &optional arg)
+  "Toggle visibility of preview overlay OV.
+If ARG is non-nil, deactivate overlay instead.
+
+If (point) is not inside OV, then a call to activate the overlay is
+ignored.  If the preview is disabled, the disabled symbol is shown when
+activated, otherwise the preview state is not changed."
+  (let* ((pt (and
+              (overlay-buffer ov)
+              (with-current-buffer (overlay-buffer ov)
+                (point))))
+         (strings (overlay-get ov 'strings))
+         (construct-p (overlay-get ov 'queued))
+         (disabled-p (eq (overlay-get ov 'preview-state) 'disabled))
+         (inside-p (preview-point-inside-overlay-p ov pt))
+         (str (car strings))
+         (show (and arg inside-p)))
+    ;; Update `strings' cdr, if needed
+    (when (or construct-p disabled-p)
+      (unless (cdr (overlay-get ov 'strings))
+        (setcdr (overlay-get ov 'strings)
+                (cond
+                 (disabled-p
+                  (if preview-leave-open-previews-visible
+                      (propertize str
+                                  'face
+                                  'preview-point-disabled-face)
+                    (preview-disabled-string ov)))
+                 (construct-p
+                  (if preview-leave-open-previews-visible
+                      (propertize str
+                                  'face
+                                  'preview-point-processing-face)
+                    (propertize "x" 'display preview-nonready-icon))))))
+      (setq str (cdr (overlay-get ov 'strings))))
+
+    (unless disabled-p
+      (overlay-put ov 'preview-state
+                   (if show
+                       'active
+                     'inactive)))
+
+    (when show
+      (overlay-put ov 'category 'preview-overlay))
+
+    (when (or show
+              (eq preview-point--current-overlay ov))
+      (setq preview-point--current-overlay (and show ov))
+      (if (or (eq preview-point 'buframe)
+              (eq (car-safe preview-point) 'buframe))
+          (preview-point--buframe show ov str)
+        (when (memq preview-point '(after-string before-string))
+          (overlay-put ov preview-point (and show str)))))))
+
+(defun preview-point-move-point ()
+  "Toggle previews as point enters or leaves overlays."
+  (preview-check-changes)
+  (let* ((pt (point))
+         (lst (overlays-at pt)))
+    ;; Hide any open overlays
+    (when-let* ((ov preview-point--current-overlay))
+      (and (overlay-buffer ov)
+           (overlay-get ov 'preview-state)
+           (not (eq (overlay-get ov 'preview-state) 'inactive))
+           (when (not (preview-point-inside-overlay-p
+                       ov pt))
+             (preview-point-activate-maybe ov nil))))
+
+    ;; Show all overlays under point
+    (dolist (ovr lst)
+      (let ((state (overlay-get ovr 'preview-state)))
+        (when ;; (eq (overlay-get ovr 'preview-state) 'inactive)
+            (and (and state (not (eq state 'active)))
+                 (not (eq ovr preview-point--current-overlay)))
+          (preview-point-activate-maybe ovr t))))))
+
+(defun preview-point-auto ()
+  "Mark current region for preview, if not already there."
+  (when (and
+         preview-point
+         (not (eq preview-point 'hidden))
+         (not (preview-point-has-preview-p))
+         preview-point-auto-p
+         (funcall preview-point-auto-p))
+    (preview-point-force-update (point) (current-buffer) t)))
+
+(defun preview-point-updated (ov)
+  "Mark preview OV as updated.
+Has effect only if `preview-point' is non-nil"
+  (when preview-point
+    (preview-point-activate-maybe ov t)))
+
+(defun preview-point-toggle-mode (mode)
+  "Set `preview-point' to MODE.
+If called interactively `preview-point' is toggled and the user is asked
+for the MODE when it is switch on.
+
+This function has an effect only if `preview-point' is non-nil, which
+should be set before opening a TeX file."
+  (interactive
+   (list (if preview-point
+             (if (not (eq preview-point 'hidden))
+                 'hidden
+               (intern
+                (cadr (read-multiple-choice
+                       "Mode :"
+                       '((?b "before-string")
+                         (?a "after-string")
+                         (?f "buframe"))))))
+           (error "Preview-point is not enabled.  \
+Set preview-point before opening the TeX file"))))
+
+  (unless preview-point
+    (error "Preview-point needs to be enabled first (before opening the tex file)."))
+  ;; Hide current overlay if it is visible.
+  (when preview-point--current-overlay
+    (preview-toggle preview-point--current-overlay nil))
+  (setq preview-point mode)
+  ;; Show the preview if it at point.
+  (preview-point-move-point))
+
+(defun preview-point-toggle-auto-update (enable &optional silent)
+  "Enable auto refresh of previews.
+When ENABLE is nil, disable auto-update instead.  If called
+interactively, auto-updating is toggled."
+  (interactive (list 'toggle))
+  (when (eq enable 'toggle)
+    (setq enable (not (memq
+                       #'preview-point-buf-change
+                       after-change-functions))))
+  (if enable
+      (progn
+        (add-hook 'after-change-functions #'preview-point-buf-change nil t)
+        (add-hook 'post-command-hook #'preview-point-auto nil t)
+        (preview-point-buf-change)
+        (unless silent
+          (message "Auto-updating previews enabled")))
+    (remove-hook 'after-change-functions #'preview-point-buf-change t)
+    (remove-hook 'post-command-hook #'preview-point-auto t)
+    (unless silent
+      (message "Auto-updating previews disabled"))))
+
+;;; preview-point -- Auto-preview
+(defcustom preview-point-auto-delay 0.1
+  "Delay in seconds for automatic preview timer."
+  :type 'number)
+(defvar preview-point-force-update--debounce-timer nil)
+
+(defun preview-point@around@write-region (orig-fun &rest args)
+  "Advice around `write-region' to suppress messages.
+ORIG-FUN is the original function.  ARGS are its arguments."
+  (let ((noninteractive t)
+        (inhibit-message t)
+        message-log-max)
+    (apply orig-fun args)))
+
+(defun preview-point-force-update (pt buffer &optional debounce)
+  "Update preview at PT in BUFFER.
+
+When DEBOUNCE is non-nil, the call is debounced using an idle
+timer. This also happens automatically when there is an ongoing
+compilation process."
+  (interactive (list (point) (current-buffer)))
+
+  (when preview-point-force-update--debounce-timer
+    (cancel-timer preview-point-force-update--debounce-timer)
+    (setq preview-point-force-update--debounce-timer nil))
+
+  (when (buffer-live-p buffer)
+    (unless debounce
+      (with-current-buffer buffer
+        (if-let* ((cur-process
+                   (or (get-buffer-process (TeX-process-buffer-name
+                                            (TeX-region-file)))
+                       (get-buffer-process (TeX-process-buffer-name
+                                            (TeX-master-file))))))
+            (progn
+              ;; Force de-bouncing
+              (when (and preview-current-region
+                         (not preview-abort-flag)
+                         ;; (< beg (cdr preview-current-region))
+                         )
+                (progn
+                  (ignore-errors (TeX-kill-job))
+                  (setq preview-abort-flag t)))
+              (with-local-quit (accept-process-output cur-process))
+              (setq debounce t))
+          ;; The code below is adopted from preview-auto
+          (let ((TeX-suppress-compilation-message t)
+                (save-silently t))
+            (advice-add 'write-region :around
+                        #'preview-point@around@write-region)
+            (unwind-protect
+                ;; If we are working in a file buffer that is not a tex file,
+                ;; then we want preview-region to operate in "non-file" mode,
+                ;; where it passes "<none>" to TeX-region-create.
+                (save-excursion
+                  (goto-char pt)
+                  ;; TODO: Check if we can rely on the `preview-region'
+                  ;; returning the process. It calls
+                  ;; `preview-generate-preview' which has this documented
+                  ;; behaviour, but not `preview-region'.
+                  (let ((process (preview-region (preview-next-border t)
+                                                 (preview-next-border nil))))
+                    (with-current-buffer (process-buffer process)
+                      (setq-local preview-silent-errors t))))
+              (advice-remove 'write-region
+                             #'preview-point@around@write-region))))))
+
+    (when debounce
+      (setq preview-point-force-update--debounce-timer
+            (run-with-idle-timer
+             preview-point-auto-delay nil
+             #'preview-point-force-update
+             pt buffer)))))
+
+(defun preview-point-has-preview-p (&optional pt)
+  "Return non-nil if PT has a preview overlay."
+  (cl-find-if
+   (lambda (ov) (overlay-get ov 'preview-state))
+   (overlays-at (or pt (point)))))
+
+(defun preview-point-buf-change (&rest _)
+  "Run preview at point if there is a preview overlay."
+  (when (and preview-point
+             (not (eq preview-point 'hidden))
+             (or
+              (preview-point-has-preview-p)
+              (and preview-point-auto-p
+                   (funcall preview-point-auto-p))))
+    (preview-point-force-update (point) (current-buffer) t)))
+
 ;;;###autoload
 (defun preview-report-bug () "Report a bug in the preview-latex package."
        (interactive)
--
2.50.1 (Apple Git-155)
_______________________________________________
bug-auctex mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/bug-auctex

Reply via email to