Previous: , Up: Minor Modes   [Contents][Index]


22.3.3 マイナーモードの定義

マクロdefine-minor-modeは、自己完結した単一定義内にモードを実装する便利な方法を提供します。

Macro: define-minor-mode mode doc [init-value [lighter [keymap]]] keyword-args… body…

このマクロは名前がmode(シンボル)の新たなマイナーモードを定義する。これはドキュメント文字列としてdocをもつマイナーモードをトグルするためにmodeという名前のコマンドを定義する。

トグルコマンドは1つのオプション(プレフィクス)引数を受け取る。引数なしでinteractiveに呼び出されると、そのモードのオンとオフをトグルする。正のプレフィクス引数はモードを有効にして、それ以外のプレフィクス引数はモードを無効にする。Lispから呼び出すと引数がtoggleならモードをトグルして、引数が省略かnilならモードを有効にする。これはたとえばメジャーモードフック内でマイナーモードを有効にするのを簡便にする。docnilなら、このマクロは上記を記述したデフォルトのドキュメント文字列を提供する。

デフォルトではこれはモードを有効にするとt、無効にするとnilにセットされる、modeという名前の変数も定義する。この変数はinit-valueに初期化される。通常(以下参照)はこの値はnilでなければならない。

文字列lighterはモード有効時にモードライン内に何を表示するか指定する。これがnilならこのモードはモードライン内に表示されない。

オプション引数keymapはそのマイナーモードにたいするキーマップを指定する。非nilなら、それは(値がキーマップであるような)変数の名前かキーマップ、または以下の形式のalistであること

(key-sequence . definition)

ここでkey-sequencedefinitiondefine-keyに渡すのに適した引数である(Changing Key Bindingsを参照)。keymapはキーマップかalistであり、これは変数mode-mapも定義する。

上記の3つの引数init-valuelighterkeymapkeyword-argsが使用されたときは(部分的に)省略できる。keyword-argsはキーワードとその後の対応する値により構成され、いくつかのキーワードは特別な意味をもつ:

:group group

生成されるすべてのdefcustomフォームで使用されるカスタムグループ名。mode (後に‘-mode’がある場合はそれを除く)にたいするデフォルトである。警告: そのグループを定義するためdefgroupを正しく記述していなければ、このデフォルトグループ名を使用してはならない。Group Definitionsを参照のこと。

:global global

nilならそのマイナーモードがバッファーローカルでなくグローバルであることを指定する。デフォルトはnil

マイナーモードをグローバルにしたときの効果の1つは、mode変数がカスタマイズ変数になることである。Customizeインターフェイスを通じてこの変数をトグルするとモードがオンやオフになり、変数の値は将来のEmacsセッション用に保存できるようになる(Saving Customizations in The GNU Emacs Manualを参照)。保存された変数が機能するためにはEmacsが開始されるたびにdefine-minor-modeフォームが確実に評価されるようにすること。Emacsの一部ではないパッケージにたいしては、:requireキーワードを指定するのがこれを行う一番簡単な方法である。

:init-value init-value

これはinit-value引数を指定するのと等しい。

:lighter lighter

これはlighter引数を指定するのと等しい。

:keymap keymap

これはkeymap引数を指定するのと等しい。

:variable place

これはそのモードの状態を格納するために使用されるデフォルトの変数modeを置き換える。これを指定するとmode変数は定義されず、すべてのinit-value引数は使用されない。placeは異なる名前の変数(あなた自身が定義しなければならない)、またはsetf関数とともに使用され得るすべてのもの(Generalized Variablesを参照)。placeにはコンス(get . set)も指定できる。ここでgetはカレント状態をリターンする式であり、setはそれをセットする1つの引数(状態)をとる関数である。

:after-hook after-hook

これはモードフック実行後に評価される単一のLispフォームを定義する。これをクォートしないこと。

その他のすべてのキーワード引数は変数modeにたいして生成されたdefcustomに直接渡される。

