Lisp at Work: a macro for managing replace-regexp routines

The following commands have all become essential in my day to day Emacs usage:

C-M-% (query-replace-regexp)
C-x ESC ESC (repeat-complex-command)
M-x re-builder
C-x C-e (eval-last-sexp)

I use them to define regular expressions for use in editing text documents. Over time, I begin to collect quite a few of these, so it makes sense to think more carefully about my key bindings: normally I just use a Function key, but there’s other stuff I want to hot key from there now…. The Emacs manual says that the combination of C-c followed by a plain letter is reserved for the user, so I can put my custom routines there with a single letter mnemonic to help me remember what’s what.

Here’s a macro (with an example of its use) for setting up these sorts of text processing routines:

(defmacro defreplacer (name description search-for replace-with chord) 
     (defun ,name (n) 
       (interactive "p") 
       (query-replace-regexp ,search-for 
                             (if (and transient-mark-mode mark-active) 
                             (if (and transient-mark-mode mark-active) 
     (global-set-key (kbd ,chord) ',name)))   

(defreplacer pull-text-from-semi-colons 
  "Remove text from between two semi-colon signs."
  "[ ]*;\\([a-z]*\\);[ ]*" ; use double back slash to 'escape' in quotes 
  "C-c ;")

In the example above, we’re replacing lower case text inside a pair of semi-colons (and surrounded with any number of spaces on each side) with just the lower case text. The command chord to trigger that replace routine is “C-c ;”. This is a pointlessly simple example, but it should give you the basic idea of how to use the macro.

Does the “defmacro” really do much more for us than “defun” would otherwise do? The main savings you get with the macro is that it defines the key binding at the same time that the replacement function is defined– having a naming type there caused me a minor headache when I was wondering why my hot-keys weren’t working once. With “defmacro” you eliminate the chance of this kind of confusion occurring. On the other hand, if you change the definition of the macro after a file has been loaded, you will not change the operation of the existing functions– the macro only affects the environment at compile time. So there are trade offs either way. In this case I went with a macro because once I get my regular expression from re-builder, I wanted to be able to write the code for everything as quickly as possible. With “defreplacer”, all I needed was four arguments and I was good to go.


3 Responses to “Lisp at Work: a macro for managing replace-regexp routines”

  1. lispy Says:

    I called this entry “Lisp at Work” because mastering this type of exercise is probably the quickest way to getting to the point where you can actually use Lisp to solve problems at your day job. Tedious text editing is something you’re liable to do regardless of what exact type of development work you’re doing. There are bigger and better things to move on to from here, but it sure is nice that I’ve actually used Lisp and Emacs so solve a real world problem quickly and efficiently. It only took me six months to get this far. Hopefully it won’t take *you* quite so long!

  2. Lisp at Work: Evidence Based Scheduling « Learning Lisp Says:

    […] how did the project go? Time spent working in Emacs seems to have been pretty rewarding. Even with the learning curve, I could get things in about the […]

  3. Advanced Codemunging: A Report from the Trenches « Learning Lisp Says:

    […] Lisp projects that mainly showed how far I was from grasping the point. Having Emacs skills did come in handy a few times, though. Engaging in such focused deliberate practice was difficult: I rarely came up […]

Leave a Reply

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

You are commenting using your 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

%d bloggers like this: