検索エンジンから来た人に注意このマニュアルは、Emacs ver. 19.x 向けのマニュアルを Mule 2.x の開発にあたり邦訳したものを、 電脳外道学会がミラーリングしているものであり、旧版製品パラノイアであるところの椅子人の趣味によるものです。しかしながら、現在の Emacs の主流は ver. 20 以降であり、ver 19.x と ver 20.x とでは、仕様の違いが少なからずあります。 したがって、一般的な Emacs ユーザーにとっては、
このマニュアルと実機の動作とが符合しない場合があります。
|
モード(mode)とは、Emacsをカスタマイズするための定義のセットのこ とであり、また、編集中に自由に使用/不使用を決めることができるものです。 モードは2種類に大別でき、それぞれ、主モード(major mode)と副 モード(minor mode)と呼ばれています。主モードとは、ほかの主モードとは同 時に使用できず、また、特定の種類のテキストの編集に適した機能を提供するも のです。また、副モードとは、ユーザが好みに応じて自由に組み合わせて使用で きるものです。
この章では、主モードと副モードの作り方、モード行での表示の仕方、ユーザ によって指定されたフックの実行の仕方について説明します。キーマップ、構文 テーブルといった関連事項についてはそれぞれsection キーマップとsection 構文テーブルを参照してください。
主モードは、編集中のテキストの種類に合わせてEmacsを変身させます。 一つのバッファで同時に複数の主モードを利用することはできません。
最も普遍的な主モードにはFundamentalモード(Fundamental mode)とい
う名前がつけられています。このモードにはモード固有の定義や変数の設定がな
いので、Emacsのコマンドはデフォルトの動作をし、すべてのオプションはデフォ
ルトの状態に設定されています。ほかの主モードは、さまざまなキーやオプショ
ンを再定義しています。たとえば、Lisp InteractionモードではLFD
(eval-print-last-sexp)、TAB (lisp-indent-line)やその
ほかのキーに関して、機能の割当が変更されています。
特殊な編集作業のために新しいコマンドをいくつも作らなくてはならなくなった とき、新しい主モードを作るのは通常よい選択です。主モードを作る のは(副モードの作成がたいてい困難なのに比べれば)それほど難しくありま せん。
もし、新しいモードによく似たモードがすでにあっても、その古いモードを書 き換えて二つの目的の両方に対応できるようにしようとするのは賢明ではありま せん。なぜなら、そのようなモードは使用するのも維持するのも難しくなりがち だからです。代わりに、既存のモードをコピーし名前を変更してそれを書き換え るようにするか、または、導出モード(derived mode) (see section 導出モードを定義する) を定義するようにしてください。たとえば、Rmail Editモード (`emacs/lisp/rmailedit.el'で定義されています)は、三つの新しいコマン ドが使えるほかはTextモードにそっくりな主モードです。Rmail Editモードの定 義はTextモードの定義とは異なるものですが、全く別に作られたものではなく、 Textモードから導出されたものです。
Rmail Editモードは、テキストを一時的に異なる主モードにして、別の方法で (つまり、Rmailのコマンドではなく、通常のEmacsのコマンドで)テキストを編集 できるようにする場合の例になっています。このような場合に一時的に使用され る主モードは、そのバッファの通常のモード(この例ではRmailモード)に戻すた めのコマンドを持っています。似たような機能を実現するには、コマンドなどの 再定義を再帰編集の中で行ない、ユーザが再帰編集から抜けたところで定義を戻 す、という方法もありますが、ユーザが複数のバッファで同時にこのようなことを 行ったときに不便さを強要することになり、好ましくありません。再帰編集は最後に 始まったものからしか順に抜けられないのです。別の主モードを使用すればこの 制限はありません。See section 再帰編集。
GNU Emacsが標準的に使用しているライブラリ・ディレクトリにはいくつかの主 モードのためのコードがあり、`text-mode.el'、`texinfo.el'、 `lisp-mode.el'、`c-mode.el'、`rmail.el'などに納められて います。これらのファイルを見て、主モードがどのように記述されるのか を知ることができます。Fundamentalモードを除くとTextモードが最も単純なモー ドでしょう。また、Rmailモードは複雑で特殊なモードです。
既存の主モードのコードは、ローカル・キーマップや構文テーブルの初期化、 グローバルな名前、フックなどに関するさまざまな慣例にしたがって記述されて います。新しい主モードを作るときには、以下の慣例にしたがってください。
describe-mode)をするとこの文字列が表示されます。
また、説明の内容を自動的にユーザのキー・バインドに合わせるために説明
文字列で使用できる特殊な文字列(`\[command]'、
`\{keymap}'、`\<keymap>')が用意されています。
See section 説明文字列でのキー・バインドの置換。
kill-all-local-variablesを呼び出
してください。これは、これまで有効だった主モードのローカル変数の影響
を受けないようにするためです。
major-modeにセットするようにしてください。これにより、
describe-modeが正しく説明文字列を表示できるようになります。
mode-nameにセットするようにしてください。この文字列はモード行の
中に表示されます。
use-local-mapを呼ぶことによって、このローカル・
マップを作るようにしてください。詳細はSee section アクティブ・キーマップ。
このキーマップは、モード名-mode-mapという名前のグローバル変
数で保持するようにしてください。普通はそのモードを定義するライブラリがこ
の変数を設定します。
モード名-mode-syntax-tableという名前の変数で保持するように
してください。See section 構文テーブル。
モード名-mode-abbrev-tableという名前の変数で保持す
るようにしてください。See section 省略形テーブル。
defvarを使用して値をセットするようにしてください。そのような再初
期化は、ユーザによるカスタマイズを無効にしてしまいます。
make-variable-buffer-localではなくmake-local-variableを使
用してください。前者を使用すると、全てのバッファにおいて次にその変数に値
がセットされたときにその変数がバッファローカルになってしまい、このモー
ドに無関係なバッファに悪影響を及ぼしてしまう可能性があります。モードはそ
のような大きな影響を起こすべきではありません。
See section バッファローカルな変数。
単一のLispパッケージの中でのみ使用されている変数に対して
make-variable-buffer-localを使用することは構いません。
モード名-mode-hookという名前で作ってください。主モード・コ
マンドの最後の処理として、run-hooksを使用してそのフックを実行する
ようにしてください。See section フック。
indented-text-modeはindented-text-mode-hookだけで
はなくtext-mode-hookも実行します。このようなほかのモードのフック
の実行は、モード固有のフックの直前(つまり、ほかの処理が全て終った後)で行っ
ても構いませんし、あるいは、もっと早い段階で行っても構いません。
change-major-mode-hookにローカルな値をセットしておく
ことができます。
specialの値をもつmode-classという名前
の属性をもつようにしてください。たとえば以下のようにしてセットします。
(put 'funny-mode 'mode-class 'special)これは、Funnyモードになっているバッファから新しいバッファを作るときに、新 しいバッファがFunnyモードを継承しないよう、Emacsに伝える例です。Dired、 Rmail、Buffer Listといったモードはこのように設定されています。
auto-mode-alistにその旨をつけ加えてくださ
い。モード・コマンドが自動ロードされるように設定する場合には、
autoloadを呼ぶそのファイルの中でauto-mode-alistの設定をす
る必要があります。そうでない場合は、モードの定義を行っているファイルの中
でauto-mode-alistの設定も行うことにしていいでしょう。See section 主モードの自動選択の仕組み。
auto-mode-alistに要素を追加する式やautoload形式をユー
ザーが`.emacs'ファイルに追加できるように、それぞれの記述例をドキュ
メントに記載してください。
kill-all-local-variablesは、その最初の処理としてこの正規フックを
実行します。このフックを利用して、ユーザがバッファをほかの主モードに変更
したときに行う特殊な処理を定義できます。続く主モードに悪影響を及ぼさないよ
うに、この変数をバッファにローカルにして、フックの実行後にこの変数が消え
るようにしてください。See section フック。
Textモードは、Fundamentalモードを除くと最も単純な主モードでしょう。以 下は、`text-mode.el'から抜粋した、上述のさまざまな慣例の実例です。 (訳注: 実際のコード中のコメント類は英語で書かれています)
;; モード特有の構文テーブルを作る。
(defvar text-mode-syntax-table nil
"Syntax table used while in text mode.")
(if text-mode-syntax-table
() ; すでにテーブルができ上がっていたら書き換えない。
(setq text-mode-syntax-table (make-syntax-table))
(modify-syntax-entry ?\" ". " text-mode-syntax-table)
(modify-syntax-entry ?\\ ". " text-mode-syntax-table)
(modify-syntax-entry ?' "w " text-mode-syntax-table))
(defvar text-mode-abbrev-table nil
"Abbrev table used while in text mode.")
(define-abbrev-table 'text-mode-abbrev-table ())
(defvar text-mode-map nil) ; モード特有のキーマップを作る。
(if text-mode-map
() ; キーマップの中身がすでにでき上がっていたら書き換えない。
(setq text-mode-map (make-sparse-keymap))
(define-key text-mode-map "\t" 'tab-to-tab-stop)
(define-key text-mode-map "\es" 'center-line)
(define-key text-mode-map "\eS" 'center-paragraph))
以下は、Textモードの主モード関数の完全な定義です。
(defun text-mode ()
"Major mode for editing text intended for humans to read.
Special commands: \\{text-mode-map}
Turning on text-mode runs the hook `text-mode-hook'."
(interactive)
(kill-all-local-variables)
(use-local-map text-mode-map) ; ローカル・キーマップを使う。
(setq mode-name "Text") ; モード行に表示される名前。
(setq major-mode 'text-mode) ; describe-modeがきちんと
; 説明文字列を見つけられるように。
(setq local-abbrev-table text-mode-abbrev-table)
(set-syntax-table text-mode-syntax-table)
(run-hooks 'text-mode-hook)) ; こうしておくと、ユーザがフック
; を使ってカスタマイズできる。
三つのLispモード(LispモードとEmacs LispモードとLisp Interaction モード)は、Textモードよりも多くの機能を持っていて、どれも非常に複雑です。 以下の例は、`lisp-mode.el'からの抜粋です。これらのモードがどのよう に書かれているかを見てください。
;; モード特有のテーブルを保持する変数を作る。
(defvar lisp-mode-syntax-table nil "")
(defvar emacs-lisp-mode-syntax-table nil "")
(defvar lisp-mode-abbrev-table nil "")
(if (not emacs-lisp-mode-syntax-table) ; テーブルの中身がすでにでき
; 上がっていたらそのままに。
(let ((i 0))
(setq emacs-lisp-mode-syntax-table (make-syntax-table))
;; 数字の0未満の文字について、シンボル名の一部であって
;; ワードではない、と定義する。
;; (数字の0はASCIIコードで48。)
(while (< i ?0)
(modify-syntax-entry i "_ " emacs-lisp-mode-syntax-table)
(setq i (1+ i)))
...
;; ほかの文字についても構文を定義する。
(modify-syntax-entry ? " " emacs-lisp-mode-syntax-table)
(modify-syntax-entry ?\t " " emacs-lisp-mode-syntax-table)
...
(modify-syntax-entry ?\( "() " emacs-lisp-mode-syntax-table)
(modify-syntax-entry ?\) ")( " emacs-lisp-mode-syntax-table)
...))
;; lisp-modeで使用される省略形テーブルを作る。
(define-abbrev-table 'lisp-mode-abbrev-table ())
沢山のコードが三つのLispモードの間で共有されています。以下の関数はさまざま な変数を設定する機能があり、それぞれのLispモードから利用されます。
(defun lisp-mode-variables (lisp-syntax) ;; Emacs Lispではlisp-syntax引数はnil、 ;; それ以外の二つのLispモードではt。 (cond (lisp-syntax (if (not lisp-mode-syntax-table) ;; Emacs Lispモードの構文テーブルは常に存在している。 ;; しかしLispモードの構文テーブルは必要になってか ;; ら作る。これは記憶領域の節約のため。 (progn (setq lisp-mode-syntax-table (copy-syntax-table emacs-lisp-mode-syntax-table)) ;; Lispモードのためにいくつかのエントリを変更する (modify-syntax-entry ?\| "\" " lisp-mode-syntax-table) (modify-syntax-entry ?\[ "_ " lisp-mode-syntax-table) (modify-syntax-entry ?\] "_ " lisp-mode-syntax-table))) (set-syntax-table lisp-mode-syntax-table))) (setq local-abbrev-table lisp-mode-abbrev-table) ...)
forward-paragraphのような関数はparagraph-start変数の値
を使います。Lispコードは通常のテキストとは違うので、
paragraph-start変数の値はLispに合わせて設定されなければなりま
せん。また、Lispではコメントは特殊なスタイルで字下げされるので、
Lispモードに特化したcomment-indent-functionも必要です。これら
の変数を設定するためのコードが、lisp-mode-variablesの残りの部分
に書かれています。
(make-local-variable 'paragraph-start)
;; こんな形で`^'を入れておかなきゃならないのは美しくないけど、
;; すでにpage-delimiterにも混じっているし、取り除くのも面倒。
(setq paragraph-start (concat "^$\\|" page-delimiter))
...
(make-local-variable 'comment-indent-function)
(setq comment-indent-function 'lisp-comment-indent))
それぞれのLispモードは、少しずつ異なるキーマップを持っています。たとえ
ば、LispモードではC-c C-zはrun-lispにバインドされていますが、
ほかの二つのLispモードでは未定義です。
しかしながら、すべてのLispモードで共通なコマンドもあります。以下の関数
は、これらの共通なコマンドを引数で与えられたキーマップに加えます。
(defun lisp-mode-commands (map) (define-key map "\e\C-q" 'indent-sexp) (define-key map "\177" 'backward-delete-char-untabify) (define-key map "\t" 'lisp-indent-line))
以下のコードは、キーマップの初期化のために、Emacs Lispモードのコードの
中でlisp-mode-commandsを使用する例です。まず最初に、
defvarを使用してモードに特有なキーマップを保持するための変数を宣
言します。このdefvarは、その変数が値を持っていないときは値を
nilにセットします。それから、その変数がnilならば、新しく
キーマップをセットアップします。
このコードは、もしすでにキーマップがセットアップされていたら、変更せず にそのままにします。これにより、ユーザがキーマップをカスタマイズできます。
(defvar emacs-lisp-mode-map () "")
(if emacs-lisp-mode-map
()
(setq emacs-lisp-mode-map (make-sparse-keymap))
(define-key emacs-lisp-mode-map "\e\C-x" 'eval-defun)
(lisp-mode-commands emacs-lisp-mode-map))
で、以下が、Emacs Lispモードのための主モード関数の完全な定義です。
(defun emacs-lisp-mode ()
"Major mode for editing Lisp code to run in Emacs.
Commands:
Delete converts tabs to spaces as it moves back.
Blank lines separate paragraphs. Semicolons start comments.
\\{emacs-lisp-mode-map}
Entry to this mode runs the hook `emacs-lisp-mode-hook'."
(interactive)
(kill-all-local-variables)
(use-local-map emacs-lisp-mode-map) ; ローカル・キーマップを使用する。
(set-syntax-table emacs-lisp-mode-syntax-table)
(setq major-mode 'emacs-lisp-mode) ; describe-modeが説明
; 文字列を見つけられるように。
(setq mode-name "Emacs-Lisp") ; モード行に表示されるモード名。
(lisp-mode-variables nil) ; いろいろな変数を定義する。
(run-hooks 'emacs-lisp-mode-hook)) ; ユーザがカスタマイズのために定
; 定したフックをここで実行する。
ファイルを読み込んで新しくバッファを作る際に、Emacsは、ファイル名やファ イルの内容から主モードを自動的に選び出します。
fundamental-mode関数はいかなるフックも実行しません。
(Fundamentalモードの振舞を変えたい場合は、Emacsのglobal state(グ
ローバル・キーマップなど)を変更するようにしてください)。
set-auto-modeを呼んでモー
ドを立ち上げ、次に、hack-local-variablesを呼んでファイルに記述され
ているローカル変数の設定や式の評価を行ないます。
もし、normal-mode関数へのfind-file引数が非nil
なら、normal-modeはfind-fileより呼ばれているものと仮定
します。この場合、ファイルの最後尾や`-*-'行にあるローカル変数リス
トの処理を行うかもしれません。変数enable-local-variablesが、そ
の処理を行うかどうかのコントロールを行ないます。
normal-modeをインタラクティブに(コマンドとして)実行した場合、
通常find-fileはnilになります。この場合、
normal-modeは無条件に全てのローカル変数リストの処理を行ないます。
(ローカル変数リストについてはSee section `Local Variables in Files' in The GNU Emacs Manualを参照)
normal-modeは、主モード関数の呼出しにcondition-caseを使用
します。そのため、主モード関数の評価中に発生したエラーは捕捉され、
`File mode specification error'としてオリジナルのエラー・メッセージ
と一緒に報告されます。
tならば処理し、nilならば無視、それ
以外ならばファイルごとにどのように扱うかをユーザに尋ねます。デフォルト値
はtです。
このリストに加えてさらに、名前のrisky-local-variable属性
が非nilであるような変数に対する値も無視されます。
tならば処
理し、nilならば無視、それ以外ならばファイルごとにどのように扱うか
をユーザに尋ねます。デフォルト値はmaybeです。
auto-mode-alistを使用)、およびローカル変数の値です。
ファイル最後尾付近の`mode:'ローカル変数の値の処理は、この関数ではなく
hack-local-variables関数が行ないます。See section `How Major Modes are Chosen' in The GNU Emacs Manual.
fundamental-modeです。
default-major-modeの値がnilの場合は、以前にカレントであっ
たバッファの主モードを新しいバッファの主モードとして使います。ただし、主
モード・シンボルがmode-class属性を持ちその値がspecialであ
る場合は、このdefault-major-mode変数の値に関わらずFundamentalモー
ドが使われます。DiredやRmailのように、特殊なテキストでのみ意味のあるモー
ドが、この属性を持っています。
default-major-modeの
値にセットします。もしその変数がnilならば、カレント・バッファの主
モードを使用します(もしそれが適当ならば)。
バッファを作るための低レベルなプリミティブはこの関数を呼ぶことはありませ
んが、switch-to-bufferやfind-file-noselectのような中レ
ベルのコマンドは、バッファを作る度にこの関数を呼び出します。
lisp-interaction-modeです。
(regexp . mode-function)のような形式をしています。
例:
(("^/tmp/fol/" . text-mode)
("\\.texinfo\\'" . texinfo-mode)
("\\.texi\\'" . texinfo-mode)
("\\.el\\'" . emacs-lisp-mode)
("\\.c\\'" . c-mode)
("\\.h\\'" . c-mode)
...)
展開されたファイル名(see section ファイル名を展開する関数)がregexpに一致する
ファイルを読み込んだとき、set-auto-modeはそれに対応した
mode-functionを呼びます。この機能により、ほとんどのファイルにつ
いて、適切な主モードの選択が自動化できます。
もし、auto-mode-alistの要素が(regexp function t)
のような形式だった場合、functionを呼び出した後、ファイル名の
regexpに一致しなかった残りの部分についてauto-mode-alist
の検索を再び行ないます。
(訳注: GNU Emacsバージョン19.28のDOCの記述によると
(regexp function)の形式となっているが、それは誤り。
19.29では修正された。)
この"もう一度一致(match-again)"の機能は、uncompressionパッケージに
おいて便利です。たとえば、("\\.gz\\'" function t)の記述によって、
ファイルをgunzipして、さらにその伸長されたファイルを、`.gz'を除いた
ファイル名から求めた適切なモードにする、といった利用ができるでしょう。
複数のパターンのペアをauto-mode-alistに設定する方法の例を挙げま
す(このような設定を`.emacs'で行うこともできます)。
(setq auto-mode-alist
(append
;; `.' (ピリオド)で始まるファイル名。
'(("/\\.[^/]*\\'" . fundamental-mode)
;; `.' (ピリオド)を含まないファイル名。
("[^\\./]*\\'" . fundamental-mode)
;; `.C'で終わるファイル名。
("\\.C\\'" . c++-mode))
auto-mode-alist))
(interpreter . mode)のような形式の要
素をもつリストで、たとえば、デフォルトでは("perl" . perl-mode)などが
指定されています。この要素は、interpreterのスクリプト・ファイルに対して
modeを使用することを意味します。
この変数は、使用する主モードをauto-mode-alistで決定できな
かったときにのみ適用されます。
normal-modeの説明中のenable-local-variablesの扱いに関す
る記述を参照してください。引数forceは通常の場合、
normal-mode関数のfind-file引数を引き継いだものです。
describe-mode関数は、主モードに関する情報を提供するために使用さ
れます。通常、C-h mにより呼び出されます。describe-mode関数は
major-modeの値を使用します。これは、主モード関数が
major-mode変数をセットしなければならない理由の一つです。
describe-mode関数は、major-modeを引数に
documentation関数を呼ぶことで、主モード関数の説明
文字列を表示します。(See section 説明文字列へのアクセス)。
describe-mode関数は、主モードの説明文字列としてこの関数の
説明文字列を使用します。
新しいモードを定義するときに、既存の主モードを基にしたくなることがよく
あります。これを簡単に行う方法の一つはdefine-derived-modeを使うこ
とです。
新しくできるコマンドvariantは、関数parentを呼んだ後、以 下のように親モードのいくつかの側面をオーバーライドするように定義されます。
variant-mapという名前の独自のキーマップを持
ちます。define-derived-modeは、このキーマップがまだ値を持っていな
い場合は、parent-mapを継承するように初期化します。
variant-syntax-tableという名前で独自の構文
テーブルを持ちます。define-derived-modeは、もしこのテーブルがセッ
トされていない場合は、parent-syntax-tableをコピーして初期化
します。
variant-abbrev-tableという名前で独自の省略
形テーブルを持ちます。define-derived-modeは、もしこのテーブルがセッ
トされていない場合は、parent-abbrev-tableをコピーして初期化
します。
variant-hookという独自のモード・フックを持ち、
このフックは通常どおり主モード関数の最後の処理として実行されます(新し
いモードは、parentを呼ぶことにより、parentのモード・フックも
実行します)。
さらに、bodyを使用することで、parentのほかの面をどのようにオー
バーライドするかを指定できます。variantコマンドは、そのオーバーラ
イド処理の後、variant-hookを実行する直前で、bodyが保
持する形式を評価します。
引数docstringは、新しいモードの説明文字列を指定します。
docstringを省略した場合、define-derived-modeが説明文字列を
自動的に作ります。
以下は架空の例です。
(define-derived-mode hypertext-mode
text-mode "Hypertext"
"Major mode for hypertext.
\\{hypertext-mode-map}"
(setq case-fold-search nil))
(define-key hypertext-mode-map
[down-mouse-3] 'do-hyper-link)
副モード(minor mode)は、それを利用するかしないかを、主モードの選 択とは無関係にユーザが選択できるような機能を提供します。副モード は単独で使用することもできるし、組み合わせて使用することもできます。"副 モード"という呼び名よりは"一般的に利用可能な、オプショナルな機能のモー ド"の方が、長過ぎるけども、より的確でしょう。
副モードは、ほとんどの場合、さまざまな主モードで使用できます。 たとえば、Auto Fillモードは、テキストの挿入を許す主モードであれば、ど のような主モードの中でも利用可能です。一般論として、副モードとは、主 モードの振舞に関わらず利用できるように作られるべきものです。
副モードの実装は、主モードの実装に比べて、たいてい非常に困難です。理由 の一つとして、使用、不使用の選択がどのような順序で行なわれるかわからない ことがあります。副モードは、主モードやほかの副モードの影響を受けずにきち んと動かなければならないのです。
副モードを実装する上で最も大きな問題となり得るのは、モードに必要な フックをEmacsにつけ加える方法です。副モード・キーマップを使えば、 従来使われてきた手段よりも簡単にこの問題を解決できます。
主モードの場合と同様に、副モードの書き方にも慣例があります。主モードで の慣例のいくつか、たとえば、モードを初期化する関数の名前、グローバルなシ ンボルの名前、キーマップなどのテーブルの扱い、などは副モードでもそのまま 当てはまります。
さらに、副モード特有の慣例もいくつかあります。
nilなら無効にし、そのほかなら有効にする)。
この変数をモード変数(mode variable)と呼びます。
この変数は、副モードの名前をモード行に表示するために、
minor-mode-alistとともに使用されます。また、副モード・キーマップ
が有効か否かを決めます。また、コマンドやフックが、この変数の値をチェック
することもあります。
もし、副モードを各バッファごとに独立に有効にしたければ、この変数をバッファローカルにしてください。
nilなら、モードをトグルするようにしてください(モードがオンだった
らオフにし、オフだったらオンにする)。引数が正の整数、または、nil
でも-でもないシンボル、または、正の整数やシンボルをCARにもつ
リストならばモードをオンにし、そのほかの場合はモードをオフにしてください。
以下はtransient-mark-modeの定義より抜き出した例です。モードの振
る舞いを有効/無効にする変数としてのtransient-mark-modeの使い方
と、前置引数の値にしたがってモードをトグル、あるいは有効/無効にするための正
しい方法を示しています。
(setq transient-mark-mode
(if (null arg) (not transient-mark-mode)
(> (prefix-numeric-value arg) 0)))
minor-mode-alistに、それぞれの副モードに適切な値を追加して
ください(see section モード行の中で使用されている変数)。この値は以下に示す形式のリストです。
(mode-variable string)ここで、mode-variableは、副モードが有効かを示す変数です。また、 stringは、モードを示すためにモード行の中に表示される、空白文 字で始まる短い文字列です。この文字列は、ほかのモードを示す文字列と一緒に表 示できるよう、短いものでなくてはなりません。
minor-mode-alistに値を追加しようとする際、すでに同じモードの値がないか
assqを使用してチェックし、重複を避けるようにしてください。
たとえば以下のようにします。
(or (assq 'leif-mode minor-mode-alist)
(setq minor-mode-alist
(cons '(leif-mode " Leif") minor-mode-alist)))
副モードは、そのモードが有効なときにのみ参照される独自のキーマップを
もつことができます。副モード独自のキーマップを持ちたいときは、連想リ
ストminor-mode-map-alistに要素を追加します。See section アクティブ・キーマップ。
副モード・キーマップの用途の一つは、いくつかの自己挿入文字の振舞を変更
し、自己挿入以外の機能を持たせることです。一般に、このような目的の場合、
副モード・キーマップの使用が唯一の方法です。なぜなら、
self-insert-commandのカスタマイズが可能なのは特殊な場合(abbrevsモー
ドとAuto Fillモードのみ)に限られているからです
(self-insert-commandの定義を独自のもので置き換えたりしないでくだ
さい。self-insert-commandは、エディタのコマンド・ループの中で特殊
な扱いをされています)。
(variable . keymap)
ここで、variableは副モードが有効かを示す変数で、
keymapはキーマップです。このキーマップkeymapは、
variableがnilでない値をもつときにのみ有効です。
minor-mode-map-alistの要素の形式は、minor-mode-alistの要
素の形式とは違うことに注意してください。要素は、variableと
keymapからなるリストではありません。キーマップが要素のCDR
になっていなければなりません。
また、キーマップそのものがCDRに来ていなければなりません。キーマップ を保持する変数を示すシンボルをCDRに置いても、望むような動作はしないでしょう。
複数の副モード・キーマップがアクティブである場合、優先順位は
minor-mode-map-alistでの並び順と一緒です。しかし、ほかの副モード
の影響を受けないように副モードを設計するべきです。そのようにできれば、順
序について悩むことはありません。
Emacsのウィンドウはそれぞれにモード行を持ち(ミニバッファ・ウィンドウ は除く)、そのウィンドウに表示されているバッファに関する情報を表示してい ます。モード行に表示される情報には、バッファの名前、結び付いているファ イル、再帰編集の深さ、主モードと副モード、などがあります。
この節では、モード行の表示内容がどのように制御されるかについ て説明します。モードの章で説明するのは、モード行に表示される情報の 多くが、有効な主モードと副モードに関係するからです。
mode-line-formatは、カレント・バッファのモード行の表示に使われ
るテンプレートを保持するバッファローカル変数です。同一のバッファを表示
するウィンドウは同一のmode-line-formatを使用するので、モード行の
表示も(表示位置のパーセント表示と行番号は除いて)同一になります。
モード行の表示の更新は、通常、ウィンドウに表示されているバッファが切
り替わったときや、バッファのmodified-statusがnilからt、
あるいはtからnilに変化したときに行なわれます。ですから、
mode-line-formatから参照される変数(see section モード行の中で使用されている変数)
を変更しても、直ちに表示に反映されるとはかぎりません。
通常、モード行は反転表示されます(section 反転表示(Inverse Video)の
mode-line-inverse-videoを参照)。
モード行の内容は、バッファローカル変数mode-line-formatに
含まれるリスト、文字列、シンボル、数値からなるデータ構造によりコントロー
ルされます。このデータ構造はモード行構成要素(mode line construct)と呼ばれ、より簡
単なモード行構成要素の再帰的な組み合わせにより構成されます。また、
同じデータ構造がフレームのタイトルを作るためにも使用されています
(see section フレーム・タイトル)。
モード行構成要素は単なる文字列でも構いませんが、通常は、ほかの変数をど のようにモード行の構築に使用するかを指定します。これらの変数の多くは、そ れ自身、モード行構成要素を値としてもつように定義されています。
デフォルトのmode-line-formatの値は、mode-nameや
minor-mode-alistといった変数の値を使用するよう定義されています。
ですから、mode-line-formatを書き換えなければならないモードはほと
んどありません。たいていの場合、mode-line-formatから参照される変
数を書き換えるだけで十分間に合います。
モード行構成要素は、リスト、シンボル、または文字列のいずれかです。もし、 値がリストならば、その要素はそれぞれ、リスト、シンボル、または文字列のい ずれかです。
string
%-指定子
(%-construct)を除いてそのまま表示されます。`%'に続く10進の
数字列は、あまりがスペースで埋められるフィールドの全体幅を示します(デー
タは左詰めされるということです)。See section モード行の表示に使われる%-指定子。
symbol
tまたはnilの場合は無視されます。同様に、
値がvoidであるシンボルも無視されます。
一つだけ例外があり、symbolの値が文字列の場合は、その値がそのまま表
示されます。その文字列中の%-指定子は、特別な意味を持ちません。
(string rest...) or (list rest...)
(symbol then else)
nilのときは、2番目
の要素thenがモード行構成要素として再帰的に処理されます。また、
symbolの値がnilならば、3番目の要素elseが再帰的に
処理されます。elseを省略することもでき、省略した場合、
symbolの値がnilならば、そのモード行構成要素は何も表示
しません。
(width rest...)
(-3 "%p")のようになります。
mode-line-formatそのものを書き換えてしまう場合でも、デフォルト値
(see section モード行の中で使用されている変数)で使用されている変数を、その内容を複製した
り別の方法で表示したりせずに、そのまま新しい値の中でも使用するべきです。
ユーザやLispプログラム(display-timeや主モードなど)に
よるモード行の表示に関するカスタマイズの多くは、それらの変数の値の変
更によりなされるからです。
以下は、ホスト名と現在のディレクトリをモード行に表示する
mode-line-formatの例です。shell-modeでは便利かも知れません。
(setq mode-line-format
(list ""
'mode-line-modified
"%b--"
(getenv "HOST") ; One element is not constant.
":"
'default-directory
" "
'global-mode-string
" %[("
'mode-name
'mode-line-process
'minor-mode-alist
"%n"
")%]----"
'(line-number-mode "L%l--")
'(-3 . "%p")
"-%-"))
この節では、モード行のテキスト表示のために、mode-line-format
内で標準的に使用されている変数について説明します。これらの変数は先天的に
特殊なものではなく、ほかのいかなる変数も、mode-line-formatがそれら
を使用するように変更されれば、モード行において同様の効果をもつことが
できます。
mode-line-modifiedのデフォルト値は("--%1*%1+-")です。こ
れは、バッファが変更されているときは`--**-'、バッファが変更されてい
ないときは`-----'、バッファが読出し専用のときは`--%%-'、バッ
ファが読出し専用でなおかつ変更されているときは`--%*-'を、モード行
に表示することを意味します。
この変数を変更しても、モード行の強制的なアップデートは起こりません。
("%F: %17b")で、`Emacs:'に
続けてスペース1文字、17文字のバッファ名を表示することを意味します(端末フ
レームでは、`Emacs'の代わりにフレーム名(`Emacs-' + フレーム番号)
を表示します(訳注: GNU Emacsバージョン19.29から、テキスト端末でも複数の
フレームをもつことができるようになった))。Rmailなどのように通常のEmacsと
は違う振舞をするモードでは、この変数の値を変更したくなるかも知れません。
display-timeは、時刻とロード情報を保持する
display-time-string変数を参照するように、この
global-mode-stringを設定します。
`%M'はglobal-mode-stringの値で置き換わります。しかし、これは
obsoleteです。代わりに、モード行内でglobal-mode-string変数を直接
使用することができます。
minor-mode-alistの要素は、
それぞれ、二つの要素からなる以下のようなリストです。
(minor-mode-variable mode-line-string)
さらに一般的に、mode-line-stringは、どのようなモード行構成要素であっ
ても構いません。この値は、minor-mode-variableの値が非nilの
とき表示され、そうでないときは表示されません。これらの文字列は、互いにくっ
つかないよう、スペースで始まるようにしてください。慣習的に、副モードがア
クティブになったときに、そのモードに対応するminor-mode-variableが非
nilにセットされます。
minor-mode-alistのデフォルト値は、以下のようになっています。
minor-mode-alist
=> ((vc-mode vc-mode)
(abbrev-mode " Abbrev")
(overwrite-mode overwrite-mode)
(auto-fill-function " Fill")
(defining-kbd-macro " Def")
(isearch-mode isearch-mode))
minor-mode-alistは、バッファローカルではありません。この連想リス
トの中に現れる変数は、もしそれに対応する副モードがバッファごとに有効にで
きるものなら、バッファローカルでなければなりません。
(": %s")なら、
`(Shell: run)'のように表示されます。通常、この変数はnilで
す。
mode-line-formatを特に設定しないモードのためのデフォ
ルト値を保持します。これは(default-value 'mode-line-format)と同
じです。
default-mode-line-formatのデフォルト値は、以下のようになっています。
(""
mode-line-modified
mode-line-buffer-identification
" "
global-mode-string
" %[("
mode-name
mode-line-process
minor-mode-alist
"%n"
")%]----"
(line-number-mode "L%l--")
(-3 . "%p")
"-%-")
vc-modeは、バッファに読み込まれ
たファイルがバージョン・コントロールされているか、されているのならその種
類は何か、を表します。この値がnilなら、バージョン・コントロールされ
ていないことを表します。また、それ以外なら、バージョン・コントロールされて
おり、モード行に表示される文字列を表します。
%-指定子
使用可能な%-指定子とその意味を、以下に示します。`%%'
以外の全ての%-指定子において、表示する文字数を表す十進数を、
`%'の後ろにつけることができます。
%b
buffer-name関数の値と同一。See section バッファの名前。
%f
buffer-file-name関数の値と同
一。See section バッファ・ファイル名。
%F
%c
%l
%*
buffer-read-onlyを参照)、buffer-modified-pを参照)、%+
buffer-modified-pを参照)、buffer-read-onlyを参照)、%&
%s
process-statusの値と同一。See section プロセス情報。
%t
%p
%P
%n
narrow-to-regionを参照してください)。
%[
%]
%%
%-指定子を使用可能な場所に、文字`%'そのもの
を含むことができる。
%-
以下の二つの%-指定子は現在でも使えますが、obsoleteです。変数
mode-nameとglobal-mode-stringを使用して同じ結果を得るこ
とができます。
%m
mode-nameの値。
%M
global-mode-stringの値。現在では、display-timeのみが
global-mode-stringの値を変更します。
フック(hook)は、既存のプログラムから呼び出される関数を、ユーザそれ ぞれの事情により収めておくことのできる変数です。Emacsでは、カスタマイズ の目的でフックの仕組みを用意しています。フックは`.emacs'ファイルの 中で設定されることが多いのですが、それ以外のLispプログラムによるフックの 設定も可能です。標準的なフック変数の一覧についてはSee section 標準のフック。
Emacsにおけるフックのほとんどは正規フック(normal hook)です。こ れらのフック変数は、引数なしで呼び出される関数のリストを持ちます。ほとん どのフックが正規フックである理由は、一律な扱いが可能だからです。正規フッ クの名前は、必ず`-hook'で終えることが慣例になっています。
正規フックにフック関数を追加するお奨めの方法は、add-hookを呼ぶ
ことです(後述します)。フック関数は、funcallが受けつけるものであれ
ばどのような関数であっても構いません(see section 関数とは)。ほとん
どのフック変数の初期値はvoidですが、add-hookはこのような変数にも
正常にフック関数を追加することができます。
もう一種類のフックである非正規フック(abnormal hook)には、名前が `-function'で終るものと`-hooks'で終わるものとがあります。名前 が`-function'で終わる非正規フックは、一つの関数を値として持ちます。 また、名前が`-hooks'で終る非正規フックは、関数のリストを値として持 ちます。非正規フックは、正規フックでは不可能な場合(たとえば関数が引数を 取ったり、あるいは関数の値に意味があったりする場合)に使用されるという点 で普通ではありません。名前が`-function'や`-hooks'で終るフック を使おうとするときは、それが非正規フックであることを思い出し、そのフックの 説明文字列で正しい使用方法を調べるようにしてください。
主モード関数は、その初期化処理の最後に、モード・フック(mode
hook)と呼ばれるフックを実行することが慣例になっています。これによりユー
ザは、モードにより設定されたローカル変数を書き換えてモードの振舞をカスタ
マイズすることができます。また、フックはほかの状況でも使われます。たとえ
ば、Emacsがサスペンドする直前に実行されるsuspend-hookというフック
があります(see section Emacsのサスペンド)。
以下は、Lisp InteractionモードでAuto Fillモードを起動するためにモード・ フックを使う例です。
(add-hook 'lisp-interaction-mode-hook 'turn-on-auto-fill)
以下は、EmacsがCのコードを字下げする方法をカスタマイズするフックの 例です(人によってコーディング・スタイルの好みはさまざまですよね)。この例 では、名前のないラムダ式をフック関数として使用しています。
(add-hook 'c-mode-hook
(function (lambda ()
(setq c-indent-level 4
c-argdecl-indent 0
c-label-offset -4
c-continued-statement-indent 0
c-brace-offset 0
comment-column 40))))
(setq c++-mode-hook c-mode-hook)
フックの実行にはrun-hooks関数が使用されます。この関数は
add-hooksで追加されたフック関数を呼び出します。
フック変数の値が非nilである場合、その値は関数のリストまたは
関数でなければなりません。値が関数(関数定義を示すシンボ
ルまたはラムダ式)ならそれが呼ばれます。値がリストなら、それぞれの要素が
順に呼ばれます。いずれの場合も、フック関数の呼出しは引数なしで行なわれ
ます。
たとえば、emacs-lisp-modeのモード・フックを実行するには以下のようにします。
(run-hooks 'emacs-lisp-mode-hook)
この関数は、関数functionをフック変数hookに追加します。引 数functionは、Lisp関数として有効で正しい数の引数を取るならど のような関数でも構いません。たとえば、
(add-hook 'text-mode-hook 'my-text-hook-function)
は、my-text-hook-functionをtext-mode-hookというフックに
追加します。
add-hookは正規フックと同様に、非正規フックにも使用できます。
フック関数は、実行順序に関わらず問題なく動くように作るのが一番です。順序
に依存するのはトラブルの元になります。もっとも、通常、functionはフッ
ク・リストの先頭に追加されるので、さらにadd-hookが呼ばれないかぎ
り最初に実行されると予想できます。
オプショナル引数のappendが非nilなら、新しいフック関数
はフック・リストの最後に追加され、実行も最後になされます。
もしlocalが非nilなら、フック関数をカレント・バッファにロー
カルにします。ただし、make-local-hook
(make-local-variableではありません)を呼ぶことにより、フッ
ク変数がバッファローカルにされていなければなりません。もしフックがバッファ
ローカルでなければ、フック関数はlocalの値に関わらず常にグローバル
になります。
この関数は、フック変数hookからfunctionを取り除きます。
もしlocalが非nilなら、グローバル・フック・リストからではな
く、ローカル・フック・リストからfunctionを取り除きます。フック変数
がバッファローカルでなければ、localの値は意味を持ちません。
この関数は、フック変数hookをカレント・バッファにローカルにします。
ローカルなフック変数は、ローカルなフック関数とグローバルなフック関数とを
もつことができ、また、run-hooksはその両方を実行します。
この関数は、フック変数のローカルな値として、tを要素として含むリス
トを設定します。このtは、フック変数のローカルな値とともにグローバ
ルな値にもフック関数が収められていることを示すフラグとして働きます。
run-hooksはこのフラグの意味を理解できるので、
make-local-hookはすべての正規フックに対して使用できます。非正規フッ
クに関しては、呼出し元がtの意味を理解できるように対策済みの一部の
ものに対してのみ使用できます。
make-local-variableだけではフック変数をローカルにすることはできま
せん。フック変数に対して直接make-local-variableを使用しないでくだ
さい。
Go to the first, previous, next, last section, table of contents.