From b9e0db41ceaa5107e318135604ea5ecfd3c5405e Mon Sep 17 00:00:00 2001 From: TEC Date: Wed, 4 Jan 2023 01:24:06 +0800 Subject: [PATCH] org-latex-preview: Check all fragments produced * lisp/org-latex-preview.el (org-latex-preview--check-all-fragments-produced): Create a new callback that checks that each fragment has indeed been produced not, and if not guesses the last produced fragment caused a problem. The last produced fragment is then marked as erroneous, its cache entry updated (replaced and re-inserted), and the remaining fragments are regenerated. (org-latex-preview-create-image-async): Run `org-latex-preview--check-all-fragments-produced' after successfully extracting images. (org-latex-preview--cache-name, org-latex-preview--cache-image, org-latex-preview--get-cached): Use a defconst instead of hardcoding the cache container string in `org-latex-preview--cache-image' and `org-latex-preview--get-cached'. (org-latex-preview--remove-cached): Easy removal of an item from the org-persist cache, as a counterpart to `org-latex-preview--cache-image'. --- lisp/org-latex-preview.el | 53 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 49 insertions(+), 4 deletions(-) diff --git a/lisp/org-latex-preview.el b/lisp/org-latex-preview.el index 38df81741..657c4ec6b 100644 --- a/lisp/org-latex-preview.el +++ b/lisp/org-latex-preview.el @@ -900,7 +900,9 @@ during processing to hold more information on the fragments." (img-extract-async (org-latex-preview--image-extract-async extended-info))) (plist-put (cddr img-extract-async) :success - (list #'org-latex-preview--cleanup-callback)) + (list ; The order is important here. + #'org-latex-preview--check-all-fragments-produced + #'org-latex-preview--cleanup-callback)) (pcase processing-type ('dvipng (plist-put (cddr img-extract-async) :filter @@ -1082,6 +1084,40 @@ The path of the created LaTeX file is returned." (when (file-exists-p (concat basename ext)) (delete-file (concat basename ext)))))) +(defun org-latex-preview--check-all-fragments-produced (_exit-code _stdout extended-info) + "Check each of the fragments in EXTENDED-INFO has a path. +Should this not be the case, the fragment immediately before the first +fragment without a path is marked as erronious, and the remaining +fragments are regenerated." + (let ((fragments (cons nil (copy-sequence (plist-get extended-info :fragments))))) + (while (cdr fragments) + (if (or (plist-get (cadr fragments) :path) + (plist-get (cadr fragments) :error)) + (setq fragments (cdr fragments)) + ;; If output ends prematurely, this is most likely due to an issue with + ;; the last "succesfully" produced fragment, and so we mark it as erronious + ;; and attempt to re-generate the rest. + (let ((bad-fragment (car fragments)) + (bad-fragment-err (plist-get (car fragments) :errors))) + (plist-put bad-fragment :errors + (concat bad-fragment-err + (and bad-fragment-err "\n\n") + "Preview generation catastrophically failed after this fragment.")) + (org-latex-preview--remove-cached + (plist-get bad-fragment :key)) + (org-latex-preview--update-overlay + (plist-get bad-fragment :overlay) + (org-latex-preview--cache-image + (plist-get bad-fragment :key) + (plist-get bad-fragment :path) + (org-latex-preview--display-info + extended-info bad-fragment)))) + ;; Re-generate the remaining fragments. + (org-latex-preview-create-image-async + (plist-get extended-info :processor) + (cdr fragments)) + (setq fragments nil))))) + (defun org-latex-preview--display-info (extended-info fragment-info) "From FRAGMENT-INFO and EXTENDED-INFO obtain display-relevant information." (let ((image-type (intern (plist-get extended-info :image-output-type))) @@ -1282,14 +1318,17 @@ listed in EXTENDED-INFO will be used." (org-latex-preview--display-info extended-info fragment-info)))))))) +(defconst org-latex-preview--cache-name "LaTeX preview cached image data" + "The name used for Org LaTeX Preview objects in the org-persist cache.") + (defun org-latex-preview--cache-image (key path info) "Save the image at PATH with associated INFO in the cache indexed by KEY. Return (path . info)." (let ((label-path-info - (or (org-persist-read "LaTeX preview cached image data" + (or (org-persist-read org-latex-preview--cache-name (list :key key) nil nil :read-related t) - (org-persist-register `("LaTeX preview cached image data" + (org-persist-register `(,org-latex-preview--cache-name (file ,path) (elisp-data ,info)) (list :key key) @@ -1308,12 +1347,18 @@ Example result: :depth 0.2 :errors nil)" (when-let ((label-path-info - (org-persist-read "LaTeX preview cached image data" + (org-persist-read org-latex-preview--cache-name (list :key key) nil nil :read-related t))) (cons (cadr label-path-info) (caddr label-path-info)))) +(defun org-latex-preview--remove-cached (key) + "Remove the fragment cache associated with KEY." + (org-persist-unregister org-latex-preview--cache-name + (list :key key) + :remove-related t)) + ;; TODO: Switching processes from imagemagick to dvi* with an existing ;; dump-file during a single Emacs session should trigger ;; re-precompilation with the new precompile command.