handlename's blog

コード片など

align設定用例集

http://atnd.org/events/21982#comments:title=Emacs Advent Calender jp: 2011 の12日目です。

11日目は id:rubikitch さんの 集中力5倍!小よく大を制するミニマリストEmacs - (rubikitch loves (Emacs Ruby CUI Books)) でした。

昨年は org-modeでTODO管理 - handlename::blog というエントリで参加しました。
今年はalignのルール設定について、例を挙げながら説明してみます。

align

emacsにはalignという機能があります。この機能は拡張elispを追加することなく、デフォルトの状態で使用することができます。

たとえばこんなコードを、

int count = 0;
float degree = 0.2;

リージョン選択して、

M-x align

とすると、こんな感じに整形してくれます。

int   count  = 0;
float degree = 0.2;

alignのルール

align-rules-listにルールを追加することで、整形する方法を自由に設定することができます。

(add-to-list 'align-rules-list
             '(hoge-assignment ; ルールの名前
               ; オプションをここに書く
               ))

オプションの詳しい説明については、

f| v align-rules-list

を参照。

例: 一番シンプルなルール

@を基準にしてalignする。

(add-to-list 'align-rules-list
             '(atmark-assignment
               (regexp . "\\( *\\)@")    ; 基準を定義する正規表現
               (modes  . '(text-mode)))) ; ルールを適用するモード
foo@bar
hoge@huga
1@2

foo  @bar
hoge @huga
1    @2

例: パターンの後ろを調整してそろえる

\\(\\s-*\\)regexpの末尾においておくことによって、パターンの後ろにあるスペースを調整してalignすることができる。

(add-to-list 'align-rules-list
             '(yaml-assignment
               (regexp . ":\\(\\s-*\\)") ; 末尾に \\(\\s-*\\)
               (modes  . '(yaml-mode))))
Winter:
  Decemberde: 12
  January: 1
  February: 2

Winter:
  Decemberde: 12
  January:    1
  February:   2

例: 1行に複数回ルールを適用する

repeatにnon-nilを指定すると、1行に複数回ルールを適用できる。

(add-to-list 'align-rules-list
             '(camma-assignment
               (regexp . ",\\( *\\)")
               (repeat . t)              ; 複数回適用を有効に
               (modes  . '(perl-mode))))
my @primes = (
    1,2,3,5,7,
    11,13,17,19,23,
    29,31,37,41,43,
);

my @primes = (
    1,  2,  3,  5,  7,
    11, 13, 17, 19, 23,
    29, 31, 37, 41, 43,
);

例: タブ位置でそろえる

tab-stopにnon-nilを指定すると、tab-widthの整数倍の位置にそろえられる。

(add-to-list 'align-rules-list
             '(tab-stop-assignment
               (regexp   . "\\(\\s-+\\)")
               (tab-stop . t)              ; タブ位置でそろえる
               (modes    . '(text-mode))))

tab-widthが4の場合

0....5..8
yes はい
no いいえ

0....5..8
yes     はい
no      いいえ

例: 固定位置でそろえる

columnに列数を指定しておくと、その列でそろえられる。

(add-to-list 'align-rules-list
             '(column-assignment
               (regexp . "\\(\\s-+\\)")
               (column . 10)            ; そろえる列数
               (modes . '(text-mode))))
0....5....10
english 英語
japanese 日本語
french フランス語

0....5....10
english   英語
japanese  日本語
french    フランス語

例: alignする段落の切れ目を指定する

separate正規表現を指定すると、alignする段落の切れ目を変更することができる。

(add-to-list 'align-rules-list
             '(custom-separete-assignment
               (regexp . ",\\(\\s-*\\)")
               (separate . "\\(===\\)")  ; 段落の切れ目
               (modes . '(text-mode))))
January, 1
February, 2
March, 3
===
April, 4
May, 5
June, 6

January,  1
February, 2
March,    3
===
April, 4
May,   5
June,  6

ほかにも

align-rules-listのオプションには、
ほかにも

  • group
  • case-fold
  • valid
  • run-if
  • spacing
  • justify

というオプションがあります。詳しくはヘルプを読んでみてください。

# 正直なところ、groupが何をするのか、とか、よくわかってないです。教えてエラい人!

実用的なルール

このあたりの記事を参考にさせてもらってます。

余談

バージョン管理との関係

alignを使っていると、列揃えの変化(長い変数名が段落に追加された場合など)もファイルの変更としてリポジトリに記録されてしまい、本来の変更箇所が隠れてしまうので、若干使用をためらうこともありました。

が、

gitを使っているならdiffに-bオプションを付けると空白文字の増減は無視してくれるので、そのような気遣いをする必要がありません。

$ git diff -b

align-regexp

ルールをその場で指定できるalign-regexpというコマンドもあります。

; regexpだけを指定する場合
M-x align-regexp

; groupやrepeatなども指定する場合
C-u M-x align-regexp

そんなに大きくない、せいぜい数百行のアクセスログなどを整形するときに、cua-modeと組み合わせてよく使います。

もちろん、こういう処理を何度もする必要がある場合は、バッチを書くなりして自動化するのが賢明です。

おわり

明日は @uwabami さんです。