Posts Tagged ‘emacs autoload’

Emacs has a few mechanisms for choosing which major mode is selected when you find a file.

auto-mode-alist determines the mode from the file extension, e.g. you might want to load a c++ mode for a file named a.cc.

interpreter-mode-alist chooses a mode depending on the first line of a file. If a file begins with #!/bin/sh you probably want to choose shell-script-mode.

I worked on a code base where the extensions used a variety of capitalization. The perl scripts could be .Perl, .perl, .PL, .Pl or .pl and there were numerous other extensions. It is fairly easy to make a regular expression to match all of these but I thought it warranted a helper function.

I want '(pl perl) to transform to \.\([Pp][Ll]\|[Pp][Ee][Rr][Ll]\)\'. The basic technique is to make a character class with the upper case and lower case version of each character in the string. We also accept a symbol on the input in order that the caller doesn’t have to add double quotes to every element.

(mapconcat (lambda (c)
             (let ((c (upcase (char-to-string c))))
               (concat "[" c (downcase c) "]")))
           (symbol-name s) ""))

This code converts 'pl to [Pp][Ll].

We want to handle a list of extensions so we can cope with permutations of .pl or .perl. We therefore surround the previous mapconcat with the following.

(mapconcat (lambda (s) ...) l "\\|")

The final part of the function adds the appropriate prefix and suffix to make the regex work in auto-mode-alist.

(defun file-extensions (l)
  (concat "\\.\\("
           (lambda (s)
             (mapconcat (lambda (c)
                          (let ((c (upcase (char-to-string c))))
                            (concat "[" c (downcase c) "]")))
                        (symbol-name s) ""))
           l "\\|")

I added a wrapper function to marry the regex to the major mode.

(defun ext-mode-map (extensions mode)
  (cons (file-extensions extensions) mode))

And now you can simply specify your mode mappings like this:

(add-to-list 'auto-mode-alist (ext-mode-map '(pl perl) 'cperl-mode))

Read Full Post »