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
;; 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.

View File

@ -2544,9 +2544,9 @@ Return the updated communication channel."
;; 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 @@ then re-opened. Making edits in the buffer copy may also trigger
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)))))))
(unless ,to-buffer
(kill-buffer ,buf-copy))))))))
(defun org-export--generate-copy-script (buffer
&optional
copy-unreadable
drop-visibility
drop-narrowing
drop-contents
drop-locals)
(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.