emacs-citar / citar

Emacs package to quickly find and act on bibliographic references, and edit org, markdown, and latex academic documents.
GNU General Public License v3.0
497 stars 54 forks source link

More performant rendering/activation of citations #842

Open krisbalintona opened 4 days ago

krisbalintona commented 4 days ago

Is your feature request related to a problem? Please describe. I notice that the rendering/activation of org-mode citations with citar (i.e. when org-cite-activate-processor is 'citar) is very slow. When editing a line with one or more citations, Emacs freezes for multiple seconds on every character inserted or deleted. This is even the case for small .bib files.

Describe the solution you'd like When editing (inserting or deleting characters) a line with citation(s), render citations as quickly as possible so that Emacs does not freeze.

Describe alternatives you've considered

  1. Other packages such as org-cite-activate-processor that activate citations differently. Different packages have different pros and cons to how they activate citations --- and having to install another package is not much of a solution with respect to citar. I did not like this solution.
  2. I defined by own activate function and replaced the org-cite-basic-activate in citar-org-activation-functions with it. My version, below, is identical to org-cite-basic-activate but with faster rendering by using citar's functions which also leverage its cache (I believe). I currently use this approach.
    
    (defun kb/citar-basic-activate (citation)
    "Set various text properties on CITATION object.

Fontify whole citation with org-cite' face. Fontify key witherror' face when it does not belong to known keys. Otherwise, use `org-cite-key' face.

Moreover, when mouse is on a known key, display the corresponding bibliography. On a wrong key, suggest a list of possible keys, and offer to substitute one of them with a mouse click.

My version of this function uses the speed of citar' (and its cache) to eliminate the extraordinary slow down of the default function's rendering. I believe the bottlenecks areorg-cite-basic--all-keys' and org-cite-basic--get-entry' so I have replaced them with equivalent functions fromcitar'." (pcase-let (((,beg . ,end) (org-cite-boundaries citation)) ;; NOTE 2024-09-05: Usecitar' (and its cache) to get all keys (keys (let (keys) (maphash (lambda (key value) (push key keys)) (citar-get-entries)) keys))) (put-text-property beg end 'font-lock-multiline t) (add-face-text-property beg end 'org-cite) (dolist (reference (org-cite-get-references citation)) (pcase-let (((,beg . ,end) (org-cite-key-boundaries reference)) (key (org-element-property :key reference))) ;; Highlight key on mouse over. (put-text-property beg end 'mouse-face org-cite-basic-mouse-over-key-face) (if (member key keys) ;; Activate a correct key. Face isorg-cite-key' and help-echo' ;; displays bibliography entry, for reference. <mouse-1> calls ;;org-open-at-point'. ;; NOTE 2024-09-05: Use `citar' (and its cache) to create the ;; bibliographic entry text used in the help echo (let ((entry (string-trim (citar-format-reference (list key)))) (bibliography-entry (org-element-interpret-data entry))) (add-face-text-property beg end 'org-cite-key) (put-text-property beg end 'help-echo bibliography-entry) (org-cite-basic--set-keymap beg end nil)) ;; Activate a wrong key. Face is error',help-echo' displays ;; possible suggestions. (add-face-text-property beg end 'error) (let ((close-keys (org-cite-basic--close-keys key keys))) (when close-keys (put-text-property beg end 'help-echo (concat "Suggestions (mouse-1 to substitute): " (mapconcat #'identity close-keys " ")))) ;; When the are close know keys, provides completion to ;; fix the current one. Otherwise, call `org-cite-insert'. (org-cite-basic--set-keymap beg end (or close-keys 'all)))))))) (setq citar-org-activation-functions '(kb/citar-basic-activate citar-org-activate-keymap))



**Additional context**
I didn't have enough time to be 100% why org's built-in `org-cite-basic-activate` is slow, but I noticed that merely replacing `org-cite-basic--get-entry` and `citar-get-entries` with citar equivalents in the activate function does wonders with respect to performance on my machine.
rudolf-adamkovic commented 4 days ago

+1 I also suffer from bad performance. When scrolling large buffers with lots of citations, Emacs regularly locks up for seconds when Citar is enabled.

bdarcus commented 3 days ago

@andras-simonyi - any thoughts on this? It's related to you your activate processor.