org-export-with-buffer-copy: Allow safe reusable buffer copy

* 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č <salutis@me.com>
Link: https://orgmode.org/list/87zge8j5iu.fsf@localhost
This commit is contained in:
Ihor Radchenko 2022-10-09 14:16:41 +08:00
parent e7feeb2225
commit 192742c9c5
No known key found for this signature in database
GPG Key ID: 6470762A7DA11D8B
2 changed files with 58 additions and 49 deletions

View File

@ -2879,25 +2879,14 @@ INFO is a plist containing export properties."
;; temporary buffer so that dvipng/imagemagick can properly ;; temporary buffer so that dvipng/imagemagick can properly
;; turn the fragment into an image. ;; turn the fragment into an image.
(setq latex-frag (concat latex-header latex-frag)))) (setq latex-frag (concat latex-header latex-frag))))
(with-current-buffer (org-export-with-buffer-copy
(org-export-copy-buffer :to-buffer (get-buffer-create " *Org HTML Export LaTeX*")
(get-buffer-create " *Org HTML Export LaTeX*") :drop-visibility t :drop-narrowing t :drop-contents t
'drop-visible 'drop-narrowing 'drop-contents) (erase-buffer)
(erase-buffer) (insert latex-frag)
(insert latex-frag) (org-format-latex cache-relpath nil nil cache-dir nil
(org-format-latex cache-relpath nil nil cache-dir nil "Creating LaTeX Image..." nil processing-type)
"Creating LaTeX Image..." nil processing-type) (buffer-string))))
;; 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))))
(defun org-html--wrap-latex-environment (contents _ &optional caption label) (defun org-html--wrap-latex-environment (contents _ &optional caption label)
"Wrap CONTENTS string within appropriate environment for equations. "Wrap CONTENTS string within appropriate environment for equations.

View File

@ -2544,9 +2544,9 @@ Return the updated communication channel."
;; a default template (or a back-end specific template) at point or in ;; a default template (or a back-end specific template) at point or in
;; current subtree. ;; current subtree.
(defun org-export-copy-buffer (&optional buffer drop-visibility (cl-defun org-export-copy-buffer (&key to-buffer drop-visibility
drop-narrowing drop-contents drop-narrowing drop-contents
drop-locals) drop-locals)
"Return a copy of the current buffer. "Return a copy of the current buffer.
The copy preserves Org buffer-local variables, visibility and The copy preserves Org buffer-local variables, visibility and
narrowing. narrowing.
@ -2561,61 +2561,81 @@ then re-opened. Making edits in the buffer copy may also trigger
Emacs save dialogue. Prefer using `org-export-with-buffer-copy' macro Emacs save dialogue. Prefer using `org-export-with-buffer-copy' macro
when possible. 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 Optional keys `:drop-visibility', `:drop-narrowing', `:drop-contents',
DROP-LOCALS are passed to `org-export--generate-copy-script'." and `:drop-locals' are passed to `org-export--generate-copy-script'."
(let ((copy-buffer-fun (org-export--generate-copy-script (let ((copy-buffer-fun (org-export--generate-copy-script
(current-buffer) (current-buffer)
'do-not-check-unreadable :copy-unreadable 'do-not-check
drop-visibility :drop-visibility drop-visibility
drop-narrowing :drop-narrowing drop-narrowing
drop-contents :drop-contents drop-contents
drop-locals)) :drop-locals drop-locals))
(new-buf (or buffer (generate-new-buffer (buffer-name))))) (new-buf (or to-buffer (generate-new-buffer (buffer-name)))))
(with-current-buffer new-buf (with-current-buffer new-buf
(funcall copy-buffer-fun) (funcall copy-buffer-fun)
(set-buffer-modified-p nil)) (set-buffer-modified-p nil))
new-buf)) 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. "Apply BODY in a copy of the current buffer.
The copy preserves local variables, visibility and contents of The copy preserves local variables, visibility and contents of
the original buffer. Point is at the beginning of the buffer 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)) (declare (debug t))
(org-with-gensyms (buf-copy) (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 (unwind-protect
(with-current-buffer ,buf-copy (with-current-buffer ,buf-copy
(goto-char (point-min)) (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) (and (buffer-live-p ,buf-copy)
;; Kill copy without confirmation. ;; Kill copy without confirmation.
(progn (with-current-buffer ,buf-copy (progn (with-current-buffer ,buf-copy
(restore-buffer-modified-p nil)) (restore-buffer-modified-p nil))
(kill-buffer ,buf-copy))))))) (unless ,to-buffer
(kill-buffer ,buf-copy))))))))
(defun org-export--generate-copy-script (buffer (cl-defun org-export--generate-copy-script (buffer
&optional &key
copy-unreadable copy-unreadable
drop-visibility drop-visibility
drop-narrowing drop-narrowing
drop-contents drop-contents
drop-locals) drop-locals)
"Generate a function duplicating BUFFER. "Generate a function duplicating BUFFER.
The copy will preserve local variables, visibility, contents and The copy will preserve local variables, visibility, contents and
narrowing of the original buffer. If a region was active in narrowing of the original buffer. If a region was active in
BUFFER, contents will be narrowed to that region instead. BUFFER, contents will be narrowed to that region instead.
When optional argument COPY-UNREADABLE is non-nil, do not ensure that When optional key `:copy-unreadable' is non-nil, do not ensure that all
all the copied local variables will be readable in another Emacs the copied local variables will be readable in another Emacs session.
session.
When optional arguments DROP-VISIBILITY, DROP-NARROWING, When optional keys `:drop-visibility', `:drop-narrowing',
DROP-CONTENTS, or DROP-LOCALS are non-nil, do not preserve visibility, `:drop-contents', or `:drop-locals' are non-nil, do not preserve
narrowing, contents, or local variables correspondingly. visibility, narrowing, contents, or local variables correspondingly.
The resulting function can be evaluated at a later time, from The resulting function can be evaluated at a later time, from
another buffer, effectively cloning the original buffer there. another buffer, effectively cloning the original buffer there.