Emacs has a few commands that can line up text with respect to whitespace, assignment, columns or regexp specified delimiters.
The following commands are available:
align align-current align-entire align-newline-and-indent align-regexp
Alignment is done with a set of rules (e.g. line up the = signs). Which rules exactly depend on the current mode, and should provide some sort of “Do What I Mean” feeling. These rules are described in the variable align-rules-list
; a few of them are explained below. Documentation is severely lacking and inspection of the list given by this variable is perhaps the best way to find which one is available in which mode.
Some custom settings are available through the use of the customize buffer. Just type M-x customize-group RET align RET
.
Sidenote: The default text-mode rules in ‘align-rules-list’
are “too aggressive” to be enabled by default, therefore you need to specify the universal arg (C-u) to enable them. See below.
In text mode, C-u M-x align
lines up text in selected region, using whitespaces (or tabs) as the column delimiter:
lastname firstname lastname firstname Smith John 33-88 Smith John 33-88 Gere Alan 24-23 => Gere Alan 24-23 Verne Bill 12-34 Verne Bill 12-34
Note that C-u M-x align
fails to align words of length one (bug ? feature ?). See below for a fix. Figures can also be lined up with respect to the decimal point, using M-- M-x align
.
green apples 10.00 green apples 10.00 carrots 16.5 => carrots 16.5 patatoes 12. patatoes 12.
This command aligns the current region using a column delimiter given by a regular expression. For example, assume we want to align first names in a list of the form:
LASTNAME Firstname DRAKE Francis BRÛLÉ Étienne IBN MĀJID Ahmad
There are two difficulties here: case and accented letters. First ensure that the case is taken into account. For this, just type:
M-: (setq case-fold-search nil) RET
Then, select the region and use the align-regexp command:
M-x align-regexp RET [[:upper:]][[:lower:]] RET
The regular expression given above matches the beginning of the firstname, which is of the form, a upper-case letter followed by a lower-case letter. This syntax is sufficiently general to deal with accented letters. The result is as follow:
LASTNAME Firstname DRAKE Francis BRÛLÉ Étienne IBN MĀJID Ahmad
Continuing on, select the region and use align-regexp again, but with a prefix argument:
C-u M-x align-regexp RET ^.*\([[:upper:]][[:lower:]].*\)$ RET DEL -1 RET RET n
The result is as follow:
LASTNAME Firstname DRAKE Francis BRÛLÉ Étienne IBN MĀJID Ahmad
The “-1” indicates to right-align (aka justify) the first matched group, by first deleting any initial whitespace and then adding the whitespace needed to do the justification. Be careful with the regexps you use here, as mistakes can give confusing results.
Instead of working on a region, M-x align-current
operates on the current section. Here is an example, taken from the blog of the Lazy Programmer, which shows how the align-current
command works in perl-mode:
my %h = my %h =
( (
key1 => value1, key1 => value1,
key11 => value11, gives key11 => value11,
key111 => value111, key111 => value111,
); );
Here is another example in c-mode:
LongTypeName a; LongTypeName a; int b; gives int b; float c; float c;
For example, let us align numbers as follows:
4000 1 2 4000 1 2 11 1 44 => 11 1 44 1 0000 999 1 0000 999
M-x align-regexp
with [[:space:]]
only align with respect to the first match of the regular expression. C-u M-x align
fails to align strings of length one (bug ? feature ?).
The align-regexp
command, however, allows a few options. These are activated by giving a prefix to the command: C-u M-x align-regexp
. The user is then prompted with a few choices:
\(\s-*\)
, which stands for “an arbitrary number of spacing characters”.n/y
, depending whether the alignment must be done once or repeated.So, in short, lining up numbers as given above amounts to typing:
C-u M-x align-regexp RET SPC RET RET RET y
Don’t forget to mark the region first.
Arguably, for daily use, it’s better to define some adhoc align command, e.g.
(defun align-repeat (start end regexp) "Repeat alignment with respect to the given regular expression." (interactive "r\nsAlign regexp: ") (align-regexp start end (concat "\\(\\s-*\\)" regexp) 1 1 t))
The final t
(aka true) is responsible for repeating the task. Call that command with the regular expression [[:space:]]+
An alternate way is to modify the align-rules-list
variable. Here is a quick hack: eval the following code, just by entering it in the scratch buffer and typing C-x C-e
at the end.
(add-to-list 'align-rules-list
'(text-column-whitespace
(regexp . "\\(^\\|\\S-\\)\\([ \t]+\\)")
(group . 2)
(modes . align-text-modes)
(repeat . t)))
This defines a new alignment rule, valid both in text-mode and outline mode, lining up sequences of whitespaces, repeatedly. You must have used M-x align
at least once before, in order to activate the align-rules-list
variable. In text mode or in outline-mode, M-x align
and M-x align-current
now put text strings in columns, using whitespace as delimiter.
This alignment rule may be loaded at startup by adding the above code to the align-load-hook
:
(add-hook 'align-load-hook (lambda () (add-to-list 'align-rules-list '(text-column-whitespace (regexp . "\\(^\\|\\S-\\)\\([ \t]+\\)") (group . 2) (modes . align-text-modes) (repeat . t)))))
Align currently has (partial) built-in support for:
New languages can be supported by adding approriate rules to align-rules-list
, align-exclude-rules-list
and perhaps a custom align-region-separate
, see the link(s) below:
See SmartTabs.