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


22.3.3 Defining Minor Modes

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

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-sequencedefinitionは、define-keyに渡すのに適した引数である(Changing Key Bindingsを参照)。keymapはキーマップまたはalistであり、これは変数mode-mapも定義する。

上記の3つの引数init-valuelighterkeymapは、keyword-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を使用する。

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