update packages

This commit is contained in:
2021-01-08 19:32:30 +01:00
parent ce8f24d28a
commit f5649dceab
467 changed files with 26642 additions and 22487 deletions

View File

@@ -118,6 +118,13 @@ Set `doi-utils-make-notes' to nil if you want no notes."
:type 'string
:group 'doi-utils)
(defcustom doi-utils-metadata-function 'doi-utils-get-json-metadata
"Function for retrieving json metadata from `doi-utils-dx-doi-org-url'.
The default is `doi-utils-get-json-metadata', but it sometimes
fails with a proxy. An alternative is
`doi-utils-get-json-metadata-curl' which requires an external
program to use curl.")
;;* Getting pdf files from a DOI
@@ -208,39 +215,18 @@ must return a pdf-url, or nil.")
"Stores url to pdf download from a callback function.")
;;** Wiley
;; Wiley have changed the url structure from
;; http://onlinelibrary.wiley.com/doi/10.1002/anie.201402680/abstract
;; http://onlinelibrary.wiley.com/doi/10.1002/anie.201402680/pdf
;; It appears that it is not enough to use the pdf url above. That takes you to
;; an html page. The actual link to teh pdf is embedded in that page. This is
;; how ScienceDirect does things too.
;; This is where the link is hidden:
;; <iframe id="pdfDocument" src="http://onlinelibrary.wiley.com/store/10.1002/anie.201402680/asset/6397_ftp.pdf?v=1&amp;t=hwut2142&amp;s=d4bb3cd4ad20eb733836717f42346ffb34017831" width="100%" height="675px"></iframe>
(defun doi-utils-get-wiley-pdf-url (redirect-url)
"Wileyscience direct hides the pdf url in html.
We get it out here by parsing the html.
Argument REDIRECT-URL URL you are redirected to."
(setq *doi-utils-waiting* t)
(url-retrieve
redirect-url
(lambda (status)
(goto-char (point-min))
(re-search-forward "<iframe id=\"pdfDocument\" src=\"\\([^\"]*\\)\"" nil t)
(setq *doi-utils-pdf-url* (match-string 1)
*doi-utils-waiting* nil)))
(while *doi-utils-waiting* (sleep-for 0.1))
*doi-utils-pdf-url*)
;; to
;; http://onlinelibrary.wiley.com/doi/abs/10.1002/anie.201402680
;; http://onlinelibrary.wiley.com/doi/pdf/10.1002/anie.201402680
;; Hence fewer steps are now required.
(defun wiley-pdf-url (*doi-utils-redirect*)
"Get url to the pdf from *DOI-UTILS-REDIRECT*."
(when (string-match "^http\\(s?\\)://onlinelibrary.wiley.com" *doi-utils-redirect*)
(doi-utils-get-wiley-pdf-url
(replace-regexp-in-string "/abstract" "/pdf" *doi-utils-redirect*))
*doi-utils-pdf-url*))
(replace-regexp-in-string "doi/abs" "doi/pdf" *doi-utils-redirect*)))
(defun agu-pdf-url (*doi-utils-redirect*)
@@ -551,15 +537,11 @@ REDIRECT-URL is where the pdf url will be in."
(match-string 1))))))))
;; ACM Digital Library
;; http(s)://dl.acm.org/citation.cfm?doid=1368088.1368132
;; <a name="FullTextPDF" title="FullText PDF" href="ft_gateway.cfm?id=1368132&ftid=518423&dwn=1&CFID=766519780&CFTOKEN=49739320" target="_blank">
;; https://dl.acm.org/doi/10.1145/1368088.1368132
(defun acm-pdf-url (*doi-utils-redirect*)
"Get a url to the pdf from *DOI-UTILS-REDIRECT* for ACM urls."
(when (string-match "^https?://dl.acm.org" *doi-utils-redirect*)
(with-current-buffer (url-retrieve-synchronously *doi-utils-redirect*)
(goto-char (point-min))
(when (re-search-forward "<a name=\"FullTextPDF\".*href=\"\\([[:ascii:]]*?\\)\"" nil t)
(concat "http://dl.acm.org/" (match-string 1))))))
(replace-regexp-in-string "doi" "doi/pdf" *doi-utils-redirect* )))
;;** Optical Society of America (OSA)
(defun osa-pdf-url (*doi-utils-redirect*)
@@ -603,6 +585,12 @@ It would be better to parse this, but here I just use a regexp.
(when (string-match "^http\\(s?\\)://epubs.siam.org" *doi-utils-redirect*)
(replace-regexp-in-string "/doi/" "/doi/pdf/" *doi-utils-redirect* )))
;; PLOS journals
;; https://plos.org/
(defun plos-pdf-url (*doi-utils-redirect*)
"Get url to the pdf from *DOI-UTILS-REDIRECT*."
(when (string-match "^http\\(s*\\)://journals.plos.org" *doi-utils-redirect*)
(concat (replace-regexp-in-string (regexp-quote "/article?id=") "/article/file?id=" *doi-utils-redirect*) "&type=printable")))
;;** Add all functions
@@ -639,6 +627,7 @@ It would be better to parse this, but here I just use a regexp.
'asme-biomechanical-pdf-url
'siam-pdf-url
'agu-pdf-url
'plos-pdf-url
'generic-full-pdf-url))
;;** Get the pdf url for a doi
@@ -750,17 +739,44 @@ Opening %s" json-data url))
(t
(json-read-from-string json-data))))))
(defun doi-utils-get-json-metadata-curl (doi)
"Try to get json metadata for DOI. Open the DOI in a browser if we do not get it."
(let ((json-object-type 'plist)
(json-data)
(url (concat doi-utils-dx-doi-org-url doi)))
(with-temp-buffer
(call-process "curl" nil t nil
"--location"
"--silent"
"--header"
"Accept: application/citeproc+json"
url)
(setq json-data (buffer-string))
(cond
((or (string-match "<title>Error: DOI Not Found</title>" json-data)
(string-match "Resource not found" json-data)
(string-match "Status *406" json-data)
(string-match "400 Bad Request" json-data))
(browse-url url)
(error "Something went wrong. We got this response:
%s
Opening %s" json-data url))
;; everything seems ok with the data
(t
(json-read-from-string json-data))))))
;; We can use that data to construct a bibtex entry. We do that by defining a
;; template, and filling it in. I wrote this template expansion code which makes
;; it easy to substitute values like %{} in emacs lisp.
;; template, and filling it in. I wrote this template expansion code which
;; makes it easy to substitute values like %{} in emacs lisp.
(defun doi-utils-expand-template (s)
"Expand a string template S containing %{} with the eval of its contents."
(replace-regexp-in-string "%{\\([^}]+\\)}"
(lambda (arg)
(let ((sexp (substring arg 2 -1)))
(format "%s" (eval (read sexp)))))
(lambda (arg)
(let ((sexp (substring arg 2 -1)))
(format "%s" (eval (read sexp)))))
s))
@@ -877,7 +893,7 @@ MATCHING-TYPES."
(defun doi-utils-doi-to-bibtex-string (doi)
"Return a bibtex entry as a string for the DOI. Not all types are supported yet."
(let* ((results (doi-utils-get-json-metadata doi))
(let* ((results (funcall doi-utils-metadata-function doi))
(type (plist-get results :type)))
;; (format "%s" results) ; json-data
(or (-some (lambda (g) (funcall g type results)) doi-utils-bibtex-type-generators)
@@ -933,59 +949,7 @@ Argument BIBFILE the bibliography to use."
(list (read-string
"DOI: "
;; now set initial input
(cond
;; If region is active and it starts like a doi we want it.
((and (region-active-p)
(s-match "^10" (buffer-substring
(region-beginning)
(region-end))))
(buffer-substring (region-beginning) (region-end)))
((and (region-active-p)
(s-match "^http://dx\\.doi\\.org/" (buffer-substring
(region-beginning)
(region-end))))
(replace-regexp-in-string "^http://dx\\.doi\\.org/" ""
(buffer-substring (region-beginning) (region-end))))
((and (region-active-p)
(s-match "^https://dx\\.doi\\.org/" (buffer-substring
(region-beginning)
(region-end))))
(replace-regexp-in-string "^https://dx\\.doi\\.org/" ""
(buffer-substring (region-beginning) (region-end))))
((and (region-active-p)
(s-match (regexp-quote doi-utils-dx-doi-org-url) (buffer-substring
(region-beginning)
(region-end))))
(replace-regexp-in-string (regexp-quote doi-utils-dx-doi-org-url) ""
(buffer-substring (region-beginning) (region-end)))
(buffer-substring (region-beginning) (region-end)))
;; if the first entry in the kill-ring looks
;; like a DOI, let's use it.
((and
;; make sure the kill-ring has something in it
(stringp (car kill-ring))
(s-match "^10" (car kill-ring)))
(car kill-ring))
;; maybe kill-ring matches http://dx.doi or somthing
((and
;; make sure the kill-ring has something in it
(stringp (car kill-ring))
(s-match "^http://dx\\.doi\\.org/" (car kill-ring)))
(replace-regexp-in-string "^http://dx\\.doi\\.org/" "" (car kill-ring)))
((and
;; make sure the kill-ring has something in it
(stringp (car kill-ring))
(s-match "^https://dx\\.doi\\.org/" (car kill-ring)))
(replace-regexp-in-string "^https://dx\\.doi\\.org/" "" (car kill-ring)))
((and
;; make sure the kill-ring has something in it
(stringp (car kill-ring))
(s-match (regexp-quote doi-utils-dx-doi-org-url) (car kill-ring)))
(replace-regexp-in-string (regexp-quote doi-utils-dx-doi-org-url) "" (car kill-ring)))
;; otherwise, we have no initial input. You
;; will have to type it in.
(t
nil)))))
(doi-utils-maybe-doi-from-region-or-current-kill))))
(unless bibfile
(setq bibfile (completing-read "Bibfile: " (org-ref-possible-bibfiles))))
@@ -1009,6 +973,53 @@ Argument BIBFILE the bibliography to use."
(defalias 'doi-add-bibtex-entry 'doi-utils-add-bibtex-entry-from-doi
"Alias function for convenience.")
(defun doi-utils-maybe-doi-from-region-or-current-kill ()
"Try to get a DOI from the active region or current kill."
(let* ((the-active-region (if (region-active-p) ;; nil if no active region
(buffer-substring (region-beginning) (region-end))
nil))
(the-current-kill (ignore-errors (current-kill 0 t))) ;; nil if empty kill ring
;; DOI urls
;; Ex: https://doi.org/10.1109/MALWARE.2014.6999410
;; Ex: https://dx.doi.org/10.1007/978-3-319-60876-1_10
(doi-url-prefix-regexp "^https?://\\(dx\\.\\)?doi\\.org/")
;; https://www.crossref.org/blog/dois-and-matching-regular-expressions/
(doi-regexp "10\\.[0-9]\\{4,9\\}/[-._;()/:A-Z0-9]+$"))
(cond
;; Check if a DOI can be found in the active region
;; DOI raw
;; Ex: 10.1109/MALWARE.2014.6999410
((and (stringp the-active-region)
(s-match (concat "^" doi-regexp) the-active-region))
the-active-region)
;; DOI url
;; Ex: https://doi.org/10.1109/MALWARE.2014.6999410
((and (stringp the-active-region)
(s-match (concat doi-url-prefix-regexp doi-regexp) the-active-region))
(replace-regexp-in-string doi-url-prefix-regexp "" the-active-region))
;; DOI url as customized
((and (stringp the-active-region)
(s-match (regexp-quote doi-utils-dx-doi-org-url) the-active-region))
(replace-regexp-in-string (regexp-quote doi-utils-dx-doi-org-url) "" the-active-region))
;; Check if DOI can be found in the current kill
;; DOI raw
;; Ex: 10.1109/MALWARE.2014.6999410
((and (stringp the-current-kill)
(s-match (concat "^" doi-regexp) the-current-kill))
the-current-kill)
;; DOI url
;; Ex: https://doi.org/10.1109/MALWARE.2014.6999410
((and (stringp the-current-kill)
(s-match (concat doi-url-prefix-regexp doi-regexp) the-current-kill))
(replace-regexp-in-string doi-url-prefix-regexp "" the-current-kill))
;; DOI url as customized
((and (stringp the-current-kill)
(s-match (regexp-quote doi-utils-dx-doi-org-url) the-current-kill))
(replace-regexp-in-string (regexp-quote doi-utils-dx-doi-org-url) "" the-current-kill))
;; otherwise, return nil
(t
nil))))
;;;###autoload
(defun doi-utils-doi-to-org-bibtex (doi)
"Convert a DOI to an org-bibtex form and insert it at point."
@@ -1074,7 +1085,7 @@ Every field will be updated, so previous change will be lost."
"https?://\\(dx.\\)?doi.org/" ""
(bibtex-autokey-get-field "doi"))
(read-string "DOI: "))))
(let* ((results (doi-utils-get-json-metadata doi))
(let* ((results (funcall doi-utils-metadata-function doi))
(type (plist-get results :type))
(author (mapconcat
(lambda (x)
@@ -1131,7 +1142,7 @@ Every field will be updated, so previous change will be lost."
Data is retrieved from the doi in the entry."
(interactive)
(let* ((doi (bibtex-autokey-get-field "doi"))
(results (doi-utils-get-json-metadata doi))
(results (funcall doi-utils-metadata-function doi))
(field (car (bibtex-find-text-internal nil nil ","))))
(cond
((string= field "volume")
@@ -1194,6 +1205,15 @@ May be empty if none are found."
"&svc_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Asch_svc&svc.related=yes")))
;;* DOI functions for ADS
;;;###autoload
(defun doi-utils-ads (doi)
"Open ADS entry for DOI"
(interactive "sDOI: ")
(browse-url
(concat
"https://ui.adsabs.harvard.edu/abs/" "%22" doi "%22")))
;;* A new doi link for org-mode
@@ -1263,6 +1283,7 @@ must take one argument, the doi.")
("w" "os" doi-utils-wos)
("c" "iting articles" doi-utils-wos-citing)
("r" "elated articles" doi-utils-wos-related)
("a" "ds" doi-utils-ads)
("s" "Google Scholar" doi-utils-google-scholar)
("f" "CrossRef" doi-utils-crossref)
("p" "ubmed" doi-utils-pubmed)

View File

@@ -148,11 +148,46 @@ Returns a formatted BibTeX entry."
(--map (s-split " +" it) authors))))
(defun arxiv-maybe-arxiv-id-from-current-kill ()
"Try to get an arxiv ID from the current kill."
(let* ((the-current-kill (ignore-errors (current-kill 0 t))) ;; nil if empty kill ring
(arxiv-url-prefix-regexp "^https?://arxiv\\.org/\\(pdf\\|abs\\|format\\)/")
(arxiv-cite-prefix-regexp "^\\(arXiv\\|arxiv\\):")
(arxiv-id-old-regexp "[a-z-]+\\(\\.[A-Z]\\{2\\}\\)?/[0-9]\\{5,7\\}$") ; Ex: math.GT/0309136
(arxiv-id-new-regexp "[0-9]\\{4\\}[.][0-9]\\{4,5\\}\\(v[0-9]+\\)?$") ; Ex: 1304.4404v2
(arxiv-id-regexp (concat "\\(" arxiv-id-old-regexp "\\|" arxiv-id-new-regexp "\\)")))
(cond
(;; make sure current-kill has something in it
;; if current-kill is not a string, return nil
(not (stringp the-current-kill))
nil)
(;; check if current-kill looks like an arxiv ID
;; if so, return it
;; Ex: 1304.4404v2
(s-match (concat "^" arxiv-id-regexp) the-current-kill)
the-current-kill)
(;; check if current-kill looks like an arxiv cite
;; if so, remove the prefix and return
;; Ex: arXiv:1304.4404v2 --> 1304.4404v2
(s-match (concat arxiv-cite-prefix-regexp arxiv-id-regexp) the-current-kill)
(replace-regexp-in-string arxiv-cite-prefix-regexp "" the-current-kill))
(;; check if current-kill looks like an arxiv url
;; if so, remove the url prefix and return
;; Ex: https://arxiv.org/pdf/1304.4404 --> 1304.4404
(s-match (concat arxiv-url-prefix-regexp arxiv-id-regexp) the-current-kill)
(replace-regexp-in-string arxiv-url-prefix-regexp "" the-current-kill))
;; otherwise, return nil
(t
nil))))
;;;###autoload
(defun arxiv-add-bibtex-entry (arxiv-number bibfile)
"Add bibtex entry for ARXIV-NUMBER to BIBFILE."
(interactive
(list (read-string "arxiv: ")
(list (read-string
"arxiv: "
(arxiv-maybe-arxiv-id-from-current-kill))
;; now get the bibfile to add it to
(completing-read
"Bibfile: "
@@ -172,7 +207,12 @@ Returns a formatted BibTeX entry."
;;;###autoload
(defun arxiv-get-pdf (arxiv-number pdf)
"Retrieve a pdf for ARXIV-NUMBER and save it to PDF."
(interactive "sarxiv: \nsPDF: ")
(interactive
(list (read-string
"arxiv: "
(arxiv-maybe-arxiv-id-from-current-kill))
(read-string
"PDF: ")))
(let ((pdf-url (with-current-buffer
(url-retrieve-synchronously
(concat
@@ -196,7 +236,9 @@ Remove troublesome chars from the bibtex key, retrieve a pdf
for ARXIV-NUMBER and save it to PDFDIR with the same name of the
key."
(interactive
(list (read-string "arxiv: ")
(list (read-string
"arxiv: "
(arxiv-maybe-arxiv-id-from-current-kill))
;; now get the bibfile to add it to
(completing-read
"Bibfile: "

View File

@@ -481,8 +481,10 @@ This is defined in `org-ref-bibtex-journal-abbreviations'."
"the" "of" "in")
"List of words to keep lowercase when changing case in a title.")
(defcustom org-ref-title-case-types '("article" "book")
"List of bibtex entry types in which the title will be converted to
(defcustom org-ref-title-case-types '(("article" . ("title"))
("book" . ("booktitle")))
"An a-list of bibtex entry types and fields that will be converted to
title-case by org-ref-title-case."
:type '(repeat string)
:group 'org-ref-bibtex)
@@ -496,64 +498,63 @@ optional, and are only there so you can use this function with
`bibtex-map-entries' to change all the title entries in articles and
books."
(interactive)
(dolist (field '("title" "booktitle"))
(save-restriction
(bibtex-narrow-to-entry)
(bibtex-beginning-of-entry)
;; Skip if field is not found in entry
(when (bibtex-search-forward-field field)
(let* ((title (bibtex-autokey-get-field field))
(words (split-string title))
(start 0))
(when
(member (downcase
(cdr (assoc "=type=" (bibtex-parse-entry))))
org-ref-title-case-types)
(setq words (mapcar
(lambda (word)
(cond
;; words containing more than one . are probably
;; abbreviations. We do not change those.
((with-temp-buffer
(insert word)
(goto-char (point-min))
(> (count-matches "\\.") 1))
word)
;; match words containing {} or \ which are probably
;; LaTeX or protected words, ignore
((string-match "\\$\\|{\\|}\\|(\\|)\\|\\\\" word)
word)
;; these words should not be capitalized, unless they
;; are the first word
((-contains? org-ref-lower-case-words
(s-downcase word))
(s-downcase word))
;; Words that are quoted
((s-starts-with? "\"" word)
(concat "\"" (s-capitalize (substring word 1))))
(t
(s-capitalize word))))
words))
(save-restriction
(bibtex-narrow-to-entry)
(bibtex-beginning-of-entry)
(let* ((entry-type (downcase (cdr (assoc "=type=" (bibtex-parse-entry)))))
(fields (cdr (assoc entry-type org-ref-title-case-types))))
(when fields
(cl-loop for field in fields
when (bibtex-autokey-get-field field)
do
(setq title (bibtex-autokey-get-field field)
words (split-string title)
start 0)
(setq words (mapcar
(lambda (word)
(cond
;; words containing more than one . are probably
;; abbreviations. We do not change those.
((with-temp-buffer
(insert word)
(goto-char (point-min))
(> (count-matches "\\.") 1))
word)
;; match words containing {} or \ which are probably
;; LaTeX or protected words, ignore
((string-match "\\$\\|{\\|}\\|(\\|)\\|\\\\" word)
word)
;; these words should not be capitalized, unless they
;; are the first word
((-contains? org-ref-lower-case-words
(s-downcase word))
(s-downcase word))
;; Words that are quoted
((s-starts-with? "\"" word)
(concat "\"" (s-capitalize (substring word 1))))
(t
(s-capitalize word))))
words))
;; Check if first word should be capitalized
(when (-contains? org-ref-lower-case-words (car words))
(setf (car words) (s-capitalize (car words))))
;; Check if first word should be capitalized
(when (-contains? org-ref-lower-case-words (car words))
(setf (car words) (s-capitalize (car words))))
(setq title (mapconcat 'identity words " "))
(setq title (mapconcat 'identity words " "))
;; Capitalize letters after a dash
(while
(string-match "[a-zA-Z]-\\([a-z]\\)" title start)
(let ((char (substring title (match-beginning 1) (match-end 1))))
(setf (substring title (match-beginning 1) (match-end 1))
(format "%s" (upcase char)))
(setq start (match-end 1))))
;; Capitalize letters after a dash
(while
(string-match "[a-zA-Z]-\\([a-z]\\)" title start)
(let ((char (substring title (match-beginning 1) (match-end 1))))
(setf (substring title (match-beginning 1) (match-end 1))
(format "%s" (upcase char)))
(setq start (match-end 1))))
;; this is defined in doi-utils
(bibtex-set-field
field
title)
(bibtex-fill-entry)))))))
;; this is defined in doi-utils
(bibtex-set-field
field
title)
(bibtex-fill-entry))))))
;;;###autoload
(defun org-ref-title-case-article (&optional key start end)
@@ -562,7 +563,7 @@ The arguments KEY, START and END are optional, and are only there
so you can use this function with `bibtex-map-entries' to change
all the title entries in articles and books."
(interactive)
(let ((org-ref-title-case-types '("article")))
(let ((org-ref-title-case-types '(("article" . ("title")))))
(org-ref-title-case)))
@@ -948,9 +949,7 @@ entry having a doi."
pdf)
;; when we have org-ref defined we may have pdf to find.
(when (boundp 'org-ref-pdf-directory)
(setq pdf (expand-file-name
(concat key ".pdf")
org-ref-pdf-directory)))
(setq pdf (funcall org-ref-get-pdf-filename-function key)))
(bibtex-copy-entry-as-kill)
(compose-mail)
(message-goto-body)
@@ -1285,7 +1284,9 @@ of format strings used."
(defun org-ref-format-entry (key)
"Returns a formatted bibtex entry for KEY."
(let* ((bibtex-completion-bibliography (org-ref-find-bibliography)))
(org-ref-format-bibtex-entry (ignore-errors (bibtex-completion-get-entry key)))))
(if (string= "*" key)
"*"
(org-ref-format-bibtex-entry (ignore-errors (bibtex-completion-get-entry key))))))
(defun org-ref-format-bibtex-entry-at-point ()

View File

@@ -35,6 +35,7 @@
(require 'htmlize)
(require 's)
(require 'doi-utils)
(require 'seq)
(add-to-list 'load-path
(expand-file-name
@@ -273,7 +274,7 @@ Just the reference, no numbering at the beginning, etc... see the
(defcustom org-ref-note-title-format
"** TODO %y - %t
:PROPERTIES:
:Custom_ID: %k
:CUSTOM_ID: %k
:AUTHOR: %9a
:JOURNAL: %j
:YEAR: %y
@@ -331,7 +332,7 @@ moves the headline to the top of the buffer."
(defcustom org-ref-create-notes-hook
'((lambda ()
(org-narrow-to-subtree)
(insert (format "cite:%s\n" (org-entry-get (point) "Custom_ID")))))
(insert (format "cite:%s\n" (org-entry-get (point) "CUSTOM_ID")))))
"List of hook functions to run in the note entry after it is created.
The function takes no arguments. It could be used to insert links
to the citation, or pdf, etc..."
@@ -719,6 +720,10 @@ If so return the position for `goto-char'."
:type 'string
:group 'org-ref)
(defcustom org-ref-latex-bib-resolve-func #'file-relative-name
"used to expand paths to the bibliography file on latex export."
:type 'function
:group 'org-ref)
(defvar org-ref-cite-re
(concat "\\(" (mapconcat
@@ -1088,7 +1093,7 @@ PREDICATE."
"\\.bib" ""
(mapconcat
'identity
(mapcar 'file-relative-name
(mapcar org-ref-latex-bib-resolve-func
(split-string keyword ","))
","))))))
@@ -1181,7 +1186,7 @@ font-lock-warning-face if any file does not exist."
(replace-regexp-in-string
"\\.bib" ""
(mapconcat 'identity
(mapcar 'file-relative-name
(mapcar org-ref-latex-bib-resolve-func
(split-string keyword ","))
","))))))
@@ -1473,37 +1478,110 @@ ARG does nothing."
custom-id-count)))
(defun org-label-store-link ()
"Store a link to a label. The output will be a ref to that label."
(defun org-ref-label-store-link ()
"Store a link to a label. The output will be a ref to that label.
This has several conditional ways to store a link to figures and
tables also. Note it does not currently work with latex labels,
only org labels and names."
;; First we have to make sure we are on a label link.
(let* ((object (and (eq major-mode 'org-mode) (org-element-context))))
(when (and
(equal (org-element-type object) 'link)
(equal (org-element-property :type object) "label"))
(let* ((object (and (eq major-mode 'org-mode) (org-element-context)))
(stored nil)
label)
(cond
;; here literally on a label link.
((and
(equal (org-element-type object) 'link)
(equal (org-element-property :type object) "label"))
(setq label (org-element-property :path object))
(org-store-link-props
:type "ref"
:link (concat "ref:" (org-element-property :path object))))
:link (concat "ref:" label)))
;; Store link on table
(when (equal (org-element-type object) 'table)
;; here on a file link that probably contains an image, although I don't check that
((and
(equal (org-element-type object) 'link)
(equal (org-element-property :type object) "file")
(org-file-image-p (org-element-property :path object)))
(if (org-element-property :name object)
(progn
(setq label (org-element-property :name object))
(org-store-link-props
:type "ref"
:link (concat "ref:"label)))
;; maybe we have a caption to get it from.
(let* ((parent (org-element-property :parent object))
(caption))
(when (and parent
(equal (org-element-type parent) 'paragraph))
(if (org-element-property :name parent)
;; caption paragraph may have a name which we use if it is there
(setq label (org-element-property :name parent))
;; else search caption
(setq caption (s-join
""
(mapcar 'org-no-properties
(org-export-get-caption parent))))
(when (string-match org-ref-label-re caption)
(setq label (match-string 1 caption))))
(org-store-link-props
:type "ref"
:link (concat "ref:" label))))))
;; here on a paragraph (eg in a caption of an image). it is a paragraph with a caption
;; in a caption, with no name, but maybe a label
((equal (org-element-type object) 'paragraph)
(if (org-element-property :name object)
(org-store-link-props
:type "ref"
:link (concat "ref:" (org-element-property :name object)))
;; See if it is in the caption name
(let ((caption (s-join "" (mapcar 'org-no-properties
(org-export-get-caption object)))))
(when (string-match org-ref-label-re caption)
(setq label (match-string 1 caption))
(org-store-link-props
:type "ref"
:link (concat "ref:" label))))))
;; If you are in a table, we need to be at the beginning to make sure we get the name.
;; Note when in a caption it appears you are in a table but org-at-table-p is nil there.
((or (equal (org-element-type object) 'table) (org-at-table-p))
(save-excursion
(goto-char (org-table-begin))
(let* ((table (org-element-context))
(label (org-element-property :name table))
(caption (s-join "" (mapcar 'org-no-properties (org-export-get-caption table)))))
(when (null label)
;; maybe there is a label in the caption?
(when (string-match org-ref-label-re caption)
(setq label (match-string 1 caption))))
(org-store-link-props
:type "ref"
:link (concat "ref:" label)))))
;; and to #+label: lines
((and (equal (org-element-type object) 'paragraph)
(org-element-property :name object))
(setq label (org-element-property :name object))
(org-store-link-props
:type "ref"
:link (concat "ref:" (org-element-property :name object))))
:link (concat "ref:" label)))
;; store link on heading with custom_id
;; this is not a ref link, but it is still what you want
(when (and (equal (org-element-type object) 'headline)
(org-entry-get (point) "CUSTOM_ID"))
(org-store-link-props
:type "custom_id"
:link (format "[[#%s]]" (org-entry-get (point) "CUSTOM_ID"))))
;; in a latex environment
((equal (org-element-type object) 'latex-environment)
(let ((value (org-element-property :value object))
label)
(when (string-match "\\\\label{\\(?1:[+a-zA-Z0-9:\\._-]*\\)}" value)
(setq label (match-string-no-properties 1 value))
(org-store-link-props
:type "ref"
:link (concat "ref:" label)))))
;; and to #+label: lines
(when (and (equal (org-element-type object) 'paragraph)
(org-element-property :name object))
(org-store-link-props
:type "ref"
:link (concat "ref:" (org-element-property :name object))))))
(t
nil))))
(defun org-ref-label-face-fn (label)
@@ -1535,7 +1613,7 @@ A number greater than one means multiple labels!"
((eq format 'md) (format "<a name=\"%s\"></a>" keyword))
((eq format 'latex)
(format "\\label{%s}" keyword))))
:store #'org-label-store-link
:store #'org-ref-label-store-link
:face 'org-ref-label-face-fn
:help-echo (lambda (window object position)
(save-excursion
@@ -1622,8 +1700,7 @@ Navigate back with \`\\[org-mark-ring-goto]'."
Optional argument ARG Does nothing."
(let ((label))
(setq label (completing-read "label: " (org-ref-get-labels)))
(format "ref:%s" label)))
(format "%s:%s" (org-ref-infer-ref-type label) label)))
(defun org-ref-ref-help-echo (window object position)
"A help-echo function for ref links."
@@ -1748,10 +1825,6 @@ Stores a list of strings.")
(defvar org-ref-label-debug nil "If non-nil print debug messages.")
(defvar-local org-ref-last-label-end 0
"Last end of position added.")
(defun org-ref-add-labels (start end)
"Add labels in the region from START to END.
This is run by font-lock. START tends to be the beginning of the
@@ -1769,11 +1842,6 @@ seems to work fine at recognizing labels by the regexps in
;; I don't know why this gets found, but some labels are
;; empty strings. we don't store these.
(unless (string= "" label)
;; if the last end is the new end -1 we are adding to a
;; label, and should pop the old one off before adding the
;; new one.
(when (eq org-ref-last-label-end (- end 1))
(pop org-ref-labels))
(with-silent-modifications
(put-text-property (match-beginning 1)
(match-end 1)
@@ -1781,16 +1849,157 @@ seems to work fine at recognizing labels by the regexps in
(put-text-property (match-beginning 1)
(match-end 1)
'rear-nonsticky '(org-ref-label)))
(when org-ref-label-debug
(message "oral: adding %s" label))
(pushnew label
org-ref-labels :test 'string=)
(when org-ref-label-debug
(message "oral: adding %s" label)
(message "%S\n" org-ref-labels))
(cl-pushnew label
org-ref-labels :test 'string=)
(when org-ref-label-debug
(message " oral: added %s" label)
(message " %S\n" org-ref-labels))
;; now store the last end so we can tell for the next run
;; if we are adding to a label.
(setq org-ref-last-label-end end))))))))
(defun org-ref-delete-labels-deletion (start end)
"Function to run before text from START to END is deleted.
If you have deleted or inserted more than one char, we just
recheck the whole buffer. It is tricky to manage labels on the
region."
(cond
;; If you are deleting a region, we just rescan the whole buffer.
((> 1 (abs (- end start)))
(org-ref-reset-labels))
;; start is at beginning of a label
((and
(null (if (bobp) nil (get-text-property (- start 1) 'org-ref-label)))
(get-text-property start 'org-ref-label))
(let ((label (buffer-substring-no-properties
start
(next-single-property-change start 'org-ref-label))))
(when org-ref-label-debug
(message "ordl-0: at beginning - removing %s" label)
(message "%S\n" org-ref-labels))
(setq org-ref-labels
(cl-remove label org-ref-labels
:test 'string=))
(when org-ref-label-debug
(message " ordl-0: removed %s" label)
(message " %S\n" org-ref-labels))))
;; in a label
((and
(if (bobp) nil (get-text-property (- start 1) 'org-ref-label))
(get-text-property start 'org-ref-label)
(if (eobp) nil (get-text-property (+ start 1) 'org-ref-label)))
(let ((label (buffer-substring-no-properties
(previous-single-property-change start 'org-ref-label)
(next-single-property-change start 'org-ref-label))))
(when org-ref-label-debug
(message "ordl-1: removing %s" label)
(message "%S\n" org-ref-labels))
(setq org-ref-labels
(cl-remove label org-ref-labels
:test 'string=))
(when org-ref-label-debug
(message " ordl-1: removed %s" label)
(message " %S\n" org-ref-labels))))
;; at end of label
((and
(get-text-property start 'org-ref-label)
(null (if (eobp) nil (get-text-property (+ start 1) 'org-ref-label))))
(let* ((start (previous-single-property-change end 'org-ref-label))
(label (buffer-substring-no-properties start end)))
(when org-ref-label-debug
(message "ordl-2: removing %s" label)
(message "%s" org-ref-labels))
(setq org-ref-labels
(cl-remove label org-ref-labels
:test 'string=))
(when org-ref-label-debug
(message " ordl-2: removed %s" label)
(message " %S\n" org-ref-labels))))))
(defun org-ref-delete-labels-insertion (start end)
"Function to run before inserting text.
START=END for an insertion."
;; this is an insertion. start=end
(cl-assert (= start end))
;; if the previous position is a label, we need to find it
(when org-ref-label-debug
(message "ordl: inserting %s %s" start end)
(message "%S\n" org-ref-labels))
(cond
;; at the beginning of a label
((and
(get-text-property start 'org-ref-label)
(not (if (bobp) nil (get-text-property (- start 1) 'org-ref-label))))
(let ((label (buffer-substring-no-properties
start
(next-single-property-change start 'org-ref-label))))
(when org-ref-label-debug
(message "ordl-5: removing %s" label)
(message "%S\n" org-ref-labels))
(setq org-ref-labels
(cl-remove
label
org-ref-labels
:test 'string=))
(when org-ref-label-debug
(message " ordl-5: removing %s" label)
(message " %S\n" org-ref-labels))))
;; in a label
((and
;; this means in a label
(if (bobp) nil (get-text-property (- start 1) 'org-ref-label))
(get-text-property start 'org-ref-label))
(let ((label (buffer-substring-no-properties
(previous-single-property-change start 'org-ref-label)
(next-single-property-change start 'org-ref-label))))
(when org-ref-label-debug
(message "ordl-4: removing %s" label)
(message "%S\n" org-ref-labels))
(setq org-ref-labels
(cl-remove label
org-ref-labels
:test 'string=))
(when org-ref-label-debug
(message " ordl-4: removed %s" label)
(message " %S\n" org-ref-labels))))
;; at the end of a label but not on it.
((and
(not (get-text-property start 'org-ref-label))
(if (bobp) nil (get-text-property (- start 1) 'org-ref-label)))
(let ((label (buffer-substring-no-properties
start
(previous-single-property-change start 'org-ref-label))))
(when org-ref-label-debug
(message "ordl-6: removing %s" label)
(message "%S\n" org-ref-labels))
(setq org-ref-labels
(cl-remove
label
org-ref-labels
:test 'string=))
(when org-ref-label-debug
(message " ordl-6: removing %s" label)
(message " %S\n" org-ref-labels))))
(t
(when org-ref-label-debug
(message "*********** ordl fell through:%s\n%s\n%s"
(if (bobp) nil (get-text-property (- start 1) 'org-ref-label))
(get-text-property start 'org-ref-label)
(if (eobp) nil (get-text-property (+ start 1) 'org-ref-label)))))))
(defun org-ref-delete-labels (start end)
"Check for labels between START and END and remove them from the known list.
This is called as a `before-change-functions' and it means text
@@ -1806,65 +2015,30 @@ deleted.
Note: this will not necessarily trigger fontification on ref
links so they might not look broken right away if their label is
missing."
;; This conditional is here because I get errors like Args out of range: 176,
;; 176 which seem to be triggered by get-text-property. I also find that this
;; can happen during export. The check on `org-export-current-backend' is not
;; perfect, this can be nil for anonyomous derived backends.
(when org-ref-label-debug
(message "ordl start-----------------------------------------------------------------")
(message "start: %S" org-ref-labels))
;; This conditional is here because I get errors like Args out of range:
;; 176, 176 which seem to be triggered by get-text-property. I also find that
;; this can happen during export. The check on `org-export-current-backend' is
;; not perfect, this can be nil for anonyomous derived backends.
(when (and org-ref-labels
(not org-export-current-backend))
(if (not (eq start end))
;; we are in a deletion. The text from start to end will be deleted
(progn
;; start is on a label, so remove back.
(when (get-text-property start 'org-ref-label)
(let ((label (buffer-substring-no-properties
(previous-single-property-change start 'org-ref-label)
(next-single-property-change start 'org-ref-label))))
(when org-ref-label-debug
(message "ordl-1: removing %s" label))
(setq org-ref-labels
(cl-remove label org-ref-labels
:test 'string=))))
;; end is on a label, get it and remove it
(when (get-text-property end 'org-ref-label)
(let* ((start (previous-single-property-change end 'org-ref-label))
(end (next-single-property-change end 'org-ref-label))
(label (buffer-substring-no-properties start end)))
(when org-ref-label-debug (message "ordl-2: removing %s" label))
(setq org-ref-labels
(cl-remove label org-ref-labels
:test 'string=))))
;; finally if we delete more than 2 chars, scan the region to remove.
(when (> (- end start) 2)
(save-excursion
(save-match-data
(cl-loop for rx in org-ref-label-regexps
do
(goto-char start)
(while (re-search-forward rx end t)
(let ((label (match-string-no-properties 1)))
;; I don't know why this gets found, but some labels are
;; empty strings. we don't store these.
(when org-ref-label-debug (message "ordl-3: removing %s" label))
(setq org-ref-labels
(cl-remove label
org-ref-labels
:test 'string=)))))))))
(if (eq start end)
(org-ref-delete-labels-insertion start end)
(org-ref-delete-labels-deletion start end)))
(when org-ref-label-debug
(message "end: %S" org-ref-labels)
(message "ordl end-----------------------------------------------------------------")))
;; this is an insertion. start=end
;; if the previous position is a label, we need to find it
(when (and
(not (eobp))
(> start 1)
(get-text-property (- start 1) 'org-ref-label))
(let ((label (buffer-substring
start
(previous-single-property-change (- start 1) 'org-ref-label))))
(when org-ref-label-debug (message "ordl-4: removing %s" label))
(setq org-ref-labels
(cl-remove label
org-ref-labels
:test 'string=)))))))
(defun org-ref-reset-labels ()
"Reset `org-ref-labels'."
(interactive)
(setq org-ref-labels nil)
(org-ref-setup-label-finders)
(org-ref-add-labels (point-min) (point-max))
org-ref-labels)
(defun org-ref-setup-label-finders ()
@@ -2042,7 +2216,14 @@ and then backwards to get a comma, or the beginning of the link. that
delimits the keyword we clicked on. We also strip the text
properties."
(let* ((object (org-element-context))
(link-string (org-element-property :path object)))
(link-string (if (eq (org-element-type object) 'link)
(org-element-property :path object)
(org-in-regexp org-link-any-re)
;; this is clunkier than I prefer, but some keys have
;; colons in them, and this gets rid of the link type,
;; then rejoins the rest of the keys
(s-join ":" (cdr (split-string
(match-string-no-properties 0) ":"))))))
;; you may click on the part before the citations. here we make
;; sure to move to the beginning so you get the first citation.
(let ((cp (point)))
@@ -2051,36 +2232,36 @@ properties."
(goto-char (match-beginning 0))
;; check if we clicked before the path and move as needed.
(unless (< cp (point))
(goto-char cp)))
(goto-char cp)))
(if (not (org-element-property :contents-begin object))
;; this means no description in the link
(progn
;; we need the link path start and end
(let (link-string-beginning link-string-end)
(save-excursion
(goto-char (org-element-property :begin object))
(search-forward link-string nil nil 1)
(setq link-string-beginning (match-beginning 0))
(setq link-string-end (match-end 0)))
;; this means no description in the link
(progn
;; we need the link path start and end
(let (link-string-beginning link-string-end)
(save-excursion
(goto-char (org-element-property :begin object))
(search-forward link-string nil nil 1)
(setq link-string-beginning (match-beginning 0))
(setq link-string-end (match-end 0)))
(let (key-beginning key-end)
;; The key is the text between commas, or the link boundaries
(save-excursion
(if (search-forward "," link-string-end t 1)
(setq key-end (- (match-end 0) 1)) ; we found a match
(setq key-end link-string-end))) ; no comma found so take the end
;; and backward to previous comma from point which defines the start character
(save-excursion
(if (search-backward "," link-string-beginning 1 1)
(setq key-beginning (+ (match-beginning 0) 1)) ; we found a match
(setq key-beginning link-string-beginning))) ; no match found
;; save the key we clicked on.
(let ((bibtex-key
(org-ref-strip-string
(buffer-substring key-beginning key-end))))
(set-text-properties 0 (length bibtex-key) nil bibtex-key)
bibtex-key))))
(let (key-beginning key-end)
;; The key is the text between commas, or the link boundaries
(save-excursion
(if (search-forward "," link-string-end t 1)
(setq key-end (- (match-end 0) 1)) ; we found a match
(setq key-end link-string-end))) ; no comma found so take the end
;; and backward to previous comma from point which defines the start character
(save-excursion
(if (search-backward "," link-string-beginning 1 1)
(setq key-beginning (+ (match-beginning 0) 1)) ; we found a match
(setq key-beginning link-string-beginning))) ; no match found
;; save the key we clicked on.
(let ((bibtex-key
(org-ref-strip-string
(buffer-substring key-beginning key-end))))
(set-text-properties 0 (length bibtex-key) nil bibtex-key)
bibtex-key))))
;; link with description and multiple keys
(if (and (org-element-property :contents-begin object)
@@ -2196,6 +2377,7 @@ set in `org-ref-default-bibliography'"
"Determine if the KEY is in the FILENAME."
(with-temp-buffer
(insert-file-contents filename)
(hack-local-variables)
(bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
(bibtex-search-entry key)))
@@ -2314,24 +2496,25 @@ Supported backends: 'html, 'latex, 'ascii, 'org, 'md, 'pandoc" type type)
(throw 'result file)
(message "%s not found in %s"
key (file-truename file))))))
(if file
(with-temp-buffer
(insert-file-contents file)
(bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
(bibtex-search-entry key nil 0)
(setq bibtex-entry (bibtex-parse-entry))
;; downcase field names so they work in the format-citation code
(dolist (cons-cell bibtex-entry)
(setf (car cons-cell) (downcase (car cons-cell))))
(setq entry-type (downcase (cdr (assoc "=type=" bibtex-entry))))
(with-temp-buffer
(insert-file-contents file)
(bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
(bibtex-search-entry key nil 0)
(setq bibtex-entry (bibtex-parse-entry))
;; downcase field names so they work in the format-citation code
(dolist (cons-cell bibtex-entry)
(setf (car cons-cell) (downcase (car cons-cell))))
(setq entry-type (downcase (cdr (assoc "=type=" bibtex-entry))))
(setq format (cdr (assoc entry-type org-ref-bibliography-entry-format)))
(if format
(setq entry (org-ref-reftex-format-citation bibtex-entry format))
;; if no format, we use the bibtex entry itself as a fallback
(save-restriction
(bibtex-narrow-to-entry)
(setq entry (buffer-string)))))
(setq format (cdr (assoc entry-type org-ref-bibliography-entry-format)))
(if format
(setq entry (org-ref-reftex-format-citation bibtex-entry format))
;; if no format, we use the bibtex entry itself as a fallback
(save-restriction
(bibtex-narrow-to-entry)
(setq entry (buffer-string)))))
"Key not found")
(replace-regexp-in-string "\"" "" (htmlize-escape-or-link entry)))
key))
(s-split "," keyword) "<sup>,</sup>"))
@@ -2458,8 +2641,10 @@ This is not smart enough yet to only highlight the bad key. If any key is bad, t
'identity
(mapcar
(lambda (key)
(assoc "=key="
(bibtex-completion-get-entry key)))
(if (string= key "*")
t
(assoc "=key="
(bibtex-completion-get-entry key))))
(split-string keys ",")))))
'org-ref-cite-face)
(t
@@ -2524,6 +2709,13 @@ citez link, with reftex key of z, and the completion function."
"Create all the link types and their completion functions."
(interactive)
(dolist (type org-ref-cite-types)
(when (fboundp 'org-link-set-parameters)
(when (assoc type org-link-parameters)
(display-warning 'org-ref
(format
"%s type is already defined, and will get redefined."
type)
:warning)))
(org-ref-define-citation-link type))
(when (fboundp 'org-link-set-parameters)
(org-link-set-parameters "cite" :store #'org-ref-bibtex-store-link)))
@@ -2675,11 +2867,13 @@ long file with headlines for each entry."
(insert key)
(kill-ring-save (point-min) (point-max)))
(let ((entry (with-temp-buffer
(insert (org-ref-get-bibtex-entry key))
(bibtex-mode)
(bibtex-set-dialect nil t)
(bibtex-beginning-of-entry)
(bibtex-parse-entry)) ))
(insert (org-ref-get-bibtex-entry key))
(reftex-parse-bibtex-entry nil (point-min) (point-max)))))
;; add =key= and =type= for code which expects `bibtex-parse-entry` style
(add-to-list 'entry
(cons "=key=" (reftex-get-bib-field "&key" entry))
(cons "=type=" (reftex-get-bib-field "&type" entry)))
(save-restriction
(if org-ref-bibliography-notes
@@ -2731,7 +2925,17 @@ for each bib entry."
collect (cons (downcase key) (s-collapse-whitespace value))))
(key (reftex-get-bib-field "=key=" entry)))
(funcall org-ref-notes-function key)))
;; Issue 746. If the bibtex file is not in `org-ref-default-bibliography'
;; you get an error. I think it is ok to just add this in a let-binding. I
;; don't think duplicates matter, and this will eliminate issue 746 in part.
;; You still need to have a bibliography file listed in the notes buffer,
;; and this does not automatically do that.
(let* ((this-bib (buffer-file-name (current-buffer)))
(org-ref-default-bibliography (append
(list
this-bib)
org-ref-default-bibliography)))
(funcall org-ref-notes-function key))))
;;** Open bibtex entry in browser
@@ -2865,16 +3069,18 @@ which will CLOBBER the file."
;;** Find bad citations
(defun org-ref-list-index (substring list)
"Return the index of SUBSTRING in a LIST of strings."
(let ((i 0)
(found nil))
(dolist (arg list i)
(if (string-match (concat "^" substring "$") arg)
(progn
(setq found t)
(cl-return i)))
(setq i (+ i 1)))
;; return counter if found, otherwise return nil
(if found i nil)))
(seq-position list substring)
;; (let ((i 0)
;; (found nil))
;; (dolist (arg list i)
;; (if (string-match (concat "^" substring "$") arg)
;; (progn
;; (setq found t)
;; (cl-return i)))
;; (setq i (+ i 1)))
;; ;; return counter if found, otherwise return nil
;; (if found i nil))
)
;;;###autoload
@@ -2902,17 +3108,17 @@ file. Makes a new buffer with clickable links."
(let ((plist (nth 1 link)))
(when (-contains? org-ref-cite-types
(plist-get plist :type))
(dolist (key (org-ref-split-and-strip-string
(plist-get plist :path)))
(when (not (org-ref-list-index key bibtex-keys))
(setq
bad-citations
(append
bad-citations
`(,(format "%s [[elisp:(progn (switch-to-buffer-other-frame \"%s\")(goto-char %s))][not found here]]\n"
key
(buffer-name)
(plist-get plist :begin))))))))))
(cl-dolist (key (org-ref-split-and-strip-string
(plist-get plist :path)))
(when (not (org-ref-list-index key bibtex-keys))
(setq
bad-citations
(append
bad-citations
`(,(format "%s [[elisp:(progn (switch-to-buffer-other-frame \"%s\")(goto-char %s))][not found here]]\n"
key
(buffer-name)
(plist-get plist :begin))))))))))
;; set with-affilates to t to get citations in a caption
nil nil nil t)
@@ -2950,12 +3156,13 @@ file. Makes a new buffer with clickable links."
(lambda (link)
(let ((plist (nth 1 link)))
(when (-contains? org-ref-cite-types (plist-get plist :type))
(dolist (key (org-ref-split-and-strip-string
(plist-get plist :path)))
(when (not (org-ref-list-index key bibtex-keys))
(goto-char (plist-get plist :begin))
(re-search-forward key)
(push (cons key (point-marker)) bad-citations))))))
(when (not (string= "*" (plist-get plist :path)))
(dolist (key (org-ref-split-and-strip-string
(plist-get plist :path)))
(when (not (org-ref-list-index key bibtex-keys))
(goto-char (plist-get plist :begin))
(re-search-forward key)
(push (cons key (point-marker)) bad-citations)))))))
;; add with-affiliates to get cites in caption
nil nil nil t)
(goto-char cp)
@@ -3537,6 +3744,53 @@ move to the beginning of the previous cite link after this one."
return i))
(goto-char (nth 1 (nth (- index 1) cps)))))))
(defvar org-ref-equation-environments
'("equation"
"equation*"
"align"
"align*"
"multline"
"multline*")
"LaTeX environments that should be treated as equations when referencing.")
(defvar org-ref-ref-type-inference-alist
'((org-ref-equation-label-p . "eqref"))
"Alist of predicate functions taking a label name and the
desired reference type if the predicate returns true.")
(defun org-ref-enclosing-environment (label)
"Returns the name of the innermost LaTeX environment containing
the first instance of the label, or nil of there is none."
(save-excursion
(save-restriction
(widen)
(goto-char (point-min))
(let ((label-point (search-forward (format "\\label{%s}" label) nil t)))
(when label-point
(catch 'return
(let (last-begin-point last-env)
(while (setq
last-begin-point (re-search-backward "\\\\begin{\\([^}]+\\)}" nil t)
last-env (match-string-no-properties 1))
(let ((env-end-point
(search-forward (format "\\end{%s}" last-env) nil t)))
(if (and env-end-point
(> env-end-point label-point))
(throw 'return last-env)
(goto-char last-begin-point)))))))))))
(defun org-ref-equation-label-p (label)
"Return non-nil if LABEL is an equation label."
(let ((maybe-env (org-ref-enclosing-environment label)))
(when maybe-env
(member maybe-env org-ref-equation-environments))))
(defun org-ref-infer-ref-type (label)
"Return inferred type for LABEL."
(or (cl-dolist (pred-pair org-ref-ref-type-inference-alist)
(when (funcall (car pred-pair) label)
(cl-return (eval (cdr pred-pair)))))
org-ref-default-ref-type))
;;** context around org-ref links
(defun org-ref-get-label-context (label)
@@ -3652,7 +3906,10 @@ move to the beginning of the previous cite link after this one."
(cond
;; cite links
((-contains? org-ref-cite-types type)
(message (org-ref-format-entry (org-ref-get-bibtex-key-under-cursor))))
(let ((key (org-ref-get-bibtex-key-under-cursor)))
(if (string= "*" key)
"*"
(message (org-ref-format-entry key)))))
;; message some context about the label we are referring to
((or (string= type "ref")

View File

@@ -72,6 +72,7 @@
(require 'org-element)
(require 'org-ref-utils)
(require 'ox)
(declare-function helm "helm")
(declare-function helm-build-sync-source "helm-source")
@@ -123,42 +124,128 @@ Typically:
(:name name :description description)
but there could be other :key value pairs."
(save-excursion
(goto-char (point-min))
(let (end-of-entry
data
(external (when (re-search-forward "\\loadglsentries\\(\\[.*\\]\\){\\(?1:.*\\)}" nil t)
(match-string 1)))
key value p1 p2)
(goto-char (point-min))
;; We may not find an entry if it is defined as an acronym
(when (re-search-forward
(format "\\newglossaryentry{%s}" entry) nil t)
(re-search-forward "{")
(save-excursion
(backward-char)
(or-find-closing-curly-bracket)
(setq end-of-entry (point)))
(catch 'data
;; look inside first for latex-headers
(goto-char (point-min))
(when (re-search-forward
(format "\\newglossaryentry{%s}" entry) nil t)
(re-search-forward "{")
(save-excursion
(backward-char)
(or-find-closing-curly-bracket)
(setq end-of-entry (point)))
(while (re-search-forward "\\(\\w+?\\)=" end-of-entry t)
(setq key (match-string 1))
;; get value
(goto-char (+ 1 (match-end 1)))
(setq p1 (point))
(if (looking-at "{")
;; value is wrapped in {}
(progn
(while (re-search-forward "\\(\\w+?\\)=" end-of-entry t)
(setq key (match-string 1))
;; get value
(goto-char (+ 1 (match-end 1)))
(setq p1 (point))
(if (looking-at "{")
;; value is wrapped in {}
(progn
(or-find-closing-curly-bracket)
(setq p2 (point)
value (buffer-substring (+ 1 p1) p2)))
;; value is up to the next comma
(re-search-forward "," end-of-entry 'mv)
(setq value (buffer-substring p1 (- (point) 1))))
;; remove #+latex_header_extra:
(setq value (replace-regexp-in-string
"#\\+latex_header_extra: " "" value))
(setq value (replace-regexp-in-string
"\n +" " " value))
(setq data (append data
(list (intern (format ":%s" key)))
(list value))))
(throw 'data data))
;; check for a glossary table
(let* ((entries (save-excursion
(catch 'found
(org-element-map
(org-element-parse-buffer)
'table
(lambda (el)
(when (string= "glossary" (org-element-property :name el))
(goto-char (org-element-property :contents-begin el))
(throw 'found
(nthcdr 2 (org-babel-read-table)))))))))
(result (assoc entry entries)))
(when result
(throw 'data (list :name (cl-second result) :description (cl-third result)))))
;; then external
(when (and external
(file-exists-p (concat external ".tex")))
(with-current-buffer (find-file-noselect (concat external ".tex"))
(goto-char (point-min))
(when (re-search-forward
(format "\\newglossaryentry{%s}" entry) nil t)
(re-search-forward "{")
(save-excursion
(backward-char)
(or-find-closing-curly-bracket)
(setq p2 (point)
value (buffer-substring (+ 1 p1) p2)))
;; value is up to the next comma
(re-search-forward "," end-of-entry 'mv)
(setq value (buffer-substring p1 (- (point) 1))))
;; remove #+latex_header_extra:
(setq value (replace-regexp-in-string
"#\\+latex_header_extra: " "" value))
(setq value (replace-regexp-in-string
"\n +" " " value))
(setq data (append data
(list (intern (format ":%s" key)))
(list value))))
data))))
(setq end-of-entry (point)))
(while (re-search-forward "\\(\\w+?\\)=" end-of-entry t)
(setq key (match-string 1))
;; get value
(goto-char (+ 1 (match-end 1)))
(setq p1 (point))
(if (looking-at "{")
;; value is wrapped in {}
(progn
(or-find-closing-curly-bracket)
(setq p2 (point)
value (buffer-substring (+ 1 p1) p2)))
;; value is up to the next comma
(re-search-forward "," end-of-entry 'mv)
(setq value (buffer-substring p1 (- (point) 1))))
(setq data (append data
(list (intern (format ":%s" key)))
(list value))))
(throw 'data data))))
;; and finally with an export in case there are includes
(let ((org-export-show-temporary-export-buffer nil))
(with-current-buffer (org-org-export-as-org)
(when (re-search-forward
(format "\\newglossaryentry{%s}" entry) nil t)
(re-search-forward "{")
(save-excursion
(backward-char)
(or-find-closing-curly-bracket)
(setq end-of-entry (point)))
(while (re-search-forward "\\(\\w+?\\)=" end-of-entry t)
(setq key (match-string 1))
;; get value
(goto-char (+ 1 (match-end 1)))
(setq p1 (point))
(if (looking-at "{")
;; value is wrapped in {}
(progn
(or-find-closing-curly-bracket)
(setq p2 (point)
value (buffer-substring (+ 1 p1) p2)))
;; value is up to the next comma
(re-search-forward "," end-of-entry 'mv)
(setq value (buffer-substring p1 (- (point) 1))))
;; remove #+latex_header_extra:
(setq value (replace-regexp-in-string
"#\\+latex_header_extra: " "" value))
(setq value (replace-regexp-in-string
"\n +" " " value))
(setq data (append data
(list (intern (format ":%s" key)))
(list value))))
(throw 'data data))))))))
;;;###autoload
@@ -179,6 +266,18 @@ Entry gets added after the last #+latex_header line."
(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."
(save-match-data
(cond
((or (not org-ref-show-broken-links)
(or-parse-glossary-entry label))
'org-ref-glossary-face)
(t
'font-lock-warning-face))))
;;** Glossary links
(defun or-follow-glossary (entry)
"Goto beginning of the glossary ENTRY."
@@ -195,7 +294,7 @@ Entry gets added after the last #+latex_header line."
(dolist (command org-ref-glossary-gls-commands)
(org-ref-link-set-parameters command
:follow #'or-follow-glossary
:face 'org-ref-glossary-face
:face 'org-ref-glossary-face-fn
:help-echo 'or-glossary-tooltip
:export (lambda (path _ format)
(cond
@@ -207,7 +306,7 @@ Entry gets added after the last #+latex_header line."
(org-ref-link-set-parameters "glslink"
:follow #'or-follow-glossary
:face 'org-ref-glossary-face
:face 'org-ref-glossary-face-fn
:help-echo 'or-glossary-tooltip
:export (lambda (path desc format)
(cond
@@ -278,12 +377,54 @@ Adds a tooltip to the link that is found."
nil)))))
;; ** exporting with a glossary table
(defun org-ref-glossary-before-parsing (backend)
"Function to preprocess a glossary table on export.
This assumes a table like
#+name: glossary
| label | name | description |
|-------+-------+---------------|
| tree | Tree | A woody plant |
| shrub | Shrub | A woody bush |
is in the org-buffer, and will add the relevant latex_header items if there is. The table is deleted in a copy of the buffer before the export.
This will run in `org-export-before-parsing-hook'."
(let* (begin
end
(entries (save-excursion
(catch 'found
(org-element-map
(org-element-parse-buffer)
'table
(lambda (el)
(when (and (org-element-property :name el)
(stringp (org-element-property :name el))
(string= "glossary" (org-element-property :name el)))
(setq begin (org-element-property :begin el)
end (org-element-property :end el))
(goto-char (org-element-property :contents-begin el))
(throw 'found
(nthcdr 2 (org-babel-read-table))))))))))
;; Delete the table
(when entries
(setf (buffer-substring begin end) "")
(goto-char (point-min))
(cl-loop for (label name description) in entries
do
(insert (format "#+latex_header_extra: \\newglossaryentry{%s}{name=%s,description={{%s}}}\n"
label name description))))))
(add-to-list 'org-export-before-parsing-hook 'org-ref-glossary-before-parsing)
;;* 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."
ABBRV is the abbreviated form.
FULL is the expanded acronym."
(interactive "sLabel: \nsAcronym: \nsFull name: ")
(save-excursion
(re-search-backward "#\\+latex_header" nil t)
@@ -299,20 +440,73 @@ FULL is the expanded acronym."
(defun or-parse-acronym-entry (label)
"Parse an acronym entry LABEL to a plist.
\(:abbrv abbrv :full full)
\(:abbrv abbrv :full full)
\newacronym{<label>}{<abbrv>}{<full>}"
(save-excursion
(let (abbrv full p1)
(goto-char (point-min))
(when
(re-search-forward (format "\\newacronym{%s}" label) nil t)
(setq p1 (+ 1 (point)))
(forward-list)
(setq abbrv (buffer-substring p1 (- (point) 1)))
(setq p1 (+ 1 (point)))
(forward-list)
(setq full (buffer-substring p1 (- (point) 1)))
(list :abbrv abbrv :full full)))))
(goto-char (point-min))
(let (abbrv
full p1
(external (when (re-search-forward "\\loadglsentries\\(\\[.*\\]\\){\\(?1:.*\\)}" nil t)
(match-string 1))))
(catch 'data
(goto-char (point-min))
;; check in the definitions of newacronym
(when (re-search-forward (format "\\newacronym{%s}" label) nil t)
(setq p1 (+ 1 (point)))
(forward-list)
(setq abbrv (buffer-substring p1 (- (point) 1)))
(setq p1 (+ 1 (point)))
(forward-list)
(setq full (buffer-substring p1 (- (point) 1)))
(throw 'data
(list :abbrv abbrv :full full)))
;; look for acronyms table
(let* ((entries (save-excursion
(catch 'found
(org-element-map
(org-element-parse-buffer)
'table
(lambda (el)
(when (string= "acronyms" (org-element-property :name el))
(setq begin (org-element-property :begin el)
end (org-element-property :end el))
(goto-char (org-element-property :contents-begin el))
(throw 'found
(nthcdr 2 (org-babel-read-table)))))))))
(result (assoc label entries)))
(when result
(throw 'data (list :abbrv (cl-second result) :full (cl-third result)))))
;; look external
(when (and external
(file-exists-p (concat external ".tex")))
(with-current-buffer (find-file-noselect (concat external ".tex"))
(goto-char (point-min))
(when (re-search-forward (format "\\newacronym{%s}" label) nil t)
(setq p1 (+ 1 (point)))
(forward-list)
(setq abbrv (buffer-substring p1 (- (point) 1)))
(setq p1 (+ 1 (point)))
(forward-list)
(setq full (buffer-substring p1 (- (point) 1)))
(throw 'data
(list :abbrv abbrv :full full)))))
;; This should be a last resort, as it involves an export
;; but, it supports #+include
;; I think these will only show as the latex header because of the export
(let ((org-export-show-temporary-export-buffer nil))
(with-current-buffer (org-org-export-as-org)
(when (re-search-forward (format "\\newacronym{%s}" label) nil t)
(setq p1 (+ 1 (point)))
(forward-list)
(setq abbrv (buffer-substring p1 (- (point) 1)))
(setq p1 (+ 1 (point)))
(forward-list)
(setq full (buffer-substring p1 (- (point) 1)))
(throw 'data
(list :abbrv abbrv :full full)))))))))
;;** Acronym links
(defun or-follow-acronym (label)
@@ -336,7 +530,7 @@ FULL is the expanded acronym."
(dolist (mapping org-ref-glossary-acr-commands-mapping)
(org-ref-link-set-parameters (car mapping)
:follow #'or-follow-acronym
:face 'org-ref-acronym-face
:face 'org-ref-acronym-face-fn
:help-echo 'or-acronym-tooltip
:export (lambda (path _ format)
(cond
@@ -352,6 +546,17 @@ FULL is the expanded acronym."
"Face for acronym links.")
(defun org-ref-acronym-face-fn (label)
"Return a face for an acronym link."
(save-match-data
(cond
((or (not org-ref-show-broken-links)
(or-parse-acronym-entry label))
'org-ref-acronym-face)
(t
'font-lock-warning-face))))
(defun or-acronym-tooltip (_window _object position)
"Return tooltip for the acronym entry.
The entry is in WINDOW and OBJECT at POSITION.
@@ -401,6 +606,48 @@ WINDOW and OBJECT are ignored."
(goto-char limit)
nil))))))
;; ** Exporting with an acronym table
(defun org-ref-acronyms-before-parsing (backend)
"Function to preprocess a glossary table on export.
This assumes a table like
#+name: acronyms
| Key | Short | Long |
|------+-------+--------------------------------|
| mimo | | multiple-input multiple output |
| qos | QoS | quality-of-service |
| bb | BB | branch and bound |
is in the org-buffer, and will add the relevant latex_header items if there is. The table is deleted in a copy of the buffer before the export.
This will run in `org-export-before-parsing-hook'."
(let* (begin
end
(entries (save-excursion
(catch 'found
(org-element-map
(org-element-parse-buffer)
'table
(lambda (el)
(when (and (org-element-property :name el)
(stringp (org-element-property :name el))
(string= "acronyms" (org-element-property :name el)))
(setq begin (org-element-property :begin el)
end (org-element-property :end el))
(goto-char (org-element-property :contents-begin el))
(throw 'found
(nthcdr 2 (org-babel-read-table))))))))))
(when entries
;; Delete the table
(setf (buffer-substring begin end) "")
(goto-char (point-min))
(cl-loop for (label name description) in entries
do
(insert (format "#+latex_header_extra: \\newacronym{%s}{%s}{%s}\n"
label name description))))))
(add-to-list 'org-export-before-parsing-hook 'org-ref-acronyms-before-parsing)
;; * Helm command to insert entries
;;;###autoload

View File

@@ -111,11 +111,25 @@ The cdr of the the cons cell is the function to use."
org-ref-cite-onclick-function 'org-ref-cite-click-helm)
;;* Helm bibtex setup.
(setq bibtex-completion-additional-search-fields '(keywords))
(defcustom org-ref-bibtex-completion-add-keywords-field t
"Whether to add the `keywords' field to bibtex-completion."
:group 'org-ref
:type 'boolean)
(setq bibtex-completion-display-formats
'((t . "${author:36} ${title:*} ${year:4} ${=has-pdf=:1}${=has-note=:1} ${=type=:7} ${keywords:31}")))
;;* Helm bibtex setup.
(when org-ref-bibtex-completion-add-keywords-field
(unless (or (member 'keywords bibtex-completion-additional-search-fields)
(member "keywords" bibtex-completion-additional-search-fields))
;; Both symbol and string values are accepted, but b-c-a-s-f's
;; Custom :type specifies string.
(push "keywords" bibtex-completion-additional-search-fields))
(let ((display-format
(alist-get t bibtex-completion-display-formats)))
(unless (string-match-p "{keywords:"
display-format)
(setf (alist-get t bibtex-completion-display-formats)
(concat display-format " ${keywords:31}")))))
(defun bibtex-completion-copy-candidate (_candidate)
"Copy the selected bibtex entries to the clipboard.

View File

@@ -606,6 +606,7 @@ Checks for pdf and doi, and add appropriate functions."
`(("WOS" . org-ref-wos-at-point)
("Related articles in WOS" . org-ref-wos-related-at-point)
("Citing articles in WOS" . org-ref-wos-citing-at-point)
("ADS" . org-ref-ads-at-point)
("Google Scholar" . org-ref-google-scholar-at-point)
("Pubmed" . org-ref-pubmed-at-point)
("Crossref" . org-ref-crossref-at-point))))

View File

@@ -50,7 +50,7 @@ instead of a label."
(org-open-link-from-string
(format "ref:%s" label)))))
,(helm-build-dummy-source "Create new label"
:action (lambda (label)
:action (lambda (label)
(with-helm-current-buffer
(if helm-current-prefix-arg
(insert (concat "<<" label ">>"))
@@ -117,7 +117,7 @@ Use a double \\[universal-argument] \\[universal-argument] to insert a
;; insert a new link
(insert
(concat
org-ref-default-ref-type ":" label))
(org-ref-infer-ref-type label) ":" label))
)))
;; one prefix, alternate ref link
((equal helm-current-prefix-arg '(4))
@@ -133,7 +133,7 @@ Use a double \\[universal-argument] \\[universal-argument] to insert a
(format "[[#%s]]" label)))))))))))
;;;###autoload
(defun org-ref ()
(defun org-ref-helm ()
"Opens a helm interface to actions for `org-ref'.
Shows bad citations, ref links and labels.
This widens the file so that all links go to the right place."
@@ -345,7 +345,7 @@ at the end of you file.
;; unreference labels
(let ((refs (org-element-map (org-element-parse-buffer) 'link
(lambda (el)
(lambda (el)
(when (or (string= "ref" (org-element-property :type el))
(string= "eqref" (org-element-property :type el))
(string= "pageref" (org-element-property :type el))

View File

@@ -232,7 +232,7 @@ This uses a citeproc library."
(defun or-ivy-bibtex-copy-formatted-citation (entry)
"Copy formatted citation to clipboard for ENTRY."
(kill-new (org-ref-format-entry entry)))
(kill-new (org-ref-format-entry (cdr (assoc "=key=" entry)))))
(defun or-ivy-bibtex-add-entry (_)
@@ -462,11 +462,10 @@ Use a prefix arg to select the ref type."
(t
(insert
(or (when (looking-at "$") " ") "")
(concat org-ref-default-ref-type
(concat (org-ref-infer-ref-type label)
":"
label))))))
(require 'hydra)
(setq hydra-is-helpful t)

View File

@@ -40,6 +40,13 @@
(declare-function org-ref-bibtex-key-from-doi "org-ref-bibtex.el")
;; See https://github.com/jkitchin/org-ref/issues/812
;; apparently there is a function name change coming in
;; (if (and (not (fboundp 'dnd-unescape-uri))
;; (fboundp 'dnd--escape-uri))
;; (defalias 'dnd-unescape-uri 'dnd--unescape-uri)
;; (warn "dnd-unescape-uri is undefined. Some things may not work."))
(defgroup org-ref-pdf nil
"Customization group for org-ref-pdf"
:tag "Org Ref PDF"
@@ -272,7 +279,8 @@ variable `org-ref-pdf-doi-regex'."
"Lookup highlighted text in PDFView in CrossRef."
(interactive)
(require 'pdf-view)
(pdf-view-assert-active-region)
(unless (pdf-view-active-region-p)
(error "The region is not active"))
(let* ((txt (pdf-view-active-region-text)))
(pdf-view-deactivate-region)
(crossref-lookup (mapconcat 'identity txt " \n"))))

View File

@@ -1,4 +1,4 @@
(define-package "org-ref" "20200624.1342" "citations, cross-references and bibliographies in org-mode"
(define-package "org-ref" "20210108.1415" "citations, cross-references and bibliographies in org-mode"
'((dash "2.11.0")
(htmlize "1.51")
(helm "1.5.5")
@@ -9,12 +9,12 @@
(s "1.10.0")
(f "0.18.0")
(pdf-tools "0.7"))
:commit "b05d6b443494cc251d2f11a882a8b27fb8f7baf6" :keywords
'("org-mode" "cite" "ref" "label")
:authors
:commit "cae67aa7fcaced2112152a343d35ff308a54c4c1" :authors
'(("John Kitchin" . "jkitchin@andrew.cmu.edu"))
:maintainer
'("John Kitchin" . "jkitchin@andrew.cmu.edu")
:keywords
'("org-mode" "cite" "ref" "label")
:url "https://github.com/jkitchin/org-ref")
;; Local Variables:
;; no-byte-compile: t

View File

@@ -55,6 +55,15 @@
(eval-when-compile
(require 'cl-lib))
;; See https://github.com/jkitchin/org-ref/issues/812
;; apparently there is a function name change coming in
;; (if (and (not (fboundp 'dnd-unescape-uri))
;; (fboundp 'dnd--escape-uri))
;; (defalias 'dnd-unescape-uri 'dnd--unescape-uri)
;; (warn "dnd-unescape-uri is undefined. Some things may not work."))
(defgroup org-ref-url nil
"Customization group for org-ref-url-utils"
:tag "Org Ref URL"
@@ -393,9 +402,11 @@ one in the minibuffer."
org-ref-url-bibtex-template)
'aget alist)))
(goto-char (point-max))
;; Place new entry one line after the last entry.
(while (not (looking-back "^}\n" 2))
(delete-char -1))
;; Place new entry one line after the last entry. Sometimes we are in a
;; new file though, in which case we don't want to do this.
(unless (bobp)
(while (not (looking-back "^}\n" 2))
(delete-char -1)))
(insert "\n")
(insert (if (require 'org-cliplink nil 'noerror)
;; Sanitize values by replacing html entities

View File

@@ -21,9 +21,14 @@
;;; Commentary:
;;
(eval-when-compile
(require 'cl-lib))
(require 'org)
(require 'org-ref-pdf) ; for pdftotext-executable
(defcustom org-ref-bib-html "<h1 class='org-ref-bib-h1'>Bibliography</h1>\n"
"HTML header to use for bibliography in HTML export."
:type 'string
@@ -75,10 +80,16 @@ Copies the string to the clipboard."
(setq git-commit
;; If in git, get current commit
(let ((default-directory org-ref-dir))
(when (= 0 (shell-command "git rev-parse --git-dir"))
(s-trim (shell-command-to-string "git rev-parse HEAD")))))
(when (and
;; this is tricky, as a submodule, .git is a file
(or (file-directory-p ".git") (file-exists-p ".git"))
(= 0 (shell-command "git rev-parse --git-dir")))
(format "%s in %s"
(s-trim (shell-command-to-string "git rev-parse HEAD"))
(s-trim (shell-command-to-string "git rev-parse --show-toplevel"))))))
(setq version-string (format "org-ref: Version %s%s" org-version
(setq version-string (format "org-ref: Version %s%s"
org-version
(if git-commit
(format " (git-commit %s)" git-commit)
"")))
@@ -153,6 +164,8 @@ ${org-latex-pdf-process}
("org-ref-default-bibliography" . ,(format "%s" org-ref-default-bibliography))
("ordb-p" . ,(format "%s" (mapcar 'file-exists-p org-ref-default-bibliography)))
("ordb-listp" . ,(ords (listp org-ref-default-bibliography)))
("orbn-p" . ,(when org-ref-bibliography-notes
(file-exists-p org-ref-bibliography-notes)))
("org-ref-pdf-directory" . ,(format "%s" org-ref-pdf-directory))
("orpd-p" . ,(format "%s" (file-exists-p org-ref-pdf-directory)))
("org-ref-location" . ,(format "%s" (locate-library "org-ref")))
@@ -217,8 +230,8 @@ It is also possible to access all other BibTeX database fields:
%D doi
%S series %N note
%f pdf filename
%F absolute pdf filename
%f pdf filename (key.pdf)
%F absolute pdf filename (returned from `org-ref-get-pdf-filename-function')
Usually, only %l is needed. The other stuff is mainly for the echo area
display, and for (setq reftex-comment-citations t).
@@ -272,7 +285,10 @@ environment, only %l is available."
(or n 2)))
((= l ?E) (car (reftex-get-bib-names "editor" entry)))
((= l ?f) (concat (org-ref-reftex-get-bib-field "=key=" entry) ".pdf"))
((= l ?F) (concat org-ref-pdf-directory (org-ref-reftex-get-bib-field "=key=" entry) ".pdf"))
((= l ?F) (funcall org-ref-get-pdf-filename-function
(org-ref-reftex-get-bib-field "=key=" entry)))
((= l ?h) (org-ref-reftex-get-bib-field "howpublished" entry))
((= l ?i) (org-ref-reftex-get-bib-field "institution" entry))
((= l ?j) (let ((jt (reftex-get-bib-field "journal" entry)))
@@ -568,6 +584,14 @@ directory. You can also specify a new file."
;;**** functions that operate on key at point for click menu
;;;###autoload
(defun org-ref-ads-at-point ()
"Open the doi in ADS for bibtex key under point."
(interactive)
(doi-utils-ads (org-ref-get-doi-at-point)))
;;;###autoload
(defun org-ref-wos-at-point ()
"Open the doi in wos for bibtex key under point."
@@ -716,7 +740,7 @@ generated by `org-ref-reftex-format-citation'."
;; Remove empty volume, number field if empty
(setq entry-html (replace-regexp-in-string "<b></b>," "" entry-html))
;; get rid of empty link and doi
(setq entry-html (replace-regexp-in-string " <a href=\"\">link</a>\\." "" entry-html))
(setq entry-html (replace-regexp-in-string " <a href=\"\">\\(link\\)?</a>\\.?" "" entry-html))
;; change double dash to single dash
(setq entry-html (replace-regexp-in-string "--" "-" entry-html))
(setq entry-html (replace-regexp-in-string " <a href=\"http://dx\\.doi\\.org/\">doi</a>\\." "" entry-html))
@@ -912,5 +936,447 @@ if FORCE is non-nil reparse the buffer no matter what."
org-ref-parse-buffer-cache))))
;; * org-ref command
(defun org-ref ()
"Check the current org-buffer for potential issues."
(interactive)
(let* ((buf (get-buffer-create "*org-ref*"))
(cb (current-buffer))
(fname (buffer-file-name))
;; Check if elc is ok before anything else because if it is not, it
;; causes problems in org-ref.
(elc-ok (let* ((org-ref-el (concat
(file-name-sans-extension
(locate-library "org-ref"))
".el"))
(orel-mod)
(org-ref-elc (concat
(file-name-sans-extension
(locate-library "org-ref"))
".elc"))
(orelc-mod)
(elc-version))
(when (file-exists-p org-ref-el)
(setq orel-mod (file-attribute-modification-time (file-attributes org-ref-el))))
(when (file-exists-p org-ref-elc)
(setq orelc-mod (file-attribute-modification-time (file-attributes org-ref-elc))))
(with-current-buffer buf
(read-only-mode -1)
(erase-buffer)
(org-mode)
(insert (format "#+title: org-ref report on [[%s][%s]]\n\n" (buffer-file-name cb) (buffer-name cb)))
(insert (format "org-ref called from %s" (buffer-file-name cb)))
(unless (time-less-p orel-mod orelc-mod)
(insert (format "org-ref.elc (%s) is older than org-ref.el (%s). That is probably not right. Please delete %s.\n"
(format-time-string "%Y-%m-%d %H:%M:%S" orelc-mod)
(format-time-string "%Y-%m-%d %H:%M:%S" orel-mod)
org-ref-elc))
(insert (format "- load-prefer-newer = %s\n" load-prefer-newer))
(insert (format " consider
- deleting %s
- [[elisp:(delete-file \"%s\")]]
- add (setq load-prefer-newer t) to your init files
- using https://github.com/emacscollective/auto-compile.\n" org-ref-elc org-ref-elc))
;; Check for byte-compiling compatibility with current emacs
(when (and org-ref-elc
(file-exists-p org-ref-elc))
(setq elc-version (with-temp-buffer
(insert-file-contents org-ref-elc)
(goto-char (point-min))
(when (re-search-forward ";;; in Emacs version \\([0-9]\\{2\\}\\.[0-9]+\\)"
nil t)
(match-string 1))))
(unless (string= elc-version
(format "%s.%s" emacs-major-version emacs-minor-version))
(insert (format "%s compiled with Emacs %s but you are running %s.%s. That could be a problem.\n"
elc-version emacs-major-version emacs-minor-version))))))))
(bad-citations (org-ref-bad-cite-candidates))
(bad-refs (org-ref-bad-ref-candidates))
(bad-labels (org-ref-bad-label-candidates))
(bad-files (org-ref-bad-file-link-candidates))
(bib-candidates '())
(unreferenced-labels '())
natbib-required
natbib-used
cleveref-required
cleveref-used
biblatex-required
biblatex-used
mbuffer
mchar
(org-latex-prefer-user-labels (and (boundp 'org-latex-prefer-user-labels)
org-latex-prefer-user-labels)))
;; See if natbib, biblatex or cleveref are required
(org-element-map (org-element-parse-buffer) 'link
(lambda (link)
(when (member (org-element-property :type link) org-ref-natbib-types)
(setq natbib-required t))
(when (member (org-element-property :type link) org-ref-biblatex-types)
(setq biblatex-required t))
(when (member (org-element-property :type link) '("cref" "Cref"))
(setq cleveref-required t)))
nil t)
;; See if natbib is probably used. This will miss a case where natbib is included somehow.
(setq natbib-used
(or
(member "natbib" (mapcar (lambda (x) (when (listp x) (nth 1 x))) org-latex-default-packages-alist))
(member "natbib" (mapcar (lambda (x) (when (listp x) (nth 1 x))) org-latex-packages-alist))
;; see of something like \usepackage{natbib} exists.
(save-excursion
(goto-char (point-min))
(re-search-forward "{natbib}" nil t))))
(setq biblatex-used
(or
(member "biblatex" (mapcar (lambda (x) (when (listp x) (nth 1 x))) org-latex-default-packages-alist))
(member "biblatex" (mapcar (lambda (x) (when (listp x) (nth 1 x))) org-latex-packages-alist))
;; see of something like \usepackage{biblatex} exists.
(save-excursion
(goto-char (point-min))
(re-search-forward "{biblatex}" nil t))))
(setq cleveref-used
(or
(member "cleveref" (mapcar (lambda (x) (when (listp x) (nth 1 x))) org-latex-default-packages-alist))
(member "cleveref" (mapcar (lambda (x) (when (listp x) (nth 1 x))) org-latex-packages-alist))
;; see of something like \usepackage{cleveref} exists.
(save-excursion
(goto-char (point-min))
(re-search-forward "{cleveref}" nil t))))
;; setup bib-candidates. This checks a variety of things in the
;; bibliography, bibtex files. check for which bibliographies are used
(cl-loop for bibfile in (org-ref-find-bibliography)
do
(let ((bibdialect))
(with-current-buffer (find-file-noselect bibfile)
(setq bibdialect bibtex-dialect))
(cl-pushnew
(format "[[%s]] (dialect = %s)\n" bibfile bibdialect)
bib-candidates)))
;; Check bibliography style exists
(save-excursion
(goto-char 0)
(unless (re-search-forward "bibliographystyle:\\|\\\\bibliographystyle{" nil t)
(cl-pushnew
"No bibliography style found. This may be ok, if your latex class style sets that up, but if not this is an error. Try adding something like:
bibliographystyle:unsrt
at the end of your file.\n"
bib-candidates)))
;; Check if latex knows of the bibliographystyle. We only check links here.
;; I also assume this style exists as a bst file that kpsewhich can find.
(save-excursion
(goto-char 0)
(when (re-search-forward "bibliographystyle:" nil t)
;; on a link. get style
(let ((path (org-element-property :path (org-element-context))))
(unless (= 0 (shell-command (format "kpsewhich %s.bst" path)))
(cl-pushnew
(format "bibliographystyle \"%s\" may be unknown" path)
bib-candidates)))))
;; check for multiple bibliography links
(let* ((bib-links (-filter
(lambda (el)
(string= (org-element-property :type el) "bibliography"))
(org-element-map (org-element-parse-buffer) 'link 'identity)))
(n-bib-links (length bib-links)))
(when (> n-bib-links 1)
(mapc (lambda (link)
(setq
bib-candidates
(append
bib-candidates
(list (format "Multiple bibliography link: %s"
(org-element-property :raw-link link))))))
bib-links)))
;; Check for bibliography files existence.
(mapc (lambda (bibfile)
(unless (file-exists-p bibfile)
(cl-pushnew
(format "%s does not exist." bibfile)
bib-candidates)))
(org-ref-find-bibliography))
;; check for spaces in bibliography
(let ((bibfiles (mapcar 'expand-file-name
(org-ref-find-bibliography))))
(mapc (lambda (bibfile)
(when (string-match " " bibfile)
(cl-pushnew
(format "One or more spaces found in path to %s. No spaces are allowed in bibtex file paths. We recommend replacing them with -. Underscores usually cause other problems." bibfile)
bib-candidates)))
bibfiles))
;; validate bibtex files
(let ((bibfiles (mapcar 'expand-file-name
(org-ref-find-bibliography))))
(mapc
(lambda (bibfile)
(unless (with-current-buffer
(find-file-noselect bibfile)
(bibtex-validate))
(cl-pushnew
(format "Invalid bibtex file found. [[file:%s]]" bibfile)
bib-candidates)))
bibfiles)
;; check types
(mapc
(lambda (bibfile)
(with-current-buffer
(find-file-noselect bibfile)
(goto-char (point-min))
(while (re-search-forward "^@\\(.*\\){" nil t)
(unless (member (s-trim (downcase (match-string 1)))
(cdr (assoc bibtex-dialect
(list
(cons 'BibTeX (mapcar (lambda (e) (downcase (car e)))
bibtex-BibTeX-entry-alist))
(cons 'biblatex (mapcar (lambda (e) (downcase (car e)))
bibtex-biblatex-entry-alist))))))
(cl-pushnew
(format "Invalid bibtex entry type (%s) found in [[file:%s::%s]]" (match-string 1)
bibfile (line-number-at-pos))
bib-candidates)))))
bibfiles))
;; unreferenced labels
(save-excursion
(save-restriction
(widen)
(goto-char (point-min))
(let ((matches '()))
;; these are the org-ref label:stuff kinds
(while (re-search-forward
"[^#+]label:\\([a-zA-Z0-9:-]*\\)" nil t)
(cl-pushnew (cons
(match-string-no-properties 1)
(point))
matches))
;; now add all the other kinds of labels.
;; #+label:
(save-excursion
(goto-char (point-min))
(while (re-search-forward "^#\\+label:\\s-+\\(.*\\)\\b" nil t)
;; do not do this for tables. We get those in `org-ref-get-tblnames'.
;; who would have thought you have save match data here? Trust me. When
;; I wrote this, you did.
(unless (save-match-data (equal (car (org-element-at-point)) 'table))
(cl-pushnew (cons (match-string-no-properties 1) (point)) matches))))
;; \label{}
(save-excursion
(goto-char (point-min))
(while (re-search-forward "\\\\label{\\([a-zA-Z0-9:-]*\\)}"
nil t)
(cl-pushnew (cons (match-string-no-properties 1) (point)) matches)))
;; #+tblname: and actually #+label
(cl-loop for cell in (org-element-map (org-element-parse-buffer 'element) 'table
(lambda (table)
(cons (org-element-property :name table)
(org-element-property :begin table))))
do
(cl-pushnew cell matches))
;; CUSTOM_IDs
(org-map-entries
(lambda ()
(let ((custom_id (org-entry-get (point) "CUSTOM_ID")))
(when (not (null custom_id))
(cl-pushnew (cons custom_id (point)) matches)))))
(goto-char (point-min))
(while (re-search-forward "^#\\+name:\\s-+\\(.*\\)" nil t)
(cl-pushnew (cons (match-string 1) (point)) matches))
;; unreference labels
(let ((refs (org-element-map (org-element-parse-buffer) 'link
(lambda (el)
(when (or (string= "ref" (org-element-property :type el))
(string= "eqref" (org-element-property :type el))
(string= "pageref" (org-element-property :type el))
(string= "nameref" (org-element-property :type el))
(string= "autoref" (org-element-property :type el))
(string= "cref" (org-element-property :type el))
(string= "Cref" (org-element-property :type el)))
(org-element-property :path el))))))
(cl-loop for (label . p) in matches
do
(when (and label (not (-contains? refs label)))
(cl-pushnew
(cons label (set-marker (make-marker) p))
unreferenced-labels)))))))
(with-current-buffer buf
(when bad-citations
(insert "* Bad citations\n")
(cl-loop for (key . marker) in bad-citations
do
(setq mbuffer (buffer-name (marker-buffer marker))
mchar (marker-position marker))
(insert (format "- [[elisp:(progn (switch-to-buffer %S) (goto-char %S)(org-show-entry))][%s]]\n"
mbuffer mchar key))))
(when bad-refs
(insert "\n* Bad ref links\n")
(cl-loop for (key . marker) in bad-refs
do
(setq mbuffer (buffer-name (marker-buffer marker))
mchar (marker-position marker))
(insert (format "- [[elisp:(progn (switch-to-buffer %S) (goto-char %S)(org-show-entry))][%s]]\n"
mbuffer mchar key))))
(when bad-labels
(insert "\n* Multiply defined label links\n")
(cl-loop for (key . marker) in bad-labels
do
(setq mbuffer (buffer-name (marker-buffer marker))
mchar (marker-position marker))
(insert (format "- [[elisp:(progn (switch-to-buffer %S) (goto-char %S)(org-show-entry))][%s]]\n"
mbuffer mchar key))))
(when unreferenced-labels
(insert "\n* Unreferenced label links\n")
(cl-loop for (key . marker) in unreferenced-labels
when (not (string= key ""))
do
(setq mbuffer (buffer-name (marker-buffer marker))
mchar (marker-position marker))
(insert (format "- [[elisp:(progn (switch-to-buffer %S) (goto-char %S)(org-show-entry))][%s]]\n"
mbuffer mchar key))))
(when bib-candidates
(insert "\n* Bibliography\n")
(cl-loop for candidate in bib-candidates
do
(insert (format "- %s" candidate))))
(insert "\n* Miscellaneous\n")
(cl-loop for s in `(,(format "org-latex-prefer-user-labels = %s"
org-latex-prefer-user-labels)
,(format "bibtex-dialect = %s" bibtex-dialect)
,(format "biblatex is%srequired." (if biblatex-required " " " not "))
,(format "biblatex is%sused." (if biblatex-used " " " not "))
,(format "emacs-version = %s" (emacs-version))
,(format "org-version = %s" (org-version))
,(org-ref-version)
,(format "org-ref.el installed at %s" (concat
(file-name-sans-extension
(locate-library "org-ref"))
".el"))
,(format "completion backend = %s" org-ref-completion-library)
,(format "org-ref-insert-cite-function = %s" org-ref-insert-cite-function)
,(format "org-ref-insert-label-function = %s" org-ref-insert-label-function)
,(format "org-ref-insert-ref-function = %s" org-ref-insert-ref-function)
,(format "org-ref-cite-onclick-function = %s" org-ref-cite-onclick-function)
,(format "org-ref-default-bibliography = %S" org-ref-default-bibliography)
,(format "org-ref-default-bibliography is a list = %S" (listp org-ref-default-bibliography))
,(format "org-latex-pdf-process is defined as %s" org-latex-pdf-process)
,(format "natbib is%srequired." (if natbib-required " " " not "))
,(format "natbib is%sin %s or %s."
(if natbib-used " " " not ")
(propertize "org-latex-default-packages-alist"
'help-echo (format "%S" (mapconcat
(lambda (s)
(format "%s" s))
org-latex-default-packages-alist
"\n"))
'font-lock-face '(:foreground "red3"))
(propertize "org-latex-packages-alist"
'help-echo (format "%S" (mapconcat
(lambda (s)
(format "%s" s))
org-latex-packages-alist
"\n"))
'font-lock-face '(:foreground "red3")))
,(format "cleveref is%srequired." (if cleveref-required " " " not "))
,(format "cleveref is%sin %s or %s."
(if cleveref-used " " " not ")
(propertize "org-latex-default-packages-alist"
'help-echo (format "%S" (mapconcat
(lambda (s)
(format "%s" s))
org-latex-default-packages-alist
"\n"))
'font-lock-face '(:foreground "red3"))
(propertize "org-latex-packages-alist"
'help-echo (format "%S" (mapconcat
(lambda (s)
(format "%s" s))
org-latex-packages-alist
"\n"))
'font-lock-face '(:foreground "red3"))))
do
(insert "- " s "\n"))
(insert (format "- org-latex-default-packages-alist\n"))
(cl-loop for el in org-latex-default-packages-alist
do
(insert (format " %S\n" el)))
(if (null org-latex-packages-alist)
(insert "- org-latex-packages-alist is nil\n")
(insert "- org-latex-packages-alist\n")
(cl-loop for el in org-latex-packages-alist
do
(insert (format " %S\n" el))))
(insert (format "- ox-bibtex loaded = %s\n" (featurep 'ox-bibtex)))
(insert (format "- ox-bibtex loaded after org-ref = %s\n"
(let ((org-ref-i (seq-position load-history (assoc (locate-library "org-ref") load-history)) )
(ox-bibtex-i (seq-position load-history (assoc (locate-library "ox-bibtex") load-history))))
(and org-ref-i ox-bibtex-i
(> org-ref-i ox-bibtex-i)))))
(insert "- cite link definition:\n" (pp (assoc "cite" org-link-parameters)))
(insert "* LaTeX setup\n\n")
(cl-loop for executable in '("latex" "pdflatex" "bibtex" "biblatex"
"makeindex" "makeglossaries")
do
(insert (format "%s is installed at %s" executable (executable-find executable))))
(insert "\n* Warnings\n")
(if (get-buffer "*Warnings*")
(cl-loop for line in (s-split "\n" (with-current-buffer "*Warnings*"
(buffer-string)))
if (s-starts-with? "Warning (org-ref):" line)
do
(insert " - " line "\n"))
(insert "- No (org-ref) Warnings found."))
(insert (format "\n* Utilities
- [[elisp:(progn (find-file %S) (ispell))][Spell check document]]
- [[elisp:(progn (find-file %S) (org-ref))][recheck document with org-ref]]
" fname fname))
(goto-char (point-min))
;; (setq header-line-format "Press q to quit.")
;; (local-set-key "q"
;; #'(lambda ()
;; (interactive)
;; (delete-window)))
(read-only-mode))
(display-buffer-in-side-window buf '((side . right)))))
(provide 'org-ref-utils)
;;; org-ref-utils.el ends here

View File

@@ -83,7 +83,7 @@ index:cite
org-ref uses the [[bibliography link]] to determine which bibtex files to get citations from, and falls back to the bibtex files defined in the variable ~reftex-default-bibliography~ or ~org-ref-default-bibliography~ if no bibliography link is found. Note that you *must* include a [[bibliography link]] in your document if you are exporting your document to pdf; ~org-ref-default-bibliography~ is not used by the [[BibTeX users][LaTeX exporter]].
For simple citation needs, org-ref is simple to use. At the point you want to insert a citation, you select the "Org -> org-ref -> Insert citation" menu (or use the key-binding ~C-c ]~ by default), select the reference(s) you want in the helm-bibtex buffer and press enter. The citation will be inserted automatically into your org-file. You "select" an entry by using the arrow keys (or ~C-n~ and ~C-p~) to move up and down to the entry you want. You can also narrow the selection by typing a pattern to match, e.g. author name, title words, year, BibTeX key and entry types. For any other field (e.g. keywords), you will need to add it to the variable ~bibtex-completion-additional-search-fields~. You can select multiple entries by pressing ~C-SPC~ to mark entries in the helm-bibtex buffer.
For simple citation needs, org-ref is simple to use. At the point you want to insert a citation, you select the "Org -> org-ref -> Insert citation" menu (or use the key-binding ~C-c ]~ by default), select the reference(s) you want in the helm-bibtex buffer and press enter. The citation will be inserted automatically into your org-file. You "select" an entry by using the arrow keys (or ~C-n~ and ~C-p~) to move up and down to the entry you want. You can also narrow the selection by typing a pattern to match, e.g. author name, title words, year, BibTeX key and entry types. If you want to match any other field, you need to add it to the variable ~bibtex-completion-additional-search-fields~; org-ref [[id:5d7a19d3-0411-4964-9154-99af4f281015][does this automatically]] for the ~keywords~ field. You can select multiple entries by pressing ~C-SPC~ to mark entries in the helm-bibtex buffer.
If the cursor is on a citation key, you should see a message in the minibuffer that summarizes which citation it refers to. If you click on a key, you should see a helm selection buffer with some actions to choose, including opening the bibtex entry, opening/getting a pdf for the entry, searching the entry in Web of Science, etc...
@@ -262,12 +262,19 @@ Org-ref can also be configured to show bad label,ref and cite links by setting t
This may be slow in large files, so you can turn it off by setting that variable to nil.
** org-ref customization of helm-bibtex
:PROPERTIES:
:ID: 5d7a19d3-0411-4964-9154-99af4f281015
:END:
index:helm-bibtex
org-ref adds a few new features to helm-bibtex. First, we add keywords as a searchable field. Second, org-ref modifies the helm-bibtex search buffer to include the keywords. Since keywords now can have a central role in searching, we add some functionality to add keywords from the helm-bibtex buffer as a new action.
org-ref adds a few new features to helm-bibtex.
First, we add =keywords= as a searchable field, and modify the helm-bibtex search buffer to include the keywords. Since keywords now can have a central role in searching, we add some functionality to add keywords from the helm-bibtex buffer as a new action.
We change the order of the actions in helm-bibtex to suit our work flow, and add some new actions as well. We define a format function for org-mode that is compatible with the usage defined in section [[#citations]]. Finally, we add some new fallback options for additional scientific search engines.
The =keywords= field is added onto the existing value, such that existing customization wouldnt be lost; if you still prefer to add the field yourself, set ~org-ref-bibtex-completion-add-keywords-field~ to nil before loading org-ref.
** Some basic org-ref utilities
[[index:bibtex!clean entry]]
@@ -862,7 +869,7 @@ You will have to incorporate running makeindex into your PDF build command.
This is not supported in anything but LaTeX export.
*** Glossaries
*** Glossaries and acronyms
index:glossary
org-ref provides some support for glossary and acronym definitions.
@@ -874,7 +881,11 @@ org-ref provides some support for glossary and acronym definitions.
- glssymbol :: The symbol term
- glsdesc :: The description of the term
- acrshort :: Short version of the acroynm
- ac :: a reference to an acronym
- Ac :: capitalized reference to an acronym
- acp :: a plural reference to an acronym
- Acp :: capitalized plural reference to an acronym
- acrshort :: Short version of the acronym
- acrfull :: The full definition of the acronym
- acrlong :: The full definition of the acronym with (abbrv).
@@ -893,15 +904,53 @@ Here is a minimal working example of an org file that makes a glossary.
#+latex_header: \makeglossaries
#+latex_header_extra: \newglossaryentry{computer}{name=computer,description={A machine}}
#+latex_header_extra: \newacronym{tla}{TLA}{Three letter acronym}
A gls:computer is good for computing. Gls:computer is capitalized. We can also use a bunch of glspl:computer to make a cluster. Glspl:computer are the wave of the future.
A gls:computer is good for computing. Gls:computer is capitalized. We can also use a bunch of glspl:computer to make a cluster. Glspl:computer are the wave of the future. Don't forget what a ac:TLA is.
\printglossaries
#+END_EXAMPLE
This is not supported in anything but LaTeX export.
If you have a lot of glossary entries and you want to have them in an external file, you can put them in a tex file, and then include them in the org file like this. Here the glossary entries are saved in a file in the same directory as glossary.tex. This should still work with the tooltips.
#+BEGIN_EXAMPLE
#+latex_header: \loadglsentries[main]{glossary}
#+END_EXAMPLE
Finally, you can define the glossary entries in org tables like this. They will be deleted before a LaTeX export.
#+BEGIN_EXAMPLE
,#+title: Test
,#+latex_header: \usepackage{glossaries}
,#+latex_header: \makeglossaries
# This will not show in your export. It must be named glossary
,#+name: glossary
| label | name | description |
|-------+-------+---------------|
| tree | Tree | A woody plant |
| shrub | Shrub | A woody bush |
Checkout how a gls:tree differs from a gls:shrub.
,#+name: acronyms
| Key | Short | Long |
|------+-------+--------------------------------|
| mimo | | multiple-input multiple output |
| qos | QoS | quality-of-service |
| bb | BB | branch and bound |
First ac:bb. Second ac:bb. First ac:qos. Second ac:qos.
# This is where your glossary and acronym entries will be put.
,#+latex: \printglossaries
#+END_EXAMPLE
\glsaddall
\printglossaries