Daily Archives: December 11, 2009

Switching identifier naming style between Camel Case and C style in Emacs

There are several naming styles for identifiers used in programming. Some use-dashes-between-words (e.g. Lisp), others MashWordsTogetherAndCapitalizeThem (most often called Camel Case), and a third one puts_underscores_between_characters_and_converts_everything_to_lower_case (sometimes called “C style”).

Often I have to convert code from one naming convention to another. When I have to do that this usually happens with languages that often use both styles, e.g. C/C++ or even PHP and Ruby. For those cases I’ve written an Emacs Lisp function that can convert the identifier at point from C style naming to Camel Case style and back. It detects the current style by looking for an underscore. Here’s the code:

(defun mo-toggle-identifier-naming-style ()
  "Toggles the symbol at point between C-style naming,
e.g. `hello_world_string', and camel case,
e.g. `HelloWorldString'."
  (interactive)
  (let* ((symbol-pos (bounds-of-thing-at-point 'symbol))
         case-fold-search symbol-at-point cstyle regexp func)
    (unless symbol-pos
      (error "No symbol at point"))
    (save-excursion
      (narrow-to-region (car symbol-pos) (cdr symbol-pos))
      (setq cstyle (string-match-p "_" (buffer-string))
            regexp (if cstyle "\\(?:\\_<\\|_\\)\\(\\w\\)" "\\([A-Z]\\)")
            func (if cstyle
                     'capitalize
                   (lambda (s)
                     (concat (if (= (match-beginning 1)
                                    (car symbol-pos))
                                 ""
                               "_")
                             (downcase s)))))
      (goto-char (point-min))
      (while (re-search-forward regexp nil t)
        (replace-match (funcall func (match-string 1))
                       t nil))
      (widen))))

The code was inspired by a question on StackOverflow about this topic.