diff --git a/citar.el b/citar.el index 436eaf51..f19129b1 100644 --- a/citar.el +++ b/citar.el @@ -78,9 +78,13 @@ (defvar embark-multitarget-actions) (defvar embark-default-action-overrides) (defvar embark-candidate-collectors) +(defvar org-element-citation-key-re) +(defvar org-element-citation-prefix-re) (declare-function embark--target-buffer "ext:embark") (declare-function embark--metadata "ext:embark") +(declare-function org-element-at-point "ext:org-element") +(declare-function org-element-property "ext:org-element") ;;; Variables @@ -914,6 +918,65 @@ FORMAT-STRING." (let ((field-names (split-string raw-field "[ ]+"))) (citar--display-value field-names entry))))) +;;; Completion at Point Function + +(defvar citar-capf--extra-properties + (list + :exclusive 'no) + "Completion extra properties for `citar-capf'.") + +;;;###autoload +(defun citar-capf () + "Complete citation key at point for org, markdown, or latex. +Parsing by citar is of bibtex, biblatex and csl json files, and +supports multiple different files. Please see citar's +documentation for further info." + (let ((element (org-element-at-point)) + (citar-capf-latex-regexp "\\(?:cite\\(?:\\(?:[pt]\\*\\|[pt]\\)?{\\)\\)\\([[:alnum:]_-]*,\\)*\\([[:alnum:]_-]*\\)") + (citar-capf-markdown-regexp (concat "-?@" ; @ preceded by optional - + "\\(?:" + "{\\(?1:.*?\\)}" ; brace-delimited key + "\\|" + "\\(?1:[[:alnum:]_][[:alnum:]]*\\(?:[:.#$%&+?<>~/-][[:alnum:]]+\\)*\\)" + "\\)"))) + + ;; only list candidates in certain contexts + (when + ;; conditional recognition of citation key by mode + (cond + ;; latex-mode + ((derived-mode-p 'latex-mode) + (looking-back citar-capf-latex-regexp 2)) + ;; org-mode + ((and (derived-mode-p 'org-mode) + (or (eq 'citation (org-element-at-point element)) + (and (or (eq ?@ (char-before)) + (looking-back org-element-citation-key-re + (line-beginning-position))) + (let ((origin (point))) + (save-excursion + (and (re-search-backward org-element-citation-prefix-re + (org-element-property + :begin element) + t) + (not (search-forward "]" origin t))))))))) + ;; markdown-mode + ((and (derived-mode-p 'markdown-mode) + (or (eq ?@ (char-before)) + (looking-back citar-capf-markdown-regexp + (line-beginning-position)))))) + ;; Get and insert candidate + (let* ((candidates (citar--ref-completion-table)) + (begin (save-excursion (backward-word) (point))) + (end (point))) + (list begin end candidates + :exit-function + (lambda (str _status) + ;; replace completion str with key + (delete-char (- (length str))) + (insert (gethash str candidates))) + citar-capf--extra-properties))))) + ;;; At-point functions for Embark ;;;###autoload