From e8e4065da6e166e9859e14c95558e385d320dcbe Mon Sep 17 00:00:00 2001 Message-Id: From: Ihor Radchenko Date: Sun, 9 Oct 2022 14:16:41 +0800 Subject: [PATCH 1/2] org-export-with-buffer-copy: Allow safe reusable buffer copy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * lisp/ox.el (org-export--generate-copy-script): (org-export-copy-buffer): Accept cl-style key arguments. * lisp/ox.el (org-export-with-buffer-copy): Allow optional cl-style key arguments for fine-grained control on what to copy from the target buffer and which buffer to use as a target. Do not kill the target buffer upon finished, when the target is provided. Make sure that remaining buffer copy does not preserve `buffer-file-name' from the original buffer and that it never overwrites the file associated with the original buffer. * lisp/ox-html.el (org-html-format-latex): Use the new version of `org-export-with-buffer-copy' instead of managing edge cases by itself. Reported-by: Rudolf Adamkovič Link: https://orgmode.org/list/87zge8j5iu.fsf@localhost --- lisp/ox-html.el | 27 +++++----------- lisp/ox.el | 82 ++++++++++++++++++++++++++++++------------------- 2 files changed, 59 insertions(+), 50 deletions(-) diff --git a/lisp/ox-html.el b/lisp/ox-html.el index 3f55be2ee..cad06aebf 100644 --- a/lisp/ox-html.el +++ b/lisp/ox-html.el @@ -2879,25 +2879,14 @@ (defun org-html-format-latex (latex-frag processing-type info) ;; temporary buffer so that dvipng/imagemagick can properly ;; turn the fragment into an image. (setq latex-frag (concat latex-header latex-frag)))) - (with-current-buffer - (org-export-copy-buffer - (get-buffer-create " *Org HTML Export LaTeX*") - 'drop-visible 'drop-narrowing 'drop-contents) - (erase-buffer) - (insert latex-frag) - (org-format-latex cache-relpath nil nil cache-dir nil - "Creating LaTeX Image..." nil processing-type) - ;; Present save dialogue to be shown for this buffer and prevent - ;; Emacs to jump into this buffer when opening - ;; `buffer-file-name' file. We need this because - ;; `org-export-copy-buffer' copies `buffer-file-name' local - ;; variable thus making Emacs think that the buffer copy is - ;; associated with file. Note that despite `buffer-file-name', - ;; `org-export-copy-buffer' arranges saving to not perform - ;; actual writing onto the disk. - (setq buffer-file-name nil) - (restore-buffer-modified-p nil) - (buffer-string)))) + (org-export-with-buffer-copy + :to-buffer (get-buffer-create " *Org HTML Export LaTeX*") + :drop-visibility t :drop-narrowing t :drop-contents t + (erase-buffer) + (insert latex-frag) + (org-format-latex cache-relpath nil nil cache-dir nil + "Creating LaTeX Image..." nil processing-type) + (buffer-string)))) (defun org-html--wrap-latex-environment (contents _ &optional caption label) "Wrap CONTENTS string within appropriate environment for equations. diff --git a/lisp/ox.el b/lisp/ox.el index e059983fb..69a95ffe5 100644 --- a/lisp/ox.el +++ b/lisp/ox.el @@ -2544,9 +2544,9 @@ ;;; Core functions ;; a default template (or a back-end specific template) at point or in ;; current subtree. -(defun org-export-copy-buffer (&optional buffer drop-visibility - drop-narrowing drop-contents - drop-locals) +(cl-defun org-export-copy-buffer (&key to-buffer drop-visibility + drop-narrowing drop-contents + drop-locals) "Return a copy of the current buffer. The copy preserves Org buffer-local variables, visibility and narrowing. @@ -2561,61 +2561,81 @@ (defun org-export-copy-buffer (&optional buffer drop-visibility Emacs save dialogue. Prefer using `org-export-with-buffer-copy' macro when possible. -When optional argument BUFFER is non-nil, copy into BUFFER. +When optional key `:to-buffer' is non-nil, copy into BUFFER. -Optional arguments DROP-VISIBILITY, DROP-NARROWING, DROP-CONTENTS, and -DROP-LOCALS are passed to `org-export--generate-copy-script'." +Optional keys `:drop-visibility', `:drop-narrowing', `:drop-contents', +and `:drop-locals' are passed to `org-export--generate-copy-script'." (let ((copy-buffer-fun (org-export--generate-copy-script (current-buffer) - 'do-not-check-unreadable - drop-visibility - drop-narrowing - drop-contents - drop-locals)) - (new-buf (or buffer (generate-new-buffer (buffer-name))))) + :copy-unreadable 'do-not-check + :drop-visibility drop-visibility + :drop-narrowing drop-narrowing + :drop-contents drop-contents + :drop-locals drop-locals)) + (new-buf (or to-buffer (generate-new-buffer (buffer-name))))) (with-current-buffer new-buf (funcall copy-buffer-fun) (set-buffer-modified-p nil)) new-buf)) -(defmacro org-export-with-buffer-copy (&rest body) +(cl-defmacro org-export-with-buffer-copy ( &rest body + &key to-buffer drop-visibility + drop-narrowing drop-contents + drop-locals + &allow-other-keys) "Apply BODY in a copy of the current buffer. The copy preserves local variables, visibility and contents of the original buffer. Point is at the beginning of the buffer -when BODY is applied." +when BODY is applied. + +Optional keys can modify what is being copied and the generated buffer +copy. `:to-buffer', `:drop-visibility', `:drop-narrowing', +`:drop-contents', and `:drop-locals' are passed as arguments to +`org-export-copy-buffer'." (declare (debug t)) (org-with-gensyms (buf-copy) - `(let ((,buf-copy (org-export-copy-buffer))) + `(let ((,buf-copy (org-export-copy-buffer + :to-buffer ,to-buffer + :drop-visibility ,drop-visibility + :drop-narrowing ,drop-narrowing + :drop-contents ,drop-contents + :drop-locals ,drop-locals))) (unwind-protect (with-current-buffer ,buf-copy (goto-char (point-min)) - (progn ,@body)) + (prog1 + (progn ,@body) + ;; `org-export-copy-buffer' carried the value of + ;; `buffer-file-name' from the original buffer. When not + ;; killed, the new buffer copy may become a target of + ;; `find-file'. Prevent this. + (setq buffer-file-name nil))) (and (buffer-live-p ,buf-copy) ;; Kill copy without confirmation. (progn (with-current-buffer ,buf-copy (restore-buffer-modified-p nil)) - (kill-buffer ,buf-copy))))))) - -(defun org-export--generate-copy-script (buffer - &optional - copy-unreadable - drop-visibility - drop-narrowing - drop-contents - drop-locals) + (unless ,to-buffer + (kill-buffer ,buf-copy)))))))) + +(cl-defun org-export--generate-copy-script (buffer + &key + copy-unreadable + drop-visibility + drop-narrowing + drop-contents + drop-locals) "Generate a function duplicating BUFFER. The copy will preserve local variables, visibility, contents and narrowing of the original buffer. If a region was active in BUFFER, contents will be narrowed to that region instead. -When optional argument COPY-UNREADABLE is non-nil, do not ensure that -all the copied local variables will be readable in another Emacs -session. +When optional key `:copy-unreadable' is non-nil, do not ensure that all +the copied local variables will be readable in another Emacs session. -When optional arguments DROP-VISIBILITY, DROP-NARROWING, -DROP-CONTENTS, or DROP-LOCALS are non-nil, do not preserve visibility, -narrowing, contents, or local variables correspondingly. +When optional keys `:drop-visibility', `:drop-narrowing', +`:drop-contents', or `:drop-locals' are non-nil, do not preserve +visibility, narrowing, contents, or local variables correspondingly. The resulting function can be evaluated at a later time, from another buffer, effectively cloning the original buffer there. -- 2.35.1