add new nonascii
[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     ("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         ("İ" . "{\\\\.I}")
189         ("ğ" . "{\\\\u{g}}")
190         ("δ" . "$\\\\delta$")
191         ("ç" . "{\\\\c{c}}")
192         ("ß" . "{\\\\ss}")
193         ("≤" . "$\\\\le$")
194         ("<" . "$\\\\lt$")
195         ("θ" . "$\\\\theta$")
196         ("μ" . "$\\\\mu$")
197         ("→" . "$\\\\rightarrow$")
198         ("⇌" . "$\\\\leftrightharpoons$")
199         ("×" . "$\\\\times$")
200         ("°" . "$\\\\deg$")
201         ;; I think these are non-ascii spaces. there seems to be more than one.
202         (" " . " ")
203         (" " . " ")
204         ("–" . "-")
205         ("−" . "-")
206         ("–" . "-")
207         ("‘" . "'")
208         ("’" . "'")
209         ("“" . "\"")
210         ("”" . "\"")))
211
212 (defun jmax-replace-nonascii ()
213   "Hook function to replace non-ascii characters in a bibtex entry."
214
215   (interactive)
216   (save-restriction
217     (bibtex-narrow-to-entry)
218     (goto-char (point-min))
219     (dolist (char (mapcar (lambda (x) (car x)) jmax-nonascii-latex-replacements))
220       (while (re-search-forward char nil t)
221         (replace-match (cdr (assoc char jmax-nonascii-latex-replacements))))
222       (goto-char (point-min)))))
223
224 (add-hook 'org-ref-clean-bibtex-entry-hook 'jmax-replace-nonascii)
225
226
227 (defvar jmax-lower-case-words
228   '("a" "an" "on" "and" "for"
229     "the" "of" "in")
230   "List of words to keep lowercase when changing case in a title.")
231
232
233 (defun jmax-title-case-article (&optional key start end)
234   "Convert a bibtex entry article title to title-case.
235 The arguments KEY, START and END are optional, and are only there
236 so you can use this function with `bibtex-map-entries' to change
237 all the title entries in articles."
238   (interactive)
239   (bibtex-beginning-of-entry)
240
241   (let* ((title (bibtex-autokey-get-field "title"))
242          (words (split-string title))
243          (start 0))
244     (when
245         (string= "article" (downcase (cdr (assoc "=type=" (bibtex-parse-entry)))))
246       (setq words (mapcar
247                    (lambda (word)
248                      (if (or
249                           ;; match words containing {} or \ which are probably
250                           ;; LaTeX or protected words
251                           (string-match "\\$\\|{\\|}\\|\\\\" word)
252                           ;; these words should not be capitalized, unless they
253                           ;; are the first word
254                           (-contains? jmax-lower-case-words (s-downcase word)))
255                          word
256                        (s-capitalize word)))
257                    words))
258
259       ;; Check if first word should be capitalized
260       (when (-contains? jmax-lower-case-words (car words))
261         (setf (car words) (s-capitalize (car words))))
262
263       (setq title (mapconcat 'identity words " "))
264
265       ;; Capitalize letters after a dash
266       (while
267           (string-match "[a-zA-Z]-\\([a-z]\\)" title start)
268         (let ((char (substring title (match-beginning 1) (match-end 1))))
269           (setf (substring title (match-beginning 1) (match-end 1))
270                 (format "%s" (upcase char)))
271           (setq start (match-end 1))))
272
273       ;; this is defined in doi-utils
274       (bibtex-set-field
275        "title"
276        title)
277       (bibtex-fill-entry))))
278
279 (add-hook 'org-ref-clean-bibtex-entry-hook 'jmax-title-case-article)
280
281
282 (defun jmax-sentence-case-article (&optional key start end)
283   "Convert a bibtex entry article title to sentence-case.
284 The arguments KEY, START and END are optional, and are only there
285 so you can use this function with `bibtex-map-entries' to change
286 all the title entries in articles."
287   (interactive)
288   (bibtex-beginning-of-entry)
289
290   (let* ((title (bibtex-autokey-get-field "title"))
291          (words (split-string title))
292          (start 0))
293     (when
294         (string= "article" (downcase (cdr (assoc "=type=" (bibtex-parse-entry)))))
295       (setq words (mapcar
296                    (lambda (word)
297                      (if
298                          ;; match words containing {} or \ which are probably
299                          ;; LaTeX or protected words
300                          (string-match "\\$\\|{\\|}\\|\\\\" word)
301                          word
302                        (s-downcase word)))
303                    words))
304
305       ;; capitalize first word
306       (setf (car words) (s-capitalize (car words)))
307
308       ;; join the words
309       (setq title (mapconcat 'identity words " "))
310
311       ;; capitalize a word after a :, eg. a subtitle, and protect it
312       (while
313           (string-match "[a-z]:\\s-+\\([A-Z]\\)" title start)
314         (let ((char (substring title (match-beginning 1) (match-end 1))))
315           (setf (substring title (match-beginning 1) (match-end 1))
316 ;;              (format "{%s}" (upcase char)))
317                 (format "%s" (upcase char)))
318           (setq start (match-end 1))))
319
320       ;; this is defined in doi-utils
321       (bibtex-set-field
322        "title" title)
323
324       ;; clean and refill entry so it looks nice
325       (bibtex-clean-entry)
326       (bibtex-fill-entry))))
327
328
329
330
331 (defun jmax-bibtex-next-entry (&optional n)
332   "Jump to the beginning of the next bibtex entry.
333 N is a prefix argument.  If it is numeric, jump that many entries
334 forward.  Negative numbers do nothing."
335   (interactive "P")
336   ;; Note if we start at the beginning of an entry, nothing
337   ;; happens. We need to move forward a char, and call again.
338   (when (= (point) (save-excursion
339                      (bibtex-beginning-of-entry)))
340     (forward-char)
341     (jmax-bibtex-next-entry))
342
343   ;; search forward for an entry
344   (when
345       (re-search-forward bibtex-entry-head nil t (and (numberp n) n))
346     ;; go to beginning of the entry
347     (bibtex-beginning-of-entry)))
348
349
350 (defun jmax-bibtex-previous-entry (&optional n)
351   "Jump to beginning of the previous bibtex entry.
352 N is a prefix argument.  If it is numeric, jump that many entries back."
353   (interactive "P")
354   (bibtex-beginning-of-entry)
355  (when
356      (re-search-backward bibtex-entry-head nil t (and (numberp n) n))
357    (bibtex-beginning-of-entry)))
358
359
360 (defun jmax-bibtex-mode-keys ()
361   "Modify keymaps used by `bibtex-mode'."
362   (local-set-key (kbd "M-n") 'jmax-bibtex-next-entry)
363   (local-set-key (kbd "M-p") 'jmax-bibtex-previous-entry))
364
365 ;; add to bibtex-mode-hook
366 (add-hook 'bibtex-mode-hook 'jmax-bibtex-mode-keys)
367
368
369 (defun jmax-bibtex-entry-doi ()
370   "get doi from entry at point"
371   (interactive)
372   (save-excursion
373     (bibtex-beginning-of-entry)
374     (reftex-get-bib-field "doi" (bibtex-parse-entry t))))
375
376
377 (defun jmax-bibtex-wos ()
378   "Open bibtex entry in Web Of Science if there is a DOI"
379   (interactive)
380   (doi-utils-wos (jmax-bibtex-entry-doi)))
381
382
383 (defun jmax-bibtex-wos-citing ()
384   "Open citing articles for bibtex entry in Web Of Science if there is a DOI"
385   (interactive)
386   (doi-utils-wos-citing (jmax-bibtex-entry-doi)))
387
388
389 (defun jmax-bibtex-wos-related ()
390   "Open related articles for bibtex entry in Web Of Science if there is a DOI"
391   (interactive)
392   (doi-utils-wos-related (jmax-bibtex-entry-doi)))
393
394
395 (defun jmax-bibtex-wos-citing ()
396   "Open citing articles for bibtex entry in Web Of Science if there is a DOI"
397   (interactive)
398   (doi-utils-wos-citing (jmax-bibtex-entry-doi)))
399
400
401 (defun jmax-bibtex-crossref ()
402   (interactive)
403   (doi-utils-crossref (jmax-bibtex-entry-doi)))
404
405
406 (defun jmax-bibtex-google-scholar ()
407   (interactive)
408   (doi-utils-google-scholar (jmax-bibtex-entry-doi)))
409
410
411 (defun jmax-bibtex-pubmed ()
412   (interactive)
413   (doi-utils-pubmed (jmax-bibtex-entry-doi)))
414
415
416 (defun jmax-bibtex-pdf (doi)
417   "thin wrapper to get `jmax-bibtex' to open pdf"
418   (interactive)
419   (org-ref-open-bibtex-pdf))
420
421
422
423 (defvar jmax-bibtex-menu-funcs '()
424  "Functions to run in doi menu. Each entry is a list of (key menu-name function).
425 The function must take one argument, the doi.")
426
427 (setq jmax-bibtex-menu-funcs
428       '(("p" "df" jmax-bibtex-pdf)
429         ("C" "opy" (lambda (doi)
430                      (kill-new (org-ref-bib-citation))
431                      (bury-buffer)))
432         ("w" "os" doi-utils-wos)
433         ("c" "iting articles" doi-utils-wos-citing)
434         ("r" "elated articles" doi-utils-wos-related)
435         ("s" "Google Scholar" doi-utils-google-scholar)
436         ("P" "Pubmed" doi-utils-pubmed)
437         ("f" "CrossRef" doi-utils-crossref)))
438
439 (defun jmax-bibtex ()
440   "Menu command to run in a bibtex entry.
441 Functions from `jmax-bibtex-menu-funcs'. They all rely on the
442 entry having a doi."
443
444   (interactive)
445   ;; construct menu string as a message
446   (message
447    (concat
448     (mapconcat
449      (lambda (tup)
450        (concat "[" (elt tup 0) "]"
451                (elt tup 1) " "))
452      jmax-bibtex-menu-funcs "") ": "))
453   (let* ((input (read-char-exclusive))
454          (choice (assoc
455                   (char-to-string input) jmax-bibtex-menu-funcs)))
456     (when choice
457       (funcall
458        (elt
459         choice
460         2)
461        (jmax-bibtex-entry-doi)
462        ))))
463
464 (defalias 'jb 'jmax-bibtex)
465
466 (provide 'jmax-bibtex)
467
468 ;;; jmax-bibtex.el ends here