Take the 2-minute tour ×

I am working in Haskell and frequently come across code similar to the following:

func i j | i == j = i
         | otherwise = j

I want to align on the '=' character using align-regexp but don't have the elisp knowhow. I have tried just doing " = " without the quotes, but this inserts an unwanted space character before each '='. I have found a proposed solution here but I can't seem to get that to do anything at all.

Please help me write a function or hard-coded macro that will allow me to set a keybinding for this.

share|improve this question

1 Answer 1

up vote 16 down vote accepted

C-u M-x align-regexp RET \(\s-*\) = RET 1 RET 0 RET n

(n.b. there's a space after the '=', but it's not very obvious.)

Which is to say...

Use a prefix argument to tell align-regexp to ask you for more parameters than it does by default.

See C-h f align-regexp and C-h v align-rules-list for details, but in short:

\(\s-*\) is the default 'group' for deletion/expansion. We append our pattern to the end of that: ' = '. (Note that \s- is Emacs regexp syntax for whitespace.)

1 simply refers to parenthesised group 1 (as above). This is the default.

0 for the spacing to use between the two parts of the line. By default this is 1, and is why you were ending up with an additional space.

n to not align any subsequent pattern matches after the first in each line.

edit: Actually, the Q&A you linked to is near identical, and works fine for me on Emacs 23.2.1, so this is a duplicate, but to continue and answer the key-binding aspect:

You can bind that (or any) sequence via keyboard macros. Here's the end result, which you can probably just add to your init file, although I recommend you go through the process yourself. Use whatever you like in place of C-c a for the key. C-c (letter) and F5-F9 are reserved for end-users to bind as they please, so one of those will be safe from being clobbered by a mode's keymap.

(global-set-key (kbd "C-c a") (lambda (&optional arg) "Keyboard macro." (interactive "p") (kmacro-exec-ring-item (quote ([21 134217848 97 108 105 103 110 45 114 101 103 101 120 112 return 32 61 32 return return backspace 48 return 110] 0 "%d")) arg)))

I did that by:

  1. selecting the text.
  2. F3 to start recording.
  3. performing the align-regexp as above (being careful to type everything verbatim, and not use minibuffer history or yanking).1
  4. F4 to stop recording.
  5. C-x C-k n align-single-equals RET to give the macro a name
  6. M-x insert-kbd-macro RET align-single-equals RET to get the lisp.
  7. Wrapping the (lambda) expression with (global-set-key) to bind it. (Although you could also use the (fset 'align-single-equals ...) code as provided, and then bind the key to that symbol.

1 If you make a mistake when recording a complicated macro, don't fret — Emacs provides a really good macro editor which you can use to fix any mistakes after you finish recording (just type C-x C-k e), so you don't need to be perfect.

edit 2: May as well add an example of a function, as per comments.

(defun my-align-single-equals ()
  "Align on a single equals sign (with a space either side)."
   (region-beginning) (region-end)
   "\\(\\s-*\\) = " 1 0 nil))

(global-set-key (kbd "C-c a") 'my-align-single-equals)
share|improve this answer
Thanks. I was able to use your solution but created a function instead of a macro, as it's more readable for me. –  Karl Jan 11 '11 at 3:18
Well that's even better :) A function is definitely preferable if you're happy writing lisp, but macros are very handy if you're not. –  phils Jan 11 '11 at 3:22
a bit late to the party, but the canonical way to solve this is to add a rule to `align-rules-list' instead of writing your own function. –  event_jr May 23 '12 at 15:35

Your Answer


