branch: externals/org commit 685d78f63cbe210448508b23c0b47d7be70aedfb Merge: a0755ebccf fa5c832e9b Author: Ihor Radchenko <yanta...@gmail.com> Commit: Ihor Radchenko <yanta...@gmail.com>
Merge branch 'bugfix' --- lisp/oc-basic.el | 42 +++++++++++++++++++++++++++--------------- lisp/org-compat.el | 29 +++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 15 deletions(-) diff --git a/lisp/oc-basic.el b/lisp/oc-basic.el index e2dfc06030..873986d07e 100644 --- a/lisp/oc-basic.el +++ b/lisp/oc-basic.el @@ -233,6 +233,8 @@ Return a hash table with citation references as keys and fields alist as values. entries))) entries)) +(defvar org-cite-basic--file-id-cache nil + "Hash table linking files to their hash.") (defun org-cite-basic--parse-bibliography (&optional info) "List all entries available in the buffer. @@ -245,14 +247,19 @@ table where keys are references and values are association lists between fields, as symbols, and values as strings or nil. Optional argument INFO is the export state, as a property list." + (unless (hash-table-p org-cite-basic--file-id-cache) + (setq org-cite-basic--file-id-cache (make-hash-table :test #'equal))) (if (plist-member info :cite-basic/bibliography) (plist-get info :cite-basic/bibliography) (let ((results nil)) (dolist (file (org-cite-list-bibliography-files)) (when (file-readable-p file) (with-temp-buffer - (insert-file-contents file) - (let* ((file-id (cons file (org-buffer-hash))) + (when (or (org-file-has-changed-p file) + (not (gethash file org-cite-basic--file-id-cache))) + (insert-file-contents file) + (puthash file (org-buffer-hash) org-cite-basic--file-id-cache)) + (let* ((file-id (cons file (gethash file org-cite-basic--file-id-cache))) (entries (or (cdr (assoc file-id org-cite-basic--bibliography-cache)) (let ((table @@ -753,19 +760,24 @@ Return nil if there are no bibliography files or no entries." (t (clrhash org-cite-basic--completion-cache) (dolist (key (org-cite-basic--all-keys)) - (let ((completion - (concat - (let ((author (org-cite-basic--get-author key nil 'raw))) - (if author - (truncate-string-to-width - (replace-regexp-in-string " and " "; " author) - org-cite-basic-author-column-end nil ?\s) - (make-string org-cite-basic-author-column-end ?\s))) - org-cite-basic-column-separator - (let ((date (org-cite-basic--get-year key nil 'no-suffix))) - (format "%4s" (or date ""))) - org-cite-basic-column-separator - (org-cite-basic--get-field 'title key nil t)))) + (let* ((entry (org-cite-basic--get-entry + key + ;; Supply pre-calculated bibliography to avoid + ;; performance degradation. + (list :cite-basic/bibliography entries))) + (completion + (concat + (let ((author (org-cite-basic--get-author entry nil 'raw))) + (if author + (truncate-string-to-width + (replace-regexp-in-string " and " "; " author) + org-cite-basic-author-column-end nil ?\s) + (make-string org-cite-basic-author-column-end ?\s))) + org-cite-basic-column-separator + (let ((date (org-cite-basic--get-year entry nil 'no-suffix))) + (format "%4s" (or date ""))) + org-cite-basic-column-separator + (org-cite-basic--get-field 'title entry nil t)))) (puthash completion key org-cite-basic--completion-cache))) (unless (map-empty-p org-cite-basic--completion-cache) ;no key (puthash entries t org-cite-basic--completion-cache) diff --git a/lisp/org-compat.el b/lisp/org-compat.el index b926756947..b35e66b84e 100644 --- a/lisp/org-compat.el +++ b/lisp/org-compat.el @@ -74,6 +74,35 @@ (defvar org-table1-hline-regexp) +;;; Emacs < 29 compatibility + +(defvar org-file-has-changed-p--hash-table (make-hash-table :test #'equal) + "Internal variable used by `org-file-has-changed-p'.") + +(if (fboundp 'file-has-changed-p) + (defalias 'org-file-has-changed-p #'file-has-changed-p) + (defun org-file-has-changed-p (file &optional tag) + "Return non-nil if FILE has changed. +The size and modification time of FILE are compared to the size +and modification time of the same FILE during a previous +invocation of `org-file-has-changed-p'. Thus, the first invocation +of `org-file-has-changed-p' always returns non-nil when FILE exists. +The optional argument TAG, which must be a symbol, can be used to +limit the comparison to invocations with identical tags; it can be +the symbol of the calling function, for example." + (let* ((file (directory-file-name (expand-file-name file))) + (remote-file-name-inhibit-cache t) + (fileattr (file-attributes file 'integer)) + (attr (and fileattr + (cons (file-attribute-size fileattr) + (file-attribute-modification-time fileattr)))) + (sym (concat (symbol-name tag) "@" file)) + (cachedattr (gethash sym org-file-has-changed-p--hash-table))) + (when (not (equal attr cachedattr)) + (puthash sym attr org-file-has-changed-p--hash-table))))) + + + ;;; Emacs < 28.1 compatibility (if (fboundp 'file-name-concat)