emacs-orgmode
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: The Org mode in the Org Git does not export


From: Ihor Radchenko
Subject: Re: The Org mode in the Org Git does not export
Date: Sun, 09 Oct 2022 14:36:58 +0800

Rudolf Adamkovič <salutis@me.com> writes:

>>> (1) re-opening the file after export always re-opens it, and
>>
>> I am not sure how to test this part.
>
> How about the attached patch?
>
> It mirrors the manual steps (find-file, export, kill-buffer, find-file),
> except it calls just the 'org-export-copy-buffer' procedure instead of
> exporting to HTML.  The test fails without your fix and passes with it.

The test in the patch is erroneous. `org-export-copy-buffer', unless it
kills the generated buffer, does nothing about `buffer-file-name' local
variable.  The patch is only working by accident because `find-file'
opens the first buffer with matching `buffer-file-name'. If there are
multiple such buffers, the return value depends on their order.

I have updated `org-export-with-buffer-copy' macro to take care about
this `buffer-file-name' issue uniformly without a need to put
workarounds into every caller. I have also updated your patch using a
more appropriate testing assertions. It now uses the updated macro.

See the attached patches.
(I'd like this patches to be tested on real export first as it is touching
on very basic export routines).

>From e8e4065da6e166e9859e14c95558e385d320dcbe Mon Sep 17 00:00:00 2001
Message-Id: 
<e8e4065da6e166e9859e14c95558e385d320dcbe.1665297377.git.yantar92@gmail.com>
From: Ihor Radchenko <yantar92@gmail.com>
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č <salutis@me.com>
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

>From 6ed84c657f4bb7a6427c0c157d69d98542531260 Mon Sep 17 00:00:00 2001
Message-Id: 
<6ed84c657f4bb7a6427c0c157d69d98542531260.1665297377.git.yantar92@gmail.com>
In-Reply-To: 
<e8e4065da6e166e9859e14c95558e385d320dcbe.1665297377.git.yantar92@gmail.com>
References: 
<e8e4065da6e166e9859e14c95558e385d320dcbe.1665297377.git.yantar92@gmail.com>
From: Ihor Radchenko <yantar92@gmail.com>
Date: Sun, 9 Oct 2022 14:31:10 +0800
Subject: [PATCH 2/2] Add a regression test for `org-export-with-buffer-copy'

* testing/lisp/test-ox.el (test-org-export/org-export-copy-buffer):
Make sure that `org-export-with-buffer-copy' does not show up when
Emacs is searching for buffers associated with file.
---
 testing/lisp/test-ox.el | 20 ++++++++++++++++----
 1 file changed, 16 insertions(+), 4 deletions(-)

diff --git a/testing/lisp/test-ox.el b/testing/lisp/test-ox.el
index 90a9eb3aa..42867919b 100644
--- a/testing/lisp/test-ox.el
+++ b/testing/lisp/test-ox.el
@@ -63,20 +63,32 @@ ;;; Internal Tests
 
 (ert-deftest test-org-export/org-export-copy-buffer ()
   "Test `org-export-copy-buffer' specifications."
-  ;; The buffer copy must not cause overwriting the original file
-  ;; buffer under any circumstances.
+  ;; The copy must not overwrite the original file.
   (org-test-with-temp-text-in-file
       "* Heading"
     (let ((file (buffer-file-name)))
       (with-current-buffer (org-export-copy-buffer)
-        (insert "This must not go into actual file.")
+        (insert "This must not go into the original file.")
         (save-buffer)
         (should
          (equal
           "* Heading"
           (with-temp-buffer
             (insert-file-contents file)
-            (buffer-string))))))))
+            (buffer-string)))))))
+  ;; The copy must not show when re-opening the original file.
+  (org-test-with-temp-text-in-file
+      "* Heading"
+    (let ((file (buffer-file-name))
+          (buffer-copy (generate-new-buffer " *Org export copy*")))
+      (org-export-with-buffer-copy
+       :to-buffer buffer-copy
+       (insert "This must not show as the original file.")
+       (save-buffer))
+      ;; Unassign the original buffer from file.
+      (setq buffer-file-name nil)
+      (should-not
+       (equal buffer-copy (get-file-buffer file))))))
 
 (ert-deftest test-org-export/bind-keyword ()
   "Test reading #+BIND: keywords."
-- 
2.35.1


-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>

reply via email to

[Prev in Thread] Current Thread [Next in Thread]