diff options
author | mattkae <mattkae@protonmail.com> | 2022-06-07 08:23:47 -0400 |
---|---|---|
committer | mattkae <mattkae@protonmail.com> | 2022-06-07 08:23:47 -0400 |
commit | bd18a38c2898548a3664a9ddab9f79c84f2caf4a (patch) | |
tree | 95b9933376770381bd8859782ae763be81c2d72b /elpa/org-9.5.2/oc-basic.el | |
parent | b07628dddf418d4f47b858e6c35fd3520fbaeed2 (diff) | |
parent | ef160dea332af4b4fe5e2717b962936c67e5fe9e (diff) |
Merge conflict
Diffstat (limited to 'elpa/org-9.5.2/oc-basic.el')
-rw-r--r-- | elpa/org-9.5.2/oc-basic.el | 789 |
1 files changed, 0 insertions, 789 deletions
diff --git a/elpa/org-9.5.2/oc-basic.el b/elpa/org-9.5.2/oc-basic.el deleted file mode 100644 index 7c83bdc..0000000 --- a/elpa/org-9.5.2/oc-basic.el +++ /dev/null @@ -1,789 +0,0 @@ -;;; oc-basic.el --- basic back-end for citations -*- lexical-binding: t; -*- - -;; Copyright (C) 2021 Free Software Foundation, Inc. - -;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr> - -;; This file is part of GNU Emacs. - -;; GNU Emacs is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. - -;;; Commentary: - -;; The `basic' citation processor provides "activate", "follow", "export" and -;; "insert" capabilities. - -;; "activate" capability re-uses default fontification, but provides additional -;; features on both correct and wrong keys according to the bibliography -;; defined in the document. - -;; When the mouse is over a known key, it displays the corresponding -;; bibliography entry. Any wrong key, however, is highlighted with `error' -;; face. Moreover, moving the mouse onto it displays a list of suggested correct -;; keys, and pressing <mouse-1> on the faulty key will try to fix it according to -;; those suggestions. - -;; On a citation key, "follow" capability moves point to the corresponding entry -;; in the current bibliography. Elsewhere on the citation, it asks the user to -;; follow any of the keys cited there, with completion. - -;; "export" capability supports the following citation styles: -;; -;; - author (a), including caps (c) variant, -;; - noauthor (na) including bare (b) variant, -;; - text (t), including bare (b), caps (c), and bare-caps (bc) variants, -;; - note (ft, including bare (b), caps (c), and bare-caps (bc) variants, -;; - nocite (n) -;; - numeric (nb), -;; - default, including bare (b), caps (c), and bare-caps (bc) variants. -;; -;; It also supports the following styles for bibliography: -;; - plain -;; - numeric -;; - author-year (default) - -;; "insert" capability inserts or edits (with completion) citation style or -;; citation reference keys. In an appropriate place, it offers to insert a new -;; citation. With a prefix argument, it removes the one at point. - -;; It supports bibliography files in BibTeX (".bibtex"), biblatex (".bib") and -;; JSON (".json") format. - -;; Disclaimer: this citation processor is meant to be a proof of concept, and -;; possibly a fall-back mechanism when nothing else is available. It is too -;; limited for any serious use case. - -;;; Code: - -(require 'bibtex) -(require 'json) -(require 'map) -(require 'oc) -(require 'seq) - -(declare-function org-open-at-point "org" (&optional arg)) - -(declare-function org-element-interpret-data "org-element" (data)) -(declare-function org-element-property "org-element" (property element)) -(declare-function org-element-type "org-element" (element)) - -(declare-function org-export-data "org-export" (data info)) -(declare-function org-export-derived-backend-p "org-export" (backend &rest backends)) -(declare-function org-export-raw-string "org-export" (contents)) - - -;;; Customization -(defcustom org-cite-basic-sorting-field 'author - "Field used to sort bibliography items as a symbol, or nil." - :group 'org-cite - :package-version '(Org . "9.5") - :type 'symbol - :safe #'symbolp) - -(defcustom org-cite-basic-author-year-separator ", " - "String used to separate cites in an author-year configuration." - :group 'org-cite - :package-version '(Org . "9.5") - :type 'string - :safe #'stringp) - -(defcustom org-cite-basic-max-key-distance 2 - "Maximum (Levenshtein) distance between a wrong key and its suggestions." - :group 'org-cite - :package-version '(Org . "9.5") - :type 'integer - :safe #'integerp) - -(defcustom org-cite-basic-author-column-end 25 - "Column where author field ends in completion table, as an integer." - :group 'org-cite - :package-version '(Org . "9.5") - :type 'integer - :safe #'integerp) - -(defcustom org-cite-basic-column-separator " " - "Column separator in completion table, as a string." - :group 'org-cite - :package-version '(Org . "9.5") - :type 'string - :safe #'stringp) - -(defcustom org-cite-basic-mouse-over-key-face 'highlight - "Face used when mouse is over a citation key." - :group 'org-cite - :package-version '(Org . "9.5") - :type 'face - :safe #'facep) - - -;;; Internal variables -(defvar org-cite-basic--bibliography-cache nil - "Cache for parsed bibliography files. - -This is an association list following the pattern: - - (FILE-ID . ENTRIES) - -FILE-ID is a cons cell (FILE . HASH), with FILE being the absolute file name of -the bibliography file, and HASH a hash of its contents. - -ENTRIES is a hash table with citation references as keys and fields alist as -values.") - -(defvar org-cite-basic--completion-cache (make-hash-table :test #'equal) - "Cache for key completion table. - -This is an a hash-table.") - - -;;; Internal functions -(defun org-cite-basic--parse-json () - "Parse JSON entries in the current buffer. -Return a hash table with citation references as keys and fields alist as values." - (let ((entries (make-hash-table :test #'equal))) - (let ((json-array-type 'list) - (json-key-type 'symbol)) - (dolist (item (json-read)) - (puthash (cdr (assq 'id item)) - (mapcar (pcase-lambda (`(,field . ,value)) - (pcase field - ('author - ;; Author is an array of objects, each - ;; of them designing a person. These - ;; objects may contain multiple - ;; properties, but for this basic - ;; processor, we'll focus on `given' and - ;; `family'. - ;; - ;; For compatibility with BibTeX, add - ;; "and" between authors. - (cons 'author - (mapconcat - (lambda (alist) - (concat (alist-get 'family alist) - " " - (alist-get 'given alist))) - value - " and "))) - ('issued - ;; Date are expressed as an array - ;; (`date-parts') or a "string (`raw'). - ;; In both cases, extract the year and - ;; associate it to `year' field, for - ;; compatibility with BibTeX format. - (let ((date (or (alist-get 'date-parts value) - (alist-get 'raw value)))) - (cons 'year - (cond - ((consp date) - (caar date)) - ((stringp date) - (car (split-string date "-"))) - (t - (error "Unknown CSL-JSON date format: %S" - date)))))) - (_ - (cons field value)))) - item) - entries)) - entries))) - -(defun org-cite-basic--parse-bibtex (dialect) - "Parse BibTeX entries in the current buffer. -DIALECT is the BibTeX dialect used. See `bibtex-dialect'. -Return a hash table with citation references as keys and fields alist as values." - (let ((entries (make-hash-table :test #'equal)) - (bibtex-sort-ignore-string-entries t)) - (bibtex-set-dialect dialect t) - (bibtex-map-entries - (lambda (key &rest _) - ;; Normalize entries: field names are turned into symbols - ;; including special "=key=" and "=type=", and consecutive - ;; white spaces are removed from values. - (puthash key - (mapcar - (pcase-lambda (`(,field . ,value)) - (pcase field - ("=key=" (cons 'id key)) - ("=type=" (cons 'type value)) - (_ - (cons - (intern (downcase field)) - (replace-regexp-in-string "[ \t\n]+" " " value))))) - (bibtex-parse-entry t)) - entries))) - entries)) - -(defun org-cite-basic--parse-bibliography (&optional info) - "List all entries available in the buffer. - -Each association follows the pattern - - (FILE . ENTRIES) - -where FILE is the absolute file name of the BibTeX file, and ENTRIES is a hash -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." - (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))) - (entries - (or (cdr (assoc file-id org-cite-basic--bibliography-cache)) - (let ((table - (pcase (file-name-extension file) - ("json" (org-cite-basic--parse-json)) - ("bib" (org-cite-basic--parse-bibtex 'biblatex)) - ("bibtex" (org-cite-basic--parse-bibtex 'BibTeX)) - (ext - (user-error "Unknown bibliography extension: %S" - ext))))) - (push (cons file-id table) org-cite-basic--bibliography-cache) - table)))) - (push (cons file entries) results))))) - (when info (plist-put info :cite-basic/bibliography results)) - results))) - -(defun org-cite-basic--key-number (key info) - "Return number associated to cited KEY. -INFO is the export state, as a property list." - (let ((predicate - (org-cite-basic--field-less-p org-cite-basic-sorting-field info))) - (org-cite-key-number key info predicate))) - -(defun org-cite-basic--all-keys () - "List all keys available in current bibliography." - (seq-mapcat (pcase-lambda (`(,_ . ,entries)) - (map-keys entries)) - (org-cite-basic--parse-bibliography))) - -(defun org-cite-basic--get-entry (key &optional info) - "Return BibTeX entry for KEY, as an association list. -When non-nil, INFO is the export state, as a property list." - (catch :found - (pcase-dolist (`(,_ . ,entries) (org-cite-basic--parse-bibliography info)) - (let ((entry (gethash key entries))) - (when entry (throw :found entry)))) - nil)) - -(defun org-cite-basic--get-field (field entry-or-key &optional info raw) - "Return FIELD value for ENTRY-OR-KEY, or nil. - -FIELD is a symbol. ENTRY-OR-KEY is either an association list, as returned by -`org-cite-basic--get-entry', or a string representing a citation key. - -Optional argument INFO is the export state, as a property list. - -Return value may be nil or a string. If current export back-end is derived -from `latex', return a raw string instead, unless optional argument RAW is -non-nil." - (let ((value - (cdr - (assq field - (pcase entry-or-key - ((pred stringp) - (org-cite-basic--get-entry entry-or-key info)) - ((pred consp) - entry-or-key) - (_ - (error "Wrong value for ENTRY-OR-KEY: %S" entry-or-key))))))) - (if (and value - (not raw) - (org-export-derived-backend-p (plist-get info :back-end) 'latex)) - (org-export-raw-string value) - value))) - -(defun org-cite-basic--number-to-suffix (n) - "Compute suffix associated to number N. -This is used for disambiguation." - (let ((result nil)) - (apply #'string - (mapcar (lambda (n) (+ 97 n)) - (catch :complete - (while t - (push (% n 26) result) - (setq n (/ n 26)) - (cond - ((= n 0) (throw :complete result)) - ((< n 27) (throw :complete (cons (1- n) result))) - ((= n 27) (throw :complete (cons 0 (cons 0 result)))) - (t nil)))))))) - -(defun org-cite-basic--get-year (entry-or-key info &optional no-suffix) - "Return year associated to ENTRY-OR-KEY. - -ENTRY-OR-KEY is either an association list, as returned by -`org-cite-basic--get-entry', or a string representing a citation -key. INFO is the export state, as a property list. - -Year is obtained from the \"year\" field, if available, or from -the \"date\" field if it starts with a year pattern. - -Unlike `org-cite-basic--get-field', this function disambiguates -author-year patterns by adding a letter suffix to the year when -necessary, unless optional argument NO-SUFFIX is non-nil." - ;; The cache is an association list with the following structure: - ;; - ;; (AUTHOR-YEAR . KEY-SUFFIX-ALIST). - ;; - ;; AUTHOR-YEAR is the author year pair associated to current entry - ;; or key. - ;; - ;; KEY-SUFFIX-ALIST is an association (KEY . SUFFIX), where KEY is - ;; the cite key, as a string, and SUFFIX is the generated suffix - ;; string, or the empty string. - (let* ((author (org-cite-basic--get-field 'author entry-or-key info 'raw)) - (year - (or (org-cite-basic--get-field 'year entry-or-key info 'raw) - (let ((date - (org-cite-basic--get-field 'date entry-or-key info t))) - (and (stringp date) - (string-match (rx string-start - (group (= 4 digit)) - (or string-end (not digit))) - date) - (match-string 1 date))))) - (cache-key (cons author year)) - (key - (pcase entry-or-key - ((pred stringp) entry-or-key) - ((pred consp) (cdr (assq 'id entry-or-key))) - (_ (error "Wrong value for ENTRY-OR-KEY: %S" entry-or-key)))) - (cache (plist-get info :cite-basic/author-date-cache))) - (pcase (assoc cache-key cache) - ('nil - (let ((value (cons cache-key (list (cons key ""))))) - (plist-put info :cite-basic/author-date-cache (cons value cache)) - year)) - (`(,_ . ,alist) - (let ((suffix - (or (cdr (assoc key alist)) - (let ((new (org-cite-basic--number-to-suffix - (1- (length alist))))) - (push (cons key new) alist) - new)))) - (if no-suffix year (concat year suffix))))))) - -(defun org-cite-basic--print-entry (entry style &optional info) - "Format ENTRY according to STYLE string. -ENTRY is an alist, as returned by `org-cite-basic--get-entry'. -Optional argument INFO is the export state, as a property list." - (let ((author (org-cite-basic--get-field 'author entry info)) - (title (org-cite-basic--get-field 'title entry info)) - (from - (or (org-cite-basic--get-field 'publisher entry info) - (org-cite-basic--get-field 'journal entry info) - (org-cite-basic--get-field 'institution entry info) - (org-cite-basic--get-field 'school entry info)))) - (pcase style - ("plain" - (let ((year (org-cite-basic--get-year entry info 'no-suffix))) - (org-cite-concat - author ". " title (and from (list ", " from)) ", " year "."))) - ("numeric" - (let ((n (org-cite-basic--key-number (cdr (assq 'id entry)) info)) - (year (org-cite-basic--get-year entry info 'no-suffix))) - (org-cite-concat - (format "[%d] " n) author ", " - (org-cite-emphasize 'italic title) - (and from (list ", " from)) ", " - year "."))) - ;; Default to author-year. Use year disambiguation there. - (_ - (let ((year (org-cite-basic--get-year entry info))) - (org-cite-concat - author " (" year "). " - (org-cite-emphasize 'italic title) - (and from (list ", " from)) ".")))))) - - -;;; "Activate" capability -(defun org-cite-basic--close-keys (key keys) - "List cite keys close to KEY in terms of string distance." - (seq-filter (lambda (k) - (>= org-cite-basic-max-key-distance - (org-string-distance k key))) - keys)) - -(defun org-cite-basic--set-keymap (beg end suggestions) - "Set keymap on citation key between BEG and END positions. - -When the key is know, SUGGESTIONS is nil. Otherwise, it may be -a list of replacement keys, as strings, which will be offered as -substitutes for the unknown key. Finally, it may be the symbol -`all'." - (let ((km (make-sparse-keymap))) - (define-key km (kbd "<mouse-1>") - (pcase suggestions - ('nil #'org-open-at-point) - ('all #'org-cite-insert) - (_ - (lambda () - (interactive) - (setf (buffer-substring beg end) - (concat "@" - (if (= 1 (length suggestions)) - (car suggestions) - (completing-read "Did you mean: " - suggestions nil t)))))))) - (put-text-property beg end 'keymap km))) - -(defun org-cite-basic-activate (citation) - "Set various text properties on CITATION object. - -Fontify whole citation with `org-cite' face. Fontify key with `error' 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." - (pcase-let ((`(,beg . ,end) (org-cite-boundaries citation)) - (keys (org-cite-basic--all-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 is `org-cite-key' and - ;; `help-echo' displays bibliography entry, for reference. - ;; <mouse-1> calls `org-open-at-point'. - (let* ((entry (org-cite-basic--get-entry key)) - (bibliography-entry - (org-element-interpret-data - (org-cite-basic--print-entry entry "plain")))) - (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, <mouse-1> provides - ;; completion to fix the current one. Otherwise, call - ;; `org-cite-insert'. - (org-cite-basic--set-keymap beg end (or close-keys 'all)))))))) - - -;;; "Export" capability -(defun org-cite-basic--format-author-year (citation format-cite format-ref info) - "Format CITATION object according to author-year format. - -FORMAT-CITE is a function of three arguments: the global prefix, the contents, -and the global suffix. All arguments can be strings or secondary strings. - -FORMAT-REF is a function of four arguments: the reference prefix, as a string or -secondary string, the author, the year, and the reference suffix, as a string or -secondary string. - -INFO is the export state, as a property list." - (org-export-data - (funcall format-cite - (org-element-property :prefix citation) - (org-cite-mapconcat - (lambda (ref) - (let ((k (org-element-property :key ref)) - (prefix (org-element-property :prefix ref)) - (suffix (org-element-property :suffix ref))) - (funcall format-ref - prefix - (org-cite-basic--get-field 'author k info) - (org-cite-basic--get-year k info) - suffix))) - (org-cite-get-references citation) - org-cite-basic-author-year-separator) - (org-element-property :suffix citation)) - info)) - -(defun org-cite-basic--citation-numbers (citation info) - "Return numbers associated to references in CITATION object. -INFO is the export state as a property list." - (let* ((numbers - (sort (mapcar (lambda (k) (org-cite-basic--key-number k info)) - (org-cite-get-references citation t)) - #'<)) - (last (car numbers)) - (result (list (number-to-string (pop numbers))))) - ;; Use compact number references, i.e., "1, 2, 3" becomes "1-3". - (while numbers - (let ((current (pop numbers)) - (next (car numbers))) - (cond - ((and next - (= current (1+ last)) - (= current (1- next))) - (unless (equal "-" (car result)) - (push "-" result))) - ((equal "-" (car result)) - (push (number-to-string current) result)) - (t - (push (format ", %d" current) result))) - (setq last current))) - (apply #'concat (nreverse result)))) - -(defun org-cite-basic--field-less-p (field info) - "Return a sort predicate comparing FIELD values for two citation keys. -INFO is the export state, as a property list." - (and field - (lambda (a b) - (org-string-collate-lessp - (org-cite-basic--get-field field a info 'raw) - (org-cite-basic--get-field field b info 'raw) - nil t)))) - -(defun org-cite-basic--sort-keys (keys info) - "Sort KEYS by author name. -INFO is the export communication channel, as a property list." - (let ((predicate (org-cite-basic--field-less-p org-cite-basic-sorting-field info))) - (if predicate - (sort keys predicate) - keys))) - -(defun org-cite-basic-export-citation (citation style _ info) - "Export CITATION object. -STYLE is the expected citation style, as a pair of strings or nil. INFO is the -export communication channel, as a property list." - (let ((has-variant-p - (lambda (variant type) - ;; Non-nil when style VARIANT has TYPE. TYPE is either - ;; `bare' or `caps'. - (member variant - (pcase type - ('bare '("bare" "bare-caps" "b" "bc")) - ('caps '("caps" "bare-caps" "c" "bc")) - (_ (error "Invalid variant type: %S" type))))))) - (pcase style - ;; "author" style. - (`(,(or "author" "a") . ,variant) - (let ((caps (member variant '("caps" "c")))) - (org-export-data - (mapconcat - (lambda (key) - (let ((author (org-cite-basic--get-field 'author key info))) - (if caps (capitalize author) author))) - (org-cite-get-references citation t) - org-cite-basic-author-year-separator) - info))) - ;; "noauthor" style. - (`(,(or "noauthor" "na") . ,variant) - (format (if (funcall has-variant-p variant 'bare) "%s" "(%s)") - (mapconcat (lambda (key) (org-cite-basic--get-year key info)) - (org-cite-get-references citation t) - org-cite-basic-author-year-separator))) - ;; "nocite" style. - (`(,(or "nocite" "n") . ,_) nil) - ;; "text" and "note" styles. - (`(,(and (or "text" "note" "t" "ft") style) . ,variant) - (when (and (member style '("note" "ft")) - (not (org-cite-inside-footnote-p citation))) - (org-cite-adjust-note citation info) - (org-cite-wrap-citation citation info)) - (let ((bare (funcall has-variant-p variant 'bare)) - (caps (funcall has-variant-p variant 'caps))) - (org-cite-basic--format-author-year - citation - (lambda (p c s) (org-cite-concat p c s)) - (lambda (p a y s) - (org-cite-concat p - (if caps (capitalize a) a) - (if bare " " " (") - y s - (and (not bare) ")"))) - info))) - ;; "numeric" style. - ;; - ;; When using this style on citations with multiple references, - ;; use global affixes and ignore local ones. - (`(,(or "numeric" "nb") . ,_) - (pcase-let ((`(,prefix . ,suffix) (org-cite-main-affixes citation))) - (org-export-data - (org-cite-concat - "(" prefix (org-cite-basic--citation-numbers citation info) suffix ")") - info))) - ;; Default ("nil") style. - (`(,_ . ,variant) - (let ((bare (funcall has-variant-p variant 'bare)) - (caps (funcall has-variant-p variant 'caps))) - (org-cite-basic--format-author-year - citation - (lambda (p c s) - (org-cite-concat (and (not bare) "(") p c s (and (not bare) ")"))) - (lambda (p a y s) - (org-cite-concat p (if caps (capitalize a) a) ", " y s)) - info))) - ;; This should not happen. - (_ (error "Invalid style: %S" style))))) - -(defun org-cite-basic-export-bibliography (keys _files style _props backend info) - "Generate bibliography. -KEYS is the list of cited keys, as strings. STYLE is the expected bibliography -style, as a string. BACKEND is the export back-end, as a symbol. INFO is the -export state, as a property list." - (mapconcat - (lambda (k) - (let ((entry (org-cite-basic--get-entry k info))) - (org-export-data - (org-cite-make-paragraph - (and (org-export-derived-backend-p backend 'latex) - (org-export-raw-string "\\noindent\n")) - (org-cite-basic--print-entry entry style info)) - info))) - (org-cite-basic--sort-keys keys info) - "\n")) - - -;;; "Follow" capability -(defun org-cite-basic-goto (datum _) - "Follow citation or citation reference DATUM. -When DATUM is a citation reference, open bibliography entry referencing -the citation key. Otherwise, select which key to follow among all keys -present in the citation." - (let* ((key - (if (eq 'citation-reference (org-element-type datum)) - (org-element-property :key datum) - (pcase (org-cite-get-references datum t) - (`(,key) key) - (keys - (or (completing-read "Select citation key: " keys nil t) - (user-error "Aborted")))))) - (file - (pcase (seq-find (pcase-lambda (`(,_ . ,entries)) - (gethash key entries)) - (org-cite-basic--parse-bibliography)) - (`(,f . ,_) f) - (_ (user-error "Cannot find citation key: %S" key))))) - (org-open-file file '(4)) - (pcase (file-name-extension file) - ("json" - ;; `rx' can not be used with Emacs <27.1 since `literal' form - ;; is not supported. - (let ((regexp (rx-to-string `(seq "\"id\":" (0+ (any "[ \t]")) "\"" ,key "\"") t))) - (goto-char (point-min)) - (re-search-forward regexp) - (search-backward "{"))) - (_ - (bibtex-set-dialect) - (bibtex-search-entry key))))) - - -;;; "Insert" capability -(defun org-cite-basic--complete-style (_) - "Offer completion for style. -Return chosen style as a string." - (let* ((styles - (mapcar (pcase-lambda (`((,style . ,_) . ,_)) - style) - (org-cite-supported-styles)))) - (pcase styles - (`(,style) style) - (_ (completing-read "Style (\"\" for default): " styles nil t))))) - -(defun org-cite-basic--key-completion-table () - "Return completion table for cite keys, as a hash table. - -In this hash table, keys are a strings with author, date, and -title of the reference. Values are the cite keys. - -Return nil if there are no bibliography files or no entries." - ;; Populate bibliography cache. - (let ((entries (org-cite-basic--parse-bibliography))) - (cond - ((null entries) nil) ;no bibliography files - ((gethash entries org-cite-basic--completion-cache) - org-cite-basic--completion-cache) - (t - (clrhash org-cite-basic--completion-cache) - (dolist (key (org-cite-basic--all-keys)) - (let ((completion - (concat - (let ((author (org-cite-basic--get-field 'author key nil t))) - (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)))) - (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) - org-cite-basic--completion-cache))))) - -(defun org-cite-basic--complete-key (&optional multiple) - "Prompt for a reference key and return a citation reference string. - -When optional argument MULTIPLE is non-nil, prompt for multiple -keys, until one of them is nil. Then return the list of -reference strings selected. - -Raise an error when no bibliography is set in the buffer." - (let* ((table - (or (org-cite-basic--key-completion-table) - (user-error "No bibliography set"))) - (prompt - (lambda (text) - (completing-read text table nil t)))) - (if (null multiple) - (let ((key (gethash (funcall prompt "Key: ") table))) - (org-string-nw-p key)) - (let* ((keys nil) - (build-prompt - (lambda () - (if keys - (format "Key (empty input exits) %s: " - (mapconcat #'identity (reverse keys) ";")) - "Key (empty input exits): ")))) - (let ((key (funcall prompt (funcall build-prompt)))) - (while (org-string-nw-p key) - (push (gethash key table) keys) - (setq key (funcall prompt (funcall build-prompt))))) - keys)))) - - -;;; Register processor -(org-cite-register-processor 'basic - :activate #'org-cite-basic-activate - :export-citation #'org-cite-basic-export-citation - :export-bibliography #'org-cite-basic-export-bibliography - :follow #'org-cite-basic-goto - :insert (org-cite-make-insert-processor #'org-cite-basic--complete-key - #'org-cite-basic--complete-style) - :cite-styles - '((("author" "a") ("caps" "c")) - (("noauthor" "na") ("bare" "b")) - (("nocite" "n")) - (("note" "ft") ("bare-caps" "bc") ("caps" "c")) - (("numeric" "nb")) - (("text" "t") ("bare-caps" "bc") ("caps" "c")) - (("nil") ("bare" "b") ("bare-caps" "bc") ("caps" "c")))) - -(provide 'oc-basic) -;;; oc-basic.el ends here |