]> git.donarmstrong.com Git - org-ref.git/blob - jmax-bibtex.el
9dc8bfd4b103cc81b03c26046fea17de1c7cfba8
[org-ref.git] / jmax-bibtex.el
1 ;;; jmax-bibtex.el --- jmax-bibtex utilities
2
3 ;;; Commentary:
4 ;; Requires: s.el, dash.el, org-ref.el, doi-utils.el, key-chord.el
5 ;;
6 ;; jmax-bibtex-generate-longtitles
7 ;; jmax-bibtex-generate-shorttitles
8 ;; jmax-stringify-journal-name :: replace a journal name with a string in `jmax-bibtex-journal-abbreviations'
9 ;; jmax-set-journal-string :: in a bibtex entry run this to replace the journal with a string
10 ;;
11 ;; jmax-replace-nonascii :: replace nonascii characters in a bibtex entry
12 ;;
13 ;; jmax-title-case-article
14 ;; jmax-sentence-case-article
15 ;;
16 ;; jmax-bibtex-next-entry :: bound to M-n
17 ;; jmax-bibtex-previous-entry :: bound to M-p
18 ;;
19 ;; Functions to act on an entry
20 ;; jmax-bibtex-hydra/body gives a hydra menu to a lot of useful functions.
21 ;; jmax-bibtex-new-entry/body gives a hydra menu to add new bibtex entries.
22
23 (require 'hydra)
24 (require 'key-chord)
25
26 ;;; Code:
27 (defgroup jmax-bibtex nil
28   "Customization group for jmax-bibtex.")
29
30
31 (defcustom jmax-bibtex-hydra-key-chord
32   nil
33   "key-chord to run `jmax-bibtex-hydra'.
34 I like \"jj\""
35   :type 'string
36   :group 'jmax-bibtex)
37
38
39 (defcustom jmax-bibtex-hydra-key-binding
40   nil
41   "key-binding to run `jmax-bibtex-hydra'.
42 I like \C-cj."
43   :type 'string
44   :group 'jmax-bibtex)
45
46
47 (defvar jmax-bibtex-journal-abbreviations
48   '(("ACAT" "ACS Catalysis" "ACS Catal.")
49     ("AM" "Acta Materialia" "Acta Mater.")
50     ("AMM" "Acta Metallurgica et Materialia" "Acta Metall. Mater.")
51     ("AMiner" "American Mineralogist" "Am. Mineral.")
52     ("AngC" "Angewandte Chemie-International Edition" "Angew. Chem. Int. Edit.")
53     ("APLM" "APL Materials" "APL Mat.")
54     ("ACBE" "Applied Catalysis B: Environmental" "Appl. Catal. B-Environ.")
55     ("APL" "Applied Physics Letters" "Appl. Phys. Lett.")
56     ("ASS" "Applied Surface Science" "Appl. Surf. Sci.")
57     ("CL" "Catalysis Letters" "Catal. Lett.")
58     ("CST" "Catalysis Science & Technology" "Catal. Sci. Technol.")
59     ("CT" "Catalysis Today" "Catal. Today")
60     ("CPL" "Chemical Physics Letters" "Chem. Phys. Lett")
61     ("CR" "Chemical Reviews" "Chem. Rev.")
62     ("CSR" "Chemical Society Reviews" "Chem. Soc. Rev.")
63     ("CSR" "Chemical Society Reviews" "Chem. Soc. Rev.")
64     ("CM" "Chemistry of Materials" "Chem. Mater.")
65     ("CSA" "Colloids and Surfaces, A: Physicochemical and Engineering Aspects" "Colloids Surf., A")
66     ("CPMS" "Computational Materials Science" "Comp. Mater. Sci.")
67     ("CPC" "Computer Physics Communications" "Comput. Phys. Commun.")
68     ("CGD" "Crystal Growth \\& Design" "Cryst. Growth Des.")
69     ("CEC" "CrystEngComm" "CrystEngComm")
70     ("ECST" "ECS Transactions" "ECS Trans.")
71     ("EES" "Energy \\& Environmental Science" "Energy Environ. Sci.")
72     ("HPR" "High Pressure Research" "High Pressure Res.")
73     ("IC" "Inorganic Chemistry" "Inorg. Chem.")
74     ("IECR" "Industrial \\& Engineering Chemistry Research" "Ind. Eng. Chem. Res.")
75     ("JJAP" "Japanese Journal of Applied Physics" "Jpn. J. Appl. Phys.")
76     ("JMatR" "Journal of  Materials Research" "J. Mater. Res.")
77     ("JALC" "Journal of Alloys and Compounds" "J. Alloy Compd.")
78     ("JAC" "Journal of Applied Crystallography" "J. Appl. Crystallogr.")
79     ("JAP" "Journal of Applied Physics" "J. Appl. Phys.")
80     ("JC" "Journal of Catalysis" "J. Catal.")
81     ("JCP" "Journal of Chemical Physics" "J. Chem. Phys.")
82     ("JCC" "Journal of Computational Chemistry" "J. Comput. Chem.")
83     ("JCG" "Journal of Crystal Growth" "J. Crys. Growth")
84     ("JMC" "Journal of Materials Chemistry" "J. Mater. Chem.")
85     ("JMC" "Journal of Materials Chemistry" "J. Mater. Chem.")
86     ("JMSL" "Journal of Materials Science Letters" "J. Mater. Sci. Lett.")
87     ("JMS" "Journal of Membrane Science" "J. Memb. Sci.")
88     ("JPE" "Journal of Phase Equilibria" "J. Phase Equilib.")
89     ("JPCS" "Journal of Physics and Chemistry of Solids" "J. Phys. Chem. Solids")
90     ("JPCM" "Journal of Physics: Condensed Matter" "J. Phys.: Condens. Matter")
91     ("JSSC" "Journal of Solid State Chemistry" "J. Solid State Chem.")
92     ("JACerS" "Journal of the American Ceramic Society" "J. Am. Ceram. Soc.")
93     ("JACS" "Journal of the American Chemical Society" "J. Am. Chem. Soc.")
94     ("JES" "Journal of The Electrochemical Society" "J. Electrochem. Soc.")
95     ("JEaC" "Journal of Electroanalytical Chemistry" "J. Electroanal. Chem.")
96     ("JMS" "Journal of Membrane Science" "J. Memb. Sci.")
97     ("JVST" "Journal of Vacuum Science \\& Technology A" "J. Vac. Sci. Technol. A")
98     ("ML" "Materials Letters" "Mater. Lett.")
99     ("MSE-BS" "Materials Science and Engineering B" "Mat. Sci. Eng. B-Solid")
100     ("MOLSIM" "Molecular Simulation" "Mol. Sim.")
101     ("Nature" "Nature" "Nature")
102     ("NM" "Nature Materials" "Nat. Mater.")
103     ("PML" "Philosophical Magazine Letters" "Phil. Mag. Lett.")
104     ("PMA" "Philosophical Magazine A" "Phil. Mag. A")
105     ("PA" "Physica A: Statistical Mechanics and its Applications" "Physica A")
106     ("PB" "Physica B-Condensed Matter" "Physica B")
107     ("PCCP" "Physical Chemistry Chemical Physics" "Phys. Chem. Chem. Phys.")
108     ("PSSB" "physica status solidi (b)" "Phys. Status Solidi B")
109     ("PRA" "Physical Review A" "Phys. Rev. A")
110     ("PRB" "Physical Review B" "Phys. Rev. B")
111     ("PRL" "Physical Review Letters" "Phys. Rev. Lett.")
112     ("PCM" "Physics and Chemistry of Minerals" "Phys. Chem. Miner.")
113     ("PSurfSci" "Progress in Surface Science" "Prog. Surf. Sci.")
114     ("Science" "Science" "Science")
115     ("SABC" "Sensors and Actuators B: Chemical" "Sensor. Actuat. B-Chem.")
116     ("SS" "Surface Science" "Surf. Sci.")
117     ("EPJB" "The European Physical Journal B" "Eur. Phys. J. B")
118     ("JPC" "The Journal of Physical Chemistry" "J. Phys. Chem.")
119     ("JPCB" "The Journal of Physical Chemistry B" "J. Phys. Chem. B")
120     ("JPCC" "The Journal of Physical Chemistry C" "J. Phys. Chem. C")
121     ("JPCL" "The Journal of Physical Chemistry Letters" "J. Phys. Chem. Lett.")
122     ("JCP" "The Journal of Chemical Physics" "J. Chem. Phys.")
123     ("MSMSE" "Modelling and Simulation in Materials Science and Engineering" "Modell. Simul. Mater. Sci. Eng.")
124     ("TSF" "Thin Solid Films" "Thin Solid Films")
125     ("TC" "Topics in Catalysis" "Top. Catal.")
126     ("WR" "Water Research" "Water Res."))
127   "List of (string journal-full-name journal-abbreviation).  Find abbreviations at http://cassi.cas.org/search.jsp.")
128
129
130 (defun jmax-bibtex-generate-longtitles ()
131   "Generate longtitles.bib which are @string definitions.
132 The full journal names are in `jmax-bibtex-journal-abbreviations'."
133   (interactive)
134   (with-temp-file "longtitles.bib"
135     (dolist (row jmax-bibtex-journal-abbreviations)
136       (insert (format "@string{%s=\"%s\"}\n"
137                       (nth 0 row)
138                       (nth 1 row))))))
139
140
141 (defun jmax-bibtex-generate-shorttitles ()
142     "Generate shorttitles.bib which are @string definitions.
143 The abbreviated journal names in `jmax-bibtex-journal-abbreviations'."
144   (interactive)
145   (with-temp-file "shorttitles.bib"
146     (dolist (row jmax-bibtex-journal-abbreviations)
147       (insert (format "@string{%s=\"%s\"}\n"
148                       (nth 0 row)
149                       (nth 2 row))))))
150
151
152 (defun jmax-stringify-journal-name (&optional key start end)
153   "Replace journal name in a bibtex entry with a string.
154 The strings are defined in
155 `jmax-bibtex-journal-abbreviations'.  The optional arguments KEY,
156 START and END allow you to use this with `bibtex-map-entries'"
157   (interactive)
158   (bibtex-beginning-of-entry)
159   (when
160       (string= "article"
161                (downcase
162                 (cdr (assoc "=type=" (bibtex-parse-entry)))))
163     (let* ((full-names (mapcar
164                         (lambda (row)
165                           (cons  (nth 1 row) (nth 0 row)))
166                         jmax-bibtex-journal-abbreviations))
167            (abbrev-names (mapcar
168                           (lambda (row)
169                             (cons  (nth 2 row) (nth 0 row)))
170                           jmax-bibtex-journal-abbreviations))
171            (journal (s-trim (bibtex-autokey-get-field "journal")))
172            (bstring (or
173                      (cdr (assoc journal full-names))
174                      (cdr (assoc journal abbrev-names)))))
175       (when bstring
176         (bibtex-set-field "journal" bstring t)
177         (bibtex-fill-entry)))))
178
179 (defun jmax-set-journal-string (full-journal-name)
180   "Set a bibtex journal name to the string that represents FULL-JOURNAL-NAME.
181 This is defined in `jmax-bibtex-journal-abbreviations'."
182   (interactive (list
183                 (ido-completing-read
184                  "Journal: "
185                  (mapcar
186                   (lambda (x)
187                     (nth 1 x))
188                   jmax-bibtex-journal-abbreviations))))
189   ;; construct data alist for the string lookup.
190   (let ((alist (mapcar
191                 (lambda (x)
192                   (cons (nth 1 x) (nth 0 x)))
193                 jmax-bibtex-journal-abbreviations)))
194     (bibtex-set-field "journal" (cdr (assoc full-journal-name alist)) t)
195     (bibtex-fill-entry)
196     (bibtex-clean-entry)))
197
198 ;; see https://github.com/fxcoudert/tools/blob/master/doi2bib for more replacements
199 (defvar jmax-nonascii-latex-replacements
200   '()
201   "Cons list of non-ascii characters and their LaTeX representations.")
202
203 (setq jmax-nonascii-latex-replacements
204       '(("í" . "{\\\\'i}")
205         ("æ" . "{\\\\ae}")
206         ("ć" . "{\\\\'c}")
207         ("é" . "{\\\\'e}")
208         ("ä" . "{\\\\\"a}")
209         ("è" . "{\\\\`e}")
210         ("à" . "{\\\\`a}")
211         ("á" . "{\\\\'a}")
212         ("ø" . "{\\\\o}")
213         ("ë" . "{\\\\\"e}")
214         ("ü" . "{\\\\\"u}")
215         ("ñ" . "{\\\\~n}")
216         ("ņ" . "{\\\\c{n}}")
217         ("å" . "{\\\\aa}")
218         ("ö" . "{\\\\\"o}")
219         ("Á" . "{\\\\'A}")
220         ("á" . "{\\\\'a}")
221         ("í" . "{\\\\'i}")
222         ("ó" . "{\\\\'o}")
223         ("ó" . "{\\\\'o}")
224         ("ú" .  "{\\\\'u}")
225         ("ú" . "{\\\\'u}")
226         ("š" . "{\\\\v{s}}")
227         ("ř"  . "{\\\\v{r}}")
228         ("İ" . "{\\\\.I}")
229         ("ğ" . "{\\\\u{g}}")
230         ("δ" . "$\\\\delta$")
231         ("ç" . "{\\\\c{c}}")
232         ("ß" . "{\\\\ss}")
233         ("≤" . "$\\\\le$")
234         ("<" . "$\\\\lt$")
235         ("θ" . "$\\\\theta$")
236         ("μ" . "$\\\\mu$")
237         ("→" . "$\\\\rightarrow$")
238         ("⇌" . "$\\\\leftrightharpoons$")
239         ("×" . "$\\\\times$")
240         ("°" . "$\\\\deg$")
241         ("ş" . "{\\\\c{s}}")
242         ("ı" . "i")                    ; I think this is a turkish i
243         ;; I think these are non-ascii spaces. there seems to be more than one.
244         (" " . " ")
245         (" " . " ")
246         ("–" . "-")
247         ("−" . "-")
248         ("–" . "-")
249         ("—" . "-")
250         ("‘" . "'")
251         ("’" . "'")
252         ("“" . "\"")
253         ("’" . "'")
254         ("”" . "\"")))
255
256 (defun jmax-replace-nonascii ()
257   "Hook function to replace non-ascii characters in a bibtex entry."
258
259   (interactive)
260   (save-restriction
261     (bibtex-narrow-to-entry)
262     (goto-char (point-min))
263     (dolist (char (mapcar (lambda (x) (car x)) jmax-nonascii-latex-replacements))
264       (while (re-search-forward char nil t)
265         (replace-match (cdr (assoc char jmax-nonascii-latex-replacements))))
266       (goto-char (point-min)))))
267
268 (add-hook 'org-ref-clean-bibtex-entry-hook 'jmax-replace-nonascii)
269
270
271 (defvar jmax-lower-case-words
272   '("a" "an" "on" "and" "for"
273     "the" "of" "in")
274   "List of words to keep lowercase when changing case in a title.")
275
276
277 (defun jmax-title-case-article (&optional key start end)
278   "Convert a bibtex entry article title to title-case.
279 The arguments KEY, START and END are optional, and are only there
280 so you can use this function with `bibtex-map-entries' to change
281 all the title entries in articles."
282   (interactive)
283   (bibtex-beginning-of-entry)
284
285   (let* ((title (bibtex-autokey-get-field "title"))
286          (words (split-string title))
287          (start 0))
288     (when
289         (string= "article" (downcase (cdr (assoc "=type=" (bibtex-parse-entry)))))
290       (setq words (mapcar
291                    (lambda (word)
292                      (if (or
293                           ;; match words containing {} or \ which are probably
294                           ;; LaTeX or protected words
295                           (string-match "\\$\\|{\\|}\\|\\\\" word)
296                           ;; these words should not be capitalized, unless they
297                           ;; are the first word
298                           (-contains? jmax-lower-case-words (s-downcase word)))
299                          word
300                        (s-capitalize word)))
301                    words))
302
303       ;; Check if first word should be capitalized
304       (when (-contains? jmax-lower-case-words (car words))
305         (setf (car words) (s-capitalize (car words))))
306
307       (setq title (mapconcat 'identity words " "))
308
309       ;; Capitalize letters after a dash
310       (while
311           (string-match "[a-zA-Z]-\\([a-z]\\)" title start)
312         (let ((char (substring title (match-beginning 1) (match-end 1))))
313           (setf (substring title (match-beginning 1) (match-end 1))
314                 (format "%s" (upcase char)))
315           (setq start (match-end 1))))
316
317       ;; this is defined in doi-utils
318       (bibtex-set-field
319        "title"
320        title)
321       (bibtex-fill-entry))))
322
323 (add-hook 'org-ref-clean-bibtex-entry-hook 'jmax-title-case-article)
324
325
326 (defun jmax-sentence-case-article (&optional key start end)
327   "Convert a bibtex entry article title to sentence-case.
328 The arguments KEY, START and END are optional, and are only there
329 so you can use this function with `bibtex-map-entries' to change
330 all the title entries in articles."
331   (interactive)
332   (bibtex-beginning-of-entry)
333
334   (let* ((title (bibtex-autokey-get-field "title"))
335          (words (split-string title))
336          (start 0))
337     (when
338         (string= "article" (downcase (cdr (assoc "=type=" (bibtex-parse-entry)))))
339       (setq words (mapcar
340                    (lambda (word)
341                      (if
342                          ;; match words containing {} or \ which are probably
343                          ;; LaTeX or protected words
344                          (string-match "\\$\\|{\\|}\\|\\\\" word)
345                          word
346                        (s-downcase word)))
347                    words))
348
349       ;; capitalize first word
350       (setf (car words) (s-capitalize (car words)))
351
352       ;; join the words
353       (setq title (mapconcat 'identity words " "))
354
355       ;; capitalize a word after a :, eg. a subtitle, and protect it
356       (while
357           (string-match "[a-z]:\\s-+\\([A-Z]\\)" title start)
358         (let ((char (substring title (match-beginning 1) (match-end 1))))
359           (setf (substring title (match-beginning 1) (match-end 1))
360 ;;              (format "{%s}" (upcase char)))
361                 (format "%s" (upcase char)))
362           (setq start (match-end 1))))
363
364       ;; this is defined in doi-utils
365       (bibtex-set-field
366        "title" title)
367
368       ;; clean and refill entry so it looks nice
369       (bibtex-clean-entry)
370       (bibtex-fill-entry))))
371
372
373
374
375 (defun jmax-bibtex-next-entry (&optional n)
376   "Jump to the beginning of the next bibtex entry.
377 N is a prefix argument.  If it is numeric, jump that many entries
378 forward.  Negative numbers do nothing."
379   (interactive "P")
380   ;; Note if we start at the beginning of an entry, nothing
381   ;; happens. We need to move forward a char, and call again.
382   (when (= (point) (save-excursion
383                      (bibtex-beginning-of-entry)))
384     (forward-char)
385     (jmax-bibtex-next-entry))
386
387   ;; search forward for an entry
388   (when
389       (re-search-forward bibtex-entry-head nil t (and (numberp n) n))
390     ;; go to beginning of the entry
391     (bibtex-beginning-of-entry)))
392
393
394 (defun jmax-bibtex-previous-entry (&optional n)
395   "Jump to beginning of the previous bibtex entry.
396 N is a prefix argument.  If it is numeric, jump that many entries back."
397   (interactive "P")
398   (bibtex-beginning-of-entry)
399  (when
400      (re-search-backward bibtex-entry-head nil t (and (numberp n) n))
401    (bibtex-beginning-of-entry)))
402
403
404 (defun jmax-bibtex-mode-keys ()
405   "Modify keymaps used by `bibtex-mode'."
406   (local-set-key (kbd "M-n") 'jmax-bibtex-next-entry)
407   (local-set-key (kbd "M-p") 'jmax-bibtex-previous-entry))
408
409 ;; add to bibtex-mode-hook
410 (add-hook 'bibtex-mode-hook 'jmax-bibtex-mode-keys)
411
412
413 (defun jmax-bibtex-entry-doi ()
414   "Get doi from entry at point."
415   (interactive)
416   (save-excursion
417     (bibtex-beginning-of-entry)
418     (reftex-get-bib-field "doi" (bibtex-parse-entry t))))
419
420
421 (defun jmax-bibtex-wos ()
422   "Open bibtex entry in Web Of Science if there is a DOI."
423   (interactive)
424   (doi-utils-wos (jmax-bibtex-entry-doi)))
425
426
427 (defun jmax-bibtex-wos-citing ()
428   "Open citing articles for bibtex entry in Web Of Science if there is a DOI."
429   (interactive)
430   (doi-utils-wos-citing (jmax-bibtex-entry-doi)))
431
432
433 (defun jmax-bibtex-wos-related ()
434   "Open related articles for bibtex entry in Web Of Science if there is a DOI."
435   (interactive)
436   (doi-utils-wos-related (jmax-bibtex-entry-doi)))
437
438
439 (defun jmax-bibtex-wos-citing ()
440   "Open citing articles for bibtex entry in Web Of Science if there is a DOI."
441   (interactive)
442   (doi-utils-wos-citing (jmax-bibtex-entry-doi)))
443
444
445 (defun jmax-bibtex-crossref ()
446   "Open the bibtex entry in Crossref by its doi."
447   (interactive)
448   (doi-utils-crossref (jmax-bibtex-entry-doi)))
449
450
451 (defun jmax-bibtex-google-scholar ()
452   "Open the bibtex entry at point in google-scholar by its doi."
453   (interactive)
454   (doi-utils-google-scholar (jmax-bibtex-entry-doi)))
455
456
457 (defun jmax-bibtex-pubmed ()
458   "Open the bibtex entry at point in Pubmed by its doi."
459   (interactive)
460   (doi-utils-pubmed (jmax-bibtex-entry-doi)))
461
462
463 (defun jmax-bibtex-pdf (doi)
464   "Open the pdf for the bibtex entry at point.
465 Thin wrapper to get `jmax-bibtex' to open pdf, because it calls
466 functions with a DOI argument."
467   (interactive)
468   (org-ref-open-bibtex-pdf))
469
470
471 ;; hydra menu for actions on bibtex entries
472 (defhydra jmax-bibtex-hydra (:color blue)
473    "
474 _p_: Open pdf     _y_: Copy key               _n_: New entry     _w_: WOS
475 _u_: Open url     _f_: Copy formatted entry   _o_: Copy entry    _c_: WOS citing
476 _r_: Refile entry _k_: Add keywords           _d_: delete entry  _r_: WOS related
477 _e_: Email entry  _K_: Edit keywords          _L_: clean entry   _P_: Pubmed
478 _U_: Update entry _N_: Open notes             _R_: Crossref      _g_: Google Scholar
479 _q_: quit
480 "
481    ("p" org-ref-open-bibtex-pdf)
482    ("P" jmax-bibtex-pubmed)
483    ("w" jmax-bibtex-wos)
484    ("c" jmax-bibtex-wos-citing)
485    ("r" jmax-bibtex-wos-related)
486    ("R" jmax-bibtex-crossref)
487    ("g" jmax-bibtex-google-scholar)
488    ("n" jmax-bibtex-new-entry/body)
489    ("N" org-ref-open-bibtex-notes)
490    ("o" bibtex-copy-entry-as-kill)
491    ("d" bibtex-kill-entry)
492    ("L" org-ref-clean-bibtex-entry)
493    ("y" (kill-new  (bibtex-autokey-get-field "=key=")))
494    ("f" bibtex-copy-summary-as-kill)
495    ("k" helm-tag-bibtex-entry)
496    ("K" (lambda ()
497           (interactive)
498           (org-ref-set-bibtex-keywords
499            (read-input "Keywords: "
500                        (bibtex-autokey-get-field "keywords"))
501            t)))
502    ("u" org-ref-open-in-browser)
503    ("r" (lambda () (interactive)
504           (bibtex-beginning-of-entry)
505           (bibtex-kill-entry)
506           (find-file (ido-completing-read
507                       "Bibtex file: "
508                       (f-entries "." (lambda (f) (f-ext? f "bib")))))
509           (goto-char (point-max))
510           (bibtex-yank)
511           (save-buffer)
512           (kill-buffer)))
513    ("e" email-bibtex-entry)
514    ("U" (doi-utils-update-bibtex-entry-from-doi (jmax-bibtex-entry-doi)))
515    ("q" nil "quit")
516    ("f" jmax-bibtex-file/body "File functions")
517    ("a" jmax-replace-nonascii "Replace non-ascii"))
518
519 ;; create key-chord and key binding for hydra
520 (when jmax-bibtex-hydra-key-chord
521   (key-chord-define-global
522    jmax-bibtex-hydra-key-chord
523    'jmax-bibtex-hydra/body))
524
525
526 (when jmax-bibtex-hydra-key-binding
527   (global-set-key jmax-bibtex-hydra-key-binding 'jmax-bibtex-hydra/body))
528
529
530 ;; A hydra for adding new bibtex entries.
531 (defhydra jmax-bibtex-new-entry (:color blue)
532   "New Bibtex entry:"
533   ("a" bibtex-Article "Article")
534   ("b" bibtex-Book "Book")
535   ("i" bibtex-InBook "In book")
536   ("l" bibtex-Booklet "Booklet")
537   ("P" bibtex-Proceedings "Proceedings")
538   ("p" bibtex-InProceedings "In proceedings")
539   ("m" bibtex-Misc "Misc.")
540   ("M" bibtex-Manual "Manual")
541   ("T" bibtex-PhdThesis "PhD Thesis")
542   ("t" bibtex-MastersThesis "MS Thesis")
543   ("R" bibtex-TechReport "Report")
544   ("u" bibtex-Unpublished "unpublished")
545   ("c" bibtex-InCollection "Article in collection")
546   ("q" nil "quit"))
547
548 ;; a hydra menu of functions to act on a bibtex file.
549 (defhydra jmax-bibtex-file (:color blue)
550   "Bibtex file functions: "
551   ("v" bibtex-validate "Validate entries")
552   ("s" bibtex-sort-buffer "Sort entries")
553   ("r" bibtex-reformat "Reformat entries")
554   ("c" bibtex-count-entries "Count entries")
555   ("p" org-ref-build-full-bibliography "PDF bibliography"))
556
557
558 (defvar jmax-bibtex-menu-funcs '()
559  "Functions to run in doi menu.
560 Each entry is a list of (key menu-name function).  The function
561 must take one argument, the doi.  This is somewhat deprecated, as
562 I prefer the hydra interfaces above.")
563
564 (setq jmax-bibtex-menu-funcs
565       '(("p" "df" jmax-bibtex-pdf)
566         ("C" "opy" (lambda (doi)
567                      (kill-new (org-ref-bib-citation))
568                      (bury-buffer)))
569         ("w" "os" doi-utils-wos)
570         ("c" "iting articles" doi-utils-wos-citing)
571         ("r" "elated articles" doi-utils-wos-related)
572         ("s" "Google Scholar" doi-utils-google-scholar)
573         ("P" "Pubmed" doi-utils-pubmed)
574         ("f" "CrossRef" doi-utils-crossref)))
575
576 (defun jmax-bibtex ()
577   "Menu command to run in a bibtex entry.
578 Functions from `jmax-bibtex-menu-funcs'.  They all rely on the
579 entry having a doi."
580
581   (interactive)
582   ;; construct menu string as a message
583   (message
584    (concat
585     (mapconcat
586      (lambda (tup)
587        (concat "[" (elt tup 0) "]"
588                (elt tup 1) " "))
589      jmax-bibtex-menu-funcs "") ": "))
590   (let* ((input (read-char-exclusive))
591          (choice (assoc
592                   (char-to-string input) jmax-bibtex-menu-funcs)))
593     (when choice
594       (funcall
595        (elt
596         choice
597         2)
598        (jmax-bibtex-entry-doi)
599        ))))
600
601 (defalias 'jb 'jmax-bibtex)
602
603 (provide 'jmax-bibtex)
604
605 ;;; jmax-bibtex.el ends here