C 系の言語 (C, C++, Java など) は、cc-mode が基本になっており、そこ から c-mode, c++-mode, java-mode などに派生しています。ですから、これ らの言語モードについては、設定方法がほぼ共通しています。
なお、筆者の現在使用している Emacs は GNU Emacs 21.3.1 です。
何はともあれ、c-mode のコーディング・スタイルを設定します。デフォル トでは GNU コーディング・スタイルになっていますが、はっきりいってこれ は亜流もいいところ。他のコーディング・スタイルにするには:
(defun my-c-mode-hook () (c-set-style "linux")) (add-hook 'c-mode-hook 'my-c-mode-hook) |
といったように .emacs に書いておきます。選べるコーディング・スタイ ルには linux の他に bsd、k&r、そして gnu があります。
独自のスタイルを定義することもできますが、簡単ではないので省きます。 cc-mode の info を読んでください。
インデントしたいときは C-j で改行します。リターン・キーだとインデン トされません。行をインデントしたい場合、ポイントを行のどこかに置いてタ ブ・キーを押せば、タブ文字が挿入されずにインデントされます。タブ文字を 挿入したい場合には M-i とタイプします。
Emacs では、デフォルトのタブ幅は 8 スペースになっています。8 個のス ペースが並ぶようなところではタブになります。c-mode ではインデント幅は 8 スペースなので 1 タブに置き換えられます。java-mode ではインデント幅 は 4 スペースになります。タブ幅は変わず、8 スペースです。
たとえば、インデントを 4 スペースにし、かつタブ幅も 4 スペースにし たい場合:
(defun my-c-mode-hook () (c-set-style "linux") (setq tab-width 4) (setq c-basic-offset tab-width)) (add-hook 'c-mode-hook 'my-c-mode-hook) |
とします。
また、スペースだけでインデントしたい場合:
(defun my-c-mode-hook () (c-set-style "linux") (setq indent-tabs-mode nil)) |
とします。
キーワードなどのハイライトも可能です:
(defun my-c-mode-hook () (c-set-style "linux") (turn-on-font-lock)) (add-hook 'c-mode-hook 'my-c-mode-hook) |
モードごとに設定するのが面倒ならば:
(global-font-lock-mode t) |
と .emacs に書いておきます。
皆さんにぜひ使ってもらいたいのが hungry-deletion という cc-mode の マイナー・モードです。これは、連続する空白類をバックスペース・キー一発 でザッと消してしまうモードです。有効にするには:
(defun my-c-common-mode () (c-toggle-hungry-state 1)) (add-hook 'c-mode-common-hook 'my-c-common-mode) |
とします。c-mode-common-hook に追加することで、C 系のメジャー・モード すべてで有効になります。
1 文字ずつ消すには C-h をタイプします。ちなみに、C-h を delete-backward-char にに割り当てておくのは Emacs 使いの常識でしょう:
(global-set-key "\C-h" 'delete-backward-char) |
以下に紹介するキー操作は、はっきりいって知らなくても構いません。同 じ操作でもポイントの位置によって挙動が微妙に違ってきますし、キー操作を 身体で覚えるまで時間もかかります。
以下に紹介するキー操作は、M と C を同時に押します。PC ならば Alt と Ctrl を同時に押しつつ、たとえば a も押します。Esc を押してから C-a で も同じ効果が得られますが、ちょっとまどろっこしいのが難点です。
| M-C-a | beginning-of-defun | 関数定義の先頭へ |
| M-C-e | end-of-defun | 関数定義の終わりへ |
| M-C-p | backward-list | 直前の開きカッコへ |
| M-C-n | forward-list | 直後の閉じカッコへ |
| M-C-b | backward-sexp | 直前のトークンへ |
| M-C-f | forward-sexp | 直後のトークンへ |
| M-C-u | backward-up-list | ネストから出る |
| M-C-d | down-list | ネストに入る |
この中で便利なものは、M-C-a, M-C-e, M-C-u でしょうか。
cc-mode のバッファでは M-x compile というコマンドが利用できます。実 際に試してみるとミニバッファに:
Compile command: make -k
というプロンプトが現れます。そのバッファと対応するディレクトリに Makefile があれば、RET をタイプすることでビルドが始まります。もちろん:
Compile command: make clean
のようなこともできますし:
Compile command: gcc -g -Wall foo.c
のようなこともできます。
compile が実行されると、*compilation* というバッファが現れ、そこに 入力したコマンドの結果が表示されます。
ちょっと注目してほしいのが、ポイントが *compilation* に移っておらず、 元のバッファに置かれたままである点です。ここでコンパイル・エラーが起き たとしましょう。そのときは、ポイントを他のバッファに移さず、M-x next-error とタイプします。すると、コンパイル・エラーが起きた個所にポ イントが移動します。
つまり M-x compile でコンパイルし、エラーが起きたらそのまま M-x next-error をタイプするというサイクルになります。
M-x compile, M-x next-error と長々とタイプするのは面倒なので、筆者 は:
(defun my-c-common-mode () (define-key c-mode-base-map "\C-cc" 'compile) (define-key c-mode-base-map "\C-ce" 'next-error) (c-toggle-hungry-state 1)) (add-hook 'c-mode-common-hook 'my-c-common-mode) |
と .emacs に書いています。
また、*compilation* を消すために一々 C-x 1 をタイプするのは面倒なの で、C-x 5-2 で *compilation* だけの小さなフレームを用意しています。
話が逸れますが、筆者のデスクトップを紹介しておきます。今のデスクトッ プは 4 つの仮想デスクトップを持ち、その 1 つの仮想デスクトップに 2 つ の Emacs と 1 つの端末エミュレータを立ち上げるという構成です:
+-----------+ +-----------+ | | | | | | | | | src1.c | | src2.c | | | | | | | | | +-----------+ +-----------+ +-----------+ +-----------+ | *compi..* | | rxvt | +-----------+ +-----------+
Emacs のフレームの大きさは 80x49 です。モニタには 17 インチの液晶を 使っていますが、2 つの Emacs を横に並べてスッポリと収まるようにしてい ます。これが最善かどうかは分かりませんが、参考まで
cc-mode とは直接関係はありませんが、ここで M-x gdb の簡単な使い方を 紹介しておきます。
M-x gdb というのは、その名のとおり、Emacs の中で gdb を動かすための コマンドです。つまり、Emacs が gdb のフロントエンドになるというわけで す。
M-x gdb とタイプすると:
Run gdb (like this): gdb
とミニバッファにプロンプトが現れます。実行ファイルが a.out ならば:
Run gdb (like this): gdb a.out
とタイプすると *gud-a.out* というバッファが開かれます。このデバッガ・ バッファでの操作は基本的に gdb と同じです。以降、よく使われるコマンド を簡単に紹介しますが、詳しくは gdb の info を参照してください。
もし core があるなら:
Run gdb (like this): gdb a.out core
とタイプすることで core ファイルを指定できます。
core を指定したときに、まずやりたいことはスタック・トレースの表示で しょう。スタック・トレースを表示させるには:
(gdb) bt
とタイプします。bt はもちろん backtrace のことです。
gdb の中でプログラムを動かす前にブレイク・ポイントを設定します。
(gdb) b main
ブレイク・ポイントには関数名の他に行数などでも指定することができま す。
ブレイク・ポイントを設定したら、いよいよプログラムを実行します:
(gdb) run
もし、プログラムにコマンド行引数を渡す必要があれば、run で指定しま す:
(gdb) run arg1 arg2
run で指定する引数は、一旦シェルによって解釈されます。ですから、必 要ならばエスケープしなければなりません:
(gdb) run abc\ def \;
run を実行すると、ソース・バッファの左端に、これから実行される行を 示すカーソルが現れます。ブレイク・ポイントとして設定した関数の最初の行 になっているはずです。たとえば、次のような状態だとしましょう:
int main(int argc, char *argv[])
{
→ foo();
bar();
return 0;
}
|
左の矢印 (→) を gdb のカーソルだと思ってください。このとき、n をタ イプすると、矢印が bar() の呼び出しに移ります:
int main(int argc, char *argv[])
{
foo();
→ bar();
return 0;
}
|
この状態でもう一度 n をタイプすると return に移ります:
int main(int argc, char *argv[])
{
foo();
bar();
→ return 0;
}
|
つまり、n は単純に今指されている行を実行し、次の行に移るというコマ ンドです。n は next のことです。
main から foo の中まで追いかけたい場合、s を使います。たとえば:
int main(int argc, char *argv[])
{
→ foo();
bar();
return 0;
}
void foo(void)
{
puts("hello, world");
}
|
という状態のときに s をタイプすると:
int main(int argc, char *argv[])
{
foo();
bar();
return 0;
}
void foo(void)
{
→ puts("hello, world");
}
|
というように gdb のカーソルが移動します。s は step のことです。
今の関数から抜けたい場合には u (up) を使います。
次のブレイク・ポイント (あるいは実行終了) まで一気に実行を行いたい ときには c (continue) を使います。
変数の中身を見るには p (print) を使います。p では式を指定することも できます:
(gdb) p ptr->value
gdb は履歴を録っています。デバッガ・バッファでは M-p と M-n で履歴 をたどることができます。さらに、M-r で履歴を正規表現で検索できます。
また、RET だけをタイプすると、最後に入力したコマンドが繰り返されま す。
2005-07-26