update of packages

This commit is contained in:
2023-11-04 19:26:41 +01:00
parent e162a12b58
commit 3b54a3236d
726 changed files with 297673 additions and 34585 deletions

View File

@@ -54,6 +54,7 @@
(require 'org-bibtex)) ; org-bibtex-yank
(require 'url-http)
(require 'url-handlers)
(require 'org-ref-utils)
(require 'hydra)
@@ -213,10 +214,23 @@ must return a pdf-url, or nil.")
;; 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*."
;; https://onlinelibrary.wiley.com/doi/10.1002/adts.202200926
;; https://onlinelibrary.wiley.com/doi/epdf/10.1002/adts.202200926
;; (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*)
;; (replace-regexp-in-string "doi/abs" "doi/pdf" *doi-utils-redirect*)))
(defun wiley-pdf-url-2 (*doi-utils-redirect*)
"Get url to the pdf from *DOI-UTILS-REDIRECT*.
[2023-04-10 Mon] updated a new rule.
https://onlinelibrary.wiley.com/doi/pdfdirect/10.1002/anie.201310461?download=true"
(when (string-match "^http\\(s?\\)://onlinelibrary.wiley.com" *doi-utils-redirect*)
(replace-regexp-in-string "doi/abs" "doi/pdf" *doi-utils-redirect*)))
(concat
(replace-regexp-in-string "doi/" "doi/pdfdirect/" *doi-utils-redirect*)
"?download=true")))
(defun agu-pdf-url (*doi-utils-redirect*)
@@ -340,39 +354,66 @@ must return a pdf-url, or nil.")
url)))
;;** Science Direct
(defun doi-utils-get-science-direct-pdf-url (redirect-url)
"Science direct hides the pdf url in html. We get it out here.
REDIRECT-URL is where the pdf url will be in."
(let ((first-url
(with-current-buffer (url-retrieve-synchronously redirect-url)
(goto-char (point-min))
(when (re-search-forward "pdf_url\" content=\"\\([^\"]*\\)\"" nil t)
(match-string-no-properties 1)))))
(and first-url
(with-current-buffer (url-retrieve-synchronously first-url)
(goto-char (point-min))
(when (re-search-forward "or click <a href=\"\\([^\"]*\\)\">" nil t)
(match-string-no-properties 1))))))
;; https://www.sciencedirect.com/science/article/pii/S001085452200577X?via%3Dihub
;; https://www.sciencedirect.com/science/article/pii/S001085452200577X/pdfft?isDTMRedir=true&download=true
(defun science-direct-pdf-url (*doi-utils-redirect*)
"Get url to the pdf from *DOI-UTILS-REDIRECT*."
(when (string-match "^http\\(s?\\)://www.sciencedirect.com" *doi-utils-redirect*)
(doi-utils-get-science-direct-pdf-url *doi-utils-redirect*)))
(replace-string "?via%3Dihub" "/pdfft?isDTMRedir=true&download=true" *doi-utils-redirect*)))
;; (defun doi-utils-get-science-direct-pdf-url (redirect-url)
;; "Science direct hides the pdf url in html. We get it out here.
;; REDIRECT-URL is where the pdf url will be in."
;; (let ((first-url
;; (with-current-buffer (url-retrieve-synchronously redirect-url)
;; (goto-char (point-min))
;; (when (re-search-forward "pdf_url\" content=\"\\([^\"]*\\)\"" nil t)
;; (match-string-no-properties 1)))))
;; (and first-url
;; (with-current-buffer (url-retrieve-synchronously first-url)
;; (goto-char (point-min))
;; (when (re-search-forward "or click <a href=\"\\([^\"]*\\)\">" nil t)
;; (match-string-no-properties 1))))))
;; (defun science-direct-pdf-url (*doi-utils-redirect*)
;; "Get url to the pdf from *DOI-UTILS-REDIRECT*."
;; (when (string-match "^http\\(s?\\)://www.sciencedirect.com" *doi-utils-redirect*)
;; (doi-utils-get-science-direct-pdf-url *doi-utils-redirect*)))
;; sometimes I get
;; http://linkinghub.elsevier.com/retrieve/pii/S0927025609004558
;; which actually redirect to
;; http://www.sciencedirect.com/science/article/pii/S0927025609004558
;; https://www.sciencedirect.com/science/article/pii/S001085452200577X?via%3Dihub
;; https://www.sciencedirect.com/science/article/pii/S001085452200577X/pdfft?isDTMRedir=true&download=true
;; (defun linkinghub-elsevier-pdf-url (*doi-utils-redirect*)
;; "Get url to the pdf from *DOI-UTILS-REDIRECT*."
;; (when (string-match
;; "^https://linkinghub.elsevier.com/retrieve" *doi-utils-redirect*)
;; (science-direct-pdf-url
;; (replace-regexp-in-string
;; ;; change URL to science direct and use function to get pdf URL
;; "https://linkinghub.elsevier.com/retrieve"
;; "https://www.sciencedirect.com/science/article"
;; *doi-utils-redirect*))))
;; https://www.sciencedirect.com/science/article/pii/S1385894723014973/pdfft?isDTMRedir=true&download=true
(defun linkinghub-elsevier-pdf-url (*doi-utils-redirect*)
"Get url to the pdf from *DOI-UTILS-REDIRECT*."
(when (string-match
"^https://linkinghub.elsevier.com/retrieve" *doi-utils-redirect*)
(doi-utils-get-science-direct-pdf-url
(concat
(replace-regexp-in-string
;; change URL to science direct and use function to get pdf URL
"https://linkinghub.elsevier.com/retrieve"
"https://www.sciencedirect.com/science/article"
*doi-utils-redirect*))))
*doi-utils-redirect*)
"/pdfft?isDTMRedir=true")))
;;** PNAS
;; http://www.pnas.org/content/early/2014/05/08/1319030111
@@ -550,9 +591,11 @@ REDIRECT-URL is where the pdf url will be in."
;;** ASME Biomechanical Journal
;;** Publishers using Highwire Press metatags
;; For context and details, see:
;; https://webmasters.stackexchange.com/questions/72746/where-are-the-complete-set-of-highwire-press-metatags-defined
(defun asme-biomechanical-pdf-url (*doi-utils-redirect*)
(defun highwire-pdf-url (*doi-utils-redirect*)
"Typical URL: http://biomechanical.asmedigitalcollection.asme.org/article.aspx?articleid=1427237
On this page the pdf might be here: <meta name=\"citation_author\" content=\"Dalong Li\" /><meta name=\"citation_author_email\" content=\"dal40@pitt.edu\" /><meta name=\"citation_author\" content=\"Anne M. Robertson\" /><meta name=\"citation_author_email\" content=\"rbertson@pitt.edu\" /><meta name=\"citation_title\" content=\"A Structural Multi-Mechanism Damage Model for Cerebral Arterial Tissue\" /><meta name=\"citation_firstpage\" content=\"101013\" /><meta name=\"citation_doi\" content=\"10.1115/1.3202559\" /><meta name=\"citation_keyword\" content=\"Mechanisms\" /><meta name=\"citation_keyword\" content=\"Biological tissues\" /><meta name=\"citation_keyword\" content=\"Stress\" /><meta name=\"citation_keyword\" content=\"Fibers\" /><meta name=\"citation_journal_title\" content=\"Journal of Biomechanical Engineering\" /><meta name=\"citation_journal_abbrev\" content=\"J Biomech Eng\" /><meta name=\"citation_volume\" content=\"131\" /><meta name=\"citation_issue\" content=\"10\" /><meta name=\"citation_publication_date\" content=\"2009/10/01\" /><meta name=\"citation_issn\" content=\"0148-0731\" /><meta name=\"citation_publisher\" content=\"American Society of Mechanical Engineers\" /><meta name=\"citation_pdf_url\" content=\"http://biomechanical.asmedigitalcollection.asme.org/data/journals/jbendy/27048/101013_1.pdf\" />
@@ -562,13 +605,17 @@ It is in the citation_pdf_url.
It would be better to parse this, but here I just use a regexp.
"
(when (string-match "^http\\(s?\\)://biomechanical.asmedigitalcollection.asme.org" *doi-utils-redirect*)
(when (or (string-match "^http\\(s?\\)://biomechanical.asmedigitalcollection.asme.org" *doi-utils-redirect*)
(string-match "^http\\(s?\\)://ojs.aaai.org" *doi-utils-redirect*)
(string-match "^http\\(s?\\)://aclanthology.org" *doi-utils-redirect*))
(setq *doi-utils-waiting* 0)
(url-retrieve
*doi-utils-redirect*
(lambda (status)
(goto-char (point-min))
(re-search-forward "citation_pdf_url\" content=\"\\(.*\\)\"" nil t)
(or (progn (goto-char (point-min))
(re-search-forward "citation_pdf_url\"? content=\"\\(.*\\)\"" nil t))
(progn (goto-char (point-min))
(re-search-forward "\"\\([^\"]*\\)\" name=\"?citation_pdf_url" nil t)))
;; (message-box (match-string 1))
(setq *doi-utils-pdf-url* (match-string 1)
*doi-utils-waiting* nil)))
@@ -592,6 +639,47 @@ It would be better to parse this, but here I just use a regexp.
(concat (replace-regexp-in-string (regexp-quote "/article?id=") "/article/file?id=" *doi-utils-redirect*) "&type=printable")))
;; https://www.frontiersin.org/articles/10.3389/fchem.2022.1037997/full
;; https://www.frontiersin.org/articles/10.3389/fchem.2022.1037997/pdf
(defun frontiers-pdf-url (*doi-utils-redirect*)
(when (string-match "^http\\(s*\\)://www.frontiersin.org" *doi-utils-redirect*)
(replace-regexp-in-string "/full" "/pdf" *doi-utils-redirect*)))
;; https://chemistry-europe.onlinelibrary.wiley.com/doi/10.1002/celc.201902035
;; https://chemistry-europe.onlinelibrary.wiley.com/doi/epdf/10.1002/celc.201902035
(defun chemistry-europe-pdf-url (*doi-utils-redirect*)
(when (string-match "^http\\(s*\\)://chemistry-europe.onlinelibrary.wiley.com" *doi-utils-redirect*)
(concat
(replace-regexp-in-string "/doi" "/doi/pdfdirect" *doi-utils-redirect*)
"?download=true")))
;; ** from issue #1081
(defun arxiv-pdf-url (*doi-utils-redirect*)
"Get url to the pdf from *DOI-UTILS-REDIRECT*."
(when (string-match-p "^https?://arxiv\\.org" *doi-utils-redirect*)
(concat (replace-regexp-in-string "/abs/" "/pdf/" *doi-utils-redirect*)
".pdf")))
(defun rss-pdf-url (*doi-utils-redirect*)
"Get url to the pdf from *DOI-UTILS-REDIRECT*."
(when (string-match-p "roboticsproceedings" *doi-utils-redirect*)
(concat (replace-regexp-in-string "\\.html" ".pdf" *doi-utils-redirect*))))
(defun ieeestamp-pdf-url (*doi-utils-redirect*)
"Get url to the pdf from *DOI-UTILS-REDIRECT*."
(when (string-match "^https?://ieeexplore\\.ieee\\.org/document/\\([0-9]+\\)"
*doi-utils-redirect*)
(concat "https://ieeexplore.ieee.org/stampPDF/getPDF.jsp?tp=&arnumber="
(match-string 1 *doi-utils-redirect*))))
;;** Add all functions
(setq doi-utils-pdf-url-functions
@@ -599,7 +687,8 @@ It would be better to parse this, but here I just use a regexp.
'aps-pdf-url
'science-pdf-url
'nature-pdf-url
'wiley-pdf-url
;; 'wiley-pdf-url
'wiley-pdf-url-2
'springer-chapter-pdf-url
'springer-pdf-url
'acs-pdf-url-1
@@ -624,11 +713,16 @@ It would be better to parse this, but here I just use a regexp.
'ieee3-pdf-url
'acm-pdf-url
'osa-pdf-url
'asme-biomechanical-pdf-url
'highwire-pdf-url
'siam-pdf-url
'agu-pdf-url
'plos-pdf-url
'generic-full-pdf-url))
'frontiers-pdf-url
'chemistry-europe-pdf-url
'generic-full-pdf-url
'arxiv-pdf-url
'rss-pdf-url
'ieeestamp-pdf-url))
;;** Get the pdf url for a doi
@@ -811,11 +905,10 @@ every field.")
(json-object-type 'plist)
(json-data)
(url (concat doi-utils-dx-doi-org-url doi)))
(with-current-buffer
(url-retrieve-synchronously
;; (concat "http://dx.doi.org/" doi)
url)
(setq json-data (buffer-substring url-http-end-of-headers (point-max)))
(with-temp-buffer
(url-insert
(url-retrieve-synchronously url))
(setq json-data (buffer-string))
(when (or (string-match "<title>Error: DOI Not Found</title>" json-data)
(string-match "Resource not found" json-data)
@@ -1011,7 +1104,8 @@ MATCHING-TYPES."
(bibtex-set-field doi-utils-timestamp-field
ts)))
(org-ref-clean-bibtex-entry)
(save-buffer))
(when (buffer-file-name)
(save-buffer)))
;;;###autoload
@@ -1020,7 +1114,7 @@ MATCHING-TYPES."
Pick the file ending with .bib or in . If you have an active region that
starts like a DOI, that will be the initial prompt. If no region
is selected and the first entry of the kill-ring starts like a
DOI, then that is the intial prompt. Otherwise, you have to type
DOI, then that is the initial prompt. Otherwise, you have to type
or paste in a DOI.
Argument BIBFILE the bibliography to use."
(interactive
@@ -1478,10 +1572,11 @@ Get a list of possible matches. Choose one with completion."
(let ((url-request-method "GET")
(url-mime-accept-string "application/citeproc+json")
(json-data))
(with-current-buffer
(url-retrieve-synchronously
(concat doi-utils-dx-doi-org-url doi))
(setq json-data (buffer-substring url-http-end-of-headers (point-max)))
(with-temp-buffer
(url-insert
(url-retrieve-synchronously
(concat doi-utils-dx-doi-org-url doi)))
(setq json-data (buffer-string))
(if (string-match "Resource not found" json-data)
(progn
(browse-url (concat doi-utils-dx-doi-org-url doi))
@@ -1502,10 +1597,11 @@ Get a list of possible matches. Choose one with completion."
(let ((url-request-method "GET")
(url-mime-accept-string "application/citeproc+json"))
(pp
(json-read-from-string (with-current-buffer
(url-retrieve-synchronously
(concat doi-utils-dx-doi-org-url doi))
(buffer-substring url-http-end-of-headers (point-max))))))
(json-read-from-string (with-temp-buffer
(url-insert
(url-retrieve-synchronously
(concat doi-utils-dx-doi-org-url doi)))
(buffer-string)))))
"\n\n")
(goto-char (point-min)))
@@ -1536,48 +1632,40 @@ Get a list of possible matches. Choose one with completion."
"Bibfile: "
(append (f-entries "." (lambda (f) (f-ext? f "bib")))
bibtex-completion-bibliography))))
(let* ((raw-json-string)
(json-string)
(json-data)
(doi))
(let* ((json-data (with-temp-buffer
(url-insert
(url-retrieve-synchronously
(concat
"https://api.crossref.org/works?query="
(url-hexify-string query))))
(json-read-from-string (buffer-string))))
(name (format "Crossref hits for %s"
;; remove carriage returns. They can make completion confusing.
(replace-regexp-in-string "\n" " " query)))
(candidates (let-alist json-data
(cl-loop for item across .message.items
collect (let-alist item
(cons (format "%s, %s, %s, %s."
(string-join .title " ")
(string-join
(cl-loop for author across .author collect
(let-alist author
(format "%s %s"
.given .family)))
", ")
.publisher
.created.date-parts)
.DOI)))))
(doi (cdr (assoc (completing-read "Choice: " candidates) candidates))))
(with-current-buffer
(url-retrieve-synchronously
(concat
"http://search.crossref.org/dois?q="
(url-hexify-string query)))
;; replace html entities
(save-excursion
(goto-char (point-min))
(while (re-search-forward "<i>\\|</i>" nil t)
(replace-match ""))
(goto-char (point-min))
(while (re-search-forward "&amp;" nil t)
(replace-match "&"))
(goto-char (point-min))
(while (re-search-forward "&quot;" nil t)
(replace-match "\\\"" nil t)))
(setq raw-json-string (buffer-substring url-http-end-of-headers (point-max)))
;; decode json string
(setq json-string (decode-coding-string (encode-coding-string raw-json-string 'utf-8) 'utf-8))
(setq json-data (json-read-from-string json-string)))
(with-current-buffer (find-file-noselect bibtex-file)
(doi-utils-add-bibtex-entry-from-doi
(replace-regexp-in-string
"^https?://\\(dx.\\)?doi.org/" "" doi)
bibtex-file)
(save-buffer))))
(let* ((name (format "Crossref hits for %s"
;; remove carriage returns. They can make completion confusing.
(replace-regexp-in-string "\n" " " query)))
(candidates (mapcar (lambda (x)
(cons
(concat
(cdr (assoc 'fullCitation x)))
(cdr (assoc 'doi x))))
json-data))
(doi (cdr (assoc (completing-read "Choice: " candidates) candidates))))
(with-current-buffer (find-file-noselect bibtex-file)
(doi-utils-add-bibtex-entry-from-doi
(replace-regexp-in-string
"^https?://\\(dx.\\)?doi.org/" "" doi)
bibtex-file)
(save-buffer)))))
(defalias 'crossref-add-bibtex-entry 'doi-utils-add-entry-from-crossref-query
"Alias function for convenience.")

459
lisp/org-ref/openalex.el Normal file
View File

@@ -0,0 +1,459 @@
;;; openalex.el --- Org-ref interface to OpenAlex
;;; Commentary:
;; This is an elisp interface to OpenAlex (https://docs.openalex.org/) for org-ref.
;;
;; This provides functionality for the Work and Author API
;;
;; See
;; https://docs.openalex.org/how-to-use-the-api/rate-limits-and-authentication#the-polite-pool
;; for why we add email to the request.
(require 'dash)
(require 'request)
;;; Code:
(defun oa--response-parser ()
"Parse the response from json to elisp."
(let ((json-array-type 'list)
(json-object-type 'plist)
(json-key-type 'keyword)
(json-false nil)
(json-encoding-pretty-print nil))
(json-read)))
;; * Work object
(defun oa--work (entity-id &optional filter)
"Retrieve json data for a Work object for ENTITY-ID.
ENTITY-ID is an OpenAlex ID, DOI, Pubmed id,etc.
ENTITY-ID may also be a list of ids with a filter.
If FILTER is non-nil it should be a string like \"filter=openalex:\"
https://docs.openalex.org/api-entities/works"
(let* ((url (concat "https://api.openalex.org/works"
(if filter
(concat "?" filter entity-id)
(concat "/" entity-id))
(if user-mail-address
(concat "?mailto=" user-mail-address)
"")))
(req (request url :sync t :parser 'oa--response-parser))
(data (request-response-data req)))
;; this is for convenience to inspect data in a browser.
(plist-put data :oa-url url)
data))
;; * Viewing works
;;
;; This section provides a replacer and helper function to format org-entries
;; from the results returned in OpenAlex.
(defun oa--replacer (query object)
"Replacer function for `s-format'.
QUERY is a string that is either a sexp for a function to
evaluate or a dot notation path to data in OBJECT. If QUERY is a
sexp, it is read and evaluated. Otherwise, the path is split, and
looked up sequentially in object.
OBJECT is a plist, usually from a Work request."
(if (s-starts-with? "(" query)
;; this is a function
(eval (read query))
;; just get data
(let ((fields (s-split "\\." query))
result)
(while fields
(setq object (plist-get object (intern-soft (concat ":" (pop fields))))))
(or (string-replace "\\n" "" (format "%s" object)) "Not found"))))
;; ** help functions for complex data
;;
;; Some things like authors need to be constructed, and cannot just be looked
;; up. In other cases, I want logic, e.g. if data is there provide something,
;; and if not return an empty string. These functions do that work.
(defun oa--authors (wrk)
"Return an author string for WRK.
The string is a comma-separated list of links to author pages in OpenAlex."
(s-join ", " (cl-loop for author in (plist-get wrk :authorships)
collect
(format "[[elisp:(oa-author \"%s\")][%s]]"
(plist-get
(plist-get author :author)
:id)
(plist-get
(plist-get author :author)
:display_name)))))
;; I want some links if they can be made so the buffer is interactive. It might
;; be nice to integrate M-, navigation.
(defun oa--elisp-get-bibtex (wrk)
"Return a elisp link to get a bibtex entry for WRK if there is a doi."
(if-let ((doi (plist-get wrk :doi)))
(format "[[elisp:(doi-add-bibtex-entry \"%s\")][Get bibtex entry]]" doi)
""))
(defun oa--elisp-get-oa-related (wrk)
"Return a elisp link to get related works for WRK."
(format "[[elisp:(progn (xref--push-markers) (oa--related-works \"%s\"))][Get related work (%s)]]"
(plist-get wrk :id)
(length (plist-get wrk :related_works))))
(defun oa--elisp-get-oa-refs (wrk)
"Return a elisp link to get references for WRK."
(format "[[elisp:(progn (xref--push-markers) (oa--referenced-works \"%s\"))][Get references (%s)]]"
(plist-get wrk :id)
(length (plist-get wrk :referenced_works))))
(defun oa--elisp-get-oa-cited-by (wrk)
"Return a elisp link to get works that cite WRK."
(format "[[elisp:(progn (xref--push-markers) (oa--cited-by-works \"%s\"))][Get cited by (%s)]]"
(plist-get wrk :id)
(plist-get wrk :cited_by_count)))
(defun oa--works-entries (works)
"Return a list of org-formatted entries in WORKS.
WORKS is a list of results from OpenAlex."
(cl-loop for wrk in (plist-get works :results)
collect
(s-format "** ${title}
:PROPERTIES:
:HOST: ${host_venue.display_name}
:YEAR: ${publication_year}
:CITED_BY_COUNT: ${cited_by_count}
:AUTHOR: ${(oa--authors wrk)}
:DOI: ${doi}
:OPENALEX: ${id}
:END:
${(oa--elisp-get-bibtex wrk)}
- ${(oa--elisp-get-oa-refs wrk)}
- ${(oa--elisp-get-oa-related wrk)}
- ${(oa--elisp-get-oa-cited-by wrk)}
"
'oa--replacer wrk)))
(defun oa--works-buffer (bufname header entries)
"Create an org-buffer with BUFNAME representing the results in WORKS.
HEADER is the first thing in the buffer
WORKS is usually a list of results from OpenAlex.
Argument ENTRIES A list of strings for each org entry."
(let ((buf (get-buffer-create bufname)))
(with-current-buffer buf
(erase-buffer)
(insert header)
(insert "#+COLUMNS: %25ITEM %YEAR %CITED_BY_COUNT
elisp:org-columns elisp:org-columns-quit
#+caption: Sort
| year | [[elisp:(oa-buffer-sort-year t)][old first]] | [[elisp:(oa-buffer-sort-year)][new first]] |
| cited by | [[elisp:(oa-buffer-sort-cited-by-count t)][low first]] | [[elisp:(oa-buffer-sort-cited-by-count)][high first]] |
")
(insert (s-join "\n" entries))
(org-mode)
(goto-char (point-min))
(org-next-visible-heading 1))
;; (display-buffer-in-side-window buf '((side . right)))
(pop-to-buffer buf)))
;; There is something funny about pages here, maybe 25 results per page?
;; https://docs.openalex.org/how-to-use-the-api/get-lists-of-entities/paging I
;; am not sure how to do pages in this approach, so I am just getting these 25
;; at a time.
(defun oa--related-works (entity-id)
"Show the Related works buffer for ENTITY-ID."
(let* ((wrk (oa--work entity-id))
(related-work (plist-get wrk :related_works))
split
entries)
(while related-work
(setq split (-split-at 25 related-work)
related-work (nth 1 split))
;; split is what we process now
(setq entries (append entries
(oa--works-entries
(oa--work (s-join "|" (nth 0 split))
"filter=openalex:")))))
(oa--works-buffer
"*OpenAlex - Related works*"
(format "* OpenAlex - Related works for %s ([[%s][json]])
%s\n\n"
entity-id
(plist-get wrk :oa-url)
(s-format ":PROPERTIES:
:TITLE: ${title}
:HOST: ${host_venue.display_name}
:AUTHOR: ${(oa--authors wrk)}
:DOI: ${doi}
:YEAR: ${publication_year}
:OPENALEX: ${id}
:END:" 'oa--replacer wrk))
entries)))
(defun oa--referenced-works (entity-id)
"Show the Referenced work for ENTITY-ID."
(let* ((wrk (oa--work entity-id))
(referenced-work (plist-get wrk :referenced_works))
split
(entries '()))
(while referenced-work
(setq split (-split-at 25 referenced-work)
referenced-work (nth 1 split))
;; split is what we process now
(setq entries (append entries
(oa--works-entries
(oa--work (s-join "|" (nth 0 split))
"filter=openalex:")))))
(oa--works-buffer
"*OpenAlex - References*"
(format "* OpenAlex - References from %s ([[%s][json]])
%s\n\n"
entity-id
(plist-get wrk :oa-url)
(s-format ":PROPERTIES:
:TITLE: ${title}
:HOST: ${host_venue.display_name}
:AUTHOR: ${(oa--authors wrk)}
:DOI: ${doi}
:YEAR: ${publication_year}
:OPENALEX: ${id}
:END:" 'oa--replacer wrk))
entries)))
;; This function is different than the previous two. First we follow a URL
;; provided by the data, and second, here we do follow pages.
(defun oa--cited-by-works (entity-id)
"Show the Cited by buffer for ENTITY-ID."
(let* ((wrk (oa--work entity-id))
(url (plist-get wrk :cited_by_api_url))
(cited-by-works (request-response-data
(request url
:sync t
:parser 'oa--response-parser)))
(count (plist-get (plist-get cited-by-works :meta) :count))
(per-page (plist-get (plist-get cited-by-works :meta) :per_page))
(entries '())
(page 2))
;; get first page
(setq entries (oa--works-entries cited-by-works))
(while (> count (* per-page (- page 1)))
(setq cited-by-works (request-response-data
(request (format "%s&page=%s" url page)
:sync t
:parser 'oa--response-parser)))
(setq entries (append entries (oa--works-entries cited-by-works)))
(cl-incf page))
(oa--works-buffer
"*OpenAlex - Cited by*"
(format "* OpenAlex - %s Cited by ([[%s][json]])
%s"
entity-id
url
(s-format ":PROPERTIES:
:TITLE: ${title}
:HOST: ${host_venue.display_name}
:AUTHOR: ${(oa--authors wrk)}
:DOI: ${doi}
:YEAR: ${publication_year}
:OPENALEX: ${id}
:END:\n\n" 'oa--replacer wrk))
entries)))
;; ** buffer utilities for sorting entries
(defun oa-buffer-sort-year (&optional ascending)
"Sort org headings by year in descending order (new to old).
With prefix arg ASCENDING, sort in ascending order (old to new)"
(interactive "P")
(if ascending
(org-sort-entries nil ?f
(lambda () (string-to-number (or (org-entry-get (point) "YEAR") "0")))
(lambda (y1 y2)
(< y1 y2)))
(org-sort-entries nil ?f
(lambda () (string-to-number (or (org-entry-get (point) "YEAR") "0")))
(lambda (y1 y2)
(> y1 y2)))))
(defun oa-buffer-sort-cited-by-count (&optional ascending)
"Sort orgheadings by cited by count in descending order high to low.
With prefix arg ASCENDING sort from low to high."
(interactive "P")
(if ascending
(org-sort-entries nil ?f
(lambda ()
(string-to-number
(or (org-entry-get (point) "CITED_BY_COUNT")
"0")))
#'<)
(org-sort-entries nil ?f
(lambda ()
(string-to-number
(or
(org-entry-get (point) "CITED_BY_COUNT")
"0")))
#'>)))
;; * Interactive versions for org-ref citations
(defun oa-related-works ()
"Open the side window for Related works on cite at point."
(interactive)
(oa--related-works (concat "doi:" (org-ref-get-doi-at-point))))
(defun oa-referenced-works ()
"Open the side window for References from the cite at point."
(interactive)
(oa--referenced-works (concat "doi:" (org-ref-get-doi-at-point))))
(defun oa-cited-by-works ()
"Open the side window for Citing works for the cite at point."
(interactive)
(oa--cited-by-works (concat "doi:" (org-ref-get-doi-at-point))))
(defhydra+ org-ref-citation-hydra () ("ar" oa-related-works "Related documents" :column "OpenAlex"))
(defhydra+ org-ref-citation-hydra () ("ac" oa-cited-by-works "Cited by documents" :column "OpenAlex"))
(defhydra+ org-ref-citation-hydra () ("af" oa-referenced-works "References from" :column "OpenAlex"))
;; * utilities
(defun oa-kill-buffers ()
"Kill OpenAlex buffers."
(interactive)
(cl-loop for buf in (buffer-list)
do
(when (s-starts-with? "*OpenAlex" (buffer-name buf))
(kill-buffer buf))))
;; * Author object
(defun oa--author (entity-id &optional filter)
"Get an Author object for entity-id"
(let* ((url (concat "https://api.openalex.org/authors"
(if filter
(concat "?" filter entity-id)
(concat "/" entity-id))
(if user-mail-address
(concat "?mailto=" user-mail-address)
"")))
(req (request url :sync t :parser 'oa--response-parser))
(data (request-response-data req)))
;; this is for convenience to inspect data in a browser.
(plist-put data :oa-url url)
data))
(defun oa-author-entries (works-data url)
"Get entries from WORKS-DATA."
(let* ((meta (plist-get works-data :meta))
(per-page (plist-get meta :per_page))
(count (plist-get meta :count))
(pages (/ count per-page))
(entries '())
purl)
;; if there is a remainder we need to get the rest
(when (> (mod count per-page) 0) (cl-incf pages))
;; Now we have to loop through the pages
(cl-loop for i from 1 to pages
do
(setq purl (concat url (format "&page=%s" i))
works-data (request-response-data
(request purl
:sync t
:parser 'oa--response-parser))
entries (append entries
(cl-loop for result in (plist-get works-data :results)
collect
(s-format "** ${title}
:PROPERTIES:
:ID: ${id}
:DOI: ${ids.doi}
:YEAR: ${publication_year}
:HOST_VENUE: ${host_venue.display_name}
:AUTHORS: ${(oa--authors result)}
:CITED_BY_COUNT: ${cited_by_count}
:END:
${(oa--elisp-get-bibtex result)}
- ${(oa--elisp-get-oa-refs result)}
- ${(oa--elisp-get-oa-related result)}
- ${(oa--elisp-get-oa-cited-by result)}
" 'oa--replacer result)))))
entries))
(defun oa-author (entity-id)
"View Author for ENTITY-ID in an org-buffer."
(let* ((buf (get-buffer-create "*OpenAlex - Author*"))
(data (oa--author entity-id))
(works-count (plist-get data :works_count))
(works-url (plist-get data :works_api_url))
(works-data (request-response-data
(request works-url
:sync t
:parser 'oa--response-parser))))
(with-current-buffer buf
(erase-buffer)
(insert (s-format "* ${display_name} ([[${oa-url}][json]])
:PROPERTIES:
:ORCID: ${orcid}
:SCOPUS: ${ids.scopus}
:WORKS_COUNT: ${works_count}
:CITED_BY_COUNT: ${cited_by_count}
:INSTITUTION: ${last_known_institution.display_name}, ${last_known_institution.country_code}
:END:
#+COLUMNS: %25ITEM %YEAR %CITED_BY_COUNT
elisp:org-columns elisp:org-columns-quit
#+caption: Sort
| year | [[elisp:(oa-buffer-sort-year t)][old first]] | [[elisp:(oa-buffer-sort-year)][new first]] |
| cited by | [[elisp:(oa-buffer-sort-cited-by-count t)][low first]] | [[elisp:(oa-buffer-sort-cited-by-count)][high first]] |
"
'oa--replacer data))
(insert (s-join "\n" (oa-author-entries works-data works-url)))
(org-mode)
(goto-char (point-min))
(org-next-visible-heading 1))
(pop-to-buffer buf)))
(provide 'openalex)
;;; openalex.el ends here

View File

@@ -261,7 +261,7 @@ Returns `org-ref-bst-styles' or sets it and returns it."
(mapcar (lambda (path)
(setq path (replace-regexp-in-string "!" "" path))
(when (file-directory-p path)
(f-entries path (lambda (f) (f-ext? f "bst")) t)))
(f-entries path (lambda (f) (f-ext? f "bst")))))
(split-string
;; https://tex.stackexchange.com/questions/431948/get-a-list-of-installed-bibliography-styles-with-kpsewhich?noredirect=1#comment1082436_431948
(shell-command-to-string "kpsewhich -expand-path '$BSTINPUTS'")

View File

@@ -1005,7 +1005,7 @@ keywords. Optional argument ARG prefix arg to replace keywords."
(if (listp keywords)
(mapconcat 'identity keywords ", ")
keywords)
;; else concatentate
;; else concatenate
(concat
(if (listp keywords)
(mapconcat 'identity keywords ", ")
@@ -1209,13 +1209,13 @@ will clobber the file."
;;** Clean a bibtex entry
;; These functions operate on a bibtex entry and "clean" it in some way.
(defun orcb-clean-nil (arg)
(defun orcb-clean-nil (&optional arg)
"Remove nil from some article fields.
The removal is conditional. Sometimes it is useful to have nil
around, e.g. for ASAP articles where the fields are not defined
yet but will be in the future.
With \\[univeral-argument], run `bibtex-clean-entry' after."
With \\[universal-argument], run `bibtex-clean-entry' after."
(interactive "P")
(bibtex-beginning-of-entry)
(let* ((entry (bibtex-parse-entry))
@@ -1405,6 +1405,16 @@ If not, issue a warning."
(doi-utils-get-bibtex-entry-pdf))))
(defun orcb-clean-<>-tags ()
"Try removing <tags> from the entry."
(sgml-mode)
(ignore-errors
(while (sgml-skip-tag-forward 1)
(sgml-skip-tag-backward 1)
(sgml-delete-tag 1)))
(bibtex-mode))
;;;###autoload
(defun org-ref-clean-bibtex-entry ()
"Clean and replace the key in a bibtex entry.

View File

@@ -158,7 +158,7 @@ Set this to nil to turn that off, which increase performance."
("Smartcite" "like parencite in a footnote, and footcite in the body with capitalization")
("cite*" "similar to cite, but prints the year or title")
("parencite*" "similar to parencite, but prints the year or title")
("supercite" "superscripted numeric citation (only in numberic styles)")
("supercite" "superscripted numeric citation (only in numeric styles)")
("autocite" "handles some punctuation nuances")
("Autocite" "handles some punctuation nuances with punctuation")
@@ -296,7 +296,7 @@ Set this to nil to turn that off, which increase performance."
(3 (let ((citation-references (split-string path ";"))
(these-results '(:version 3)))
;; if the first ref doesn't match a key, it must be a global prefix
;; this pops the referenc off.
;; this pops the reference off.
(when (null (string-match org-ref-citation-key-re (cl-first citation-references)))
(setq these-results (append these-results (list :prefix (cl-first citation-references)))
citation-references (cdr citation-references)))
@@ -543,6 +543,7 @@ PATH has the citations in it."
(bibtex-copy-entry-as-kill)
(kill-new (pop bibtex-entry-kill-ring))))
"Copy bibtex" :column "Copy")
("a" org-ref-add-pdf-at-point "add pdf to library" :column "Copy")
("k" (kill-new (car (org-ref-get-bibtex-key-and-file))) "Copy key" :column "Copy")
("f" (kill-new (bibtex-completion-apa-format-reference
(org-ref-get-bibtex-key-under-cursor)))
@@ -930,16 +931,20 @@ arg COMMON, edit the common prefixes instead."
(setq prefix (concat
(read-string "prenote: "
(string-trim
(plist-get
(nth index (plist-get data :references))
:prefix)))
(or
(plist-get
(nth index (plist-get data :references))
:prefix)
"")))
" ")
suffix (concat " "
(read-string "postnote: "
(string-trim
(plist-get
(nth index (plist-get data :references))
:suffix))))
(or
(plist-get
(nth index (plist-get data :references))
:suffix)
""))))
delta (- (length (plist-get
(nth index (plist-get data :references))
:prefix))
@@ -955,8 +960,8 @@ arg COMMON, edit the common prefixes instead."
nil suffix))))
(setf (buffer-substring (org-element-property :begin cite) (org-element-property :end cite))
(format "[[%s:%s]]" type (org-ref-interpret-cite-data data)))
(cl--set-buffer-substring (org-element-property :begin cite) (org-element-property :end cite)
(format "[[%s:%s]]" type (org-ref-interpret-cite-data data)))
;; This doesn't exactly save the point. I need a fancier calculation for
;; that I think that accounts for the change due to the prefix change. e.g.
@@ -995,41 +1000,79 @@ arg COMMON, edit the common prefixes instead."
(defun org-ref-get-bibtex-key-under-cursor ()
"Return key under the cursor in org-mode.
If not on a key, but on a cite, prompt for key."
(if-let ((key (get-text-property (point) 'cite-key)))
;; Point is on a key, so we get it directly
key
;; point is not on a key, but may still be on a cite link
(let ((el (org-element-context))
data
keys)
(cond
;; on a cite-link type
((and
(eq (org-element-type el) 'link)
(assoc (org-element-property :type el) org-ref-cite-types))
(goto-char (org-element-property :begin el))
(setq data (org-ref-parse-cite-path (org-element-property :path el))
keys (cl-loop for ref in (plist-get data :references)
collect (plist-get ref :key)))
(cond
(org-ref-activate-cite-links
(if-let ((key (get-text-property (point) 'cite-key)))
;; Point is on a key, so we get it directly
key
;; point is not on a key, but may still be on a cite link
(let ((el (org-element-context))
(cp (point))
data
keys)
(cond
((= 1 (length keys))
(search-forward (car keys))
(goto-char (match-beginning 0)))
;; multiple keys
(t
(setq key (completing-read "Key: " keys))
(search-forward key)
(goto-char (match-beginning 0))))
(get-text-property (point) 'cite-key))
;; on a cite-link type
((and
(eq (org-element-type el) 'link)
(assoc (org-element-property :type el) org-ref-cite-types))
;; somewhere else, but looking at a cite-type see issue #908. links in
;; places like keywords are not parsed as links, but they seem to get
;; activated, so we can just get onto the key, and then open it.
((assoc (thing-at-point 'word) org-ref-cite-types)
(save-excursion
(when (re-search-forward ":" (line-end-position) t)
(get-text-property (point) 'cite-key))))))))
(goto-char (org-element-property :begin el))
(setq data (org-ref-parse-cite-path (org-element-property :path el))
keys (cl-loop for ref in (plist-get data :references)
collect (plist-get ref :key)))
(cond
((= 1 (length keys))
(search-forward (car keys))
(goto-char (match-beginning 0)))
;; multiple keys
(t
(setq key (completing-read "Key: " keys))
(search-forward key)
(goto-char (match-beginning 0))))
(prog1
(get-text-property (point) 'cite-key)
(goto-char cp)))
;; somewhere else, but looking at a cite-type see issue #908. links in
;; places like keywords are not parsed as links, but they seem to get
;; activated, so we can just get onto the key, and then open it.
((assoc (thing-at-point 'word) org-ref-cite-types)
(save-excursion
(when (re-search-forward ":" (line-end-position) t)
(prog1
(get-text-property (point) 'cite-key)
(goto-char cp)))))))))
;; org-ref-activate-cite-links is nil so font-lock does not put
;; text-properties on keys. We temporarily activate this
(t
(let ((el (org-element-context))
(cp (point))
(org-ref-activate-cite-links t) ;; temporary
data
keys
)
(and
(eq (org-element-type el) 'link)
(assoc (org-element-property :type el) org-ref-cite-types))
(save-excursion
;; We activate just this one link
(org-ref-cite-activate
(org-element-property :begin el)
(org-element-property :end el)
(org-element-property :path el)
nil))
;; Now we have to handle some cases.
(cond
;; on a key, return a key
((get-text-property (point) 'cite-key)
(get-text-property (point) 'cite-key))
;; not on a key, but on a cite. this is lazy, but we just search forward
;; to the first key
(t
(search-forward ":")
(get-text-property (point) 'cite-key)))))))
;; ** Shift-arrow sorting of keys in a cite link
@@ -1097,7 +1140,8 @@ If not on a key, but on a cite, prompt for key."
(link-string (org-element-property :path object))
(data (org-ref-parse-cite-path link-string))
(references (plist-get data :references))
(bibtex-completion-bibliography (org-ref-find-bibliography)))
(bibtex-completion-bibliography (org-ref-find-bibliography))
current-point)
(setq references (cl-sort (cl-loop for ref in references collect
(append ref (list :year (bibtex-completion-get-value
@@ -1107,11 +1151,12 @@ If not on a key, but on a cite, prompt for key."
(lambda (x y)
(< (string-to-number (plist-get x :year))
(string-to-number (plist-get y :year))))))
(setq data (plist-put data :references references))
(save-excursion
(goto-char begin)
(re-search-forward link-string)
(replace-match (org-ref-interpret-cite-data data)))))
(setq data (plist-put data :references references)
current-point (point))
(goto-char begin)
(re-search-forward link-string)
(replace-match (org-ref-interpret-cite-data data))
(goto-char current-point)))
;;** C-arrow navigation of cite keys
@@ -1369,10 +1414,10 @@ Here is an example use:
(plist-put data :prefix (cl-first prefix-suffix))
(plist-put data :suffix (cl-second prefix-suffix)))
(plist-put data :version 3)
(setf (buffer-substring (org-element-property :begin cite)
(org-element-property :end cite))
(format "[[%s:%s]]" (org-element-property :type cite)
(org-ref-interpret-cite-data data))))))
(cl--set-buffer-substring (org-element-property :begin cite)
(org-element-property :end cite)
(format "[[%s:%s]]" (org-element-property :type cite)
(org-ref-interpret-cite-data data))))))
(provide 'org-ref-citation-links)

View File

@@ -0,0 +1,94 @@
;;; org-ref-compat.el --- Compatibility functions for org-cite
;;; Commentary:
;;
;; The main function of this library is to provide compatibility functions for
;; converting between org-ref and org-cite.
(require 'org-ref-export)
(defcustom org-ref-to-org-cite-mapping
'(("cite" . "")
("citep" . "")
("Citep" . "//caps-full")
("citealp" . "//bare")
("Citealp" . "//bare-caps")
("Citealp*" . "//bare-caps-full")
("citep*" . "//full")
("citet" . "/text")
("citeyear" . "/noauthor/bare")
("citeyearpar" . "/noauthor")
("nocite" . "/nocite")
("citeauthor" . "/author")
("citeauthor*" . "/author/full")
("Citeauthor" . "/author/caps"))
"A-list of (org-ref-type . org-cite-style).
This builds from
https://blog.tecosaur.com/tmio/2021-07-31-citations.html#cite-syntax.
There is no way to get them all though, there are conflicting
translations with some biblatex and some natbib commands. This
list maps the natbib commands. I have also opted to use the full
names rather than the short names."
:group 'org-ref)
(defun org-ref-to-org-cite ()
(interactive)
(let ((ref-cites (reverse (org-ref-get-cite-links)))
ref-type
path
beg end)
;; This takes care of the cite links
(cl-loop for rc in ref-cites do
(setq
type (org-element-property :type rc)
path (org-element-property :path rc)
beg (org-element-property :begin rc)
end (org-element-property :end rc))
(cl--set-buffer-substring
beg end
(format "[cite%s:%s]"
(or (cdr (assoc type org-ref-to-org-cite-mapping)) "")
;; This is not 100% correct, if someone has put an extra &
;; anywhere in a note, this will be a little wrong. It
;; would be a little more correct if I also look for a
;; word next to it. The most correct would probably be to
;; build the data and then use org-element interpret I
;; think
(replace-regexp-in-string "&" "@" path))))
;; Next replace bibliography links. I assume the paths are ok, and we just
;; need to convert them to keywords.
(cl-loop for bib-link in
(reverse (org-element-map (org-element-parse-buffer) 'link
(lambda (bl)
(when (member (org-element-property :type bl)
'("bibliography" "nobibliography"))
bl))))
do
(cl--set-buffer-substring
(org-element-property :begin bib-link)
(org-element-property :end bib-link)
(format "#+bibliography: %s%s"
(org-element-property :path bib-link)
(if (string= "bibliography"
(org-element-property :type bib-link))
"\n#+print_bibliography:"
""))))
;; Note it is a bit ambiguous what do do about where the bibliography is to
;; be printed. This should be done via #+print_bibliography:. In org-ref the
;; bibliography normally goes where the bibliography link was, and I sue
;; that convention.
))
(provide 'org-ref-compat)
;;; org-ref-compat.el ends here

View File

@@ -389,7 +389,7 @@ BACKEND is the org export backend."
;;
;; Here we add style css for html output.
(cond
((eq 'html backend)
((or (eq 'html backend) (eq 'html csl-backend))
(let ((s1 "")
(s2 ""))
(when (cdr (assq 'second-field-align bib-parameters))

View File

@@ -0,0 +1,190 @@
;;; org-ref-extract.el --- Extract BibTeX from HTML -*- lexical-binding: t; -*-
;; Copyright (C) 2023 Justus Piater
;; Author: Justus Piater <Justus-dev@Piater.name>
;; Keywords:
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;;
(defun org-ref--extract (html-buffer rx num)
"Return content matched within HTML-BUFFER by RX at parenthesized
sub-expression NUM."
(with-current-buffer html-buffer
(goto-char (point-min))
(if (re-search-forward rx nil t)
(match-string num)
nil)))
(defun org-ref--get-pdf (pdf-url)
"For BibTeX entry at point, if not already present, get PDF, place
it in`bibtex-completion-library-path', and add a corresponding
FILE field to the entry."
(bibtex-beginning-of-entry)
(let* ((key (cdr (assoc "=key=" (bibtex-parse-entry))))
(pdf-file (concat (car bibtex-completion-library-path) key ".pdf")))
(unless (file-exists-p pdf-file)
(url-copy-file pdf-url pdf-file)
(if (org-ref-pdf-p pdf-file)
(message "%s saved" pdf-file)
(delete-file pdf-file)
(message "No pdf was downloaded.")
(browse-url pdf-url)))
(when (file-exists-p pdf-file)
(bibtex-set-field "file" pdf-file)
(when doi-utils-open-pdf-after-download
(org-open-file pdf-file)))))
(defun org-ref--extract-entry-from-html
(html-buffer bibtex pdf-url &rest more-fields)
"At point, create a BibTeX entry using information extracted
from the HTML-BUFFER, and kill HTML-BUFFER."
(bibtex-mode)
(let ((bibtex (if (consp bibtex)
(org-ref--extract html-buffer (car bibtex) (cdr bibtex))
bibtex))
(pdf-url (if (consp pdf-url)
(org-ref--extract html-buffer (car pdf-url) (cdr pdf-url))
pdf-url))
(more-fields
(mapcar
(lambda (field)
(cons (car field)
(if (consp (cdr field))
(org-ref--extract html-buffer (cadr field) (cddr field))
(cdr field))))
more-fields)))
(insert bibtex)
(goto-char (point-min))
(while (search-forward "{\\n" nil t)
(replace-match "{"))
(goto-char (point-min))
(while (search-forward "\\n" nil t)
(replace-match "\n"))
(org-ref-clean-bibtex-entry)
(dolist (pair more-fields)
(when (cdr pair)
(bibtex-set-field (car pair) (cdr pair))))
(org-ref--get-pdf pdf-url))
(kill-buffer html-buffer))
(defun org-ref--html-buffer (url)
"Retrieve resource from URL, decode it, substitute XML entities,
and return the buffer."
(with-current-buffer (generate-new-buffer "org-ref--html")
(let ((url-request-method "GET"))
(url-insert (url-retrieve-synchronously url)))
(goto-char (point-min))
(insert (xml-substitute-special (buffer-string)))
(delete-region (point) (point-max))
(current-buffer)))
(defun org-ref-extract-from-openreview (id)
"At point, create a BibTeX entry for the given OpenReview ID."
(interactive "MOpenReview ID: ")
(let* ((url (concat "https://openreview.net/forum?id=" id))
(html-buffer (org-ref--html-buffer url)))
(org-ref--extract-entry-from-html
html-buffer
'("\"_bibtex\":\"\\(@.+?}\\)\"" . 1)
(replace-regexp-in-string "forum" "pdf" url)
'("abstract" .
("<meta name=\"citation_abstract\" content=\"\\(.+?\\(\n.*?\\)*?\\)\"/>" . 1))
'("area" .
("\"Please_choose_the_closest_area_that_your_submission_falls_into\":\"\\(.+?\\)\"" . 1))
'("keywords" . ("Keywords.*?\"note-content-value\">\\(.+?\\)</span>" . 1))
'("summary" .
("\\(Summary\\|TL;DR\\).*?\"note-content-value\">\\(.+?\\)</span>" . 2))
;; Should we proactively download supplementary materials too?
(cons "supp"
(if-let ((supp (org-ref--extract
html-buffer
">Supplementary Material<.*?href=\"\\([^\"]+\\)" 1)))
(concat "https://openreview.net" supp))))))
(defun org-ref-extract-from-pmlr (url)
"At point, create a BibTeX entry for the given PMLR URL."
(interactive "MPMLR URL: ")
(org-ref--extract-entry-from-html
(org-ref--html-buffer url)
'("id=\"bibtex\">\n\\(@.+\\(\n.*?\\)+?\\)\n</" . 1)
'("{\\(http.+\\.pdf\\)}" . 1)
;; Should we proactively download supplementary materials too?
'("supp" . ("href=\"\\(https?://proceedings\\.mlr\\.press/[^\"]+?-supp[^\"]*?\\)\".*?>Supplementary PDF</" . 1))))
(defun org-ref-extract-from-neurips (url)
"At point, create a BibTeX entry for the given NeurIPS Abstract URL."
(interactive "MNeurIPS Abstract URL: ")
(let ((hash (progn (string-match "/\\([0-9a-f]+\\)-" url)
(match-string 1 url)))
(neurips-url "https://proceedings.neurips.cc")
(html-buffer (org-ref--html-buffer url))
(bibtex))
(with-current-buffer html-buffer
(goto-char (point-min))
(re-search-forward "href=[\"']\\([^\"']+bibtex[^\"']*\\)[\"']")
(let ((bibtex-url (match-string 1)))
(with-temp-buffer
(url-insert
(url-retrieve-synchronously (concat neurips-url bibtex-url)))
(setq bibtex (buffer-string)))))
(org-ref--extract-entry-from-html
html-buffer
bibtex
(concat neurips-url
(org-ref--extract html-buffer
"href=[\"']\\([^\"']+-Paper[^\"']*\\)[\"']" 1))
(cons "url" url)
'("abstract" . ("<h4>Abstract</h4>[ \n]*?\\(<p>\\)+\\(.+?\\)</p>" . 2))
;; Should we proactively download supplementary materials too?
(cons "supp"
(if-let
((supp (org-ref--extract
html-buffer
"href=[\"']\\([^\"']+-Supplemental[^\"']*\\)[\"']" 1)))
(concat neurips-url supp))))))
(defun org-ref-extract-from-cvf (url)
"At point, create a BibTeX entry for the given CVF HTML URL."
(interactive "MCVF HTML URL: ")
(let ((cvf-url "https://openaccess.thecvf.com")
(html-buffer (org-ref--html-buffer url)))
(org-ref--extract-entry-from-html
html-buffer
'("class=\"bibref[^\"]*\">[ \n]*\\(@.+?\\(\n.*?\\)+?\\)[ \n]*</" . 1)
(concat cvf-url (org-ref--extract
html-buffer "<a href=[\"']\\([^\"']+\\)[\"']>pdf</a>" 1))
(cons "url" url)
'("abstract" . ("id=\"abstract\">[ \n]*\\([^<]+\\)[ \n]*</" . 1))
;; Should we proactively download supplementary materials too?
(cons "supp" (concat cvf-url
(org-ref--extract html-buffer
"href=[\"']\\([^\"']+\\)[\"']>supp</"
1))))))
(provide 'org-ref-extract)
;;; org-ref-extract.el ends here

View File

@@ -429,13 +429,13 @@ This is intended to be run in `org-export-before-parsing-hook'."
(nthcdr 2 (org-babel-read-table))))))))))
;; Delete the table
(when entries
(setf (buffer-substring begin end) "")
(cl--set-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)))))))
(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))))))
;;* Acronyms
@@ -447,7 +447,7 @@ This is intended to be run in `org-export-before-parsing-hook'."
FULL is the expanded acronym.
This is not the preferred way to add acronyms, you should add
them manually to the acroynms table."
them manually to the acronyms table."
(interactive "sLabel: \nsAcronym: \nsFull name: ")
(save-excursion
(re-search-backward "#\\+latex_header" nil t)
@@ -668,13 +668,13 @@ This will run in `org-export-before-parsing-hook'."
(nthcdr 2 (org-babel-read-table))))))))))
(when entries
;; Delete the table
(setf (buffer-substring begin end) "")
(cl--set-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)))))))
(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))))))
;; * Interactive command to insert acroynm/glossary links
@@ -907,9 +907,9 @@ Meant for non-LaTeX exports."
;; skip header and hline
(nthcdr 2 (org-babel-read-table))
;; delete the table
(setf (buffer-substring (org-element-property :begin el)
(org-element-property :end el))
""))))
(cl--set-buffer-substring (org-element-property :begin el)
(org-element-property :end el)
""))))
nil t))
(setq acronyms (org-element-map
(org-element-parse-buffer)
@@ -922,9 +922,9 @@ Meant for non-LaTeX exports."
(prog1
(nthcdr 2 (org-babel-read-table))
;; delete the table
(setf (buffer-substring (org-element-property :begin el)
(org-element-property :end el))
""))))
(cl--set-buffer-substring (org-element-property :begin el)
(org-element-property :end el)
""))))
nil t))
;; Replace printglossary link
@@ -939,20 +939,20 @@ Meant for non-LaTeX exports."
lnk))
nil t))
(when printglossary-link
(setf (buffer-substring (org-element-property :begin printglossary-link)
(org-element-property :end printglossary-link))
(concat "*Glossary*\n"
(string-join
(cl-loop for (label name description) in glossary collect
(format "<<%s>>\n- %s :: %s" label name description))
"\n")
(cl--set-buffer-substring (org-element-property :begin printglossary-link)
(org-element-property :end printglossary-link)
(concat "*Glossary*\n"
(string-join
(cl-loop for (label name description) in glossary collect
(format "<<%s>>\n- %s :: %s" label name description))
"\n")
"\n*Acronyms*\n"
(string-join
(cl-loop for (label name description) in acronyms collect
(format "<<%s>>\n- %s :: %s " label name description))
"\n"))))
"\n*Acronyms*\n"
(string-join
(cl-loop for (label name description) in acronyms collect
(format "<<%s>>\n- %s :: %s " label name description))
"\n"))))
;; Replace links
@@ -967,13 +967,13 @@ Meant for non-LaTeX exports."
lnk))))
;; For each link, replace with [[label][link description]]
(cl-loop for lnk in (reverse links) do
(setf (buffer-substring (org-element-property :begin lnk)
(org-element-property :end lnk))
(format "[[%s][%s]]%s"
(org-element-property :path lnk)
(buffer-substring (org-element-property :contents-begin lnk)
(org-element-property :contents-end lnk))
(make-string (org-element-property :post-blank lnk) ? )))))))
(cl--set-buffer-substring (org-element-property :begin lnk)
(org-element-property :end lnk)
(format "[[%s][%s]]%s"
(org-element-property :path lnk)
(buffer-substring (org-element-property :contents-begin lnk)
(org-element-property :contents-end lnk))
(make-string (org-element-property :post-blank lnk) ? )))))))
(provide 'org-ref-glossary)

View File

@@ -191,5 +191,69 @@ in the file. Data comes from www.ebook.de."
(s-trim (buffer-string))))
(save-buffer))))
(defun isbn-to-bibtex-open-library (isbn bibfile)
"Retrieve bibtex entry for a book with ISBN using openlibrary.org.
API: https://openlibrary.org/developers/api
"
(interactive
(list
(read-string
"ISBN: "
;; now set initial input
(cond
;; If region is active and it starts with a number, we use it
((and (region-active-p)
(s-match "^[0-9]" (buffer-substring (region-beginning) (region-end))))
(buffer-substring (region-beginning) (region-end)))
;; if first entry in kill ring starts with a number assume it is an isbn
;; and use it as the guess
((stringp (car kill-ring))
(when (s-match "^[0-9]" (car kill-ring))
(car kill-ring)))
;; type or paste it in
(t
nil)))
(completing-read "Bibfile: " (org-ref-possible-bibfiles))))
(let* ((url (format "https://openlibrary.org/isbn/%s.json" isbn))
(json (with-current-buffer (url-retrieve-synchronously url)
(json-read-from-string (string-trim (buffer-substring url-http-end-of-headers (point-max))))))
(title (cdr (assoc 'title json)))
(publisher (s-join ", " (cdr (assoc 'publishers json))))
(year (cdr (assoc 'publish_date json)))
;; this is a list of urls
(author-urls (cdr (assoc 'authors json)))
(authors (s-join " and "
(cl-loop for aurl across author-urls
collect
(with-current-buffer (url-retrieve-synchronously
(format "https://openlibrary.org%s.json"
(cdr (assoc 'key aurl))))
(cdr (assoc 'personal_name
(json-read-from-string
(string-trim (buffer-substring url-http-end-of-headers (point-max))))))))))
(burl (format "https://openlibrary.org%s" (cdr (assoc 'key json))))
(bibtex (format "@Book{,
author = {%s},
title = {%s},
publisher = {%s},
year = {%s},
url = {%s}
}"
authors
title
publisher
year
burl)))
(with-current-buffer (find-file-noselect bibfile)
(goto-char (point-max))
(insert "\n\n")
(insert bibtex)
(org-ref-clean-bibtex-entry)
(save-buffer))))
(provide 'org-ref-isbn)
;;; org-ref-isbn.el ends here

View File

@@ -58,7 +58,17 @@
(insert (bibtex-completion-apa-format-reference
(cdr (assoc "=key=" candidate)))))
"Insert formatted citation")
("f" (lambda (_candidate) (ivy-bibtex-fallback ivy-text)) "Fallback options"))
("f" (lambda (_candidate) (ivy-bibtex-fallback ivy-text)) "Fallback options")
("d" (lambda (_)
"Add a bibtex entry from doi and insert cite to it at point."
(funcall-interactively 'doi-utils-add-bibtex-entry-from-doi
(read-string
"DOI: "
;; now set initial input
(doi-utils-maybe-doi-from-region-or-current-kill)))
(org-ref-insert-cite-key
(current-kill 0 t)))
"Insert from a DOI"))
"Alternate actions to do instead of inserting."
:type '(list (repeat (string function string)))
:group 'org-ref)

View File

@@ -270,33 +270,34 @@ replaced by links to them."
link-replacements)))
(cl-loop for il in index-links collect
(setf (buffer-substring (org-element-property :begin il)
(org-element-property :end il))
(cdr (assoc (org-element-property :begin il) link-replacements))))
(cl--set-buffer-substring
(org-element-property :begin il)
(org-element-property :end il)
(cdr (assoc (org-element-property :begin il) link-replacements))))
;; Now we replace the printindex link
(org-element-map (org-element-parse-buffer) 'link
(lambda (lnk)
(when (string= "printindex" (org-element-property :type lnk))
(setf (buffer-substring (org-element-property :begin lnk)
(org-element-property :end lnk))
;; If sorted-groups is empty, we should do nothing I think.
(if sorted-groups
(format "*Index*\n\n%s"
(string-join
(cl-loop for (key . links) in sorted-groups collect
(format "%s: %s"
key
(string-join
(cl-loop for i from 0 for lnk in links collect
(format "[[%s-%s][%s-%s]] "
(org-element-property :path lnk)
i
(org-element-property :path lnk)
i))
", ")))
"\n\n"))
"")))))))
(cl--set-buffer-substring (org-element-property :begin lnk)
(org-element-property :end lnk)
;; If sorted-groups is empty, we should do nothing I think.
(if sorted-groups
(format "*Index*\n\n%s"
(string-join
(cl-loop for (key . links) in sorted-groups collect
(format "%s: %s"
key
(string-join
(cl-loop for i from 0 for lnk in links collect
(format "[[%s-%s][%s-%s]] "
(org-element-property :path lnk)
i
(org-element-property :path lnk)
i))
", ")))
"\n\n"))
"")))))))
(provide 'org-ref-misc-links)

View File

@@ -140,15 +140,7 @@ should be open in Emacs using the `pdf-tools' package."
(let ((key (org-ref-bibtex-key-from-doi doi)))
(funcall org-ref-pdf-to-bibtex-function
(buffer-file-name)
(expand-file-name (format "%s.pdf" key)
(cond
((stringp bibtex-completion-library-path)
bibtex-completion-library-path)
((and (listp bibtex-completion-library-path)
(= 1 (length bibtex-completion-library-path)))
(car bibtex-completion-library-path))
(t
(completing-read "Dir: " bibtex-completion-library-path))))))))
(expand-file-name (format "%s.pdf" key) (org-ref-library-path))))))
;;;###autoload

View File

@@ -1,4 +1,4 @@
(define-package "org-ref" "20221129.1925" "citations, cross-references and bibliographies in org-mode"
(define-package "org-ref" "20231101.2355" "citations, cross-references and bibliographies in org-mode"
'((org "9.4")
(dash "0")
(s "0")
@@ -10,7 +10,9 @@
(bibtex-completion "0")
(citeproc "0")
(ox-pandoc "0"))
:commit "26735e914f09559c7b9753462a596e62595b135e" :authors
:commit "195b8d3209aff956ecdd755422700e8517a34d11" :authors
'(("John Kitchin" . "jkitchin@andrew.cmu.edu"))
:maintainers
'(("John Kitchin" . "jkitchin@andrew.cmu.edu"))
:maintainer
'("John Kitchin" . "jkitchin@andrew.cmu.edu")

View File

@@ -0,0 +1,107 @@
;;; org-ref-publish.el --- org-publish with org-ref
;;; Commentary:
;; First draft proposed by madhu 230826 (Madhu <enometh@meer.net>)
;; This code provides publishing capability that leverages
;;; Code:
;; modified from org-publish-org-to to call org-ref-process-buffer before
;; calling org-export-to-file
(defun org-ref-publish-org-to (backend filename extension plist &optional pub-dir)
"Publish an Org file to a specified backend using org-ref.
BACKEND is a symbol representing the backend used for
transcoding. FILENAME is the filename of the Org file to be
published. EXTENSION is the extension used for the output
string, with the leading dot. PLIST is the property list for the
given project.
Optional argument PUB-DIR, when non-nil is the publishing
directory.
Return output file name."
(unless (or (not pub-dir) (file-exists-p pub-dir))
(make-directory pub-dir t))
;; Check if a buffer visiting FILENAME is already open.
(let* ((org-inhibit-startup t)
(visiting (find-buffer-visiting filename))
(work-buffer (or visiting (find-file-noselect filename))))
(unwind-protect
(with-current-buffer work-buffer
(let* ((output (org-export-output-file-name extension nil pub-dir)))
(org-export-with-buffer-copy
(org-export-expand-include-keyword)
(goto-char (point-min))
(org-ref-process-buffer backend nil) ;no subtreep
(goto-char (point-min))
(org-export-to-file backend output
nil nil nil (plist-get plist :body-only)
;; Add `org-publish--store-crossrefs' and
;; `org-publish-collect-index' to final output filters.
;; The latter isn't dependent on `:makeindex', since we
;; want to keep it up-to-date in cache anyway.
(org-combine-plists
plist
`(:crossrefs
,(org-publish-cache-get-file-property
;; Normalize file names in cache.
(file-truename filename) :crossrefs nil t)
:filter-final-output
(org-publish--store-crossrefs
org-publish-collect-index
,@(plist-get plist :filter-final-output))))))))
;; Remove opened buffer in the process.
(unless visiting (kill-buffer work-buffer)))))
;; modified from org-html-publish-to-html to call org-ref-publish-org-to instead
;; of org-publish-org-to
(defun org-ref-publish-to-html (plist filename pub-dir)
"Publish an org file to HTML through org-ref.
FILENAME is the filename of the Org file to be published. PLIST
is the property list for the given project. PUB-DIR is the
publishing directory.
Return output file name."
(org-ref-publish-org-to 'html filename
(concat (when (> (length org-html-extension) 0) ".")
(or (plist-get plist :html-extension)
org-html-extension
"html"))
plist pub-dir))
;; modified from org-latex-publish-to-latex to call org-ref-publish-org-to
;; instead of org-publish-org-to
(defun org-ref-publish-to-latex (plist filename pub-dir)
"Publish an Org file to LaTeX using org-ref.
FILENAME is the filename of the Org file to be published. PLIST
is the property list for the given project. PUB-DIR is the
publishing directory.
Return output file name."
(org-ref-publish-org-to 'latex filename ".tex" plist pub-dir))
;; modified from org-latex-publish-to-pdf to call org-ref-publish-org-to instead of org-publish-org-to
(defun org-ref-publish-to-pdf (plist filename pub-dir)
"Publish an Org file to PDF (via LaTeX) using org-ref.
FILENAME is the filename of the Org file to be published. PLIST
is the property list for the given project. PUB-DIR is the
publishing directory.
Return output file name."
(org-publish-attachment
plist
(let ((default-directory (file-name-directory filename)))
(org-latex-compile
(org-ref-publish-org-to
'latex filename ".tex" plist (file-name-directory filename))))
pub-dir))
(provide 'org-ref-publish)
;;; org-ref-publish.el ends here

View File

@@ -23,6 +23,7 @@
;;; Code:
(eval-and-compile (require 'org-macs))
(eval-and-compile (require 'ol))
(require 'hydra)
(defcustom org-ref-default-ref-type "ref"
@@ -83,6 +84,7 @@ The label should always be in group 1.")
("pageref" "to the page number a label is on")
("nameref" "to the name associated with a label (e.g. a caption)")
("autoref" "from hyperref, adds automatic prefixes")
("Autoref" "from hyperref, capitalized version of autoref")
("cref" "from cleveref, adds automatic prefixes, and condenses multiple refs")
("Cref" "from cleveref, capitalized version of cref")
("crefrange" "from cleveref, makes a range of refs from two refs with a prefix")
@@ -113,11 +115,11 @@ The label should always be in group 1.")
(path (org-element-property :path cite-link))
(deltap (- (point) begin)))
;; note this does not respect brackets
(setf (buffer-substring begin end)
(concat
(if bracketp "[[" "")
new-type ":" path
(if bracketp "]]" "")))
(cl--set-buffer-substring begin end
(concat
(if bracketp "[[" "")
new-type ":" path
(if bracketp "]]" "")))
;; try to preserve the character the point is on.
(goto-char (+ begin deltap (- (length new-type) (length old-type))))))
@@ -275,9 +277,10 @@ This is meant to be used with `apply-partially' in the link definitions."
(concat refstyle ":" (completing-read "Label: " (org-ref-get-labels))))
(defun org-ref-store-ref ()
(defun org-ref-store-ref-link (&optional reftype)
"Store a ref link to a label. The output will be a ref to that label."
;; First we have to make sure we are on a label link.
(unless reftype (setq reftype "ref"))
(let* ((object (and (eq major-mode 'org-mode) (org-element-context)))
(label (cond
;; here literally on a label link.
@@ -357,17 +360,16 @@ This is meant to be used with `apply-partially' in the link definitions."
nil))))
(when label
(cl-loop for (reftype _) in org-ref-ref-types do
(org-link-store-props
:type reftype
:link (concat reftype ":" label)))
(format (concat org-ref-default-ref-type ":" label)))))
(org-link-store-props
:type reftype
:link (concat reftype ":" label))
t)))
;; ** ref link
(org-link-set-parameters "ref"
:store #'org-ref-store-ref
:store (defun org-ref-store-ref () (org-ref-store-ref-link "ref"))
:complete (apply-partially #'org-ref-complete-link "ref")
:activate-func #'org-ref-ref-activate
:follow #'org-ref-ref-jump-to
@@ -379,7 +381,7 @@ This is meant to be used with `apply-partially' in the link definitions."
;;** pageref link
(org-link-set-parameters "pageref"
:store #'org-ref-store-ref
:store (defun org-ref-store-pageref () (org-ref-store-ref-link "pageref"))
:complete (apply-partially #'org-ref-complete-link "pageref")
:activate-func #'org-ref-ref-activate
:follow #'org-ref-ref-jump-to
@@ -392,7 +394,7 @@ This is meant to be used with `apply-partially' in the link definitions."
;;** nameref link
(org-link-set-parameters "nameref"
:store #'org-ref-store-ref
:store (defun org-ref-store-nameref () (org-ref-store-ref-link "nameref"))
:complete (apply-partially #'org-ref-complete-link "nameref")
:activate-func #'org-ref-ref-activate
:follow #'org-ref-ref-jump-to
@@ -403,7 +405,7 @@ This is meant to be used with `apply-partially' in the link definitions."
;;** eqref link
(org-link-set-parameters "eqref"
:store #'org-ref-store-ref
:store (defun org-ref-store-eqref () (org-ref-store-ref-link "eqref"))
:complete (apply-partially #'org-ref-complete-link "eqref")
:activate-func #'org-ref-ref-activate
:follow #'org-ref-ref-jump-to
@@ -414,7 +416,7 @@ This is meant to be used with `apply-partially' in the link definitions."
;;** autoref link
(org-link-set-parameters "autoref"
:store #'org-ref-store-ref
:store (defun org-ref-store-autoref () (org-ref-store-ref-link "autoref"))
:complete (apply-partially #'org-ref-complete-link "autoref")
:activate-func #'org-ref-ref-activate
:follow #'org-ref-ref-jump-to
@@ -422,13 +424,23 @@ This is meant to be used with `apply-partially' in the link definitions."
:face 'org-ref-ref-face
:help-echo #'org-ref-ref-help-echo)
(org-link-set-parameters "Autoref"
:store (defun org-ref-store-Autoref () (org-ref-store-ref-link "Autoref"))
:complete (apply-partially #'org-ref-complete-link "Autoref")
:activate-func #'org-ref-ref-activate
:follow #'org-ref-ref-jump-to
:export (apply-partially #'org-ref-ref-export "Autoref")
:face 'org-ref-ref-face
:help-echo #'org-ref-ref-help-echo)
;;** cref link
;; for LaTeX cleveref package:
;; https://www.ctan.org/tex-archive/macros/latex/contrib/cleveref
(org-link-set-parameters "cref"
:store #'org-ref-store-ref
:store (defun org-ref-store-cref () (org-ref-store-ref-link "cref"))
:complete (apply-partially #'org-ref-complete-link "cref")
:activate-func #'org-ref-ref-activate
:follow #'org-ref-ref-jump-to
@@ -438,7 +450,7 @@ This is meant to be used with `apply-partially' in the link definitions."
(org-link-set-parameters "Cref"
:store #'org-ref-store-ref
:store (defun org-ref-store-Cref () (org-ref-store-ref-link "Cref"))
:complete (apply-partially #'org-ref-complete-link "Cref")
:activate-func #'org-ref-ref-activate
:follow #'org-ref-ref-jump-to
@@ -458,7 +470,7 @@ This is meant to be used with `apply-partially' in the link definitions."
(pcase backend
('latex
(let ((labels (split-string path ",")))
(format "\\crefrange{%s}{%s}" (cl-first labels) (cl-second labels))))))
(format "\\Crefrange{%s}{%s}" (cl-first labels) (cl-second labels))))))
(defun org-ref-crefrange-complete (cmd &optional _arg)
@@ -487,6 +499,19 @@ This is meant to be used with `apply-partially' in the link definitions."
:help-echo #'org-ref-ref-help-echo)
;; ** remove store functions
(defun org-ref-ref-remove-store ()
"Remove the store functions from ref links.
These tend to clobber the org store links. You can use C-u C-u
C-c C-l to not use them, but if you prefer not to use them, this
function removes the store functions from the links."
(interactive)
(cl-loop for reflink in '("ref" "pageref" "nameref" "eqref" "autoref" "Autoref"
"cref" "Cref" "crefrange" "Crefrange")
do
(setf (cdr (assoc reflink org-link-parameters))
(org-plist-delete (cdr (assoc reflink org-link-parameters)) :store))))
;; * Insert link
(defvar org-ref-equation-environments
'("equation"

View File

@@ -134,6 +134,9 @@ environments)."
(when (or (and (eq type 'equation)
(string-match "\\\\begin{equation}"
(org-element-property :value e)))
(and (eq type 'equation)
(string-match "\\\\begin{align}"
(org-element-property :value e)))
(and (eq type 'proof) (string-match "\\\\begin{proof}"
(org-element-property :value e))))
@@ -144,7 +147,13 @@ environments)."
;; latex label in the value
((string-match "\\\\label{\\(.*\\)}" (org-element-property :value e))
(match-string 1 (org-element-property :value e))))))
(save-match-data
(let ((pos 1)
matches)
(while (string-match "\\\\label{\\(.*\\)}" (org-element-property :value e) pos)
(push (match-string 1 (org-element-property :value e)) matches)
(setq pos (match-end 0)))
matches))))))
;; special blocks
('special-block
@@ -169,7 +178,9 @@ environments)."
('src-block
(when-let (name (org-element-property :name e))
name)))))))))
referencables))
;; the align equation environment needs to be flattened
(cl-loop for type in referencables
collect (cons (car type) (-flatten (cdr type))))))
(defun org-ref-refproc-get-type (label referenceables)
@@ -340,9 +351,7 @@ REFERENCEABLES comes from `org-ref-refproc-referenceables'.
If CAPITALIZE is non-nil, capitalize the first entry (this is for
Cref) and is different than the capitalize option in #+refproc:
which capitalizes each prefix."
(let* ((options (org-ref-refproc-get-options))
;; I guess I know this will be cref or Cref here.
;; (ref-type (org-element-property :type ref-link))
(let* ((options (org-ref-refproc-get-options))
(labels (split-string (org-element-property :path ref-link) ","))
(post-blanks (org-element-property :post-blank ref-link))
(data (cl-loop for label in labels collect (org-ref-refproc-get-type label referenceables)))
@@ -371,12 +380,17 @@ which capitalizes each prefix."
:full)))
(when (plist-get options :capitalize)
(setq prefix (capitalize prefix)))
(format "%s [[%s]]"
(format "%s %s"
;; prefix
prefix
(concat
(if (eq 'section (plist-get collection :type)) "#" "")
(plist-get collection :label))))
(cond
((eq 'section (plist-get collection :type))
(format "[[#%s]]" (plist-get collection :label)))
((eq 'equation (plist-get collection :type))
(format "\\ref{%s}" (plist-get collection :label)))
(t
(format "[[%s]]" (plist-get collection :label)))))))
(2
;; the prefix can be found from the first label, but we have to make it plural.
(setq prefix-data (cdr (assoc (plist-get (cl-first collection) :type)

View File

@@ -190,6 +190,16 @@ You set =pdftotext-executable= to ${pdftotext-executable} (exists: ${pdftotext-e
(bibtex-copy-entry-as-kill)
(pop bibtex-entry-kill-ring)))
(defun org-ref-library-path ()
"return the library path"
(cond
((stringp bibtex-completion-library-path)
bibtex-completion-library-path)
((and (listp bibtex-completion-library-path)
(= 1 (length bibtex-completion-library-path)))
(car bibtex-completion-library-path))
(t
(completing-read "Dir: " bibtex-completion-library-path))))
;;*** key at point functions
(defun org-ref-get-pdf-filename (key)
@@ -261,6 +271,36 @@ Jabref, Mendeley and Zotero. See `bibtex-completion-find-pdf'."
(completing-read "pdf: " pdf-file))))))
;;;###autoload
(defun org-ref-add-pdf-at-point (&optional prefix)
"Add the pdf for bibtex key under point if it exists.
Similar to org-ref-bibtex-assoc-pdf-with-entry prompt for pdf
associated with bibtex key at point and rename it. Check whether a
pdf already exists in `bibtex-completion-library' with the name
'[bibtexkey].pdf'. If the file does not exist, rename it to
'[bibtexkey].pdf' using
`org-ref-bibtex-assoc-pdf-with-entry-move-function' and place it
in a directory. Optional PREFIX argument toggles between
`rename-file' and `copy-file'."
(interactive)
(let* ((bibtex-completion-bibliography (org-ref-find-bibliography))
(results (org-ref-get-bibtex-key-and-file))
(key (car results))
(pdf-file (bibtex-completion-find-pdf-in-library key)))
(if pdf-file
(message "PDF for key [%s] already exists %s" key pdf-file)
(let* (
(source-file-name (read-file-name (format "Select pdf file associated with key [%s]: " key)
org-ref-bibtex-pdf-download-dir))
(dest-file-name (expand-file-name (format "%s.pdf" key) (org-ref-library-path)))
(file-move-func (org-ref-bibtex-get-file-move-func prefix))
)
(progn
(funcall file-move-func source-file-name dest-file-name)
(message "added file %s to key %s" dest-file-name key))))))
;;;###autoload
(defun org-ref-open-url-at-point ()
"Open the url for bibtex key under point."
@@ -1131,13 +1171,18 @@ if FORCE is non-nil reparse the buffer no matter what."
;;** Find non-ascii charaters
;;** Find non-ascii characters
;;;###autoload
(defun org-ref-find-non-ascii-characters ()
"Find non-ascii characters in the buffer. Useful for cleaning up bibtex files."
(interactive)
(occur "[^[:ascii:]]"))
;;* Utilities
;;** Extract bibtex entries in org-file
;;;###autoload
(defun org-ref-extract-bibtex-to-file (bibfile &optional clobber)
"Extract all bibtex entries for citations buffer to BIBFILE.
@@ -1176,10 +1221,6 @@ which will CLOBBER the file."
"\n\n")))))
;;* Utilities
;;** Extract bibtex entries in org-file
;;;###autoload
(defun org-ref-extract-bibtex-entries ()
"Extract the bibtex entries in the current buffer into a bibtex src block."
@@ -1216,6 +1257,22 @@ which will CLOBBER the file."
"\n\n")))))
;;** Extract cited pdfs
;;;###autoload
(defun org-ref-extract-cited-pdfs (newdir)
"Copy PDFs in citations in current buffer to NEWDIR."
(interactive (list (read-directory-name "Copy to: ")))
;; Make sure newdir exists
(unless (file-directory-p newdir)
(mkdir newdir t))
(cl-loop for key in (org-ref-get-bibtex-keys) do
(let ((pdf (org-ref-get-pdf-filename key)))
(if (file-exists-p pdf)
(progn
(message "Copying %s to %s." pdf newdir)
(copy-file pdf newdir t))
(message "%s not found" pdf)))))
(provide 'org-ref-utils)