Reduce repetitive calls to `find-buffer-visiting' + `find-file-noselect'
* lisp/org-macs.el (org-with-file-buffer): New macro switching to a file buffer temporarily and killing it if a buffer visiting file did not exist previously. (org-file-buffer-created): New variable set when buffer visiting file has been created. * lisp/ob-tangle.el (org-babel-tangle-file): * lisp/org-archive.el (org-archive-subtree): * lisp/org-refile.el (org-refile): (org-refile-check-position): (org-refile-new-child): * lisp/ox-org.el (org-org-publish-to-org): * lisp/ox-publish.el (org-publish-org-to): (org-publish-find-property): Avoid calling `find-buffer-visiting' + `find-file-noselect'. The latter calls the former. Instead, either just call `find-file-noselect' or use `org-with-file-buffer'. This commit addresses O(N_buffers) complexity in `find-buffer-visiting', reducing the number of calls to it. See Emacs bug#66117.
This commit is contained in:
parent
0e2a9524dc
commit
051e7b9d7c
|
@ -222,14 +222,10 @@ source code blocks by languages matching a regular expression.
|
||||||
|
|
||||||
Return list of the tangled file names."
|
Return list of the tangled file names."
|
||||||
(interactive "fFile to tangle: \nP")
|
(interactive "fFile to tangle: \nP")
|
||||||
(let* ((visited (find-buffer-visiting file))
|
(org-with-file-buffer file
|
||||||
(buffer (or visited (find-file-noselect file))))
|
(org-with-wide-buffer
|
||||||
(prog1
|
(mapcar #'expand-file-name
|
||||||
(with-current-buffer buffer
|
(org-babel-tangle nil target-file lang-re)))))
|
||||||
(org-with-wide-buffer
|
|
||||||
(mapcar #'expand-file-name
|
|
||||||
(org-babel-tangle nil target-file lang-re))))
|
|
||||||
(unless visited (kill-buffer buffer)))))
|
|
||||||
|
|
||||||
(defun org-babel-tangle-publish (_ filename pub-dir)
|
(defun org-babel-tangle-publish (_ filename pub-dir)
|
||||||
"Tangle FILENAME and place the results in PUB-DIR."
|
"Tangle FILENAME and place the results in PUB-DIR."
|
||||||
|
|
|
@ -254,8 +254,7 @@ direct children of this heading."
|
||||||
(newfile-p (and (org-string-nw-p afile)
|
(newfile-p (and (org-string-nw-p afile)
|
||||||
(not (file-exists-p afile))))
|
(not (file-exists-p afile))))
|
||||||
(buffer (cond ((not (org-string-nw-p afile)) this-buffer)
|
(buffer (cond ((not (org-string-nw-p afile)) this-buffer)
|
||||||
((find-buffer-visiting afile))
|
((find-file-noselect afile 'nowarn))
|
||||||
((find-file-noselect afile))
|
|
||||||
(t (error "Cannot access file \"%s\"" afile))))
|
(t (error "Cannot access file \"%s\"" afile))))
|
||||||
(org-odd-levels-only
|
(org-odd-levels-only
|
||||||
(if (local-variable-p 'org-odd-levels-only (current-buffer))
|
(if (local-variable-p 'org-odd-levels-only (current-buffer))
|
||||||
|
|
|
@ -291,6 +291,31 @@ FILE is the file name passed to `find-buffer-visiting'."
|
||||||
(find-buffer-visiting file))))
|
(find-buffer-visiting file))))
|
||||||
(org-base-buffer buf)))
|
(org-base-buffer buf)))
|
||||||
|
|
||||||
|
(defvar-local org-file-buffer-created nil
|
||||||
|
"Non-nil when current buffer is created from `org-with-file-buffer'.
|
||||||
|
The value is FILE argument passed to `org-with-file-buffer'.")
|
||||||
|
(defmacro org-with-file-buffer (file &rest body)
|
||||||
|
"Evaluate BODY with current buffer visiting FILE.
|
||||||
|
When no live buffer is visiting FILE, create one and kill after
|
||||||
|
evaluating BODY.
|
||||||
|
During evaluation, when the buffer was created, `org-file-buffer-created'
|
||||||
|
variable is set to FILE."
|
||||||
|
(declare (debug (form body)) (indent 1))
|
||||||
|
(org-with-gensyms (mark-function filename buffer)
|
||||||
|
`(let ((,mark-function (lambda () (setq-local org-file-buffer-created ,file)))
|
||||||
|
(,filename ,file)
|
||||||
|
,buffer)
|
||||||
|
(add-hook 'find-file-hook ,mark-function)
|
||||||
|
(unwind-protect
|
||||||
|
(progn
|
||||||
|
(setq ,buffer (find-file-noselect ,filename t))
|
||||||
|
(with-current-buffer ,buffer
|
||||||
|
(prog1 (progn ,@body)
|
||||||
|
(with-current-buffer ,buffer
|
||||||
|
(when (equal ,filename org-file-buffer-created)
|
||||||
|
(kill-buffer))))))
|
||||||
|
(remove-hook 'find-file-hook ,mark-function)))))
|
||||||
|
|
||||||
(defun org-fit-window-to-buffer (&optional window max-height min-height
|
(defun org-fit-window-to-buffer (&optional window max-height min-height
|
||||||
shrink-only)
|
shrink-only)
|
||||||
"Fit WINDOW to the buffer, but only if it is not a side-by-side window.
|
"Fit WINDOW to the buffer, but only if it is not a side-by-side window.
|
||||||
|
|
|
@ -541,8 +541,7 @@ prefix argument (`C-u C-u C-u C-c C-w')."
|
||||||
(< pos (save-excursion
|
(< pos (save-excursion
|
||||||
(org-end-of-subtree t t))))))
|
(org-end-of-subtree t t))))))
|
||||||
(error "Cannot refile to position inside the tree or region"))
|
(error "Cannot refile to position inside the tree or region"))
|
||||||
(setq nbuf (or (find-buffer-visiting file)
|
(setq nbuf (find-file-noselect file 'nowarn))
|
||||||
(find-file-noselect file)))
|
|
||||||
(if (and arg (not (equal arg 3)))
|
(if (and arg (not (equal arg 3)))
|
||||||
(progn
|
(progn
|
||||||
(pop-to-buffer-same-window nbuf)
|
(pop-to-buffer-same-window nbuf)
|
||||||
|
@ -562,8 +561,7 @@ prefix argument (`C-u C-u C-u C-c C-w')."
|
||||||
;; will then remain before the inserted subtree in
|
;; will then remain before the inserted subtree in
|
||||||
;; unexpected location.
|
;; unexpected location.
|
||||||
(set-marker-insertion-type origin t)
|
(set-marker-insertion-type origin t)
|
||||||
(with-current-buffer (setq nbuf (or (find-buffer-visiting file)
|
(with-current-buffer (setq nbuf (find-file-noselect file 'nowarn))
|
||||||
(find-file-noselect file)))
|
|
||||||
(setq reversed (org-notes-order-reversed-p))
|
(setq reversed (org-notes-order-reversed-p))
|
||||||
(org-with-wide-buffer
|
(org-with-wide-buffer
|
||||||
(if pos
|
(if pos
|
||||||
|
@ -727,8 +725,7 @@ this function appends the default value from
|
||||||
(when (org-string-nw-p re)
|
(when (org-string-nw-p re)
|
||||||
(setq buffer (if (markerp pos)
|
(setq buffer (if (markerp pos)
|
||||||
(marker-buffer pos)
|
(marker-buffer pos)
|
||||||
(or (find-buffer-visiting file)
|
(find-file-noselect file 'nowarn)))
|
||||||
(find-file-noselect file))))
|
|
||||||
(with-current-buffer buffer
|
(with-current-buffer buffer
|
||||||
(org-with-wide-buffer
|
(org-with-wide-buffer
|
||||||
(goto-char pos)
|
(goto-char pos)
|
||||||
|
@ -743,8 +740,7 @@ this function appends the default value from
|
||||||
(let ((file (nth 1 parent-target))
|
(let ((file (nth 1 parent-target))
|
||||||
(pos (nth 3 parent-target))
|
(pos (nth 3 parent-target))
|
||||||
level)
|
level)
|
||||||
(with-current-buffer (or (find-buffer-visiting file)
|
(with-current-buffer (find-file-noselect file 'nowarn)
|
||||||
(find-file-noselect file))
|
|
||||||
(org-with-wide-buffer
|
(org-with-wide-buffer
|
||||||
(if pos
|
(if pos
|
||||||
(goto-char pos)
|
(goto-char pos)
|
||||||
|
|
|
@ -345,10 +345,8 @@ Return output file name."
|
||||||
(htmlize-output-type 'css)
|
(htmlize-output-type 'css)
|
||||||
(html-ext (concat "." (or (plist-get plist :html-extension)
|
(html-ext (concat "." (or (plist-get plist :html-extension)
|
||||||
org-html-extension "html")))
|
org-html-extension "html")))
|
||||||
(visitingp (find-buffer-visiting filename))
|
|
||||||
(work-buffer (or visitingp (find-file-noselect filename)))
|
|
||||||
newbuf)
|
newbuf)
|
||||||
(with-current-buffer work-buffer
|
(org-with-file-buffer filename
|
||||||
(font-lock-ensure)
|
(font-lock-ensure)
|
||||||
(org-fold-show-all)
|
(org-fold-show-all)
|
||||||
(setq newbuf (htmlize-buffer)))
|
(setq newbuf (htmlize-buffer)))
|
||||||
|
@ -363,8 +361,7 @@ Return output file name."
|
||||||
org-org-htmlized-css-url)
|
org-org-htmlized-css-url)
|
||||||
t t)))
|
t t)))
|
||||||
(write-file (concat pub-dir (file-name-nondirectory filename) html-ext)))
|
(write-file (concat pub-dir (file-name-nondirectory filename) html-ext)))
|
||||||
(kill-buffer newbuf)
|
(kill-buffer newbuf))))
|
||||||
(unless visitingp (kill-buffer work-buffer)))))
|
|
||||||
|
|
||||||
|
|
||||||
(provide 'ox-org)
|
(provide 'ox-org)
|
||||||
|
|
|
@ -565,30 +565,25 @@ directory.
|
||||||
Return output file name."
|
Return output file name."
|
||||||
(unless (or (not pub-dir) (file-exists-p pub-dir)) (make-directory pub-dir t))
|
(unless (or (not pub-dir) (file-exists-p pub-dir)) (make-directory pub-dir t))
|
||||||
;; Check if a buffer visiting FILENAME is already open.
|
;; Check if a buffer visiting FILENAME is already open.
|
||||||
(let* ((org-inhibit-startup t)
|
(let* ((org-inhibit-startup t))
|
||||||
(visiting (find-buffer-visiting filename))
|
(org-with-file-buffer filename
|
||||||
(work-buffer (or visiting (find-file-noselect filename))))
|
(let ((output (org-export-output-file-name extension nil pub-dir)))
|
||||||
(unwind-protect
|
(org-export-to-file backend output
|
||||||
(with-current-buffer work-buffer
|
nil nil nil (plist-get plist :body-only)
|
||||||
(let ((output (org-export-output-file-name extension nil pub-dir)))
|
;; Add `org-publish--store-crossrefs' and
|
||||||
(org-export-to-file backend output
|
;; `org-publish-collect-index' to final output filters.
|
||||||
nil nil nil (plist-get plist :body-only)
|
;; The latter isn't dependent on `:makeindex', since we
|
||||||
;; Add `org-publish--store-crossrefs' and
|
;; want to keep it up-to-date in cache anyway.
|
||||||
;; `org-publish-collect-index' to final output filters.
|
(org-combine-plists
|
||||||
;; The latter isn't dependent on `:makeindex', since we
|
plist
|
||||||
;; want to keep it up-to-date in cache anyway.
|
`(:crossrefs
|
||||||
(org-combine-plists
|
,(org-publish-cache-get-file-property
|
||||||
plist
|
;; Normalize file names in cache.
|
||||||
`(:crossrefs
|
(file-truename filename) :crossrefs nil t)
|
||||||
,(org-publish-cache-get-file-property
|
:filter-final-output
|
||||||
;; Normalize file names in cache.
|
(org-publish--store-crossrefs
|
||||||
(file-truename filename) :crossrefs nil t)
|
org-publish-collect-index
|
||||||
:filter-final-output
|
,@(plist-get plist :filter-final-output)))))))))
|
||||||
(org-publish--store-crossrefs
|
|
||||||
org-publish-collect-index
|
|
||||||
,@(plist-get plist :filter-final-output)))))))
|
|
||||||
;; Remove opened buffer in the process.
|
|
||||||
(unless visiting (kill-buffer work-buffer)))))
|
|
||||||
|
|
||||||
(defun org-publish-attachment (_plist filename pub-dir)
|
(defun org-publish-attachment (_plist filename pub-dir)
|
||||||
"Publish a file with no transformation of any kind.
|
"Publish a file with no transformation of any kind.
|
||||||
|
@ -852,17 +847,13 @@ Return value may be a string or a list, depending on the type of
|
||||||
PROPERTY, i.e. \"behavior\" parameter from `org-export-options-alist'."
|
PROPERTY, i.e. \"behavior\" parameter from `org-export-options-alist'."
|
||||||
(let ((file (org-publish--expand-file-name file project)))
|
(let ((file (org-publish--expand-file-name file project)))
|
||||||
(when (and (file-readable-p file) (not (directory-name-p file)))
|
(when (and (file-readable-p file) (not (directory-name-p file)))
|
||||||
(let* ((org-inhibit-startup t)
|
(let* ((org-inhibit-startup t))
|
||||||
(visiting (find-buffer-visiting file))
|
(plist-get (org-with-file-buffer file
|
||||||
(buffer (or visiting (find-file-noselect file))))
|
(if (not org-file-buffer-created) (org-export-get-environment backend)
|
||||||
(unwind-protect
|
;; Protect local variables in open buffers.
|
||||||
(plist-get (with-current-buffer buffer
|
(org-export-with-buffer-copy
|
||||||
(if (not visiting) (org-export-get-environment backend)
|
(org-export-get-environment backend))))
|
||||||
;; Protect local variables in open buffers.
|
property)))))
|
||||||
(org-export-with-buffer-copy
|
|
||||||
(org-export-get-environment backend))))
|
|
||||||
property)
|
|
||||||
(unless visiting (kill-buffer buffer)))))))
|
|
||||||
|
|
||||||
(defun org-publish-find-title (file project)
|
(defun org-publish-find-title (file project)
|
||||||
"Find the title of FILE in PROJECT."
|
"Find the title of FILE in PROJECT."
|
||||||
|
|
Loading…
Reference in New Issue