update packages
This commit is contained in:
@@ -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&t=hwut2142&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)
|
||||
|
||||
@@ -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: "
|
||||
|
||||
@@ -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 ()
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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))))
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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"))))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 wouldn’t 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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user