From bee3e389fe248b43557574f78aa6348f92e21745 Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 1 Aug 2024 20:49:03 -0400 Subject: [PATCH] Attempt to improve performance (see issue #1120) I have tried to make it only parse the document once, and then use a cache on subsequent lookups. I found an error in the cache where it wasn't using the right test for equal that is fixed now. I also store data on text properties now, so it should be much faster to compute faces and tooltips. Some things are not quite as good as I want, like following links is not as precise as I would like, and may still need some fine tuning. hopefully this is more performant in large files. --- org-ref-glossary.el | 232 ++++++++++++++++++-------------------------- 1 file changed, 94 insertions(+), 138 deletions(-) diff --git a/org-ref-glossary.el b/org-ref-glossary.el index 6aaedbb0..f00b1495 100644 --- a/org-ref-glossary.el +++ b/org-ref-glossary.el @@ -45,7 +45,7 @@ ;; #+name: acronyms ;; | key | abbreviation | full form | ;; |------+--------------+--------------------------------| -;; | mimo | | multiple-input multiple output | +;; | mimo | mimo | multiple-input multiple output | ;; | qos | QoS | quality-of-service | ;; | bb | BB | branch and bound | ;; @@ -102,7 +102,7 @@ This is not always fast, so we provide a way to disable it." :group 'org-ref-glossary) -(defvar org-ref-glsentries '() +(defcustom org-ref-glsentries '() "Variable to hold locations of glsentries load files.") @@ -152,7 +152,7 @@ changes." ;; We don't have a cache, or an entry in it, so we find it. ;; No cache? we make one (unless org-ref-glossary-cache - (setq-local org-ref-glossary-cache (make-hash-table))) + (setq-local org-ref-glossary-cache (make-hash-table :test 'equal))) ;; Now we search to get the data (save-excursion @@ -171,13 +171,14 @@ changes." external)))) org-ref-glsentries) (cdr (assoc external org-ref-glsentries)))))) - key value p1 p2) + key value p1 p2 position) (setq data (catch 'data ;; look inside first for latex-headers (goto-char (point-min)) (when (re-search-forward (format "\\newglossaryentry{%s}" entry) nil t) + (setq position (match-beginning 0)) (re-search-forward "{") (save-excursion (backward-char) @@ -206,7 +207,8 @@ changes." (setq data (append data (list :label entry) (list (intern (format ":%s" key))) - (list value)))) + (list value) + (list :position position)))) (throw 'data data)) ;; check for a glossary table @@ -218,11 +220,15 @@ changes." (lambda (el) (when (string= "glossary" (org-element-property :name el)) (goto-char (org-element-property :contents-begin el)) + (setq position (point)) (throw 'found (nthcdr 2 (org-babel-read-table))))))))) (result (assoc entry entries))) (when result - (throw 'data (list :label entry :name (cl-second result) :description (cl-third result))))) + (throw 'data (list :label entry + :name (cl-second result) + :description (cl-third result) + :position position)))) ;; then external (when (and glsentries @@ -231,7 +237,7 @@ changes." (with-current-buffer (find-file-noselect glsentries) (goto-char (point-min)) (when (re-search-forward - (format "\\newglossaryentry{%s}" entry) nil t) + (format "\\newglossaryentry{%s}" entry) nil t) (re-search-forward "{") (save-excursion (backward-char) @@ -255,65 +261,56 @@ changes." (setq data (append data (list :label entry) (list (intern (format ":%s" key))) - (list value)))) + (list value) + (list :position nil)))) (throw 'data data)))))) (puthash entry data org-ref-glossary-cache) data)))) -;;;###autoload -(defun org-ref-add-glossary-entry (label name description) - "Insert a new glossary entry. -LABEL is how you refer to it with links. -NAME is the name of the entry to be defined. -DESCRIPTION is the definition of the entry. -Entry gets added after the last #+latex_header line. -This is not a preferred way to add entries. It is preferred to -manually add them to the glossary table." - (interactive "sLabel: \nsName: \nsDescription: ") - (save-excursion - (goto-char (point-max)) - ;; get to the last latex_header line - (re-search-backward "#\\+latex_header" nil t) - (forward-line) - (when (not (looking-at "^$")) - (beginning-of-line) - (insert "\n") - (forward-line -1)) - (insert (format "#+latex_header_extra: \\newglossaryentry{%s}{name={%s},description={%s}}\n" - label name description)))) - - -(defun org-ref-glossary-face-fn (label) - "Return a face for a glossary link." - (if org-ref-activate-glossary-links - (save-match-data - (cond - ((or-parse-glossary-entry label) - 'org-ref-glossary-face) - (t - 'font-lock-warning-face))) - 'org-ref-glossary-face)) +;;** Glossary links + +(defun or-activate-glossary (start end path bracketp) + "Activate function for a glossary link. +set data on text with properties +Set face property, and help-echo." + (let ((data (or (or-parse-glossary-entry path) + (or-parse-acronym-entry path)))) + (add-text-properties + start end + (list 'or-glossary data + 'face (if data + 'org-ref-glossary-face + 'font-lock-warning-face))))) + +(defface org-ref-glossary-face + `((t (:inherit org-link :foreground "Mediumpurple3"))) + "Face for glossary links.") -;;** Glossary links (defun or-follow-glossary (entry) "Goto beginning of the glossary ENTRY." (org-mark-ring-push) - - (cond - ;; Try finding in the table - ((progn (goto-char (point-min)) - (and (re-search-forward "#\\+name: glossary" nil t) - (re-search-forward entry nil t))) - nil) + (goto-char (plist-get (get-text-property (point) 'or-glossary) :position))) - ((progn (goto-char (point-min)) (re-search-forward (format "\\newglossaryentry{%s}" entry) nil t)) - (goto-char (match-beginning 0))) - (t - (message "no entry found for %s" entry)))) +(defun or-glossary-tooltip (_window _object position) + "Return tooltip for the glossary entry. +The entry is in WINDOW and OBJECT at POSITION. +Used in fontification." + (let* ((data (get-text-property position 'or-glossary)) + (name (or (plist-get data :name) + (plist-get data :abbrv))) + (description (or (plist-get data :description) + (plist-get data :full)))) + (format + "%s: %s" + name + (with-temp-buffer + (insert (concat description ".")) + (fill-paragraph) + (buffer-string))))) (defvar org-ref-glossary-gls-commands @@ -330,7 +327,7 @@ manually add them to the glossary table." (dolist (command org-ref-glossary-gls-commands) (org-link-set-parameters (cl-first command) :follow #'or-follow-glossary - :face 'org-ref-glossary-face-fn + :activate-func #'or-activate-glossary :help-echo 'or-glossary-tooltip :export (lambda (path _ format) (cond @@ -342,6 +339,7 @@ manually add them to the glossary table." (org-link-set-parameters "glslink" :follow #'or-follow-glossary + :activate-func #'or-activate-glossary :face 'org-ref-glossary-face-fn :help-echo 'or-glossary-tooltip :export (lambda (path desc format) @@ -351,33 +349,8 @@ manually add them to the glossary table." (t (format "%s" path))))) -;;** Tooltips on glossary entries -(defface org-ref-glossary-face - `((t (:inherit org-link :foreground "Mediumpurple3"))) - "Face for glossary links.") -(defun or-glossary-tooltip (_window _object position) - "Return tooltip for the glossary entry. -The entry is in WINDOW and OBJECT at POSITION. -Used in fontification." - (save-excursion - (goto-char position) - (let* ((label (org-element-property :path (org-element-context))) - (data (or (or-parse-glossary-entry label) - (or-parse-acronym-entry label))) - (name (or (plist-get data :name) - (plist-get data :abbrv))) - (description (or (plist-get data :description) - (plist-get data :full)))) - (format - "%s: %s" - name - (with-temp-buffer - (insert (concat description ".")) - (fill-paragraph) - (buffer-string)))))) - ;; ** printglossaries links ;; There is a printglossary command in LaTeX, but I am not supporting it for now. @@ -440,26 +413,6 @@ This is intended to be run in `org-export-before-parsing-hook'." ;;* Acronyms -;;;###autoload -(defun org-ref-add-acronym-entry (label abbrv full) - "Add an acronym entry with LABEL. - ABBRV is the abbreviated form. - FULL is the expanded acronym. - -This is not the preferred way to add acronyms, you should add -them manually to the acronyms table." - (interactive "sLabel: \nsAcronym: \nsFull name: ") - (save-excursion - (re-search-backward "#\\+latex_header" nil t) - (forward-line) - (when (not (looking-at "^$")) - (beginning-of-line) - (insert "\n") - (forward-line -1)) - (insert (format "#+latex_header_extra: \\newacronym{%s}{%s}{%s}\n" - label abbrv full)))) - - (defun or-parse-acronym-entry (label) "Parse an acronym entry LABEL to a plist. Returns (:abbrv abbrv :full full :label label) @@ -470,7 +423,7 @@ The plist maps to \newacronym{