|
|
- ;;; org-ref-bibtex.el -- org-ref-bibtex utilities
-
- ;; Copyright(C) 2014 John Kitchin
-
- ;; Author: John Kitchin <jkitchin@andrew.cmu.edu>
- ;; URL: https://github.com/jkitchin/org-ref
- ;; Version: 0.1
- ;; Keywords: org-mode, bibtex
- ;; Package-Requires: ((org-ref) (s) (dash) (doi-utils) (key-chord))
-
- ;; This file is not currently part of GNU Emacs.
-
- ;; 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 2, 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 ; see the file COPYING. If not, write to
- ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- ;; Boston, MA 02111-1307, USA.
-
- ;;; Commentary:
-
- ;; org-ref-bibtex-generate-longtitles
- ;; org-ref-bibtex-generate-shorttitles
- ;; org-ref-stringify-journal-name :: replace a journal name with a string in
- ;; `org-ref-bibtex-journal-abbreviations'
- ;; org-ref-set-journal-string :: in a bibtex entry run this to replace the
- ;; journal with a string
- ;;
- ;; org-ref-title-case-article :: title case the title in an article or book
- ;; org-ref-sentence-case-article :: sentence case the title in an article.
-
- ;; org-ref-replace-nonascii :: replace nonascii characters in a bibtex
- ;; entry. Replacements are in `org-ref-nonascii-latex-replacements'.
- ;;
- ;; org-ref-title-case-article
- ;; org-ref-sentence-case-article
- ;;
- ;; org-ref-bibtex-next-entry :: bound to M-n
- ;; org-ref-bibtex-previous-entry :: bound to M-p
- ;;
- ;; Functions to act on a bibtex entry or file
- ;; org-ref-bibtex-hydra/body gives a hydra menu to a lot of useful functions.
- ;; org-ref-bibtex-new-entry/body gives a hydra menu to add new bibtex entries.
- ;; org-ref-bibtex-file/body gives a hydra menu of actions for the bibtex file
- ;;
- ;; org-ref-bibtex :: a deprecated menu of actions
-
- (require 'bibtex)
- (require 'dash)
- (require 'hydra)
- (require 'key-chord nil 'no-error)
- (require 'message)
- (require 's)
-
- (require 'org-ref-citeproc)
- (require 'doi-utils)
-
- (defvar org-ref-pdf-directory)
- (defvar org-ref-notes-directory)
- (defvar org-ref-default-bibliography)
-
- (declare-function reftex-get-bib-field "reftex-cite")
- (declare-function key-chord-define-global "key-chord")
- (declare-function org-ref-find-bibliography "org-ref-core")
- (declare-function org-ref-open-bibtex-pdf "org-ref-core")
- (declare-function org-ref-open-bibtex-notes "org-ref-core")
- (declare-function org-ref-clean-bibtex-entry "org-ref-core")
- (declare-function org-ref-open-in-browser "org-ref-core")
- (declare-function org-ref-sort-bibtex-entry "org-ref-core")
- (declare-function org-ref-build-full-bibliography "org-ref-core")
- (declare-function helm-tag-bibtex-entry "org-ref-helm")
- (declare-function bibtex-completion-edit-notes "bibtex-completion")
- (declare-function bibtex-completion-get-value "bibtex-completion")
- (declare-function bibtex-completion-get-entry "bibtex-completion")
- (declare-function parsebib-find-next-item "parsebib")
- (declare-function parsebib-read-entry "parsebib")
- (declare-function helm-bibtex "helm-bibtex")
- (declare-function helm "helm")
-
- ;;; Code:
-
- ;; This is duplicated from org-ref-core to try to avoid a byte-compile error.
- (add-to-list 'load-path
- (expand-file-name
- "citeproc"
- (file-name-directory (or load-file-name (buffer-file-name)))))
-
- (add-to-list 'load-path
- (expand-file-name
- "citeproc/csl"
- (file-name-directory (or load-file-name (buffer-file-name)))))
-
- ;;* Custom variables
- (defgroup org-ref-bibtex nil
- "Customization group for org-ref-bibtex."
- :group 'org-ref-bibtex)
-
-
- (defcustom org-ref-bibtex-hydra-key-chord
- nil
- "Key-chord to run `org-ref-bibtex-hydra'.
- I like \"jj\""
- :type '(choice (const nil :tag "None")
- (string))
- :group 'org-ref-bibtex)
-
-
- (defcustom org-ref-bibtex-hydra-key-binding
- nil
- "Key-binding to run `org-ref-bibtex-hydra'.
- I like \"C-c j\"."
- :type '(choice (const nil :tag "No binding")
- (key-sequence))
- :group 'org-ref-bibtex)
-
-
- (defcustom org-ref-helm-cite-shorten-authors nil
- "If non-nil show only last names in the helm selection buffer."
- :type 'boolean
- :group 'org-ref-bibtex)
-
-
- (defcustom org-ref-formatted-citation-formats
- '(("text" . (("article" . "${author}, ${title}, ${journal}, ${volume}(${number}), ${pages} (${year}). ${doi}")
- ("inproceedings" . "${author}, ${title}, In ${editor}, ${booktitle} (pp. ${pages}) (${year}). ${address}: ${publisher}.")
- ("book" . "${author}, ${title} (${year}), ${address}: ${publisher}.")
- ("phdthesis" . "${author}, ${title} (Doctoral dissertation) (${year}). ${school}, ${address}.")
- ("inbook" . "${author}, ${title}, In ${editor} (Eds.), ${booktitle} (pp. ${pages}) (${year}). ${address}: ${publisher}.")
- ("incollection" . "${author}, ${title}, In ${editor} (Eds.), ${booktitle} (pp. ${pages}) (${year}). ${address}: ${publisher}.")
- ("proceedings" . "${editor} (Eds.), ${booktitle} (${year}). ${address}: ${publisher}.")
- ("unpublished" . "${author}, ${title} (${year}). Unpublished manuscript.")
- (nil . "${author}, ${title} (${year}).")))
- ("org" . (("article" . "${author}, /${title}/, ${journal}, *${volume}(${number})*, ${pages} (${year}). ${doi}")
- ("inproceedings" . "${author}, /${title}/, In ${editor}, ${booktitle} (pp. ${pages}) (${year}). ${address}: ${publisher}.")
- ("book" . "${author}, /${title}/ (${year}), ${address}: ${publisher}.")
- ("phdthesis" . "${author}, /${title}/ (Doctoral dissertation) (${year}). ${school}, ${address}.")
- ("inbook" . "${author}, /${title}/, In ${editor} (Eds.), ${booktitle} (pp. ${pages}) (${year}). ${address}: ${publisher}.")
- ("incollection" . "${author}, /${title}/, In ${editor} (Eds.), ${booktitle} (pp. ${pages}) (${year}). ${address}: ${publisher}.")
- ("proceedings" . "${editor} (Eds.), _${booktitle}_ (${year}). ${address}: ${publisher}.")
- ("unpublished" . "${author}, /${title}/ (${year}). Unpublished manuscript.")
- (nil . "${author}, /${title}/ (${year})."))))
- "Format strings for formatted bibtex entries for different citation backends.
- Used in `org-ref-format-entry'."
- :type '(alist)
- :group 'org-ref-bibtex)
-
- (defcustom org-ref-formatted-citation-backend "text"
- "The backend format for formatted citations.
- Should be one of the cars of `org-ref-formatted-citation-formats'."
- :type 'string
- :group 'org-ref-bibtex)
-
- ;;* Journal abbreviations
- (defvar org-ref-bibtex-journal-abbreviations
- '()
- "List of (string journal-full-name journal-abbreviation). Find
- new abbreviations at http://cassi.cas.org/search.jsp.")
-
- (defcustom org-ref-bibtex-assoc-pdf-with-entry-move-function 'rename-file
- "Function to use when associating pdf files with bibtex entries.
- The value should be either `rename-file' or `copy-file'. The former
- will move and rename the original file. The latter will leave the
- original file in place while creating a renamed copy in
- `org-ref-pdf-directory'."
- :type 'function
- :group 'org-ref-bibtex)
-
- (setq org-ref-bibtex-journal-abbreviations
- '(("ACR" "Accounts of Chemical Research" "Acc. Chem. Res.")
- ("ACAT" "ACS Catalysis" "ACS Catal.")
- ("AM" "Acta Materialia" "Acta Mater.")
- ("AMM" "Acta Metallurgica et Materialia" "Acta Metall. Mater.")
- ("AEM" "Advanced Energy Materials" "Adv. Energy Mater.")
- ("AAMI" "ACS Applied Materials \\& Interfaces"
- "ACS Appl. Mater. Interfaces")
- ("AMiner" "American Mineralogist" "Am. Mineral.")
- ("AngC" "Angewandte Chemie-International Edition"
- "Angew. Chem. Int. Edit.")
- ("APLM" "APL Materials" "APL Mat.")
- ("ACBE" "Applied Catalysis B: Environmental" "Appl. Catal. B-Environ.")
- ("APL" "Applied Physics Letters" "Appl. Phys. Lett.")
- ("ASS" "Applied Surface Science" "Appl. Surf. Sci.")
- ("CL" "Catalysis Letters" "Catal. Lett.")
- ("CC" "Catalysis Communications" "Catal. Commun.")
- ("CST" "Catalysis Science & Technology" "Catal. Sci. Technol.")
- ("CT" "Catalysis Today" "Catal. Today")
- ("ChC" "Chemical Communications" "Chem. Commun.")
- ("CPL" "Chemical Physics Letters" "Chem. Phys. Lett")
- ("CR" "Chemical Reviews" "Chem. Rev.")
- ("CSR" "Chemical Society Reviews" "Chem. Soc. Rev.")
- ("CSR" "Chemical Society Reviews" "Chem. Soc. Rev.")
- ("CM" "Chemistry of Materials" "Chem. Mater.")
- ("CSA" "Colloids and Surfaces, A: Physicochemical and Engineering Aspects"
- "Colloids Surf., A")
- ("CF" "Combustion and Flame" "Combust. Flame")
- ("CPMS" "Computational Materials Science" "Comp. Mater. Sci.")
- ("CPC" "Computer Physics Communications" "Comput. Phys. Commun.")
- ("CSE" "Computing in Science \\& Engineering" "Comput. Sci. Eng.")
- ("CGD" "Crystal Growth \\& Design" "Cryst. Growth Des.")
- ("CEC" "CrystEngComm" "CrystEngComm")
- ("EA" "Electrochimica Acta" "Electrochim. Acta")
- ("ECST" "ECS Transactions" "ECS Trans.")
- ("EES" "Energy \\& Environmental Science" "Energy Environ. Sci.")
- ("HPR" "High Pressure Research" "High Pressure Res.")
- ("IC" "Inorganic Chemistry" "Inorg. Chem.")
- ("IECR" "Industrial \\& Engineering Chemistry Research"
- "Ind. Eng. Chem. Res.")
- ("JJAP" "Japanese Journal of Applied Physics" "Jpn. J. Appl. Phys.")
- ("JMatR" "Journal of Materials Research" "J. Mater. Res.")
- ("JALC" "Journal of Alloys and Compounds" "J. Alloy Compd.")
- ("JAC" "Journal of Applied Crystallography" "J. Appl. Crystallogr.")
- ("JAE" "Journal of Applied Electrochemistry" "J. Appl. Electrochem.")
- ("JAP" "Journal of Applied Physics" "J. Appl. Phys.")
- ("JC" "Journal of Catalysis" "J. Catal.")
- ("JCP" "Journal of Chemical Physics" "J. Chem. Phys.")
- ("JCC" "Journal of Computational Chemistry" "J. Comput. Chem.")
- ("JCG" "Journal of Crystal Growth" "J. Crys. Growth")
- ("JMC" "Journal of Materials Chemistry" "J. Mater. Chem.")
- ("JMC" "Journal of Materials Chemistry" "J. Mater. Chem.")
- ("JMSL" "Journal of Materials Science Letters" "J. Mater. Sci. Lett.")
- ("JMS" "Journal of Membrane Science" "J. Memb. Sci.")
- ("JPE" "Journal of Phase Equilibria" "J. Phase Equilib.")
- ("JPCS" "Journal of Physics and Chemistry of Solids"
- "J. Phys. Chem. Solids")
- ("JPCM" "Journal of Physics: Condensed Matter"
- "J. Phys.: Condens. Matter")
- ("JPS" "Journal of Power Sources" "J. Power Sources")
- ("JSSC" "Journal of Solid State Chemistry" "J. Solid State Chem.")
- ("JACerS" "Journal of the American Ceramic Society" "J. Am. Ceram. Soc.")
- ("JACS" "Journal of the American Chemical Society" "J. Am. Chem. Soc.")
- ("JASIST" "Journal of the American Society for Information Science and Technology"
- "J. Am. Soc. Inf. Sci. Technol.")
- ("JES" "Journal of The Electrochemical Society" "J. Electrochem. Soc.")
- ("JEaC" "Journal of Electroanalytical Chemistry" "J. Electroanal. Chem.")
- ("JMS" "Journal of Membrane Science" "J. Memb. Sci.")
- ("JRS" "Journal of Raman Spectroscopy" "J. Raman Spectrosc.")
- ("JVST" "Journal of Vacuum Science \\& Technology A"
- "J. Vac. Sci. Technol. A")
- ("ML" "Materials Letters" "Mater. Lett.")
- ("MSE-BS" "Materials Science and Engineering B" "Mat. Sci. Eng. B-Solid")
- ("MOLSIM" "Molecular Simulation" "Mol. Sim.")
- ("Nature" "Nature" "Nature")
- ("NM" "Nature Materials" "Nat. Mater.")
- ("NC" "Nature Chemistry" "Nat. Chem.")
- ("PML" "Philosophical Magazine Letters" "Phil. Mag. Lett.")
- ("PMA" "Philosophical Magazine A" "Phil. Mag. A")
- ("PA" "Physica A: Statistical Mechanics and its Applications" "Physica A")
- ("PB" "Physica B-Condensed Matter" "Physica B")
- ("PCCP" "Physical Chemistry Chemical Physics" "Phys. Chem. Chem. Phys.")
- ("PSSB" "physica status solidi (b)" "Phys. Status Solidi B")
- ("PRA" "Physical Review A" "Phys. Rev. A")
- ("PRB" "Physical Review B" "Phys. Rev. B")
- ("PRL" "Physical Review Letters" "Phys. Rev. Lett.")
- ("PCM" "Physics and Chemistry of Minerals" "Phys. Chem. Miner.")
- ("PNAS" "Proceedings of the National Academy of Sciences of the United States of America"
- "Proc. Natl. Acad. Sci. U. S. A.")
- ("PSurfSci" "Progress in Surface Science" "Prog. Surf. Sci.")
- ("Science" "Science" "Science")
- ("SM" "Scripta Materialia" "Scr. Mater.")
- ("SABC" "Sensors and Actuators B: Chemical" "Sensor. Actuat. B-Chem.")
- ("SS" "Surface Science" "Surf. Sci.")
- ("EPJB" "The European Physical Journal B" "Eur. Phys. J. B")
- ("JPC" "The Journal of Physical Chemistry" "J. Phys. Chem.")
- ("JPCB" "The Journal of Physical Chemistry B" "J. Phys. Chem. B")
- ("JPCC" "The Journal of Physical Chemistry C" "J. Phys. Chem. C")
- ("JPCL" "The Journal of Physical Chemistry Letters"
- "J. Phys. Chem. Lett.")
- ("JCP" "The Journal of Chemical Physics" "J. Chem. Phys.")
- ("MSMSE" "Modelling and Simulation in Materials Science and Engineering"
- "Modell. Simul. Mater. Sci. Eng.")
- ("TSF" "Thin Solid Films" "Thin Solid Films")
- ("TC" "Topics in Catalysis" "Top. Catal.")
- ("WR" "Water Research" "Water Res.")))
-
-
- ;;;###autoload
- (defun org-ref-bibtex-generate-longtitles ()
- "Generate longtitles.bib which are @string definitions.
- The full journal names are in `org-ref-bibtex-journal-abbreviations'."
- (interactive)
- (with-temp-file "longtitles.bib"
- (dolist (row org-ref-bibtex-journal-abbreviations)
- (insert (format "@string{%s=\"%s\"}\n"
- (nth 0 row)
- (nth 1 row))))))
-
-
- ;;;###autoload
- (defun org-ref-bibtex-generate-shorttitles ()
- "Generate shorttitles.bib which are @string definitions.
- The abbreviated journal names in `org-ref-bibtex-journal-abbreviations'."
- (interactive)
- (with-temp-file "shorttitles.bib"
- (dolist (row org-ref-bibtex-journal-abbreviations)
- (insert (format "@string{%s=\"%s\"}\n"
- (nth 0 row)
- (nth 2 row))))))
-
-
- ;;;###autoload
- (defun org-ref-stringify-journal-name (&optional key start end)
- "Replace journal name in a bibtex entry with a string.
- The strings are defined in
- `org-ref-bibtex-journal-abbreviations'. The optional arguments KEY,
- START and END allow you to use this with `bibtex-map-entries'"
- (interactive)
- (bibtex-beginning-of-entry)
- (when
- (string= "article"
- (downcase
- (cdr (assoc "=type=" (bibtex-parse-entry)))))
- (let* ((full-names (mapcar
- (lambda (row)
- (cons (nth 1 row) (nth 0 row)))
- org-ref-bibtex-journal-abbreviations))
- (abbrev-names (mapcar
- (lambda (row)
- (cons (nth 2 row) (nth 0 row)))
- org-ref-bibtex-journal-abbreviations))
- (journal (s-trim (bibtex-autokey-get-field "journal")))
- (bstring (or
- (cdr (assoc journal full-names))
- (cdr (assoc journal abbrev-names)))))
- (when bstring
- (bibtex-set-field "journal" bstring t)
- (bibtex-fill-entry)))))
-
-
- ;;;###autoload
- (defun org-ref-helm-set-journal-string ()
- "Helm interface to set a journal string in a bibtex entry.
- Entries come from `org-ref-bibtex-journal-abbreviations'."
- (interactive)
- (bibtex-set-field
- "journal"
- (helm :sources
- `((name . "journal")
- (candidates . ,(mapcar
- (lambda (x)
- (cons (format "%s | %s" (nth 1 x) (nth 2 x))
- (car x)))
- org-ref-bibtex-journal-abbreviations))
- (action . (lambda (x) (identity x))))
- :input (s-trim (bibtex-autokey-get-field "journal")))
- t)
- (bibtex-fill-entry)
- (bibtex-clean-entry))
-
-
- ;;;###autoload
- (defun org-ref-set-journal-string (full-journal-name)
- "Set a bibtex journal name to the string that represents FULL-JOURNAL-NAME.
- This is defined in `org-ref-bibtex-journal-abbreviations'."
- (interactive (list
- (completing-read
- "Journal: "
- (mapcar
- (lambda (x)
- (nth 1 x))
- org-ref-bibtex-journal-abbreviations))))
- ;; construct data alist for the string lookup.
- (let ((alist (mapcar
- (lambda (x)
- (cons (nth 1 x) (nth 0 x)))
- org-ref-bibtex-journal-abbreviations)))
- (bibtex-set-field "journal" (cdr (assoc full-journal-name alist)) t)
- (bibtex-fill-entry)
- (bibtex-clean-entry)))
-
- ;;* Non-ascii character replacement
- ;; see https://github.com/fxcoudert/tools/blob/master/doi2bib for more replacements
- (defvar org-ref-nonascii-latex-replacements
- '()
- "Cons list of non-ascii characters and their LaTeX representations.")
-
-
- (setq org-ref-nonascii-latex-replacements
- '(("í" . "{\\\\'i}")
- ("æ" . "{\\\\ae}")
- ("ć" . "{\\\\'c}")
- ("é" . "{\\\\'e}")
- ("ä" . "{\\\\\"a}")
- ("è" . "{\\\\`e}")
- ("à" . "{\\\\`a}")
- ("á" . "{\\\\'a}")
- ("ø" . "{\\\\o}")
- ("ë" . "{\\\\\"e}")
- ("ü" . "{\\\\\"u}")
- ("ñ" . "{\\\\~n}")
- ("ņ" . "{\\\\c{n}}")
- ("ñ" . "{\\\\~n}")
- ("å" . "{\\\\aa}")
- ("ö" . "{\\\\\"o}")
- ("Á" . "{\\\\'A}")
- ("í" . "{\\\\'i}")
- ("ó" . "{\\\\'o}")
- ("ó" . "{\\\\'o}")
- ("ú" . "{\\\\'u}")
- ("ú" . "{\\\\'u}")
- ("ý" . "{\\\\'y}")
- ("š" . "{\\\\v{s}}")
- ("č" . "{\\\\v{c}}")
- ("ř" . "{\\\\v{r}}")
- ("š" . "{\\\\v{s}}")
- ("İ" . "{\\\\.I}")
- ("ğ" . "{\\\\u{g}}")
- ("δ" . "$\\\\delta$")
- ("ç" . "{\\\\c{c}}")
- ("ß" . "{\\\\ss}")
- ("≤" . "$\\\\le$")
- ("≥" . "$\\\\ge$")
- ("<" . "$<$")
- ("θ" . "$\\\\theta$")
- ("μ" . "$\\\\mu$")
- ("→" . "$\\\\rightarrow$")
- ("⇌" . "$\\\\leftrightharpoons$")
- ("×" . "$\\\\times$")
- ("°" . "$\\\\deg$")
- ("ş" . "{\\\\c{s}}")
- ("γ" . "$\\\\gamma$")
- ("ɣ" . "$\\\\gamma$")
- ("º" . "degC")
- ("η" . "$\\\\eta$")
- ("µ" . "$\\\\mu$")
- ("α" . "$\\\\alpha$")
- ("β" . "$\\\\beta$")
- ("ɛ" . "$\\\\epsilon$")
- ("Ⅵ" . "\\textrm{VI}")
- ("Ⅲ" . "\\textrm{III}")
- ("Ⅴ" . "\\textrm{V}")
- ("λ" . "$\\\\lambda$")
- ("π" . "$\\\\pi$")
- ("∞" . "$\\\\infty$")
- ("χ" . "$\\\\chi$")
- ("∼" . "\\\\textasciitilde{}")
- ("‑" . "\\\\textemdash{}")
- (" " . " ")
- ("…" . "...")
- ("•" . "\\\\textbullet ")
- ;; I think these are non-ascii spaces. there seems to be more than one.
- (" " . " ")
- (" " . " ")
- (" " . " ")
- ("–" . "-")
- ("−" . "-")
- ("–" . "-")
- ("—" . "-")
- ("‒" . "\\\\textemdash{}")
- ("‘" . "'")
- ("’" . "'")
- ("’" . "'")
- ("“" . "\"")
- ("’" . "'")
- ("”" . "\"")))
-
-
- ;;;###autoload
- (defun org-ref-replace-nonascii ()
- "Hook function to replace non-ascii characters in a bibtex entry."
- (interactive)
- (save-restriction
- (bibtex-narrow-to-entry)
- (goto-char (point-min))
- (dolist (char (mapcar (lambda (x)
- (car x))
- org-ref-nonascii-latex-replacements))
- (while (re-search-forward char nil t)
- (replace-match (cdr (assoc char org-ref-nonascii-latex-replacements))))
- (goto-char (point-min)))))
-
- ;;* Title case transformations
- (defvar org-ref-lower-case-words
- '("a" "an" "on" "and" "for"
- "the" "of" "in")
- "List of words to keep lowercase when changing case in a title.")
-
- (defcustom org-ref-title-case-types '("article" "book")
- "List of bibtex entry types in which the title will be converted to
- title-case by org-ref-title-case."
- :type '(repeat string)
- :group 'org-ref-bibtex)
-
- ;;;###autoload
- (defun org-ref-title-case (&optional key start end)
- "Convert a bibtex entry title and booktitle to title-case.
- Convert only if the entry type is a member of the list
- `org-ref-title-case-types'. The arguments KEY, START and END are
- optional, and are only there so you can use this function with
- `bibtex-map-entries' to change all the title entries in articles and
- books."
- (interactive)
- (dolist (field '("title" "booktitle"))
- (save-restriction
- (bibtex-narrow-to-entry)
- (bibtex-beginning-of-entry)
- ;; Skip if field is not found in entry
- (when (bibtex-search-forward-field field)
- (let* ((title (bibtex-autokey-get-field field))
- (words (split-string title))
- (start 0))
- (when
- (member (downcase
- (cdr (assoc "=type=" (bibtex-parse-entry))))
- org-ref-title-case-types)
- (setq words (mapcar
- (lambda (word)
- (cond
- ;; words containing more than one . are probably
- ;; abbreviations. We do not change those.
- ((with-temp-buffer
- (insert word)
- (goto-char (point-min))
- (> (count-matches "\\.") 1))
- word)
- ;; match words containing {} or \ which are probably
- ;; LaTeX or protected words, ignore
- ((string-match "\\$\\|{\\|}\\|(\\|)\\|\\\\" word)
- word)
- ;; these words should not be capitalized, unless they
- ;; are the first word
- ((-contains? org-ref-lower-case-words
- (s-downcase word))
- (s-downcase word))
- ;; Words that are quoted
- ((s-starts-with? "\"" word)
- (concat "\"" (s-capitalize (substring word 1))))
- (t
- (s-capitalize word))))
- words))
-
- ;; Check if first word should be capitalized
- (when (-contains? org-ref-lower-case-words (car words))
- (setf (car words) (s-capitalize (car words))))
-
- (setq title (mapconcat 'identity words " "))
-
- ;; Capitalize letters after a dash
- (while
- (string-match "[a-zA-Z]-\\([a-z]\\)" title start)
- (let ((char (substring title (match-beginning 1) (match-end 1))))
- (setf (substring title (match-beginning 1) (match-end 1))
- (format "%s" (upcase char)))
- (setq start (match-end 1))))
-
- ;; this is defined in doi-utils
- (bibtex-set-field
- field
- title)
- (bibtex-fill-entry)))))))
-
- ;;;###autoload
- (defun org-ref-title-case-article (&optional key start end)
- "Convert a bibtex entry article or book title to title-case.
- The arguments KEY, START and END are optional, and are only there
- so you can use this function with `bibtex-map-entries' to change
- all the title entries in articles and books."
- (interactive)
- (let ((org-ref-title-case-types '("article")))
- (org-ref-title-case)))
-
-
- ;;;###autoload
- (defun org-ref-sentence-case-article (&optional key start end)
- "Convert a bibtex entry article title to sentence-case.
- The arguments KEY, START and END are optional, and are only there
- so you can use this function with `bibtex-map-entries' to change
- all the title entries in articles."
- (interactive)
- (bibtex-beginning-of-entry)
-
- (let* ((title (bibtex-autokey-get-field "title"))
- (words (split-string title))
- (start 0))
- (when
- (string= "article"
- (downcase
- (cdr (assoc "=type="
- (bibtex-parse-entry)))))
- (setq words (mapcar
- (lambda (word)
- (if
- ;; match words containing {} or \ which are probably
- ;; LaTeX or protected words
- (string-match "\\$\\|{\\|}\\|\\\\" word)
- word
- (s-downcase word)))
- words))
-
- ;; capitalize first word
- (setf (car words) (s-capitalize (car words)))
-
- ;; join the words
- (setq title (mapconcat 'identity words " "))
-
- ;; capitalize a word after a :, eg. a subtitle, and protect it
- (while
- (string-match "[a-z]:\\s-+\\([A-Z]\\)" title start)
- (let ((char (substring title (match-beginning 1) (match-end 1))))
- (setf (substring title (match-beginning 1) (match-end 1))
- (format "%s" (upcase char)))
- (setq start (match-end 1))))
-
- ;; this is defined in doi-utils
- (bibtex-set-field
- "title" title)
-
- ;; clean and refill entry so it looks nice
- (bibtex-clean-entry)
- (bibtex-fill-entry))))
-
- ;;* Navigation in bibtex file
- ;;;###autoload
- (defun org-ref-bibtex-next-entry (&optional n)
- "Jump to the beginning of the next bibtex entry.
- N is a prefix argument. If it is numeric, jump that many entries
- forward. Negative numbers do nothing."
- (interactive "P")
- ;; Note if we start at the beginning of an entry, nothing
- ;; happens. We need to move forward a char, and call again.
- (when (= (point) (save-excursion
- (bibtex-beginning-of-entry)))
- (forward-char)
- (org-ref-bibtex-next-entry))
-
- ;; search forward for an entry
- (when
- (re-search-forward bibtex-entry-head nil t (and (numberp n) n))
- ;; go to beginning of the entry
- (bibtex-beginning-of-entry)))
-
-
- ;;;###autoload
- (defun org-ref-bibtex-previous-entry (&optional n)
- "Jump to beginning of the previous bibtex entry.
- N is a prefix argument. If it is numeric, jump that many entries back."
- (interactive "P")
- (bibtex-beginning-of-entry)
- (when
- (re-search-backward bibtex-entry-head nil t (and (numberp n) n))
- (bibtex-beginning-of-entry)))
-
-
- (defun org-ref-bibtex-mode-keys ()
- "Modify keymaps used by `bibtex-mode'."
- (local-set-key (kbd "M-n") 'org-ref-bibtex-next-entry)
- (local-set-key (kbd "M-p") 'org-ref-bibtex-previous-entry))
-
- ;; add to bibtex-mode-hook
- (add-hook 'bibtex-mode-hook 'org-ref-bibtex-mode-keys)
-
- ;;* Functions to act on an entry with a doi
- ;;;###autoload
- (defun org-ref-bibtex-entry-doi ()
- "Get doi from entry at point."
- (interactive)
- (save-excursion
- (bibtex-beginning-of-entry)
- (when (not (looking-at bibtex-any-valid-entry-type))
- (error "This entry does not appear to be a valid type."))
- (let ((entry (bibtex-parse-entry t)))
- (when (null entry)
- (error "Unable to parse this bibtex entry."))
- (reftex-get-bib-field "doi" entry))))
-
- ;; function that ensures that the url field of a bibtex entry is the
- ;; properly-formatted hyperlink of the DOI. See
- ;; http://blog.crossref.org/2016/09/new-crossref-doi-display-guidelines.html
- ;; for more information.
- ;;;###autoload
- (defun org-ref-bibtex-format-url-if-doi ()
- "Hook function to format url to follow the current DOI conventions."
- (interactive)
- (if (eq (org-ref-bibtex-entry-doi) "") nil
- (let ((front-url "https://doi.org/")
- (doi (org-ref-bibtex-entry-doi)))
- (bibtex-set-field "url"
- (concat front-url doi)))))
-
-
- ;;;###autoload
- (defun org-ref-bibtex-wos ()
- "Open bibtex entry in Web Of Science if there is a DOI."
- (interactive)
- (doi-utils-wos (org-ref-bibtex-entry-doi)))
-
-
- ;;;###autoload
- (defun org-ref-bibtex-wos-citing ()
- "Open citing articles for bibtex entry in Web Of Science if
- there is a DOI."
- (interactive)
- (doi-utils-wos-citing (org-ref-bibtex-entry-doi)))
-
-
- ;;;###autoload
- (defun org-ref-bibtex-wos-related ()
- "Open related articles for bibtex entry in Web Of Science if
- there is a DOI."
- (interactive)
- (doi-utils-wos-related (org-ref-bibtex-entry-doi)))
-
-
- ;;;###autoload
- (defun org-ref-bibtex-crossref ()
- "Open the bibtex entry in Crossref by its doi."
- (interactive)
- (doi-utils-crossref (org-ref-bibtex-entry-doi)))
-
-
- ;;;###autoload
- (defun org-ref-bibtex-google-scholar ()
- "Open the bibtex entry at point in google-scholar by its doi."
- (interactive)
- (let ((doi (org-ref-bibtex-entry-doi)))
- (doi-utils-google-scholar
- (if (string= "" doi)
- (save-excursion
- (bibtex-beginning-of-entry)
- (reftex-get-bib-field "title" (bibtex-parse-entry t)))
- doi))))
-
-
- ;;;###autoload
- (defun org-ref-bibtex-pubmed ()
- "Open the bibtex entry at point in Pubmed by its doi."
- (interactive)
- (doi-utils-pubmed (org-ref-bibtex-entry-doi)))
-
-
- ;;;###autoload
- (defun org-ref-bibtex-pdf (&optional _)
- "Open the pdf for the bibtex entry at point.
- Thin wrapper to get `org-ref-bibtex' to open pdf, because it
- calls functions with a DOI argument."
- (interactive)
- (org-ref-open-bibtex-pdf))
-
- (defun org-ref-bibtex-get-file-move-func (prefix)
- "Determine whether to use `rename-file' or `copy-file' for `org-ref-bibtex-assoc-pdf-with-entry'.
- When called with a PREFIX argument,
- `org-ref-bibtex-assoc-pdf-with-entry-move-function' switches to the
- opposite function from that which is defined in
- `org-ref-assoc-pdf-with-entry-move-function'."
- (message (format "%s" prefix))
- (if (eq prefix nil)
- org-ref-bibtex-assoc-pdf-with-entry-move-function
- (if (eq org-ref-bibtex-assoc-pdf-with-entry-move-function 'rename-file)
- 'copy-file
- 'rename-file)))
-
- ;;;###autoload
- (defun org-ref-bibtex-assoc-pdf-with-entry (&optional prefix)
- "Prompt for pdf associated with entry at point and rename it.
- Check whether a pdf already exists in `org-ref-pdf-directory' 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
- `org-ref-pdf-directory'. Optional PREFIX argument toggles between
- `rename-file' and `copy-file'."
- (interactive "P")
- (save-excursion
- (bibtex-beginning-of-entry)
- (let* ((file (read-file-name "Select file associated with entry: "))
- (bibtex-expand-strings t)
- (entry (bibtex-parse-entry t))
- (key (reftex-get-bib-field "=key=" entry))
- (pdf (concat org-ref-pdf-directory (concat key ".pdf")))
- (file-move-func (org-ref-bibtex-get-file-move-func prefix)))
- (if (file-exists-p pdf)
- (message (format "A file named %s already exists" pdf))
- (progn
- (funcall file-move-func file pdf)
- (message (format "Created file %s" pdf)))))))
-
-
- ;;* Hydra menus
- ;;** Hydra menu for bibtex entries
- ;; hydra menu for actions on bibtex entries
- (defhydra org-ref-bibtex-hydra (:color blue)
- "
- _p_: Open pdf _y_: Copy key _N_: New entry _w_: WOS
- _b_: Open url _f_: Copy formatted entry _o_: Copy entry _c_: WOS citing
- _r_: Refile entry _k_: Add keywords _d_: delete entry _a_: WOS related
- _e_: Email entry _K_: Edit keywords _L_: clean entry _P_: Pubmed
- _U_: Update entry _N_: New entry _R_: Crossref _g_: Google Scholar
- _s_: Sort entry _a_: Remove nonascii _h_: helm-bibtex _q_: quit
- _u_: Update field _F_: file funcs _A_: Assoc pdf with entry
- _n_: Open notes _T_: Title case
- _S_: Sentence case
- "
- ("p" org-ref-open-bibtex-pdf)
- ("P" org-ref-bibtex-pubmed)
- ("w" org-ref-bibtex-wos)
- ("c" org-ref-bibtex-wos-citing)
- ("a" org-ref-bibtex-wos-related)
- ("R" org-ref-bibtex-crossref)
- ("g" org-ref-bibtex-google-scholar)
- ("N" org-ref-bibtex-new-entry/body)
- ("n" org-ref-open-bibtex-notes)
- ("o" (lambda ()
- (interactive)
- (bibtex-copy-entry-as-kill)
- (message "Use %s to paste the entry"
- (substitute-command-keys (format "\\[bibtex-yank]")))))
- ("d" bibtex-kill-entry)
- ("L" org-ref-clean-bibtex-entry)
- ("y" (save-excursion
- (bibtex-beginning-of-entry)
- (when (looking-at bibtex-entry-maybe-empty-head)
- (kill-new (bibtex-key-in-head)))))
- ("f" (progn
- (bibtex-beginning-of-entry)
- (kill-new
- (org-ref-format-entry
- (cdr (assoc "=key=" (bibtex-parse-entry t)))))))
- ("k" helm-tag-bibtex-entry)
- ("K" (lambda ()
- (interactive)
- (org-ref-set-bibtex-keywords
- (read-string "Keywords: "
- (bibtex-autokey-get-field "keywords"))
- t)))
- ("b" org-ref-open-in-browser)
- ("r" (lambda ()
- (interactive)
- (bibtex-beginning-of-entry)
- (bibtex-kill-entry)
- (find-file (completing-read
- "Bibtex file: "
- (f-entries "." (lambda (f) (f-ext? f "bib")))))
- (goto-char (point-max))
- (bibtex-yank)
- (save-buffer)
- (kill-buffer)))
- ("e" org-ref-email-bibtex-entry)
- ("U" (doi-utils-update-bibtex-entry-from-doi (org-ref-bibtex-entry-doi)))
- ("u" doi-utils-update-field)
- ("F" org-ref-bibtex-file/body)
- ("h" helm-bibtex)
- ("A" org-ref-bibtex-assoc-pdf-with-entry)
- ("a" org-ref-replace-nonascii)
- ("s" org-ref-sort-bibtex-entry)
- ("T" org-ref-title-case-article)
- ("S" org-ref-sentence-case-article)
- ("q" nil))
-
- ;; create key-chord and key binding for hydra
- (when (and (featurep 'key-chord) org-ref-bibtex-hydra-key-chord)
- (key-chord-define-global
- org-ref-bibtex-hydra-key-chord
- 'org-ref-bibtex-hydra/body))
-
-
- (when org-ref-bibtex-hydra-key-binding
- (define-key bibtex-mode-map org-ref-bibtex-hydra-key-binding 'org-ref-bibtex-hydra/body))
-
- ;;** Hydra menu for new bibtex entries
- ;; A hydra for adding new bibtex entries.
- (defhydra org-ref-bibtex-new-entry (:color blue)
- "New Bibtex entry:"
- ("a" bibtex-Article "Article")
- ("b" bibtex-Book "Book")
- ("i" bibtex-InBook "In book")
- ("l" bibtex-Booklet "Booklet")
- ("P" bibtex-Proceedings "Proceedings")
- ("p" bibtex-InProceedings "In proceedings")
- ("m" bibtex-Misc "Misc.")
- ("M" bibtex-Manual "Manual")
- ("T" bibtex-PhdThesis "PhD Thesis")
- ("t" bibtex-MastersThesis "MS Thesis")
- ("R" bibtex-TechReport "Report")
- ("u" bibtex-Unpublished "unpublished")
- ("c" bibtex-InCollection "Article in collection")
- ("q" nil "quit"))
-
-
- ;;** Hydra menu of functions to act on a bibtex file.
- (defhydra org-ref-bibtex-file (:color blue)
- "Bibtex file functions: "
- ("v" bibtex-validate "Validate entries")
- ("s" bibtex-sort-buffer "Sort entries")
- ("r" bibtex-reformat "Reformat entries")
- ("c" bibtex-count-entries "Count entries")
- ("p" org-ref-build-full-bibliography "PDF bibliography"))
-
-
- ;;* DEPRECATED bibtex menu
- (defvar org-ref-bibtex-menu-funcs '()
- "Functions to run in doi menu.
- Each entry is a list of (key menu-name function). The function
- must take one argument, the doi. This is somewhat deprecated, as
- I prefer the hydra interfaces above.")
-
- (setq org-ref-bibtex-menu-funcs
- '(("p" "df" org-ref-bibtex-pdf)
- ("C" "opy" (lambda (doi)
- (kill-new (org-ref-bib-citation))
- (bury-buffer)))
- ("w" "os" doi-utils-wos)
- ("c" "iting articles" doi-utils-wos-citing)
- ("r" "elated articles" doi-utils-wos-related)
- ("s" "Google Scholar" doi-utils-google-scholar)
- ("P" "Pubmed" doi-utils-pubmed)
- ("f" "CrossRef" doi-utils-crossref)))
-
- ;;;###autoload
- (defun org-ref-bibtex ()
- "Menu command to run in a bibtex entry.
- Functions from `org-ref-bibtex-menu-funcs'. They all rely on the
- entry having a doi."
- (interactive)
- ;; construct menu string as a message
- (message
- (concat
- (mapconcat
- (lambda (tup)
- (concat "[" (elt tup 0) "]"
- (elt tup 1) " "))
- org-ref-bibtex-menu-funcs "") ": "))
- (let* ((input (read-char-exclusive))
- (choice (assoc
- (char-to-string input) org-ref-bibtex-menu-funcs)))
- (when choice
- (funcall
- (elt
- choice
- 2)
- (org-ref-bibtex-entry-doi)))))
-
- (defalias 'jb 'org-ref-bibtex)
-
-
- ;;;###autoload
- (defun org-ref-email-bibtex-entry ()
- "Email current bibtex entry at point and pdf if it exists."
- (interactive)
-
- (save-excursion
- (bibtex-beginning-of-entry)
- (let* ((key (reftex-get-bib-field "=key=" (bibtex-parse-entry t)))
- pdf)
- ;; when we have org-ref defined we may have pdf to find.
- (when (boundp 'org-ref-pdf-directory)
- (setq pdf (expand-file-name
- (concat key ".pdf")
- org-ref-pdf-directory)))
- (bibtex-copy-entry-as-kill)
- (compose-mail)
- (message-goto-body)
- (insert (pop bibtex-entry-kill-ring))
- (message-goto-subject)
- (insert key)
- (message "%s exists %s" pdf (file-exists-p pdf))
- (when (file-exists-p pdf)
- (mml-attach-file pdf))
- (message-goto-to))))
-
- ;;* org-ref bibtex keywords
- ;; adapted from bibtex-utils.el
- ;; these are candidates for selecting keywords/tags
- (defun org-ref-bibtex-keywords ()
- "Get keywords defined in current bibtex file.
- These are in the keywords field, and are comma or semicolon separated."
- (save-excursion
- (goto-char (point-min))
- (let (keywords kstring)
- (while (re-search-forward "^\\s-*keywords.*{\\([^}]+\\)}" nil t)
- ;; TWS - remove newlines/multiple spaces:
- (setq kstring (replace-regexp-in-string
- "[ \t\n]+" " "
- (match-string 1)))
- (mapc
- (lambda (v)
- (add-to-list 'keywords v t))
- (split-string kstring "\\(,\\|;\\)[ \n]*\\|{\\|}" t)))
- keywords)))
-
-
- ;;;###autoload
- (defun org-ref-set-bibtex-keywords (keywords &optional arg)
- "Add KEYWORDS to a bibtex entry.
- If KEYWORDS is a list, it is converted to a comma-separated
- string. The KEYWORDS are added to the beginning of the
- field. Otherwise KEYWORDS should be a string of comma-separate
- keywords. Optional argument ARG prefix arg to replace keywords."
- (interactive
- (list
- (completing-read "Keyword: " (org-ref-bibtex-keywords))
- current-prefix-arg))
- (bibtex-set-field
- "keywords"
- (if arg
- ;; replace with arg
- (if (listp keywords)
- (mapconcat 'identity keywords ", ")
- keywords)
- ;; else concatentate
- (concat
- (if (listp keywords)
- (mapconcat 'identity keywords ", ")
- keywords)
- (when (not (string= "" (bibtex-autokey-get-field "keywords")))
- (concat ", " (bibtex-autokey-get-field "keywords"))))))
- (when (buffer-file-name)
- (save-buffer)))
-
-
- (defun org-ref-save-all-bibtex-buffers ()
- "Save all bibtex-buffers."
- (cl-loop for buffer in (buffer-list)
- do
- (with-current-buffer buffer
- (when (and (buffer-file-name) (f-ext? (buffer-file-name) "bib"))
- (save-buffer)))))
-
-
- ;;* org-ref bibtex cache
- (defvar orhc-bibtex-cache-data
- '((hashes . ())
- (candidates . ()))
- "Cache data as an alist.
- 'hashes is a list of cons cells (bibfile . hash)
- 'candidates is a list of cons cells (bibfile . candidates).
- Stored persistently in `orhc-bibtex-cache-file'.")
-
-
- (defvar orhc-bibtex-cache-file
- "~/.orhc-bibtex-cache"
- "File to store cached data in.")
-
-
- (defvar org-ref-bibtex-files nil
- "List of bibtex files to get entries from.
- This is set internally.")
-
-
- (defvar orhc-candidate-formats
- '(("article" . "${pdf}${notes}|${=key=}| ${author}, ${title}, ${journal} (${year}). ${keywords}")
- ("book" . " |${=key=}| ${author}, ${title} (${year}) ${keywords}.")
- ("inbook" . " |${=key=}| ${author}, ${chapter} in ${title} (${year}) ${keywords}")
- ("techreport" . " |${=key=}| ${title}, ${institution} (${year}). ${keywords}")
- ("inproceedings" . " |${=key=}| ${author}, ${title} in ${booktitle} (${year}). ${keywords}")
- ("incollection" . " |${=key=}| ${author}, ${title} in ${booktitle} (${year}). ${keywords}")
- ("phdthesis" . " |${=key=}| ${author}, ${title}, ${school} (${year}). Phd thesis. ${keywords}")
- ("mastersthesis" . " |${=key=}| ${author}, ${title}, ${school} (${year}). MS thesis. ${keywords}")
- ("misc" . " |${=key=}| ${author}, ${title}")
- ("unpublished" . " |${=key=}| ${author}, ${title}"))
- "Formats for candidates.
- It is an alist of (=type= . s-format-string).")
-
-
- ;; when you load, we should check the hashes and files
- (defun orhc-load-cache-file ()
- "Load the cache file to set `orhc-bibtex-cache-data'."
- (when (file-exists-p orhc-bibtex-cache-file)
- (with-current-buffer (find-file-noselect orhc-bibtex-cache-file)
- (goto-char (point-min))
- (setq orhc-bibtex-cache-data (read (current-buffer))))
- (when (find-buffer-visiting orhc-bibtex-cache-file)
- (kill-buffer (find-buffer-visiting orhc-bibtex-cache-file)))))
-
-
- (defun orhc-clear-cache ()
- "Clear the cache and delete `orhc-bibtex-cache-file'."
- (interactive)
- (setq orhc-bibtex-cache-data '((hashes . nil)
- (candidates . nil)))
- (when (find-buffer-visiting orhc-bibtex-cache-file)
- (kill-buffer (find-buffer-visiting orhc-bibtex-cache-file)))
- (when (file-exists-p orhc-bibtex-cache-file)
- (delete-file orhc-bibtex-cache-file))
- (message "org-ref-helm-cite cache cleared."))
-
-
- (defun orhc-bibtex-cache-up-to-date ()
- "Return if bibtex caches are up to date.
- This means the hash of each bibfile is equal to the one for it in
- the cache."
- (-all? 'identity
- (cl-loop
- for bibfile in org-ref-bibtex-files
- collect
- (string= (with-temp-buffer
- (insert-file-contents bibfile)
- (secure-hash 'sha256 (current-buffer)))
- (or (cdr (assoc
- bibfile
- (cdr (assoc 'hashes orhc-bibtex-cache-data)))) "")))))
-
- (defun orhc-bibtex-field-formatter (field entry)
- "Format FIELD in a bibtex parsed ENTRY.
- A few fields are treated specially, e.g. authors are replaced by
- comma-separated list, and I put :: around keywords to make it
- easier to search specifically for them."
- (let ((s (replace-regexp-in-string
- "^{\\|}$" ""
- (replace-regexp-in-string
- "[\n\t\s]+" " "
- (or (cdr (assoc field entry))
- (and (string= field "author")
- (cdr (assoc "editor" entry)))
- "")))))
- (cond
- ((string= field "author")
- (if org-ref-helm-cite-shorten-authors
- ;; copied from `helm-bibtex-shorten-authors'
- (cl-loop for a in (s-split " and " s)
- for p = (s-split "," a t)
- for sep = "" then ", "
- concat sep
- if (eq 1 (length p))
- concat (-last-item (s-split " +" (car p) t))
- else
- concat (car p))
- (mapconcat 'identity (s-split " and " s) ", ")))
- ((string= field "keywords")
- (if (> (length s) 0)
- (mapconcat (lambda (keyword)
- (concat ":" (s-trim keyword) ":"))
- (s-split "," s)
- " ")
- ""))
- ((string= field "pdf")
- (if (file-exists-p (expand-file-name
- (concat (cdr (assoc "=key=" entry)) ".pdf")
- org-ref-pdf-directory))
- "⌘"
- " "))
- ((string= field "notes")
- (if (file-exists-p (expand-file-name
- (concat (cdr (assoc "=key=" entry)) ".org")
- org-ref-notes-directory))
- "✎"
- " "))
- ;; catch all the other fields and just return them.
- (t
- s))))
-
- (defun orhc-update-bibfile-cache (bibfile)
- "Update cache for BIBFILE.
- This generates the candidates for the file. Some of this code is
- adapted from `helm-bibtex-parse-bibliography'. This function runs
- when called, it resets the cache for the BIBFILE."
- ;; check if the bibfile is already open, and preserve this state. i.e. if it
- ;; is not open close it, and if it is leave it open.
- (let ((bibfile-open (find-buffer-visiting bibfile)))
- (with-current-buffer (find-file-noselect bibfile)
- (bibtex-beginning-of-first-entry)
- (message "Updating cache for %s" bibfile)
- (let ((hash (secure-hash 'sha256 (current-buffer)))
- (entries
- (cl-loop
- for entry-type = (parsebib-find-next-item)
- while entry-type
- unless (member-ignore-case entry-type
- '("preamble" "string" "comment"))
- collect
- (let* ((entry (cl-loop for cons-cell in (parsebib-read-entry entry-type)
- ;; we remove all properties too. they
- ;; cause errors in reading/writing.
- collect
- (cons (substring-no-properties
- (downcase (car cons-cell)))
- (substring-no-properties
- ;; clumsy way to remove surrounding
- ;; brackets
- (let ((s (cdr cons-cell)))
- (if (or (and (s-starts-with? "{" s)
- (s-ends-with? "}" s))
- (and (s-starts-with? "\"" s)
- (s-ends-with? "\"" s)))
- (substring s 1 -1)
- s))))))
- ;; (key (cdr (assoc "=key=" entry)))
- )
- (cons
- ;; this is the display string for helm. We try to use the formats
- ;; in `orhc-candidate-formats', but if there isn't one we just put
- ;; all the fields in.
- (s-format
- (or (cdr (assoc (downcase entry-type) orhc-candidate-formats))
- (format "%s: %s" (cdr (assoc "=key=" entry)) entry))
- 'orhc-bibtex-field-formatter
- entry)
- ;; this is the candidate that is returned, the entry a-list +
- ;; file and position.
- (append entry (list (cons "bibfile" (buffer-file-name))
- (cons "position" (point)))))))))
-
- ;; Now update the cache variables for hash and entries
- (if (assoc bibfile (cdr (assoc 'candidates orhc-bibtex-cache-data)))
- (setf (cdr (assoc bibfile
- (cdr (assoc 'candidates orhc-bibtex-cache-data))))
- entries)
- (cl-pushnew (cons bibfile entries)
- (cdr (assoc 'candidates orhc-bibtex-cache-data))))
- (if (assoc bibfile (cdr (assoc 'hashes orhc-bibtex-cache-data)))
- (setf (cdr (assoc
- bibfile
- (cdr (assoc 'hashes orhc-bibtex-cache-data))))
- hash)
- (cl-pushnew (cons bibfile hash)
- (cdr (assoc 'hashes orhc-bibtex-cache-data))))
-
- ;; And save it to disk for persistent use
- (with-temp-file orhc-bibtex-cache-file
- (print orhc-bibtex-cache-data (current-buffer)))))
- (unless bibfile-open (kill-buffer (find-buffer-visiting bibfile)))))
-
- (defun orhc-update-bibtex-cache ()
- "Conditionally update cache for all files in `org-ref-bibtex-files'.
- Files that have the same hash as in the cache are not updated."
- (cl-loop for bibfile in org-ref-bibtex-files
- unless (string= (with-temp-buffer
- (insert-file-contents bibfile)
- (secure-hash 'sha256 (current-buffer)))
- (or (cdr
- (assoc bibfile
- (cdr
- (assoc 'hashes orhc-bibtex-cache-data))))
- ""))
- do
- (orhc-update-bibfile-cache bibfile)))
-
-
- (defun orhc-helm-cite-describe-cache ()
- "Show what is in the cache."
- (interactive)
- (let ((hash-cache (cdr (assoc 'hashes orhc-bibtex-cache-data)))
- (candidates-cache (cdr (assoc 'candidates orhc-bibtex-cache-data))))
- (message "%s\n\n%s"
- (mapconcat (lambda (h)
- (format "%s - %s" (car h) (cdr h)))
- hash-cache "\n")
- (mapconcat (lambda (c)
- (format "%s - %s entries" (car c) (length (cdr c))))
- candidates-cache "\n"))))
-
-
- (defun orhc-bibtex-candidates ()
- "Return the candidates from cache for files listed in `org-ref-bibtex-files'.
- Update the cache if necessary."
- ;; this only does something when the cache is out of date
- (org-ref-save-all-bibtex-buffers)
- (orhc-update-bibtex-cache)
- (let ((candidates (cdr (assoc 'candidates orhc-bibtex-cache-data))))
- (apply 'append
- (cl-loop for bibfile in org-ref-bibtex-files
- collect (cdr (assoc bibfile candidates))))))
-
-
- ;; Now load files and update them if needed. We do this when you load the
- ;; library so they are available later.
- (orhc-load-cache-file)
- (orhc-update-bibtex-cache)
-
-
- ;;* org-ref bibtex formatted citation
-
- (defun org-ref-format-bibtex-entry (entry)
- "Return a formatted citation for the bibtex entry at point.
- Formats are from `org-ref-formatted-citation-formats'. The
- variable `org-ref-formatted-citation-backend' determines the set
- of format strings used."
- (save-excursion
- (bibtex-beginning-of-entry)
- (let* ((formats (cdr (assoc org-ref-formatted-citation-backend org-ref-formatted-citation-formats)))
- (format-string)
- (ref))
- (if (null entry)
- "!!! No entry found !!!"
- (setq format-string (cdr (or (assoc (downcase (bibtex-completion-get-value "=type=" entry)) formats)
- (assoc nil formats))))
- (setq ref (s-format format-string 'bibtex-completion-apa-get-value entry))
- (replace-regexp-in-string "\\([.?!]\\)\\." "\\1" ref)))))
-
-
- (defun org-ref-format-entry (key)
- "Returns a formatted bibtex entry for KEY."
- (let* ((bibtex-completion-bibliography (org-ref-find-bibliography)))
- (org-ref-format-bibtex-entry (ignore-errors (bibtex-completion-get-entry key)))))
-
-
- (defun org-ref-format-bibtex-entry-at-point ()
- "Return a formatted citation for the bibtex entry at point."
- (save-excursion
- (bibtex-beginning-of-entry)
- (org-ref-format-bibtex-entry (bibtex-parse-entry t))))
-
-
- ;; ** using citeproc
- (defun orhc-formatted-citation (entry)
- "Get a formatted string for ENTRY."
- (require 'unsrt)
- (let* ((adaptive-fill-function '(lambda () " "))
- (indent-tabs-mode nil)
- (entry-type (downcase
- (cdr (assoc "=type=" entry))))
- (entry-styles (cdr (assoc 'entries bibliography-style)))
- (entry-fields
- (progn
- (if (cdr (assoc (intern entry-type) entry-styles))
- (cdr (assoc (intern entry-type) entry-styles))
- (warn "%s not found. Using default." entry-type)
- (cdr (assoc 't entry-styles)))))
- (funcs (mapcar
- (lambda (field)
- (if (fboundp (intern
- (format "orcp-%s" field)))
- (intern
- (format "orcp-%s" field))
- ;; No formatter found. just get the data
- `(lambda (entry)
- (orcp-get-entry-field
- ,(symbol-name field) entry))))
- entry-fields)))
-
- ;; this is the entry. We do this in a buffer to make it
- ;; easy to indent, fill, etc...
- (with-temp-buffer
- (insert (mapconcat (lambda (field-func)
- (funcall field-func entry))
- funcs
- ""))
- (buffer-string))))
-
- ;; * Extract bibtex blocks from an org-file
- ;;;###autoload
- (defun org-ref-extract-bibtex-blocks (bibfile)
- "Extract all bibtex blocks in buffer to BIBFILE.
- If BIBFILE exists, append, unless you use a prefix arg (C-u), which
- will clobber the file."
- (interactive
- (list (read-file-name "Bibfile: " nil nil nil
- (file-name-nondirectory
- (concat (file-name-sans-extension
- (buffer-file-name))
- ".bib")))))
-
- (let ((contents ""))
- (when (and (file-exists-p bibfile)
- (not current-prefix-arg))
- (setq contents (with-temp-buffer
- (insert-file-contents bibfile)
- (buffer-string))))
-
- (save-excursion
- (goto-char (point-min))
- (while (re-search-forward "#\\+BEGIN_SRC bibtex" nil t)
- (setq contents
- (concat
- contents
- (org-element-property :value (org-element-at-point))))))
-
- (with-temp-file bibfile
- (insert contents))))
-
- (defun org-ref-bibtex-key-from-doi (doi &optional bib)
- "Return a bibtex entry's key from a DOI.
- BIB is an optional filename to get the entry from. Defaults to
- the first entry of `org-ref-default-bibliography'."
- (let ((bibfile (if bib bib (car org-ref-default-bibliography))))
- (with-temp-buffer
- (insert-file-contents (expand-file-name bibfile))
- (search-forward doi)
- (bibtex-beginning-of-entry)
- (cdr (assoc "=key=" (bibtex-parse-entry))))))
-
- ;;* The end
- (provide 'org-ref-bibtex)
-
- ;;; org-ref-bibtex.el ends here
|