目次 / 第1回 第2回 第3回 第4回 第5回 第6回 第7回 第8回 第9回

cc-mode

Emacs では cc-mode というパッケージが C 系言語のコーディングスタイルを統括しています。cc-mode はパッケージ名で、個々のメジャーモード名は c-mode や c++-mode です。

cc-mode がサポートする言語を cc-mode.el から抜粋しておきます。

CC Mode supports K&R and ANSI C, ANSI C++, Objective-C, Java,
CORBA’s IDL, Pike and AWK with a consistent indentation model
across all modes.

設定例

前述の言語の中で私が使うのは C 言語だけで、以下の設定をしていました。

(add-hook 'c-mode-common-hook
          (lambda ()
            (c-set-style "bsd")                            ;;; (a)
            (setq c-basic-offset 4)                        ;;; (b)
            ;; 演算式が複数行にまたがるときのオフセット
            (c-set-offset 'statement-cont 'c-lineup-math)  ;;; (c)
            ;; 行末のスペースやタブに色づけして警告する。
            (setq show-trailing-whitespace t)))            ;;; (d)

c-mode-common-hook は C と C++ 両方に影響する hook です。C だけに設定したい場合は c-mode-hook を、C++ だけに設定したい場合は c++-mode-hook を使います。

インデントは以下の手順で設定します。

  1. 近いスタイルを選ぶ。
  2. 気にいらないインデント部分を見つける。
  3. Ctl-c Ctrl-s でインデントに効いてくる変数を見つける。
  4. その変数の値をc-set-offset関数で変える。

1 が (a) です。加えて (b) も設定しています。私の場合は bsd スタイルが一番しっくり来ました。bsd 以外の他のスタイルは M-x c-set-style し、TAB キーを押すと確認できます。

2 は私の場合、以下のようなインデントでした。

ret = a +
    b +
    c;

このようにしたかったのです。

ret = a +
      b +
      c;

3 の見つけ方です。

まず “b +” の行で Ctrl-c Ctrl-s します。すると *Messages* バッファに以下のように表示されました。

Syntactic analysis: ((statement-cont 107))

この行のインデントは statement-cont によって設定されていることが分かりました。

statement-cont とは何でしょうか。

cc-mode では c-basic-offset と c-offsets-alist がインデントに関係してきます。この c-offsets-alist を構成する値が statement-cont です。c-offsets-alist の値を確認してみると以下のように設定されていました。

(statement-cont . +)

4 の方法です。が、ここで一点注意。

c-basic-offset は (b) のように setq() で設定すれば良いのですが、c-offsets-alist は直接 setq() でいじってはいけません。c-set-offset() で修正します。

(statement-cont . +) に相当する設定は以下になります。

(c-set-offset 'statement-cont '+)

'+ は c-basic-offset の値です。'++ にすると 2 倍になるそうです。

しかし、今回は意図した設定になりませんでした。どうやらこの設定を調べていた当時、2ch で質問して c-lineup-math にしたようです。チャンチャン。
Emacs part8 の 891 レス目 - 2ch

(d) はコメントのとおり、不必要なスペースやタブに色付けして警告する設定です。ソースによっては警告されまくりで、真っ赤になったりするのであまりオススメはしません。

第9回終わり。

目次 / 第1回 第2回 第3回 第4回 第5回 第6回 第7回 第8回 第9回