2023-11-13 Coloring CamelCase

Some time ago one of the members of the Emacs mailing list asked about coloring CamelCase identifiers. His idea is to define two faces and have all “even” words in a camel case indentifier colored with one of them, and the “odd” words colored with the other one. The question suggests using some code from Glasses mode, which is a lesser-known Emacs feature which inserts undescores between words in camel case identifiers (and it does it using overlays, so the underscores are not really part of the buffer, they just look like this). My general rule is to avoid camel case whenever I can, but I sometimes use Glasses mode, especially when I have to deal with jsx files, where camel case is the standard.

It turns out that Glasses mode already has (almost) what is asked for. If you customize glasses-separator to be an empty string and glasses-face to be, for example, 'bold, Glasses mode makes all capital letters starting words in identifiers bold (which already helps a lot).

In order to color every other CamelCase subword with some face, however, one has to write a bit of Elisp. So, I set out to do just that, and started with looking at glasses.el.

One interesting feature of Glasses mode is that it uses overlays, which may seem a slightly controversial choice. Glasses mode is pretty old (it has at least two decades!), and overlays used to have performance issues when there were too many of them in one buffer. Fortunately, their implementation was changed in Emacs 29.1 and we no longer have to worry about that. A significant advantage of overlays in the context of Glasses mode is that they are “separate” from the text in the sense that killing text decorated with overlays and yanking it elsewhere loses them. This means that when you kill some text from a buffer with Glasses mode on and yank it in another buffer where it is off does not make the underscores (or faces for word-starting capitals) visible in the target buffer. Given that, I decided to also use overlays and not features like font-lock-keywords. This means that I can steal some code from glasses.el, too. (I could advise glasses-make-readable instead, but I think it will be more educational if I show how to build a minor mode from scratch. Note: as usual, you may freely use code shown in this blog, but this time it is explicitly covered by GPL3+, since a significant portion is copied from Emacs sources.)

All in all, it turned out that modifying Glasses mode to do what I want turned out to be pretty simple. To be fair, I ditched quite a few corner cases which are taken care for in glasses.el, like strings of continuous capital letters in CamelCase identifiers or digits (like in, say, PrintISO8601Date). I am almost sure that handling them would not be terribly difficult, though – I just treated my code as a proof of concept rather than a complete, production-grade solution.

CategoryEnglish, CategoryBlog, CategoryEmacs