Adding Keywords in Emacs

As you already know—if you read my blog before—I use Emacs as my primary editor, for C, C++, Python, LaTeX, etc., and I’ve grown fond of the clunky ol’ piece of software. Still, once in a while, I need an extra, potentially weird customization.

In my case, I have a series of macros that control conditional compilation (such as described in a previous post). Suppose I have set of macros BEGIN_UNIT_TEST_ONLY, END_UNIT_TEST_ONLY and UNIT_TEST_ONLY that start a unit-test specific block of code, ends it, and enables only a single statement, respectively.

These are UGLY_MACROs and I want them to poke conspicuously out of the source code. So, How do I tell Emacs to display them in a special way, using bright ugly colors?

The first thing to do if you don’t want to reuse an existing face customization (such as font-lock-comment-face, for example) is to create one. Let’s start with a new face descriptor initialized with a default color. In my case, I wanted it to inherit all properties of normal text except for its color. You add:

(make-face 'font-lock-special-macro-face)
(set-face-foreground 'font-lock-special-macro-face "pink")

This creates a new face named font-lock-special-macro-face set to pink. Or whatever color you’d like. I used magenta finally, because although it is ugly, it’s still better than pink in my color scheme.

We proceed to add regular expressions to the list of keywords and associate each regexp with a face.

(defun add-custom-keyw()
  "adds a few special keywords for c and c++ modes"
  ;
  (font-lock-add-keywords nil
   '(
     ("\\<\\(UNIT_TEST_ONLY\\)" . 'font-lock-special-macro-face )
     ("\\<\\(BEGIN_UNIT_TEST_ONLY\\)" . 'font-lock-special-macro-face )
     ("\\<\\(END_UNIT_TEST_ONLY\\)" . 'font-lock-special-macro-face)

     ; more of those would go here
     )
   )
 )

Which we hook to the initialization of C and C++ (minor) modes:

(add-hook 'c++-mode-hook 'add-custom-keyw)
(add-hook 'c-mode-hook 'add-custom-keyw)

and voilà! we’re done. When the c- and c++-mode initialize, they will run add-custom-keyw, and they will activate with the desired face. You can enjoy the result:

*
* *

Thanks to the people of #emacs on Freenode.org for hinting be to the right solution. Emacs programming isn’t the easiest of all. Fortunately, there’s google and the Emacs wiki.

3 Responses to Adding Keywords in Emacs

  1. Hi Steven,

    I was wondering why you are not using the macro as an if condition like this :

    if (UNIT_TEST)
    {
    // Unit test only code
    }

    The compiler should completely ignore the code if UNIT_TEST evaluates to false and it’s in my opinion less ugly than your macro that don’t really fit in with the C syntax.

    • Steven Pigeon says:

      while it’d work for code, it would’nt for data declarations. For example:

      class A {

      if (unit_test) {
      int x;
      }
      ….
      };

      would’nt work. You have to use macros there. You could mix both, I suppose; but I prefer to have only one mechanism to do that rather than a host of special cases.

  2. Jisang Yoo says:

    The three calls to font-lock-add-keywords can be replaced with one call.

    (defvar special-macro-regexp (rx bow (or “UNIT_TEST_ONLY” “BEGIN_UNIT_TEST_ONLY” “END_UNIT_TEST_ONLY”) eow))
    (font-lock-add-keywords nil `((,special-macro-regexp . ‘font-lock-special-macro-face)))

    That will be faster when there are lots of special macros because the function regexp-opt (which rx calls) returns an optimized regular expression.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 74 other followers

%d bloggers like this: