Title casing bibtex entry journal titles

| categories: bibtex | tags:

I mostly love bibtex. You keep bibliographic entries in a central file, and you can cite them in your writing. Bibtex takes care of most of the formatting for you, but not always all of it. Lately, we have been writing some manuscripts for submission to ACS journals. They want the titles of journal articles included in the bibliography, preferrably in title-case, or in sentence case, but all the same format either way. Unfortunately, the achemso.bst bibtex format does not make this happen. You have to title-case or sentence case the titles themselves in your bibtex file. Well, at least we can get Emacs to do the heavy lifting on that for us.

First, the manual approach. Open your bibtex file, navigate to a title field, put your cursor on the first letter of the title, and press M-c until you get to the end of the title. That runs (capitalize-word). For a few titles, you might just do this. It does not take long.

For a lot of entries though, you might prefer some code to do it. Here we consider how to convert all article titles to Title case. The current code can be found at https://github.com/jkitchin/jmax/blob/master/jmax-bibtex.el .

First, we need to decide on some rules. We will capitalize every word in a title except for words like a, an, the, … unless they start the title. We do not want to change words with $, {} in them, or \, because these are either protected or LaTeX commands and we probably do not want to change them. The gist of our idea is to get the title, split it into words, capitalize each word that needs to be, join the words together, and then set the entry title to the new capitalized title.

We use functions from s.el , and doi-utils.org here.

(defvar jmax-lower-case-words
  '("a" "an" "on" "and" "for"
    "the" "of" "in")
  "List of words to keep lowercase")

(defun jmax-title-case-article (&optional key start end)
  "Convert a bibtex entry article title to title-case. The
arguments are optional, and are only there so you can use this
function with `bibtex-map-entries' to change all the title
entries in articles."

  (let* ((title (bibtex-autokey-get-field "title"))
         (words (split-string title))
         (lower-case-words '("a" "an" "on" "and" "for"
                             "the" "of" "in")))
        (string= "article" (downcase (cdr (assoc "=type=" (bibtex-parse-entry)))))
      (setq words (mapcar
                   (lambda (word)
                     (if (or
                          ;; match words containing {} or \ which are probably
                          ;; LaTeX or protected words
                          (string-match "\\$\\|{\\|}\\|\\\\" word)
                          ;; these words should not be capitalized, unless they
                          ;; are the first word
                          (-contains? lower-case-words (s-downcase word)))
                       (s-capitalize word)))

      ;; Check if first word should be capitalized
      (when (-contains? jmax-lower-case-words (car words))
        (setf (car words) (s-capitalize (car words))))

      ;; this is defined in doi-utils
       (mapconcat 'identity words " "))

Now, a single command converts this:

  author =       {Charles T. Campbell and Jason R. V. Sellers},
  title =        {Enthalpies and entropies of adsorption on
                  well-defined oxide surfaces: experimental
  journal =      CR,
  volume =       113,
  number =       6,
  pages =        {4106-4135},
  year =         2013,
  doi =          {10.1021/cr300329s},
  url =          {https://doi.org/10.1021/cr300329s},
  month =        6,

to this:

  author =       {Charles T. Campbell and Jason R. V. Sellers},
  title =        {Enthalpies and Entropies of Adsorption on
                  Well-defined Oxide Surfaces: Experimental
  journal =      CR,
  volume =       113,
  number =       6,
  pages =        {4106-4135},
  year =         2013,
  doi =          {10.1021/cr300329s},
  url =          {https://doi.org/10.1021/cr300329s},
  month =        6,

We wrote the title case function so we can use it with bibtex-map-entries. That means we can fix every entry in a file by putting a comment at the top like this:

% (bibtex-map-entries 'jmax-title-case-article)  <- put cursor here. C-x C-e

The function is not perfect, and does not include every word that should not be capitalized. You will still want to review your entries, but hopefully this saves some typing in the end.

Copyright (C) 2014 by John Kitchin. See the License for information about copying.

org-mode source

Org-mode version = 8.2.7c

Discuss on Twitter