modeという名前のコマンドは最初にmodeという名前の変数をセットする等の標準的な動作を処理した後に、もしあればbodyフォームを実行する。それからモードフック変数mode-hookを実行してから:after-hook内のフォームを評価して終了する。

init-valueの値はnilでなければなりません。ただし、(1)Emacsによりそのモードが事前ロードされている、または(2)たとえユーザーが要求しなくともモードを有効にするためにロードするのが容易な場合を除きます。たとえば他の何かが有効でなければそのモードの効果がなく、常にそのタイミングでロードされるような場合には、デフォルトでそのモードを有効にすることに害はありません。しかしこの状況は通常はあり得ません。通常はinit-valueの値はnilでなければなりません。

easy-mmode-define-minor-modeという名前はこのマクロにたいするエイリアスです。

以下はdefine-minor-modeの使い方の例です:

(define-minor-mode hungry-mode
  "Hungryモードをトグルする
引数なしでinteractiveに呼び出すとモードをトグルする
正のプレフィクス引数でモードを有効に、その他のプレフィクス引数で
無効にする。Lispから呼び出す場合、引数を省略、またはnilなら
モードを有効に、`toggle'なら状態をトグルする

Hungryモードが有効なときは、C-DELキーは、
最後を除く先行するすべての空白を飲み込む
コマンド \\[hungry-electric-delete] を参照"
 ;; 初期値
 nil
 ;; モードラインの標示
 " Hungry"
 ;; マイナーモードのバインディング
 '(([C-backspace] . hungry-electric-delete))
 :group 'hunger)

これは“Hungry mode”という名前のマイナーモード、モードをトグルするhungry-modeという名前のコマンド、モードが有効かどうかを示すhungry-modeという名前の変数、モードが有効なときそのキーマップを保持するhungry-mode-mapという名前の変数を定義します。これはC-DELにたいするキーバインディングでキーマップを初期化します。また変数hungry-modeをカスタムグループhungerに配置します。bodyフォームはありません — 多くのマイナーモードはそれを必要としません。

以下はこれを記述する等価な方法です:

(define-minor-mode hungry-mode
  "Hungryモードをトグルする
...省略..."
 ;; 初期値
 :init-value nil
 ;; モードラインへのインジケーター
 :lighter " Hungry"
 ;; マイナーモードのバインディング
 :keymap
 '(([C-backspace] . hungry-electric-delete)
   ([C-M-backspace]
    . (lambda ()
        (interactive)
        (hungry-electric-delete t))))
 :group 'hunger)
Macro: define-globalized-minor-mode global-mode mode turn-on keyword-args…

これはglobal-modeという名前をグローバルにトグルする。これはmodeという名前のバッファーローカルなマイナーモードをすべてのバッファーで有効か無効にするということを意味する。あるバッファー内でそのマイナーモードをオンにするには関数turn-onを使用する。マイナーモードをオフにするには-1を引数としてmodeを呼び出す。

モードをグローバルに有効にすると、それ以降ファイルをvisitすることによって作成されるバッファーやFundamental以外のメジャーモードを使用するバッファーにも影響がある。しかしFundamentalで作成される新たなバッファーは検知しない。

これはCustomizeインターフェイス内でそのマイナーモードのオン/オフを切り替えるカスタムオプションglobal-mode (Customization)を定義する。define-minor-modeと同様に、たとえば:requireを与える等によってEmacs開始時に毎回確実にdefine-globalized-minor-modeフォームが評価されるようにすること。

グローバルマイナーモードのモード変数にたいしてカスタムグループを指定するにはkeyword-args内で:group groupを使用する。

一般的にはグローバル化されたマイナーモードを定義するときは、ユーザーがバッファーごとにモードを使用(または無効に)できるように非グローバル版も定義すること。これにより特定のメジャーモード内でそのモードのフックを使用すればグローバルに有効化されたマイナーモードを無効にすることができるようになる。