removed org-ref references
[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
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     ("TSF" "Thin Solid Films" "Thin Solid Films")
85     ("TC" "Topics in Catalysis" "Top. Catal.")
86     ("WR" "Water Research" "Water Res."))
87   "List of (string journal-full-name journal-abbreviation).  Find abbreviations at http://cassi.cas.org/search.jsp.")
88
89
90 (defun jmax-bibtex-generate-longtitles ()
91   "Generate longtitles.bib which are @string definitions.
92 The full journal names are in `jmax-bibtex-journal-abbreviations'."
93   (interactive)
94   (with-temp-file "longtitles.bib"
95     (dolist (row jmax-bibtex-journal-abbreviations)
96       (insert (format "@string{%s=\"%s\"}\n"
97                       (nth 0 row)
98                       (nth 1 row))))))
99
100
101 (defun jmax-bibtex-generate-shorttitles ()
102     "Generate shorttitles.bib which are @string definitions.
103 The abbreviated journal names in `jmax-bibtex-journal-abbreviations'."
104   (interactive)
105   (with-temp-file "shorttitles.bib"
106     (dolist (row jmax-bibtex-journal-abbreviations)
107       (insert (format "@string{%s=\"%s\"}\n"
108                       (nth 0 row)
109                       (nth 2 row))))))
110
111
112 (defun jmax-stringify-journal-name (&optional key start end)
113   "Replace journal name in a bibtex entry with a string.
114 The strings are defined in
115 `jmax-bibtex-journal-abbreviations'.  The optional arguments KEY,
116 START and END allow you to use this with `bibtex-map-entries'"
117   (interactive)
118   (bibtex-beginning-of-entry)
119   (when
120       (string= "article"
121                (downcase
122                 (cdr (assoc "=type=" (bibtex-parse-entry)))))
123     (let* ((full-names (mapcar
124                         (lambda (row)
125                           (cons  (nth 1 row) (nth 0 row)))
126                         jmax-bibtex-journal-abbreviations))
127            (abbrev-names (mapcar
128                           (lambda (row)
129                             (cons  (nth 2 row) (nth 0 row)))
130                           jmax-bibtex-journal-abbreviations))
131            (journal (s-trim (bibtex-autokey-get-field "journal")))
132            (bstring (or
133                      (cdr (assoc journal full-names))
134                      (cdr (assoc journal abbrev-names)))))
135       (when bstring
136         (bibtex-set-field "journal" bstring t)
137         (bibtex-fill-entry)))))
138
139 (defun jmax-set-journal-string (full-journal-name)
140   "Set a bibtex journal name to the string that represents FULL-JOURNAL-NAME.
141 This is defined in `jmax-bibtex-journal-abbreviations'."
142   (interactive (list
143                 (ido-completing-read
144                  "Journal: "
145                  (mapcar
146                   (lambda (x)
147                     (nth 1 x))
148                   jmax-bibtex-journal-abbreviations))))
149   ;; construct data alist for the string lookup.
150   (let ((alist (mapcar
151                 (lambda (x)
152                   (cons (nth 1 x) (nth 0 x)))
153                 jmax-bibtex-journal-abbreviations)))
154     (bibtex-set-field "journal" (cdr (assoc full-journal-name alist)) t)
155     (bibtex-fill-entry)
156     (bibtex-clean-entry)))
157
158 ;; see https://github.com/fxcoudert/tools/blob/master/doi2bib for more replacements
159 (defvar jmax-nonascii-latex-replacements
160   '()
161   "Cons list of non-ascii characters and their LaTeX representations.")
162
163 (setq jmax-nonascii-latex-replacements
164       '(("í" . "{\\\\'i}")
165         ("æ" . "{\\\\ae}")
166         ("ć" . "{\\\\'c}")
167         ("é" . "{\\\\'e}")
168         ("ä" . "{\\\\\"a}")
169         ("è" . "{\\\\`e}")
170         ("à" . "{\\\\`a}")
171         ("á" . "{\\\\'a}")
172         ("ø" . "{\\\\o}")
173         ("ë" . "{\\\\\"e}")
174         ("ü" . "{\\\\\"u}")
175         ("ñ" . "{\\\\~n}")
176         ("å" . "{\\\\aa}")
177         ("ö" . "{\\\\\"o}")
178         ("í" . "{\\\\'i}")
179         ("ó" . "{\\\\'o}")
180         ("ó" . "{\\\\'o}")
181         ("ú" .  "{\\\\'u}")
182         ("ú" . "{\\\\'u}")
183         ("š" . "{\\\\v{s}}")
184         ("İ" . "{\\\\.I}")
185         ("ğ" . "{\\\\u{g}}")
186         ("δ" . "$\\\\delta$")
187         ("ç" . "{\\\\c{c}}")
188         ("ß" . "{\\\\ss}")
189         ("≤" . "$\\\\le$")
190         ("<" . "$\\\\lt$")
191         ("θ" . "$\\\\theta$")
192         ("μ" . "$\\\\mu$")
193         ("→" . "$\\\\rightarrow$")
194         ("⇌" . "$\\\\leftrightharpoons$")
195         ("×" . "$\\\\times$")
196         ("°" . "$\\\\deg$")
197         ;; I think these are non-ascii spaces. there seems to be more than one.
198         (" " . " ")
199         (" " . " ")
200         ("–" . "-")
201         ("−" . "-")
202         ("–" . "-")
203         ("‘" . "'")
204         ("’" . "'")
205         ("“" . "\"")
206         ("”" . "\"")))
207
208 (defun jmax-replace-nonascii ()
209   "Hook function to replace non-ascii characters in a bibtex entry."
210
211   (interactive)
212   (save-restriction
213     (bibtex-narrow-to-entry)
214     (goto-char (point-min))
215     (dolist (char (mapcar (lambda (x) (car x)) jmax-nonascii-latex-replacements))
216       (while (re-search-forward char nil t)
217         (replace-match (cdr (assoc char jmax-nonascii-latex-replacements))))
218       (goto-char (point-min)))))
219
220 (add-hook 'org-ref-clean-bibtex-entry-hook 'jmax-replace-nonascii)
221
222
223 (defvar jmax-lower-case-words
224   '("a" "an" "on" "and" "for"
225     "the" "of" "in")
226   "List of words to keep lowercase when changing case in a title.")
227
228
229 (defun jmax-title-case-article (&optional key start end)
230   "Convert a bibtex entry article title to title-case.
231 The arguments KEY, START and END are optional, and are only there
232 so you can use this function with `bibtex-map-entries' to change
233 all the title entries in articles."
234   (interactive)
235   (bibtex-beginning-of-entry)
236
237   (let* ((title (bibtex-autokey-get-field "title"))
238          (words (split-string title))
239          (start 0))
240     (when
241         (string= "article" (downcase (cdr (assoc "=type=" (bibtex-parse-entry)))))
242       (setq words (mapcar
243                    (lambda (word)
244                      (if (or
245                           ;; match words containing {} or \ which are probably
246                           ;; LaTeX or protected words
247                           (string-match "\\$\\|{\\|}\\|\\\\" word)
248                           ;; these words should not be capitalized, unless they
249                           ;; are the first word
250                           (-contains? jmax-lower-case-words (s-downcase word)))
251                          word
252                        (s-capitalize word)))
253                    words))
254
255       ;; Check if first word should be capitalized
256       (when (-contains? jmax-lower-case-words (car words))
257         (setf (car words) (s-capitalize (car words))))
258
259       (setq title (mapconcat 'identity words " "))
260       
261       ;; Capitalize letters after a dash
262       (while
263           (string-match "[a-zA-Z]-\\([a-z]\\)" title start)
264         (let ((char (substring title (match-beginning 1) (match-end 1))))
265           (setf (substring title (match-beginning 1) (match-end 1))
266                 (format "%s" (upcase char)))
267           (setq start (match-end 1))))
268             
269       ;; this is defined in doi-utils
270       (bibtex-set-field
271        "title"
272        title)
273       (bibtex-fill-entry))))
274
275 (add-hook 'org-ref-clean-bibtex-entry-hook 'jmax-title-case-article)
276
277
278 (defun jmax-sentence-case-article (&optional key start end)
279   "Convert a bibtex entry article title to sentence-case.
280 The arguments KEY, START and END are optional, and are only there
281 so you can use this function with `bibtex-map-entries' to change
282 all the title entries in articles."
283   (interactive)
284   (bibtex-beginning-of-entry)
285
286   (let* ((title (bibtex-autokey-get-field "title"))
287          (words (split-string title))
288          (start 0))
289     (when
290         (string= "article" (downcase (cdr (assoc "=type=" (bibtex-parse-entry)))))
291       (setq words (mapcar
292                    (lambda (word)
293                      (if
294                          ;; match words containing {} or \ which are probably
295                          ;; LaTeX or protected words
296                          (string-match "\\$\\|{\\|}\\|\\\\" word)
297                          word
298                        (s-downcase word)))
299                    words))
300       
301       ;; capitalize first word
302       (setf (car words) (s-capitalize (car words)))
303
304       ;; join the words
305       (setq title (mapconcat 'identity words " "))
306
307       ;; capitalize a word after a :, eg. a subtitle, and protect it
308       (while
309           (string-match "[a-z]:\\s-+\\([A-Z]\\)" title start)
310         (let ((char (substring title (match-beginning 1) (match-end 1))))
311           (setf (substring title (match-beginning 1) (match-end 1))
312 ;;              (format "{%s}" (upcase char)))
313                 (format "%s" (upcase char)))
314           (setq start (match-end 1))))
315             
316       ;; this is defined in doi-utils
317       (bibtex-set-field
318        "title" title)
319
320       ;; clean and refill entry so it looks nice
321       (bibtex-clean-entry)
322       (bibtex-fill-entry))))
323
324
325
326
327 (defun jmax-bibtex-next-entry (&optional n)
328   "Jump to the beginning of the next bibtex entry.
329 N is a prefix argument.  If it is numeric, jump that many entries
330 forward.  Negative numbers do nothing."
331   (interactive "P")
332   ;; Note if we start at the beginning of an entry, nothing
333   ;; happens. We need to move forward a char, and call again.
334   (when (= (point) (save-excursion
335                      (bibtex-beginning-of-entry)))
336     (forward-char)
337     (jmax-bibtex-next-entry))
338
339   ;; search forward for an entry
340   (when
341       (re-search-forward bibtex-entry-head nil t (and (numberp n) n))
342     ;; go to beginning of the entry
343     (bibtex-beginning-of-entry)))
344
345
346 (defun jmax-bibtex-previous-entry (&optional n)
347   "Jump to beginning of the previous bibtex entry.
348 N is a prefix argument.  If it is numeric, jump that many entries back."
349   (interactive "P")
350   (bibtex-beginning-of-entry)
351  (when
352      (re-search-backward bibtex-entry-head nil t (and (numberp n) n))
353    (bibtex-beginning-of-entry)))
354
355
356 (defun jmax-bibtex-mode-keys ()
357   "Modify keymaps used by `bibtex-mode'."
358   (local-set-key (kbd "M-n") 'jmax-bibtex-next-entry)
359   (local-set-key (kbd "M-p") 'jmax-bibtex-previous-entry))
360
361 ;; add to bibtex-mode-hook
362 (add-hook 'bibtex-mode-hook 'jmax-bibtex-mode-keys)
363
364
365 (defun jmax-bibtex-entry-doi ()
366   "get doi from entry at point"
367   (interactive)
368   (save-excursion
369     (bibtex-beginning-of-entry)
370     (reftex-get-bib-field "doi" (bibtex-parse-entry t))))
371
372
373 (defun jmax-bibtex-wos ()
374   "Open bibtex entry in Web Of Science if there is a DOI"
375   (interactive)
376   (doi-utils-wos (jmax-bibtex-entry-doi)))
377
378
379 (defun jmax-bibtex-wos-citing ()
380   "Open citing articles for bibtex entry in Web Of Science if there is a DOI"
381   (interactive)
382   (doi-utils-wos-citing (jmax-bibtex-entry-doi)))
383
384
385 (defun jmax-bibtex-wos-related ()
386   "Open related articles for bibtex entry in Web Of Science if there is a DOI"
387   (interactive)
388   (doi-utils-wos-related (jmax-bibtex-entry-doi)))
389
390
391 (defun jmax-bibtex-wos-citing ()
392   "Open citing articles for bibtex entry in Web Of Science if there is a DOI"
393   (interactive)
394   (doi-utils-wos-citing (jmax-bibtex-entry-doi)))
395
396
397 (defun jmax-bibtex-crossref ()
398   (interactive)
399   (doi-utils-crossref (jmax-bibtex-entry-doi)))
400
401
402 (defun jmax-bibtex-google-scholar ()
403   (interactive)
404   (doi-utils-google-scholar (jmax-bibtex-entry-doi)))
405
406
407 (defun jmax-bibtex-pubmed ()
408   (interactive)
409   (doi-utils-pubmed (jmax-bibtex-entry-doi)))
410
411
412 (defun jmax-bibtex-pdf (doi)
413   "thin wrapper to get `jmax-bibtex' to open pdf"
414   (interactive)
415   (org-ref-open-bibtex-pdf))
416   
417
418
419 (defvar jmax-bibtex-menu-funcs '()
420  "Functions to run in doi menu. Each entry is a list of (key menu-name function). 
421 The function must take one argument, the doi.")
422
423 (setq jmax-bibtex-menu-funcs
424       '(("p" "df" jmax-bibtex-pdf)
425         ("w" "os" doi-utils-wos)
426         ("c" "iting articles" doi-utils-wos-citing)
427         ("r" "elated articles" doi-utils-wos-related)
428         ("s" "Google Scholar" doi-utils-google-scholar)
429         ("P" "Pubmed" doi-utils-pubmed)
430         ("f" "CrossRef" doi-utils-crossref)))
431
432 (defun jmax-bibtex ()
433   "Menu command to run in a bibtex entry.
434 Functions from `jmax-bibtex-menu-funcs'. They all rely on the
435 entry having a doi."
436   
437   (interactive)
438   ;; construct menu string as a message
439   (message
440    (concat
441     (mapconcat
442      (lambda (tup)
443        (concat "[" (elt tup 0) "]"
444                (elt tup 1) " "))
445      jmax-bibtex-menu-funcs "") ": "))
446   (let* ((input (read-char-exclusive))
447          (choice (assoc
448                   (char-to-string input) jmax-bibtex-menu-funcs)))
449     (when choice
450       (funcall
451        (elt 
452         choice
453         2)
454        (jmax-bibtex-entry-doi)
455        ))))
456
457 (defalias 'jb 'jmax-bibtex)
458
459 (provide 'jmax-bibtex)
460
461 ;;; jmax-bibtex.el ends here