ErgoEmacsEmacsLispBlogEmacsLispBuy Tutorial
Web Hosting by 1&1

Emacs Lisp: Change Case by Title Convention

Xah Lee,

This page shows you how to write a emacs lisp command to change letter case by title convention.

In English writing, the title follows a particular convention of capitalization. For example, it should be “A Tale of Two Cities”, not “A Tale Of Two Cities”.

I think this is rather a silly convention. For a while, i experimented by simply following a logically simpler style, of capitalizing the first letter of all words. 〔☛ The Writing Style of Xah Lee〕 But after a while, i find it rather jarring.

Part of the reason is that it's new, thus it will get some used to. This i expected. However, the other thing that turns out is that, the capitalization has subtle function for emphasis. For example, “Kung Fu versus Karate” seems better than “Kung Fu Versus Karate”.

It's rather cumbersome to manually capitalize words following this convention. So, i wrote a emacs command. Here's the code:

(defun title-case-string-region-or-line (ξstring &optional ξregion-boundary)
  "Capitalize the current line or text selection, following title conventions.

Capitalize first letter of each word, except words like {to, of,
the, a, in, or, and, …}. If a word already contains cap letters
such as HTTP, URL, they are left as is.

When called in a elisp program, if ξREGION-BOUNDARY is nil,
returns the changed ξSTRING, else, work on the region.
ξREGION-BOUNDARY is a pair [from to], it can be a vector or
list."
  (interactive
   (let ((bds (get-selection-or-unit 'line)))
     (list nil (vector (elt bds 1) (elt bds 2)) ) ) )

  (let ( replacePairs
         (workOnStringP (if ξregion-boundary nil t ) )
         (p1 (elt ξregion-boundary 0))
         (p2 (elt ξregion-boundary 1))
         )

    (setq replacePairs '(
                         [" A " " a "]
                         [" And " " and "]
                         [" At " " at "]
                         [" As " " as "]
                         [" By " " by "]
                         [" Be " " be "]
                         [" Into " " into "]
                         [" In " " in "]
                         [" Is " " is "]
                         [" It " " it "]
                         [" For " " for "]
                         [" Of " " of "]
                         [" Or " " or "]
                         [" On " " on "]
                         [" The " " the "]
                         [" That " " that "]
                         [" To " " to "]
                         [" Vs " " vs "]
                         [" With " " with "]
                         [" From " " from "]
                         ))

    (let ((case-fold-search nil))
      (if workOnStringP
          (progn
            (replace-pairs-in-string-recursive (upcase-initials ξstring) replacePairs)
            )
        (progn
          (save-restriction
            (narrow-to-region p1 p2)
            (upcase-initials-region (point-min) (point-max) )
            (replace-regexp-pairs-region (point-min) (point-max) replacePairs t t)
            ) ) ) ) ) )

I used some elisp utils i wrote. You'll need 〔xeu_elisp_util.el〕 at http://code.google.com/p/ergoemacs/source/browse/packages/xeu_elisp_util.el.

blog comments powered by Disqus