From: Ihor Radchenko <yantar92@posteo.net>
To: David Lukes <dafydd.lukes@gmail.com>
Cc: emacs-orgmode@gnu.org
Subject: Re: [PATCH] ox-odt: Prevent auto-formatting in export buffers
Date: Sat, 18 Mar 2023 11:42:59 +0000 [thread overview]
Message-ID: <87zg8axp30.fsf@localhost> (raw)
In-Reply-To: <20221002035931.12191-1-dafydd.lukes@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 1117 bytes --]
David Lukes <dafydd.lukes@gmail.com> writes:
> * lisp/ox-odt.el (org-odt-template, org-odt--export-wrap):
> `write-region' instead of `save-buffer'.
>
> `write-file' and `save-buffer' trigger major mode changes, which leads
> to various mode-related hooks being run. This is undesirable: running
> these on generated files is wasted time and computation, and it can even
> lead to hard to track data corruption when auto-formatting hooks are
> involved. One such case is the 2006 version of the tidy program which
> ships with stock macOS and can corrupt multi-byte UTF-8 codepoints in
> HTML and ODT (via XML) exports. And even recent versions of tidy can
> re-arrange whitespace in the exported documents in unwanted ways.
See the attached patch where I applied the idea across Org, where it
made sense. Note that I did not alter `org-odt--export-wrap' because
`save-buffer' there is applied only when XML files are opened as buffers
in Emacs, presumably manually. Interactive `save-buffer' makes sense
then. (Though maybe that code is not needed at all, IDK)
Please let me know if there are any objections.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Prefer-write-region-to-save-file.patch --]
[-- Type: text/x-patch, Size: 9278 bytes --]
From 8d8884bb6be0ba7cb7f9662f067d42b53393e92e Mon Sep 17 00:00:00 2001
Message-Id: <8d8884bb6be0ba7cb7f9662f067d42b53393e92e.1679139580.git.yantar92@posteo.net>
From: Ihor Radchenko <yantar92@posteo.net>
Date: Sat, 18 Mar 2023 12:34:17 +0100
Subject: [PATCH] Prefer `write-region' to `save-file'
* lisp/ob-haskell.el (org-babel-haskell-export-to-lhs): Use
non-interactive `insert-file-contents' + `write-region' to avoid
triggering various interactive hooks. Ensure that temp files are
always deleted.
* lisp/org-agenda.el (org-agenda-write):
* lisp/org-table.el: Simplify code using `write-region'.
* lisp/ox-odt.el (org-odt-template): Use `insert-file-contents' +
`write-region' instead of `find-file-noselect' that may trigger
various hooks. The new approach makes `revert-buffer' not
necessary (and do not trigger `revert-buffer' hooks). Also, the
problem with backups will no longer exists.
Original idea: https://list.orgmode.org/orgmode/20221002035931.12191-1-dafydd.lukes@gmail.com/
---
lisp/ob-haskell.el | 41 ++++++++++++------------
lisp/org-agenda.el | 9 ++----
lisp/org-table.el | 10 ++----
lisp/ox-odt.el | 78 ++++++++++++++++++++--------------------------
4 files changed, 59 insertions(+), 79 deletions(-)
diff --git a/lisp/ob-haskell.el b/lisp/ob-haskell.el
index 2b1441c2a..3e64c1657 100644
--- a/lisp/ob-haskell.el
+++ b/lisp/ob-haskell.el
@@ -255,26 +255,27 @@ (defun org-babel-haskell-export-to-lhs (&optional arg)
t t)
(indent-code-rigidly (match-beginning 0) (match-end 0) indentation)))
(save-excursion
- ;; export to latex w/org and save as .lhs
- (require 'ox-latex)
- (find-file tmp-org-file)
- ;; Ensure we do not clutter kill ring with incomplete results.
- (let (org-export-copy-to-kill-ring)
- (org-export-to-file 'latex tmp-tex-file))
- (kill-buffer nil)
- (delete-file tmp-org-file)
- (find-file tmp-tex-file)
- (goto-char (point-min)) (forward-line 2)
- (insert "%include polycode.fmt\n")
- ;; ensure all \begin/end{code} statements start at the first column
- (while (re-search-forward "^[ \t]+\\\\begin{code}[^\000]+\\\\end{code}" nil t)
- (replace-match (save-match-data (org-remove-indentation (match-string 0)))
- t t))
- (setq contents (buffer-string))
- (save-buffer) (kill-buffer nil))
- (delete-file tmp-tex-file)
- ;; save org exported latex to a .lhs file
- (with-temp-file lhs-file (insert contents))
+ (unwind-protect
+ (with-temp-buffer
+ ;; Export to latex w/org and save as .lhs
+ (require 'ox-latex)
+ (insert-file-contents tmp-org-file)
+ ;; Ensure we do not clutter kill ring with incomplete results.
+ (let (org-export-copy-to-kill-ring)
+ (org-export-to-file 'latex tmp-tex-file)))
+ (delete-file tmp-org-file))
+ (unwind-protect
+ (with-temp-buffer
+ (insert-file-contents tmp-tex-file)
+ (goto-char (point-min)) (forward-line 2)
+ (insert "%include polycode.fmt\n")
+ ;; ensure all \begin/end{code} statements start at the first column
+ (while (re-search-forward "^[ \t]+\\\\begin{code}[^\000]+\\\\end{code}" nil t)
+ (replace-match (save-match-data (org-remove-indentation (match-string 0)))
+ t t))
+ ;; save org exported latex to a .lhs file
+ (write-region nil nil lhs-file))
+ (delete-file tmp-tex-file)))
(if (not arg)
(find-file lhs-file)
;; process .lhs file with lhs2tex
diff --git a/lisp/org-agenda.el b/lisp/org-agenda.el
index 3da0967f0..859a80c47 100644
--- a/lisp/org-agenda.el
+++ b/lisp/org-agenda.el
@@ -3667,13 +3667,8 @@ (defun org-agenda-write (file &optional open nosettings agenda-bufname)
"ox-icalendar" (file))
(org-icalendar-export-current-agenda (expand-file-name file)))
(t
- (let ((bs (buffer-string)))
- (find-file file)
- (erase-buffer)
- (insert bs)
- (save-buffer 0)
- (kill-buffer (current-buffer))
- (message "Plain text written to %s" file))))))))
+ (write-region nil nil file)
+ (message "Plain text written to %s" file)))))))
(set-buffer (or agenda-bufname
;; FIXME: I'm pretty sure called-interactively-p
;; doesn't do what we want here!
diff --git a/lisp/org-table.el b/lisp/org-table.el
index 5116b1127..97120fffd 100644
--- a/lisp/org-table.el
+++ b/lisp/org-table.el
@@ -4332,14 +4332,8 @@ (defun org-table-export (&optional file format)
(table (org-table-to-lisp)))
(unless (fboundp transform)
(user-error "No such transformation function %s" transform))
- (let (buf)
- (with-current-buffer (find-file-noselect file)
- (setq buf (current-buffer))
- (erase-buffer)
- (fundamental-mode)
- (insert (funcall transform table params) "\n")
- (save-buffer))
- (kill-buffer buf))
+ (with-temp-file file
+ (insert (funcall transform table params) "\n"))
(message "Export done."))
(user-error "TABLE_EXPORT_FORMAT invalid")))))
diff --git a/lisp/ox-odt.el b/lisp/ox-odt.el
index cf217c9e7..8fc34a749 100644
--- a/lisp/ox-odt.el
+++ b/lisp/ox-odt.el
@@ -1365,50 +1365,40 @@ (defun org-odt-template (contents info)
;; Ensure we have write permissions to this file.
(set-file-modes (concat org-odt-zip-dir "styles.xml") #o600)
- ;; FIXME: Who is opening an empty styles.xml before this point?
- (with-current-buffer
- (find-file-noselect (concat org-odt-zip-dir "styles.xml") t)
- (revert-buffer t t)
-
- ;; Write custom styles for source blocks
- ;; Save STYLES used for colorizing of source blocks.
- ;; Update styles.xml with styles that were collected as part of
- ;; `org-odt-hfy-face-to-css' callbacks.
- (let ((styles (mapconcat (lambda (style) (format " %s\n" (cddr style)))
- hfy-user-sheet-assoc "")))
- (when styles
- (goto-char (point-min))
- (when (re-search-forward "</office:styles>" nil t)
- (goto-char (match-beginning 0))
- (insert "\n<!-- Org Htmlfontify Styles -->\n" styles "\n"))))
-
- ;; Update styles.xml - take care of outline numbering
-
- ;; Don't make automatic backup of styles.xml file. This setting
- ;; prevents the backed-up styles.xml file from being zipped in to
- ;; odt file. This is more of a hackish fix. Better alternative
- ;; would be to fix the zip command so that the output odt file
- ;; includes only the needed files and excludes any auto-generated
- ;; extra files like backups and auto-saves etc etc. Note that
- ;; currently the zip command zips up the entire temp directory so
- ;; that any auto-generated files created under the hood ends up in
- ;; the resulting odt file.
- (setq-local backup-inhibited t)
-
- ;; Outline numbering is retained only up to LEVEL.
- ;; To disable outline numbering pass a LEVEL of 0.
-
- (goto-char (point-min))
- (let ((regex
- "<text:outline-level-style\\([^>]*\\)text:level=\"\\([^\"]*\\)\"\\([^>]*\\)>")
- (replacement
- "<text:outline-level-style\\1text:level=\"\\2\" style:num-format=\"\">"))
- (while (re-search-forward regex nil t)
- (unless (let ((sec-num (plist-get info :section-numbers))
- (level (string-to-number (match-string 2))))
- (if (wholenump sec-num) (<= level sec-num) sec-num))
- (replace-match replacement t nil))))
- (save-buffer 0)))
+ (let ((styles-xml (concat org-odt-zip-dir "styles.xml")))
+ (with-temp-buffer
+ (when (file-exists-p styles-xml)
+ (insert-file-contents styles-xml))
+
+ ;; Write custom styles for source blocks
+ ;; Save STYLES used for colorizing of source blocks.
+ ;; Update styles.xml with styles that were collected as part of
+ ;; `org-odt-hfy-face-to-css' callbacks.
+ (let ((styles (mapconcat (lambda (style) (format " %s\n" (cddr style)))
+ hfy-user-sheet-assoc "")))
+ (when styles
+ (goto-char (point-min))
+ (when (re-search-forward "</office:styles>" nil t)
+ (goto-char (match-beginning 0))
+ (insert "\n<!-- Org Htmlfontify Styles -->\n" styles "\n"))))
+
+ ;; Update styles.xml - take care of outline numbering
+ ;; Outline numbering is retained only up to LEVEL.
+ ;; To disable outline numbering pass a LEVEL of 0.
+
+ (let ((regex
+ "<text:outline-level-style\\([^>]*\\)text:level=\"\\([^\"]*\\)\"\\([^>]*\\)>")
+ (replacement
+ "<text:outline-level-style\\1text:level=\"\\2\" style:num-format=\"\">"))
+ (goto-char (point-min))
+ (while (re-search-forward regex nil t)
+ (unless (let ((sec-num (plist-get info :section-numbers))
+ (level (string-to-number (match-string 2))))
+ (if (wholenump sec-num) (<= level sec-num) sec-num))
+ (replace-match replacement t nil))))
+
+ ;; Write back the new contents.
+ (write-region nil nil styles-xml))))
;; Update content.xml.
(let* ( ;; `org-display-custom-times' should be accessed right
--
2.39.1
[-- Attachment #3: Type: text/plain, Size: 224 bytes --]
--
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>
next prev parent reply other threads:[~2023-03-18 11:42 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-10-02 3:59 [PATCH] ox-odt: Prevent auto-formatting in export buffers David Lukes
2022-10-02 7:25 ` Ihor Radchenko
2022-10-03 12:10 ` David Lukeš
2023-03-18 11:42 ` Ihor Radchenko [this message]
2023-04-02 14:27 ` Ihor Radchenko
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.orgmode.org/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87zg8axp30.fsf@localhost \
--to=yantar92@posteo.net \
--cc=dafydd.lukes@gmail.com \
--cc=emacs-orgmode@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).