GNU Emacs Lispには、便利なオンラインのヘルプ機能があります。 そのほとんどは、関数や変数に付随した説明文字列から取り出したものです。 本章では、説明文を参照するプログラムの書き方に加えて、 読者のLispプログラムに適切な説明文字列を書く方法を説明します。
Emacsの説明文字列は、Emacsマニュアルと同じものではないことに注意願います。 マニュアルには言語texinfoで書いた独自のソースファイルがありますが、 説明文字列は関数や変数の定義の中で指定されています。 説明文字列を集めても、よいマニュアルとは構成が違いますので、 マニュアルとしては十分ではありません。
説明文字列は、文字列に対するLisp構文、 つまり、文字列のテキストをダブルクォートで囲って書きます。 これは、説明文字列が実際にはLispの文字列オブジェクトだからです。 関数や変数の定義の正しい箇所に文字列を書くと、 説明文としての役割を果たします。 関数定義においては、説明文字列は引数のつぎにあります。 変数定義においては、変数の初期値のつぎにあります。
説明文字列を書くときには、
最初の1行は1つの(あるいは2つの)完全な文にしてください。
aproposなどのある種のコマンドは、
複数行にまたがる説明文字列の最初の1行だけを表示するからです。
また、説明文字列の2行目以降を字下げしないでください。
字下げがあると、
C-h f(describe-function)や
C-h v(describe-variable)で説明文字列を表示すると
不恰好になります。
See section 説明文字列に関するヒント。
説明文字列には、特別な部分文字列、つまり、 説明文を表示するときに現在のキーマップからキーバインディングを探す ことを表すものがあります。 これにより、ユーザーがキーバインディングを変更していても 説明文字列から関連するコマンドのキーを参照できます。 (see section 説明文字列の参照)。
Emacs Lispでは、説明文字列はその説明対象である関数や変数を介して参照します。
documentationがその取り出し方を知っている。
variable-documentationで収められている。
関数documentation-propertyがその取り出し方を知っている。
場所を節約するために、あらかじめロード済みの関数や変数 (基本関数や自動ロード対象の関数を含む)に対する説明文は、 Emacs本体にではなく、ファイル`emacs/etc/DOC-version'に 収めてあります。 Emacsセッションの最中にバイトコンパイル済みのファイルから ロードされる関数や変数の説明文字列は、当該ファイルに収めてあります (see section 説明文字列とコンパイル)。
Emacs内部のデータ構造では、説明文字列のかわりに、
ファイル内の位置を表す整数かファイル名と整数を含むリストで表します。
関数documentationやdocumentation-propertyは、
この情報を用いて適切なファイルから説明文字列を取り出します。
この処理はユーザーには見えません。
説明文字列の利用に関する情報は、 section `ヘルプ機能' in GNU Emacs マニュアルを参照してください。
ディレクトリ`emacs/lib-src'には、 ファイル`emacs/etc/DOC-version'を美しく印刷するための コマンドが2つあります。 `sorted-doc'と`digest-doc'です。
substitute-command-keysを実行する。
(verbatimがnil以外であると、置換を行わない。)
(documentation-property 'command-line-processed
'variable-documentation)
=> "Non-nil once command line has been processed"
(symbol-plist 'command-line-processed)
=> (variable-documentation 188902)
nilならば)
実際の(現在の)キーバインディングを含んだ値を返すために
substitute-command-keysを実行する。
関数documentationは、functionに関数定義がないと
エラーvoid-functionを通知する。
しかし、関数定義に説明文字列がなくてもエラーではない。
その場合、documentationはnilを返す。
2つの関数documentationとdocumentation-propertyを用いて、
数個のシンボルの説明文字列をバッファ`*Help*'に表示する例を示します。
(defun describe-symbols (pattern)
"Describe the Emacs Lisp symbols matching PATTERN.
All symbols that have PATTERN in their name are described
in the `*Help*' buffer."
(interactive "sDescribe symbols matching: ")
(let ((describe-func
(function
(lambda (s)
;; Print description of symbol.
(if (fboundp s) ; これは関数
(princ
(format "%s\t%s\n%s\n\n" s
(if (commandp s)
(let ((keys (where-is-internal s)))
(if keys
(concat
"Keys: "
(mapconcat 'key-description
keys " "))
"Keys: none"))
"Function")
(or (documentation s)
"not documented"))))
(if (boundp s) ; これは変数
(princ
(format "%s\t%s\n%s\n\n" s
(if (user-variable-p s)
"Option " "Variable")
(or (documentation-property
s 'variable-documentation)
"not documented")))))))
sym-list)
;; パターンに一致するシンボルのリストを作る
(mapatoms (function
(lambda (sym)
(if (string-match pattern (symbol-name sym))
(setq sym-list (cons sym sym-list))))))
;; データを表示する
(with-output-to-temp-buffer "*Help*"
(mapcar describe-func (sort sym-list 'string<))
(print-help-return-message))))
関数describe-symbolsはaproposのように動作しますが、
より多くの情報を提供します。
(describe-symbols "goal") ---------- Buffer: *Help* ---------- goal-column Option *Semipermanent goal column for vertical motion, as set by ... set-goal-column Keys: C-x C-n Set the current horizontal position as a goal for C-n and C-p. Those commands will move to this position in the line moved to rather than trying to keep the same horizontal position. With a non-nil argument, clears out the goal column so that C-n and C-p resume vertical motion. The goal column is stored in the variable `goal-column'. temporary-goal-column Variable Current goal column for vertical motion. It is the column where point was at the start of current run of vertical motion commands. When the `track-eol' feature is doing its job, the value is 9999. ---------- Buffer: *Help* ----------
Emacsはファイルfilenameをディレクトリ`emacs/etc'から読む。
ダンプしたEmacsをのちに実行すると、
同じファイルをディレクトリdoc-directoryで探す。
通常、filenameは"DOC-version"である。
"DOC-version"を置いた
ディレクトリの名前を保持する。
ほとんどの場合、これはdata-directoryと同じである。
Emacsをインストールせずに構築したディレクトリから起動すると、
それらは異なることがある。
section ヘルプ機能のdata-directoryを参照。
Emacsの古い版では、この目的にはexec-directoryを用いていた。
説明文字列からキー列を参照するときには、
現在の活性なキーバインディングを使うべきです。
これは以下に述べる特別なテキスト列でできます。
普通の方法で説明文字列を参照すると、
これらの特別な列は現在のキーバインディング情報で置き換えられます。
置き換えはsubstitute-command-keysを呼び出して行います。
読者自身がこの関数を使うこともできます。
特別な列とその意味を以下にあげます。
\[command]
\{mapvar}
describe-bindingsを使って作成する。
\<mapvar>
\=
注意:
Emacs Lispでは、文字列内の`\'は、2つ続けて書くこと。
特別な列の例を示します。
(substitute-command-keys
"To abort recursive edit, type: \\[abort-recursive-edit]")
=> "To abort recursive edit, type: C-]"
(substitute-command-keys
"The keys that are defined for the minibuffer here are:
\\{minibuffer-local-must-match-map}")
=> "The keys that are defined for the minibuffer here are:
? minibuffer-completion-help
SPC minibuffer-complete-word
TAB minibuffer-complete
C-j minibuffer-complete-and-exit
RET minibuffer-complete-and-exit
C-g abort-recursive-edit
"
(substitute-command-keys
"To abort a recursive edit from the minibuffer, type\
\\<minibuffer-local-must-match-map>\\[abort-recursive-edit].")
=> "To abort a recursive edit from the minibuffer, type C-g."
これらの関数は、イベント、キー列、文字をテキスト表記に変換します。 これらの表記は、メッセージに文字やキー列をテキストとして含めるのに有用です。 というのは、非印字文字や白文字を印字文字の列に変換するからです。 白文字でない印字文字は文字そのもので表記します。
single-key-descriptionの例を参照。
(single-key-description ?\C-x)
=> "C-x"
(key-description "\C-x \M-y \n \t \r \f123")
=> "C-x SPC M-y SPC C-j SPC TAB SPC RET SPC C-l 1 2 3"
(single-key-description 'C-mouse-1)
=> "C-mouse-1"
single-key-descriptionに似ているが、
コントロール文字は、始めにカレットを付けて表現する点が異なる
(Emacsのバッファでは、コントロールは普通このように表示される)。
(text-char-description ?\C-c)
=> "^C"
(text-char-description ?\M-m)
=> "M-m"
(text-char-description ?\C-\M-m)
=> "M-^M"
key-descriptionに対するおおまかな逆変換にも使える。
空白で区切ったキーの表記を収めた文字列で、この関数を呼び出す。
対応するイベントを収めた文字列かベクトルを返す。
(指定したイベントに依存して、正しい単一のキー列であったりなかったりする。
see section キーマップの用語。)
Emacsにはさまざまオンラインヘルプ関数があり、 それらはすべてプレフィックスC-hのサブコマンドとして使えます。 それらについて詳しくは、 section `ヘルプ機能' in GNU Emacs マニュアルを参照してください。 ここでは、同じ情報を得るプログラムレベルのインターフェイスを説明します。
do-allがnil以外であると、
aproposは、みつけた関数に対するキーバインディングも表示する。
さらに、関数や変数以外も含めてすべてのシンボルを表示する。
つぎの例では、aproposは、
`exec'を名前に含むすべてのシンボルを探しだす。
(ここではバッファ`*Help*'の表示は示さない。)
(apropos "exec")
=> (Buffer-menu-execute command-execute exec-directory
exec-path execute-extended-command execute-kbd-macro
executing-kbd-macro executing-macro)
help-mapとして知られるキーマップを保持している。
`help.el'での定義はつぎのとおりである。
(define-key global-map "\C-h" 'help-command) (fset 'help-command help-map)
nil以外であれば、
メッセージをfunctionに適用する。
さもなければ、メッセージをエコー領域に表示するためにmessageを呼び出す。
この関数は、スペシャルフォームwith-output-to-temp-bufferの
中から呼び出され、しかも、
当該スペシャルフォームでstandard-outputに値が束縛されているものと
仮定する。
使用例については、section 説明文字列の参照の長い例を参照。
help-formがnil以外のLisp式であると、
Emacsがこの文字を読み取るとその式を評価し、
その結果が文字列であれば結果をウィンドウに表示する。
通常、help-formの値はnilである。
そうすると、ヘルプ文字にはコマンド入力のレベルでは特別な意味はなく、
普通の意味でのキー列の一部になる。
C-hの標準のキーバインディングは、
いくつかの汎用目的のヘルプ機能向けのプレフィックスキーである。
ヘルプ文字は、プレフィックスキーのうしろでも特別である。
プレフィックスのサブコマンドとしてのバインディングがないと、
プレフィックスキーのすべてのサブコマンドの一覧を表示する
describe-prefix-bindingsを実行する。
help-charで指定されたイベントと
まったく同様に扱われる。
nil以外であると、その値は、
help-charを読むたびに評価すべきフォームである。
フォームを評価すると文字列を生成すれば、その文字列が表示される。
read-eventやread-charを呼ぶコマンドは、
入力中にはhelp-formをnil以外に(たぶん)束縛すべきである。
(C-hに別の意味がある場合には、こうしないこと。)
この式の評価結果は、なんのための入力でどのように入力すべきかを
説明する文字列であること。
ミニバッファに入ると、この変数はminibuffer-help-form
(see section ミニバッファに関するその他)の値に束縛される。
describe-prefix-bindingsである。
describe-bindingsを呼び出す。
プレフィックスの説明には、当該キー列の最後のイベント以外のすべてが含まれる。
(最後のイベントはヘルプ文字であると仮定する。)
つぎの2つの関数は、『エレクトリック』モードのように 制御を放棄せずにヘルプを提供したいモードのためです。 それらの名前は、普通のヘルプ関数と区別するために`Helper'で始まります。
describe-bindingsを呼び出すことで動作する。
nilを返す。
このコマンドは、キーマップHelper-help-mapを
変更することでカスタマイズできる。
exec-directoryを用いていた。
起動されると、fnameはウィンドウにhelp-textを表示し、 help-mapに従ってキー列を読み実行する。 文字列help-textは、help-mapが提供する バインディングを記述するべきである。
コマンドfnameは、help-textの表示をスクロールすることで、 それ自身では少数のイベントを扱うように定義される。 fnameがそれらの特殊イベントの1つを読み取ると、 スクロールしてつぎのイベントを読み取る。 読み取ったイベントが、扱えるものでなく、 help-mapにバインディングがあれば、 当該キーのバインディングを実行して戻る。
help-lineは、help-map内の選択項目を1行にまとめたものであること。
Emacsの現在の版では、この引数はオプションthree-step-helpをtに
設定してある場合にのみ使われる。
このマクロは、C-h C-hのバインディングである
コマンドhelp-for-helpで使われている。
nil以外であると、
make-help-screenで定義されたコマンドは、
まず文字列help-lineをエコー領域に表示し、
ユーザーがヘルプ文字を再度打った場合にのみより長い文字列を表示する。
Go to the first, previous, next, last section, table of contents.