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