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 "\\. \\ ( " (mapconcat ( 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))