|
|
- ;;; org-ref-utils.el --- Utility functions for org-ref -*- lexical-binding: t; -*-
-
- ;; Copyright (C) 2016 John Kitchin
-
- ;; Author: John Kitchin <jkitchin@andrew.cmu.edu>
- ;; 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:
-
- ;;
- (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
- :group 'org-ref)
-
- (defcustom org-ref-bib-html-sorted nil
- "Determine whether the HTML bibliography should be sorted."
- :type 'boolean
- :group 'org-ref)
-
- (defcustom org-ref-search-whitespace-regexp "\\s-+"
- "A whitespace regexp for use in `org-ref-strip-string."
- :group 'org-ref)
-
- (defvar org-ref-cite-types)
- (defvar org-ref-get-pdf-filename-function)
- (defvar org-ref-notes-function)
- (defvar org-ref-bibliography-entry-format)
-
- (declare-function 'org-ref-get-bibtex-key-and-file "org-ref-core.el")
- (declare-function 'org-ref-key-in-file-p "org-ref-core.el")
- (declare-function 'org-ref-find-bibliography "org-ref-core.el")
- (declare-function 'org-ref-bib-citation "org-ref-core.el")
- (declare-function 'org-ref-get-bibtex-key-under-cursor "org-ref-core.el")
-
- ;;; Code:
- ;;;###autoload
- (defun org-ref-version ()
- "Provide a version string for org-ref.
- Copies the string to the clipboard."
- (interactive)
- ;; version in the el file.
- (let* ((org-ref-el (concat
- (file-name-sans-extension
- (locate-library "org-ref"))
- ".el"))
- (org-ref-dir (file-name-directory org-ref-el))
- org-version
- git-commit
- version-string)
-
- (setq org-version (with-temp-buffer
- (insert-file-contents org-ref-el)
- (goto-char (point-min))
- (re-search-forward ";; Version:")
- (s-trim (buffer-substring (point)
- (line-end-position)))))
-
- (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")))))
-
- (setq version-string (format "org-ref: Version %s%s" org-version
- (if git-commit
- (format " (git-commit %s)" git-commit)
- "")))
- (kill-new version-string)
- (message version-string)))
-
-
- (defun org-ref-report-issue ()
- "Report an issue in org-ref.
- Opens https://github.com/jkitchin/org-ref/issues/new."
- (save-window-excursion
- (org-ref-debug)
- (kill-new (buffer-string)))
- (message "org-ref-debug has been run. You can paste the results in the issue website if you like.")
- (browse-url "https://github.com/jkitchin/org-ref/issues/new"))
-
-
- ;;* Debug(require 'org-ref-pdf)
- (defmacro ords (&rest body)
- "Evaluate BODY and return a string."
- `(format "%s" (progn ,@body)))
-
-
- ;;;###autoload
- (defun org-ref-debug ()
- "Print some debug information to a buffer."
- (interactive)
- (switch-to-buffer "*org-ref-debug*")
- (erase-buffer)
- (org-mode)
- (insert
- (s-format "#+TITLE: org-ref debug
-
- ${org-ref-version}
-
- * Variables
- 1. org-ref-completion-library: ${org-ref-completion-library}
- 2. org-ref-bibliography-notes: ${org-ref-bibliography-notes} (exists ${orbn-p})
- 3. org-ref-default-bibliography: ${org-ref-default-bibliography} (exists ${ordb-p}) (listp ${ordb-listp})
- 4. org-ref-pdf-directory: ${org-ref-pdf-directory} (exists ${orpd-p})
-
- * System
- system-type: ${system}
- system-configuration: ${system-configuration}
- window system: ${window-system}
- Emacs: ${emacs-version}
- org-version: ${org-version}
-
- * about org-ref
- org-ref installed in ${org-ref-location}.
-
- ** Dependencies
- helm-bibtex ${helm-bibtex-path}
-
- * org-ref-pdf (loaded: ${org-ref-pdf-p})
- system pdftotext: ${pdftotext}
- You set pdftotext-executable to ${pdftotext-executable} (exists: ${pdftotext-executable-p})
-
- * org-ref-url-utils (loaded: ${org-ref-url-p})
-
- * export variables
- org-latex-pdf-process:
- ${org-latex-pdf-process}
- "
- 'aget
- `(("org-ref-completion-library" . ,(format "%s" org-ref-completion-library))
- ("org-ref-bibliography-notes" . ,(format "%s" org-ref-bibliography-notes))
- ("org-ref-bibliography-notes exists" . ,(format "%s" (when org-ref-bibliography-notes
- (file-exists-p org-ref-bibliography-notes))))
- ("org-ref-version" . ,(org-ref-version))
- ("org-latex-pdf-process" . ,(format "%S" 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)))
- ("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")))
-
- ("system" . ,(format "System: %s" system-type))
- ("system-configuration" . ,(ords system-configuration))
- ("window-system" . ,(format "Window system: %s" window-system))
- ("emacs-version" . ,(ords (emacs-version)))
- ("org-version" . ,(org-version))
-
- ("helm-bibtex-path" . ,(ords (locate-library "helm-bibtex")))
-
- ("org-ref-pdf-p" . ,(ords (featurep 'org-ref-pdf)))
- ("pdftotext" . ,(ords (if (featurep 'org-ref-pdf)
- (executable-find "pdftotext")
- "org-ref-pdf not loaded")))
- ("pdftotext-executable" . ,(ords (if (featurep 'org-ref-pdf)
- pdftotext-executable
- "org-ref-pdf not loaded")))
- ("pdftotext-executable-p" . ,(ords (if (featurep 'org-ref-pdf)
- (or
- (executable-find pdftotext-executable)
- (file-exists-p pdftotext-executable))
- "org-ref-pdf not loaded")))
- ("org-ref-url-p" . ,(ords (featurep 'org-ref-url)))))))
-
-
-
- (defun org-ref-reftex-get-bib-field (field entry &optional format)
- "Get FIELD from a bibtex ENTRY in optional FORMAT.
- Similar to `reftex-get-bib-field', but removes enclosing braces
- and quotes in FIELD in the bibtex ENTRY."
- (let ((result))
- (setq result (reftex-get-bib-field field entry format))
- (when (and (not (string= result "")) (string= "{" (substring result 0 1)))
- (setq result (substring result 1 -1)))
- (when (and (not (string= result "")) (string= "\"" (substring result 0 1)))
- (setq result (substring result 1 -1)))
- result))
-
- (defun org-ref-reftex-format-citation (entry format)
- "Format the bibtex ENTRY according to the FORMAT argument.
- ENTRY is from `bibtex-parse-entry'
- The FORMAT is a string with these percent escapes.
-
- In the format, the following percent escapes will be expanded.
-
- %l The BibTeX label of the citation.
- %a List of author names, see also `reftex-cite-punctuation'.
- %2a Like %a, but abbreviate more than 2 authors like Jones et al.
- %A First author name only.
- %e Works like %a, but on list of editor names. (%2e and %E work as well)
-
- It is also possible to access all other BibTeX database fields:
- %b booktitle %c chapter %d edition %h howpublished
- %i institution %j journal %k key %m month
- %n number %o organization %p pages %P first page
- %r address %s school %u publisher %t title
- %v volume %y year
- %B booktitle, abbreviated %T title, abbreviated
- %U url
- %D doi
- %S series %N note
-
- %f pdf filename
- %F absolute pdf filename
-
- Usually, only %l is needed. The other stuff is mainly for the echo area
- display, and for (setq reftex-comment-citations t).
-
- %< as a special operator kills punctuation and space around it after the
- string has been formatted.
-
- A pair of square brackets indicates an optional argument, and RefTeX
- will prompt for the values of these arguments.
-
- Beware that all this only works with BibTeX database files. When
- citations are made from the \bibitems in an explicit thebibliography
- environment, only %l is available."
- ;; Format a citation from the info in the BibTeX ENTRY
- (unless (stringp format) (setq format "\\cite{%l}"))
-
- (if (and reftex-comment-citations
- (string-match "%l" reftex-cite-comment-format))
- (error "Reftex-cite-comment-format contains invalid %%l"))
-
- (while (string-match
- "\\(\\`\\|[^%]\\)\\(\\(%\\([0-9]*\\)\\([a-zA-Z]\\)\\)[.,;: ]*\\)"
- format)
- (let ((n (string-to-number (match-string 4 format)))
- (l (string-to-char (match-string 5 format)))
- rpl b e)
- (save-match-data
- (setq rpl
- (cond
- ((= l ?l) (concat
- (org-ref-reftex-get-bib-field "&key" entry)
- (if reftex-comment-citations
- reftex-cite-comment-format
- "")))
- ((= l ?a) (replace-regexp-in-string
- "\n\\|\t\\|\s+" " "
- (reftex-format-names
- (reftex-get-bib-names "author" entry)
- (or n 2))))
- ((= l ?A) (replace-regexp-in-string
- "\n\\|\t\\|\s+" " "
- (car (reftex-get-bib-names "author" entry))))
- ((= l ?b) (org-ref-reftex-get-bib-field "booktitle" entry "in: %s"))
- ((= l ?B) (reftex-abbreviate-title
- (org-ref-reftex-get-bib-field "booktitle" entry "in: %s")))
- ((= l ?c) (org-ref-reftex-get-bib-field "chapter" entry))
- ((= l ?d) (org-ref-reftex-get-bib-field "edition" entry))
- ((= l ?D) (org-ref-reftex-get-bib-field "doi" entry))
- ((= l ?e) (reftex-format-names
- (reftex-get-bib-names "editor" entry)
- (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 ?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)))
- (if (string= "" jt)
- (reftex-get-bib-field "journaltitle" entry)
- jt)))
- ((= l ?k) (org-ref-reftex-get-bib-field "=key=" entry))
- ((= l ?m) (org-ref-reftex-get-bib-field "month" entry))
- ((= l ?n) (org-ref-reftex-get-bib-field "number" entry))
- ((= l ?N) (org-ref-reftex-get-bib-field "note" entry))
- ((= l ?o) (org-ref-reftex-get-bib-field "organization" entry))
- ((= l ?p) (org-ref-reftex-get-bib-field "pages" entry))
- ((= l ?P) (car (split-string
- (org-ref-reftex-get-bib-field "pages" entry)
- "[- .]+")))
- ((= l ?s) (org-ref-reftex-get-bib-field "school" entry))
- ((= l ?S) (org-ref-reftex-get-bib-field "series" entry))
- ((= l ?u) (org-ref-reftex-get-bib-field "publisher" entry))
- ((= l ?U) (org-ref-reftex-get-bib-field "url" entry))
- ((= l ?r) (org-ref-reftex-get-bib-field "address" entry))
- ;; strip enclosing brackets from title if they are there
- ((= l ?t) (replace-regexp-in-string
- "\n\\|\t\\|\s+" " "
- (org-ref-reftex-get-bib-field "title" entry)))
- ((= l ?T) (reftex-abbreviate-title
- (replace-regexp-in-string
- "\n\\|\t\\|\s+" " "
- (org-ref-reftex-get-bib-field "title" entry))))
- ((= l ?v) (org-ref-reftex-get-bib-field "volume" entry))
- ((= l ?y) (org-ref-reftex-get-bib-field "year" entry)))))
-
- (if (string= rpl "")
- (setq b (match-beginning 2) e (match-end 2))
- (setq b (match-beginning 3) e (match-end 3)))
- (setq format (concat (substring format 0 b) rpl (substring format e)))))
- (while (string-match "%%" format)
- (setq format (replace-match "%" t t format)))
- (while (string-match "[ ,.;:]*%<" format)
- (setq format (replace-match "" t t format)))
- format)
-
-
- (defun org-ref-get-bibtex-entry-citation (key)
- "Return a string for the bibliography entry corresponding to KEY.
- Format according to the type in `org-ref-bibliography-entry-format'."
-
- (let ((org-ref-bibliography-files (org-ref-find-bibliography))
- (file) (entry) (bibtex-entry) (entry-type) (format))
-
- (setq file (catch 'result
- (cl-loop for file in org-ref-bibliography-files do
- (if (org-ref-key-in-file-p key (file-truename file))
- (throw 'result file)
- (message "%s not found in %s"
- key (file-truename 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))))
- (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)))))
- entry))
-
-
- (defun org-ref-get-bibtex-entry (key)
- "Return the bibtex entry as a string."
- (let ((org-ref-bibliography-files (org-ref-find-bibliography))
- (file) (entry))
-
- (setq file (catch 'result
- (cl-loop for file in org-ref-bibliography-files do
- (if (org-ref-key-in-file-p key (file-truename file))
- (throw 'result file)
- (message "%s not found in %s"
- key (file-truename file))))))
-
- (with-temp-buffer
- (insert-file-contents file)
- (bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
- (bibtex-search-entry key nil 0)
- (save-restriction
- (bibtex-narrow-to-entry)
- (setq entry (buffer-string)))
- entry)))
-
-
- ;;*** key at point functions
- (defun org-ref-get-pdf-filename (key)
- "Return the pdf filename associated with a bibtex KEY.
- This searches for the pattern KEY*.pdf. If one result is found it
- is returned, but if multiple results are found, e.g. there are
- related files to the KEY you are prompted for which one you want."
- (if org-ref-pdf-directory
- (let ((pdfs (-flatten (--map (file-expand-wildcards
- (f-join it (format "%s*.pdf" key)))
- (-flatten (list org-ref-pdf-directory))))))
- (cond
- ((= 0 (length pdfs))
- (expand-file-name (format "%s.pdf" key) org-ref-pdf-directory))
- ((= 1 (length pdfs))
- (car pdfs))
- ((> (length pdfs) 1)
- (completing-read "Choose: " pdfs))))
- ;; No org-ref-pdf-directory defined so return just a file name.
- (format "%s.pdf" key)))
-
-
- (defun org-ref-get-mendeley-filename (key)
- "Return the pdf filename indicated by mendeley file field.
- Falls back to `org-ref-get-pdf-filename' if file field does not exist.
- Contributed by https://github.com/autosquid.
- Argument KEY is the bibtex key."
- (let* ((results (org-ref-get-bibtex-key-and-file key))
- (bibfile (cdr results))
- entry)
- (with-temp-buffer
- (insert-file-contents bibfile)
- (bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
- (bibtex-search-entry key nil 0)
- (setq entry (bibtex-parse-entry))
- (let ((e (org-ref-reftex-get-bib-field "file" entry)))
- (if (> (length e) 4)
- (let ((clean-field (replace-regexp-in-string "{\\|}\\|\\\\" "" e)))
- (let ((first-file (car (split-string clean-field ";" t))))
- (format "/%s" (substring first-file 1
- (- (length first-file) 4)))))
- (format (concat
- (file-name-as-directory org-ref-pdf-directory)
- "%s.pdf")
- key))))))
-
- (defun org-ref-get-pdf-filename-helm-bibtex (key)
- "Use helm-bibtex to retrieve a PDF filename for KEY.
- helm-bibtex looks in both the configured directory
- `bibtex-completion-library-path' and in the fields of the bibtex
- item for a filename. It understands file fields exported by
- Jabref, Mendeley and Zotero. See `bibtex-completion-find-pdf'."
- (let ((bibtex-completion-bibliography (org-ref-find-bibliography)))
- (or (car (bibtex-completion-find-pdf key)) "")))
-
-
- ;;;###autoload
- (defun org-ref-open-pdf-at-point ()
- "Open the pdf for bibtex key under point if it exists."
- (interactive)
- (let* ((results (org-ref-get-bibtex-key-and-file))
- (key (car results))
- (pdf-file (funcall org-ref-get-pdf-filename-function key)))
- (if (file-exists-p pdf-file)
- (org-open-file pdf-file)
- (message "no pdf found for %s" key))))
-
-
- ;;;###autoload
- (defun org-ref-open-url-at-point ()
- "Open the url for bibtex key under point."
- (interactive)
- (let* ((results (org-ref-get-bibtex-key-and-file))
- (key (car results))
- (bibfile (cdr results)))
- (save-excursion
- (with-temp-buffer
- (insert-file-contents bibfile)
- (bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
- (bibtex-search-entry key)
- ;; I like this better than bibtex-url which does not always find
- ;; the urls
- (catch 'done
- (let ((url (s-trim (bibtex-autokey-get-field "url"))))
- (unless (s-blank? url)
- (browse-url url)
- (throw 'done nil)))
-
- (let ((doi (s-trim (bibtex-autokey-get-field "doi"))))
- (unless (s-blank? doi)
- (if (string-match "^http" doi)
- (browse-url doi)
- (browse-url (format "http://dx.doi.org/%s" doi)))
- (throw 'done nil))))))))
-
-
- ;;;###autoload
- (defun org-ref-open-notes-at-point (&optional thekey)
- "Open the notes for bibtex key under point in a cite link in a buffer.
- Can also be called with THEKEY in a program."
- (interactive)
- (funcall org-ref-notes-function thekey))
-
-
- ;;;###autoload
- (defun org-ref-citation-at-point ()
- "Give message of current citation at point."
- (interactive)
- (org-ref-format-entry (org-ref-get-bibtex-key-under-cursor))
- ;; (let* ((results (org-ref-get-bibtex-key-and-file))
- ;; (key (car results))
- ;; (bibfile (cdr results)))
- ;; (message "%s" (progn
- ;; (with-temp-buffer
- ;; (insert-file-contents bibfile)
- ;; (bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
- ;; (bibtex-search-entry key)
- ;; (org-ref-bib-citation)))))
- )
-
-
- ;;;###autoload
- (defun org-ref-open-citation-at-point ()
- "Open bibtex file to key at point."
- (interactive)
- (let* ((results (org-ref-get-bibtex-key-and-file))
- (key (car results))
- (bibfile (cdr results)))
- (find-file bibfile)
- (bibtex-search-entry key)))
-
- ;;*** cite menu
- (defvar org-ref-cite-menu-funcs '()
- "Functions to run on cite click menu.
- Each entry is a list of (key menu-name function). The function
- must take no arguments and work on the key at point. Do not
- modify this variable, it is set to empty in the menu click
- function, and functions are conditionally added to it.")
-
-
- (defvar org-ref-user-cite-menu-funcs
- '(("C" "rossref" org-ref-crossref-at-point)
- ("y" "Copy entry to file" org-ref-copy-entry-at-point-to-file)
- ("s" "Copy summary" org-ref-copy-entry-as-summary))
- "User-defined functions to run on bibtex key at point.")
-
-
- ;;;###autoload
- (defun org-ref-copy-entry-as-summary ()
- "Copy the bibtex entry for the citation at point as a summary."
- (interactive)
- (kill-new (org-ref-bib-citation)))
-
-
- ;;;###autoload
- (defun org-ref-copy-cite-as-summary ()
- "Copy a summary for the citation at point to the clipboard."
- (interactive)
- (kill-new (org-ref-link-message)))
-
-
- ;;;###autoload
- (defun org-ref-copy-entry-at-point-to-file ()
- "Copy the bibtex entry for the citation at point to NEW-FILE.
- Prompt for NEW-FILE includes bib files in
- `org-ref-default-bibliography', and bib files in current working
- directory. You can also specify a new file."
- (interactive)
- (let ((new-file (completing-read
- "Copy to bibfile: "
- (append org-ref-default-bibliography
- (f-entries "." (lambda (f) (f-ext? f "bib"))))))
- (key (org-ref-get-bibtex-key-under-cursor)))
- (save-window-excursion
- (org-ref-open-citation-at-point)
- (bibtex-copy-entry-as-kill))
-
- (let ((bibtex-files (list (file-truename new-file))))
- (if (assoc key (bibtex-global-key-alist))
- (message "That key already exists in %s" new-file)
- ;; add to file
- (save-window-excursion
- (find-file new-file)
- (goto-char (point-max))
- ;; make sure we are at the beginning of a line.
- (unless (looking-at "^") (insert "\n\n"))
- (bibtex-yank)
- (save-buffer))))))
-
-
- (defun org-ref-get-doi-at-point ()
- "Get doi for key at point."
- (let* ((results (org-ref-get-bibtex-key-and-file))
- (key (car results))
- (bibfile (cdr results))
- doi)
- (save-excursion
- (with-temp-buffer
- (insert-file-contents bibfile)
- (bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
- (bibtex-search-entry key)
- (setq doi (bibtex-autokey-get-field "doi"))
- ;; in case doi is a url, remove the url part.
- (replace-regexp-in-string "^http://dx.doi.org/" "" doi)))))
-
-
- ;;**** functions that operate on key at point for click menu
- ;;;###autoload
- (defun org-ref-wos-at-point ()
- "Open the doi in wos for bibtex key under point."
- (interactive)
- (doi-utils-wos (org-ref-get-doi-at-point)))
-
-
- ;;;###autoload
- (defun org-ref-wos-citing-at-point ()
- "Open the doi in wos citing articles for bibtex key under point."
- (interactive)
- (doi-utils-wos-citing (org-ref-get-doi-at-point)))
-
-
- ;;;###autoload
- (defun org-ref-wos-related-at-point ()
- "Open the doi in wos related articles for bibtex key under point."
- (interactive)
- (doi-utils-wos-related (org-ref-get-doi-at-point)))
-
-
- ;;;###autoload
- (defun org-ref-google-scholar-at-point ()
- "Search google scholar for bibtex key under point using the title."
- (interactive)
- (browse-url
- (format
- "http://scholar.google.com/scholar?q=%s"
- (let* ((key-file (org-ref-get-bibtex-key-and-file))
- (key (car key-file))
- (file (cdr key-file))
- entry)
- (with-temp-buffer
- (insert-file-contents file)
- (bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
- (bibtex-search-entry key nil 0)
- (setq entry (bibtex-parse-entry))
- (org-ref-reftex-get-bib-field "title" entry))))))
-
-
- ;;;###autoload
- (defun org-ref-pubmed-at-point ()
- "Open the doi in pubmed for bibtex key under point."
- (interactive)
- (doi-utils-pubmed (org-ref-get-doi-at-point)))
-
-
- ;;;###autoload
- (defun org-ref-crossref-at-point ()
- "Open the doi in crossref for bibtex key under point."
- (interactive)
- (doi-utils-crossref (org-ref-get-doi-at-point)))
-
-
- ;;* General org-ref utilities
- (defun org-ref-strip-string (string)
- "Strip leading and trailing whitespace from the STRING."
- (replace-regexp-in-string
- (concat org-ref-search-whitespace-regexp "$" ) ""
- (replace-regexp-in-string
- (concat "^" org-ref-search-whitespace-regexp ) "" string)))
-
-
- (defun org-ref-split-and-strip-string (string)
- "Split key-string and strip keys in STRING.
- Assumes the key-string is comma delimited."
- (mapcar 'org-ref-strip-string (split-string string ",")))
-
-
- (defun org-ref-get-bibtex-keys (&optional sort)
- "Return a list of unique keys in the buffer.
- Use SORT to specify alphabetical order by key."
- (let ((keys '()))
- (org-element-map (org-element-parse-buffer) 'link
- (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 (-contains? keys key))
- (setq keys (append keys (list key))))))))
- ;; set with-affiliated to get keys in captions
- nil nil nil t)
- (when sort
- ;; Sort keys alphabetically
- (setq keys (cl-sort keys 'string-lessp :key 'downcase)))
- keys))
-
-
- ;;;###autoload
- (defun org-ref-bibliography (&optional sort)
- "Create a new buffer with a bibliography.
- If SORT is non-nil it is alphabetically sorted by key
- This is mostly for convenience to see what has been cited.
- Entries are formatted according to the bibtex entry type in
- `org-ref-bibliography-entry-format', and the actual entries are
- generated by `org-ref-reftex-format-citation'."
- (interactive)
- (let ((bib (mapconcat
- 'identity
- (cl-loop for i from 1
- for citation in
- (mapcar
- (lambda (key)
- (let* ((results (org-ref-get-bibtex-key-and-file key))
- (key (car results))
- (bibfile (cdr results)))
- (format "cite:%s %s" key
- (if bibfile
- (save-excursion
- (with-temp-buffer
- (insert-file-contents bibfile)
- (bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
- (bibtex-search-entry key)
- (org-ref-format-entry key)))
- "!!! No entry found !!!"))))
- (org-ref-get-bibtex-keys sort))
- collect (format "%3s. %s" i citation))
- "\n\n")))
-
- (switch-to-buffer-other-window (format "%s-bibliography" (buffer-file-name)))
- (erase-buffer)
- (insert bib)
- (org-mode)))
-
-
- (defun org-ref-get-bibtex-entry-html (key)
- "Return an html string for the bibliography entry corresponding to KEY."
- (let ((output))
- (setq output (concat (format "<a name=\"%s\"></a>" key)
- (org-ref-get-bibtex-entry-citation key)))
- (setq output (org-ref-clean-unused-entry-html output))
- (format "<li><a id=\"%s\">[%s]</a> %s</li>"
- key key output)))
-
- (defun org-ref-clean-unused-entry-html (entry-html)
- "Return from the html string ENTRY-HTML a cleaner version"
- ;; unescape the &
- (setq entry-html (replace-regexp-in-string "\\\\&" "&" entry-html))
- ;; hack to replace {} around text
- (setq entry-html (replace-regexp-in-string "{" "" entry-html))
- (setq entry-html (replace-regexp-in-string "}" "" entry-html))
- ;; get rid of empty parens
- (setq entry-html (replace-regexp-in-string "()" "" entry-html))
- ;; 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))
- ;; 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))
- entry-html)
-
- (defun org-ref-get-html-bibliography (&optional sort)
- "Create an html bibliography when there are keys.
- If one of SORT and `org-ref-bib-html-sorted' is non-nil,
- the bibliography is alphabetically sorted."
- (let ((keys (org-ref-get-bibtex-keys (or sort org-ref-bib-html-sorted))))
- (when keys
- (concat org-ref-bib-html "<ul class='org-ref-bib'>"
- (mapconcat (lambda (x) (org-ref-get-bibtex-entry-html x)) keys "\n")
- "\n</ul>"))))
-
-
- (defun org-ref-get-bibtex-entry-org (key)
- "Return an org string for the bibliography entry corresponding to KEY."
- (let ((org-ref-bibliography-files (org-ref-find-bibliography))
- file entry)
-
- (setq file (catch 'result
- (cl-loop for file in org-ref-bibliography-files do
- (if (org-ref-key-in-file-p key (file-truename file))
- (throw 'result file)
- (message "%s not found in %s" key
- (file-truename file))))))
-
- (with-temp-buffer
- (insert-file-contents file)
- (bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
- (bibtex-search-entry key nil 0)
- (setq entry (bibtex-parse-entry))
- (format "** %s - %s
- :PROPERTIES:
- %s
- :END:
- " (org-ref-reftex-get-bib-field "author" entry)
- (org-ref-reftex-get-bib-field "title" entry)
- (concat " :CUSTOM_ID: " (org-ref-reftex-get-bib-field "=key=" entry) "\n"
- (mapconcat
- (lambda (element) (format " :%s: %s"
- (upcase (car element))
- (cdr element)))
- entry
- "\n"))))))
-
-
- (defun org-ref-get-org-bibliography (&optional sort)
- "Create an org bibliography when there are keys.
- If SORT is non-nil the bibliography is sorted alphabetically by key."
- (let ((keys (org-ref-get-bibtex-keys sort)))
- (when keys
- (concat "* Bibliography\n"
- (mapconcat (lambda (x)
- (org-ref-get-bibtex-entry-org x)) keys "\n")
- "\n"))))
-
-
- (defun org-ref-get-bibtex-entry-ascii (key)
- "Return an ascii string for the bibliography entry corresponding to KEY."
-
- (format "[%s] %s" key (org-ref-get-bibtex-entry-citation key)))
-
-
- (defun org-ref-get-bibtex-entry-md (key)
- "Return a md string for the bibliography entry corresponding to KEY."
- ;; We create an anchor to the key that we can jump to, and provide a jump back
- ;; link with the md5 of the key.
- (format "<a id=\"%s\"></a>[%s] %s%s [↩](#%s)"
- key key
- (org-ref-clean-unused-entry-html (org-ref-get-bibtex-entry-citation key))
- ""
- ;; Note: This is to temporarily resolve issue #558. This worked fine
- ;; for me earlier, so I don't know why it doesn't work in this issue.
-
- ;; (if (plist-get info :md-publish-bibtex)
- ;; (format
- ;; " <a href=\"data:text/plain;charset=US-ASCII;base64,%s\" title=\"%s\">[bib]</a>"
- ;; (base64-encode-string (org-ref-get-bibtex-entry key))
- ;; (concat "Right-click to open\n" (xml-escape-string
- ;; (org-ref-get-bibtex-entry key))))
- ;; "")
- (md5 key)))
-
-
- (defun org-ref-get-ascii-bibliography (&optional sort)
- "Create an ascii bibliography when there are keys.
- if SORT is non-nil the bibliography is sorted alphabetically by key."
- (let ((keys (org-ref-get-bibtex-keys sort)))
- (when keys
- (concat
- "\n\nBibliography\n=============\n\n"
- (mapconcat (lambda (x) (org-ref-get-bibtex-entry-ascii x)) keys "\n")
- "\n"))))
-
- (defun org-ref-get-md-bibliography (&optional sort)
- "Create an md bibliography when there are keys.
- if SORT is non-nil the bibliography is sorted alphabetically by key."
- (let ((keys (org-ref-get-bibtex-keys sort)))
- (when keys
- (concat
- "# Bibliography\n"
- (mapconcat (lambda (x) (org-ref-get-bibtex-entry-md x)) keys "\n\n")
- "\n"))))
-
- (defun org-ref-get-odt-bibliography (&optional sort)
- "Create an ascii bibliography ofr odt export when there are keys.
- if SORT is non-nil the bibliography is sorted alphabetically by
- key. This is a variant of `org-ref-get-ascii-bibliography' where
- some things are escaped since odt is an xml format."
- (let ((keys (org-ref-get-bibtex-keys sort)))
- (when keys
- (mapconcat (lambda (x)
- (xml-escape-string (org-ref-get-bibtex-entry-ascii x)))
- keys "\n"))))
-
- (defun org-ref-pdf-p (filename)
- "Check if FILENAME is PDF file.
-
- From the PDF specification 1.7:
-
- The first line of a PDF file shall be a header consisting of
- the 5 characters %PDF- followed by a version number of the
- form 1.N, where N is a digit between 0 and 7."
- (let ((header (with-temp-buffer
- (set-buffer-multibyte nil)
- (insert-file-contents-literally filename nil 0 5)
- (buffer-string))))
- (string-equal (encode-coding-string header 'utf-8) "%PDF-")))
-
-
- ;;;###autoload
- (defmacro org-ref-link-set-parameters (type &rest parameters)
- "Set link TYPE properties to PARAMETERS."
- (declare (indent 1))
- (if (fboundp 'org-link-set-parameters)
- `(org-link-set-parameters ,type ,@parameters)
- `(org-add-link-type ,type ,(plist-get parameters :follow) ,(plist-get parameters :export))))
-
-
-
- ;; This section creates some code that should speed up org-ref for large files.
- ;; I use org-element-parse-buffer a lot for getting information about labels
- ;; etc. However, it gets called a lot, and this is slow in large documents. Here
- ;; we try to use a cache that helps speed this up at least on loading. Some
- ;; notes for the future: on loading, it seems like fontification triggers buffer
- ;; changes, so here we only consider char changes. I am not sure this is the
- ;; best strategy overall. It is faster to use regexps for finding this
- ;; information, but those are substantially more difficult to debug in my
- ;; experience. There is an unfortunate number of ways to reference things in
- ;; org-mode, and so far this has been most reliable. An alternative might be to
- ;; leveralge what happens in font-lock somehow to update local variables
- ;; containing org-ref labels, refs, cites, etc. That would miss some #+names
- ;; though, and maybe some other things like custom-ids.
-
- (defvar-local org-ref-char-change-tick nil
- "Local variable to track character changes.")
-
-
- (defvar-local org-ref-parse-buffer-cache nil
- "Local variable to store parse buffer data.")
-
-
- (defun org-ref-parse-buffer (&optional force)
- "This is a thin wrapper around `org-element-parse-buffer'.
- The idea is to cache the data, and return it unless we can tell
- the buffer has been modified since the last time we ran it.
- if FORCE is non-nil reparse the buffer no matter what."
- (if force
- (progn
- (message "Forcing update.")
- (setq-local org-ref-char-change-tick (buffer-chars-modified-tick))
- (setq-local org-ref-parse-buffer-cache (org-element-parse-buffer)))
-
- (cond
- ((null org-ref-parse-buffer-cache)
- ;; (message "First parse.")
- (setq-local org-ref-char-change-tick (buffer-chars-modified-tick))
- (setq-local org-ref-parse-buffer-cache (org-element-parse-buffer)))
-
- ((not (eq org-ref-char-change-tick (buffer-chars-modified-tick)))
- ;; (message "Updating from a char change in the buffer.")
- (setq-local org-ref-char-change-tick (buffer-chars-modified-tick))
- (setq-local org-ref-parse-buffer-cache (org-element-parse-buffer)))
-
- (t
- ;; (message "Using cache.")
- org-ref-parse-buffer-cache))))
-
-
- (provide 'org-ref-utils)
- ;;; org-ref-utils.el ends here
|