[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13. ロード

Lispコードのファイルをロードするとは、その内容をLisp環境に Lispオブジェクトの形式で持ち込むことを意味します。Emacsはそのファイルを 見つけて開き、テキストを読み込み、各形式を評価し、その後ファイルを閉じます。

ロード関数群は、eval-current-buffer関数がバッファ内の全ての式を 評価するのと同じように、ファイル内の全ての式を評価します。違いは、 ロード関数群が読み込んで評価するのは、ディスク上にあるファイル中の テキストであり、Emacsバッファ内のテキストではないことです。

ロードされたファイルは、ソース・コードかバイトコンパイル・コードかの いずれかの形のLisp式を含ねばなりません。ファイル中の各形式は、 トップレベルの形式(top-level form)と呼ばれます。ロード可能な ファイル中の形式に特別なフォーマットは存在しません。ファイル中のどの形式も、 同じように、直接バッファにタイプしてそこで評価ができます(実際、 ほとんどのコードはこの方法で検査されます)。ほとんどの場合、それらの形式は 関数定義と変数定義です。

Lispコードを含むファイルはしばしばライブラリ(library)と呼ばれます。 それゆえ、「Rmailライブラリ」はRmailモードのためのコードを含むファイル であるといえます。 同様に、「Lispライブラリ・ディレクトリ」は、Lispコードを含むファイルの ディレクトリであるといえます。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.1 プログラムでロードする方法

Emacs Lispにはロードのためのインタフェースがいくつかあります。 たとえば、autoloadはあるファイル中の関数のために、名札オブジェクトを 作成します。自動ロード関数を呼び出そうとすると、その関数の実際の定義を 得るために、そのファイルがロードされます(see section 自動ロード)。requireは そのファイルがまだロードされてないならば、ロードします (see section 機能)。 結局、これらの機能全てはload関数を呼び出してその作業を行ないます。

Function: load filename &optional missing-ok nomessage nosuffix

この関数は、Lispコード・ファイルを見つけて開き、ファイル中の全ての形式を 評価し、ファイルを閉じます。

ファイルを見つけるのに、loadは最初に`filename.elc'という 名前のファイルを探します。つまり、filename`.elc'を追加した 名前のファイルを探します。その名前のファイルがあれば、それがロードされます。 その名前のファイルがないならば、load`filename.el'という 名前のファイルを探します。そのファイルがあれば、それがロードされます。 最後に、これらいずれの名前も見つからなかった場合に、loadfilenameに何もつけない名前のファイルを探し、あればそれをロードします (load関数のfilenameの探し方は、そんなに賢くありません。 `foo.el.el'という意地悪な名前のファイルがあるときに、 (load "foo.el")を評価すると、まさにこれを見つけてしまいます)。

オプション引数nosuffixが非nilならば、 接尾辞`.elc'`.el'は試しません。この場合は、 欲しいファイル名を正確に指定する必要があります。

filenameが、たとえば`foo'`baz/foo.bar'のように 相対ファイル名ならば、loadは変数load-pathを使って そのファイルを探します。load-pathのリストの各ディレクトリに filenameを追加して、名前が一致した最初のファイルをロードします。 現在のデフォルト・ディレクトリは、load-pathに指定されたときにかぎり 試されます。nilが現在のデフォルト・ディレクトリを表します。 loadは三つの接尾辞候補全てについて、load-pathの最初の ディレクトリで試し、次に2番目のディレクトリで試し、次のディレクトリで試し、 としていきます。

`foo.elc'`foo.el'よりも古いという警告を受け取ったなら、 `foo.el'のリコンパイルを考えるべきでです。See section バイトコンパイル

nomessagenilならば、ロード中、 `Loading foo...'`Loading foo...done'といったメッセージが エコー領域に現れます。

ファイル・ロード中にハンドルされないエラーが起こると、ロードは打ち切られます。 ロードがautoloadのためになされたものであった場合、 そのロード中に行なわれた関数定義はいずれも取り消されます。

loadがロードすべきファイルを見つけられなかった場合、 file-errorエラーを(`Cannot open load file filename'とともに) 通知するのが普通です。しかし、missing-okが非nilならば、 loadは単にnilを返します。

変数load-read-functionを使ってloadが式を読み込むために readの代わりに使う関数を指定することもできます。 以下を参照してください。

loadはファイルのロードが成功した場合、tを返します。

User Option: load-path

この変数の値は、loadでファイルをロードするときに検索を行なう ディレクトリのリストです。各要素は文字列(ディレクトリ名であること)あるいは nil(現在の作業ディレクトリを表す)です。 load-pathの値は、環境変数EMACSLOADPATHが設定されていれば その値で初期化されます。さもなくば、Emacs構築時に`emacs/src/paths.h'で 指定したデフォルト値になります。

EMACSLOADPATHの構文は、PATHに使うものと同じです。 `:'(オペレーティング・システムによっては`;')で ディレクトリ名を分離し、`.'を現在のデフォルト・ディレクトリに使用します。 EMACSLOADPATH変数をcsh`.login'ファイルで 設定する例を挙げます:

 
setenv EMACSLOADPATH .:/user/bil/emacs:/usr/lib/emacs/lisp

shで設定する方法を挙げます:

 
export EMACSLOADPATH
EMACSLOADPATH=.:/user/bil/emacs:/usr/local/lib/emacs/lisp

`.emacs'ファイルで、デフォルトのload-pathの前に ディレクトリをいくつか追加するコードを挙げます:

 
(setq load-path
      (append (list nil "/user/bil/emacs"
                    "/usr/local/lisplib"
                    "~/emacs")
              load-path))

本例では、パスは現在の作業ディレクトリを最初に、 続いて`/user/bil/emacs'ディレクトリで、 次に`/usr/local/lisplib'ディレクトリで、 次に個人の`~/emacs'ディレクトリで、 それらの後でLispコードの標準ディレクトリを探します。

コマンド行オプション`-l'あるいは`-load'で、Emacs起動の一部として ロードするLispライブラリを指定します。 このファイルは現在のディレクトリにあるかもしれないので、Emacs 18は一時的に 現在のディレクトリをload-pathの前に追加して、 そのファイルを見つけられるようにしていました。新しいEmacsの版では、 load-pathを変更せずに、こういった現在のディレクトリのファイルも 見つけることができます。

Emacsのダンプでは、load-pathに特別な値を使用します。 ダンプ終了時点でload-pathの値が変更されない(即ち、同じ特殊な値のまま) ならば、ダンプされたEmacsは通常のload-pathの値に起動時に切替えます。 しかし、ダンプ終了時点でload-pathがそれ以外の値だったら、 その値がダンプされたEmacsの実行時にも使用されます。

そのため、`site-init.el'`site-load.el'内でいくつかのライブラリを ロードするために一時的にload-pathを変更したいならば、 load-pathload呼出し周辺でletによって、 ローカルに束縛しなければなりません。

Variable: load-in-progress

この変数は、Emacsがファイルのロード中ならば非nilで、 それ以外ならばnilとなります。

Variable: load-read-function

この変数は、loadeval-regionについて、 readの代わりに使用する代替式読込み関数を指定します。 関数は引数を一つ、readと全く同じように受け取らねばなりません。

通常この変数の値はnilで、ロード関数群がreadを使わなければならない ことを意味します。

loadがEmacs構築時にどのように使われるかについて知るには、 Emacsを作るを参照してください。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.2 自動ロード

自動ロード(autoload)機能によって、関数やマクロを、 Lisp内で既知ではあるが、それが定義されているファイルのロードは延期する、 ということができます。その関数への最初の呼出しで、適切なファイルを自動的に 読み込んで、実定義とほかの関連コードをインストールし、その後、実定義を あたかも元々からあったかのように実行します。

自動ロード関数を設定するには、二つの方法があります。autoloadを 呼ぶ方法と、特殊な「魔法」のコメントをソースの実定義の前に書く方法です。 自動ロードのためのautoloadは低水準のプリミティブですが、 任意のLispプログラムがautoloadを任意の時点で呼び出すことができます。 魔法のコメントは、それ自体は何もしません。しかしそれは、Emacs構築時に 実行されるようにautoload呼出しを構築し調整する、 コマンドupdate-file-autoloadsの案内役として働きます。 魔法のコメントは関数を自動ロード化する最も簡便な方法ですが、 Emacsとともにインストールされるパッケージにしか使えません。

Function: autoload function filename &optional docstring interactive type

この関数は、functionという名前の関数(あるいはマクロ)を、 filenameから自動的にロードするように定義します。 文字列filenamefunctionの実定義を取り出すためにロードする ファイルを指定します。

引数docstringはその関数の説明文字列です。通常、これは関数定義自身の 説明文字列と同じです。autoload呼出しで説明文字列を指定することで、 関数の実定義をロードしなくても説明文字列を見ることができるようになります。

interactiveが非nilならば、関数は対話的に呼び出すことができます。 これでその関数の実定義をロードしなくても、M-xの補完が働くようになります。 完全な対話引数の指定はここでは与えなくて構いません。 ユーザが実際にfunctionを呼び出すまで、引数は不要であり、 もし呼び出したなら、実定義をロードするまでです。

マクロやキーマップも普通の関数同様に自動ロードできます。 functionが実際はマクロならば、typemacroとして 指定してください。functionが実際はキーマップならば、 typekeymapとして指定してください。Emacsのさまざまな部分で、 実定義をロードせずにこの情報を知る必要があります。

自動ロード・キーマップは、キー検索の際に、 前置キーのバインドがシンボルfunctionであったならば、 自動的にロードします。それ以外の種類のキーマップへのアクセスでは、 自動ロードは起こりません。特に、Lispプログラムが変数の値からキーマップを 取り出し、define-keyを呼び出す時には、起こりません。 変数名がシンボルfunctionと同一であっても起こりません。

訳注: キーマップの指定の仕方の例。

 
;; (autoload 'hoge-prefix "hoge.el" "Hoge map" t 'keymap)
;; (local-set-key "\C-c\C-c" 'hoge-prefix)

;; contents of file hoge.el follows.
(defvar hoge-map nil)
(if hoge-map
    nil
  (setq hoge-map (make-keymap))
  (define-key hoge-map "\C-c"
    (lambda () (interactive) (message "hoge!"))))
(fset 'hoge-prefix hoge-map)

functionがすでに非voidな関数定義を持ち、 それが自動ロード・オブジェクトではない場合、autoloadは何もしないで nilを返します。functionの関数セルがvoidな場合、 あるいはそれがすでに自動ロード・オブジェクトならば、 このような自動ロード・オブジェクトとして定義されます:

 
(autoload filename docstring interactive type)

たとえば、

 
(symbol-function 'run-prolog)
     ⇒ (autoload "prolog" 169681 t nil)

この場合、"prolog"はロードするファイルの名前で、 169681は`emacs/etc/DOC'ファイル中の説明文字列を参照し (see section 説明文字列の基礎)、tは関数が対話的であることを意味し、 nilでそれがマクロでもキーマップでもないことを示します。

自動ロード・ファイルは普通ほかの定義も含み、一つ以上の機能を 要求/提供します。ファイルが完全にロードされなかった場合(その内容の評価で出た エラーのため)、ロード中に行なった、いかなる関数定義もprovideの呼出しも、 取り消されます。 こうして、このファイルから自動ロードされるどの関数でも次の呼出しでは、 ファイルのロードをやり直すことを保証します。もしこうなっていなかったならば、 ファイル中のいくつかの関数が、定義されたようには見えるかもしれないが、 ファイルの後ろの方にあったためにうまくロードされなかった サブルーチンの欠如により、それらは正しく動作しない、ということが起こり得ます。

自動ロードされたファイルが望みのLisp関数やマクロの定義に失敗すると、 "Autoloading failed to define function function-name"という データでエラーが通知されます。

魔法の自動ロード・コメントは、自動ロード可能なソース・ファイル中の 関数の実定義の直前に`;;;###autoload'のように行に単独で書きます。 コマンドM-x update-file-autoloadsは、対応するautoload呼出しを `loaddefs.el'に書き込みます。`loaddefs.el'はEmacsの構築中に ロードされるので、autoloadが呼び出されます。 これは現在のディレクトリ中の全てのファイルについて、自動ロードを更新します。

同じ魔法のコメントで任意の形式を`loaddefs.el'にコピーできます。 魔法のコメントに続く形式が関数定義でないならば、それはそのままコピーされます。 魔法のコメントを、そのファイルがロードされるときには実行せずに、 構築時に実行するという形式を作るために使うこともできます。 こうするには、形式を魔法のコメントと同じ行に書きます。 それはコメント中にあるので、ファイルをロードしたときには何もしません。 しかし、update-directory-autoloadsはそれを`loaddefs.el'に コピーするので、Emacs構築中に実行されます。

以下の例は、魔法のコメントでdoctorの自動ロードが どのように準備されるかを示します:

 
;;;###autoload
(defun doctor ()
  "Switch to *doctor* buffer and start giving psychotherapy."
  (interactive)
  (switch-to-buffer "*doctor*")
  (doctor-mode))

これが`loaddefs.el'に生成されます:

 
(autoload 'doctor "doctor"
  "\
Switch to *doctor* buffer and start giving psychotherapy."
  t)

二重引用符直後に続くバックスラッシュと改行は、`loaddefs.el'のように プリロードされるLispファイル中だけで使う、お決まりの手法です。 これによってmake-docfileに、この説明文字列は`etc/DOC'ファイルに 置くとのだということを示します。See section Emacsを作る


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.3 ロードの反復

1回のEmacsセッション中で、一つのファイルを複数回ロードしても構いません。 たとえば、バッファで編集して、関数定義を書き直して再インストールした後に、 元の版に戻りたいと思うかもしれません。 そうするには、その関数があったファイルを再ロードすればよいのです。

ファイルをロードあるいは再ロードするときは、loadload-library関数がコンパイルされてないファイルではなく、 類似の名前のバイトコンパイルされたファイルを自動的にロードするということを 覚えておいてください。保存して再インストールしたいと思ったファイルを 書き直した場合には、必要ならそれをバイトコンパイルしてください。 さもないと不注意にも古いバイトコンパイルされたファイルを、 新しいコンパイルされてないファイルの代わりに再ロードしてしまうかも知れません!

Lispライブラリ・ファイル中に形式を書く時は、そのファイルが複数回 ロードされるかもしれないことを念頭に置いてください。 たとえば、変数定義がdefvardefconstかというのは、 ライブラリが再ロードされたときにその変数を再初期化するのが望ましいか否かに 依存します。つまりdefconstは再初期化しますが、defvarは これを行ないません(See section グローバル変数の定義)。

要素をalistに追加する最も簡単な方法は、こうなります:

 
(setq minor-mode-alist
      (cons '(leif-mode " Leif") minor-mode-alist))

しかしこれではライブラリが再ロードされた場合、要素が重複して追加されます。 この問題を避けるには、次のように書きます:

 
(or (assq 'leif-mode minor-mode-alist)
    (setq minor-mode-alist
          (cons '(leif-mode " Leif") minor-mode-alist)))

リストに要素を重複せずに追加するには、add-to-listを使います。 (see section 変数の値を変更する方法)。

ライブラリがすでにロードされたか否かを明示的に検査したくなることも あるでしょう。ライブラリ中で、それが以前ロードされたか否かを検査する 一つの方法をここに示します:

 
(defvar foo-was-loaded)

(if (not (boundp 'foo-was-loaded))
    execute-first-time-only)

(setq foo-was-loaded t)

ライブラリがprovideを使って名前つき機能を提供しているならば、 featurepでそのライブラリがロードされたか否かを検査できます。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.4 機能

providerequireとはファイルを自動的にロードする autoloadの代わりになります。これらは、名前つき機能(feature)に 基づいて働きます。 自動ロードは特定の関数の呼出しによって起動されますが、機能はほかのプログラムが はじめてそれを名前で要求したときにロードされます。

機能名は関数や変数などをまとめたものを代表するシンボルです。 それらを定義するファイルはその機能を提供(provide)しなくてはならりません。 それらを使うほかのプログラムはその機能を要求(require)することで、 定義されていることを保証するかも知れません。要求した機能が まだロードされてなければ、定義ファイルをロードします。

機能が存在することを要求するには、機能名を引数としてrequireを 呼び出します。requireはグローバル変数featuresを覗いて、 望みの機能がすでに提供されているか調べます。 なければ、その機能を適切なファイルからロードします。ロードされるファイルは featuresにその機能を追加するために、provideをトップレベルで 呼び出す必要があります。それに失敗すると、requireはエラーを通知します。

機能は普通それを提供するファイルに因んで名づけられます。そうすると、 requireにファイル名を与える必要がなくなります。

たとえば、`emacs/lisp/prolog.el'においては、run-prologの 定義が次のコードを含みます:

 
(defun run-prolog ()
  "Run an inferior Prolog process, input and output via buffer *prolog*."
  (interactive)
  (require 'comint)
  (switch-to-buffer (make-comint "prolog" prolog-program-name))
  (inferior-prolog-mode))

(require 'comint)で、`comint.el'がまだロードされてなければ、 それをロードします。これによって、make-comintが定義されていることを 保証します。

`comint.el'は次のトップレベルの式を含んでいます。

 
(provide 'comint)

これはcomintをグローバルなfeaturesリストに追加し、 そうすることで(require 'comint)に、もう何もしなくてよいことを 知らせます。

requireをファイルのトップレベルで使うと、 ロードしたときと同様、そのファイルのバイトコンパイル時 (see section バイトコンパイル)にも効果を発揮します。要求されたパッケージが バイトコンパイラが知るべきマクロを含む時には、このようにします。

requireのトップレベルでの呼出しはバイトコンパイル時に 評価されますが、provide呼出しは違います。それゆえ、定義ファイルに 同じ機能についてのprovideに続くrequireを含めることで、 それがバイトコンパイル以前にロードされることを保証できます。 次の例のようになります。

 
(provide 'my-feature)  ; バイトコンパイラは無視し、
                       ;   loadは評価する。
(require 'my-feature)  ; バイトコンパイラが評価する。

コンパイラはprovideを無視し、requireを処理することで 問題のファイルをロードします。問題のファイルをロードすると、 provide呼出しが実行されるので、続くrequire呼出しは ロード中何もしなくてよくなります。

Function: provide feature

この関数は、featureが今ロードされたことを、あるいはロードされつつある ことを現在のEmacsセッションに告知します。featureに関連する機能がほかの Lispプログラムにも利用可能になった、あるいはなる、という意味です。

provide呼出しの直接の効果は、まだ入ってないならばfeatureを、 リストfeatureの先頭に追加することです。 引数featureは実際シンボルでなければなりません。 providefeatureを返します。

 
features
     ⇒ (bar bish)

(provide 'foo)
     ⇒ foo
features
     ⇒ (foo bar bish)

ファイルが自動ロードを満足するためにロードされ、 それが内容の評価中にエラーでストップした場合、 そのロード中に発生した関数定義やprovide呼出しは、全て取り消されます。 See section 自動ロード

Function: require feature &optional filename

この関数は、featureが現在のEmacsセッションに存在するか否かを チェックします((featurep feature)を使います。以下参照)。 存在しないならば、requirefilenameloadでロードします。 filenameが与えられないならば、シンボルfeatureの名前を ロードのファイル名として使います。

ファイルのロードでfeatureの提供に失敗すると、 require`Required feature feature was not provided' というエラーを通知します。

Function: featurep feature

この関数は、featureが現在のEmacsセッションに提供されている (即ち、featurefeaturesのメンバである)ならば、 tを返します。

Variable: features

この変数の値は現在のEmacsセッションにロードされた機能シンボルのリストです。 各シンボルはprovide呼出しによって本リストに置かれます。 featuresリスト内の要素順序に意味はありません。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.5 アンロード

ライブラリによってロードされた関数や変数を捨てて、 ほかのLispオブジェクトのためにメモリを再生することができます。 そうするには、関数unload-featureを使います:

Command: unload-feature feature &optional force

本コマンドは機能featureを提供したライブラリをアンロードします。 このコマンドは、ライブラリによってdefconst, defvar, defun, defmacro, defsubst, defaliasで定義された 全ての関数、マクロ、変数を未定義化します。 その後、以前これらシンボルに関連づけられていた自動ロードを全て復元します (ロードはこれらをシンボルのautoload属性に保存しています)。

通常unload-featureは、ほかのロードされたライブラリが依存するような ライブラリのアンロードは拒否します(ライブラリaがライブラリbに 依存するのは、abrequireを含む時です)。 オプション引数forceが非nilならば、 依存性を無視して任意のライブラリをアンロードできます。

unload-feature関数はLispで書かれています。 そしてその動作は、変数load-historyに基づいています。

Variable: load-history

この変数の値はライブラリ名に、それが定義する関数と変数の名前、 それが提供する機能、それが要求する機能、を結びつけたalistです。

各要素がリストで、一つのライブラリを表します。 そのリストのCARはライブラリの名前の文字列です。 リストの残りは以下のオブジェクトから成ります:

load-historyの値にCARnilである要素が一つあるかも 知れません。この要素は、ファイルに対応づいていないバッファで行なった eval-bufferによる定義であることを表しています。

コマンドeval-regionload-historyを更新しますが、 読み込んだファイルに関しての要素を置き換えるのではなく、 その要素に定義されたシンボルを追加する、というやり方をします。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.6 ロードのためのフック

特定のライブラリがロードされたときに、あるコードを実行するように、 eval-after-loadを呼び出すことで要求することができます。

Function: eval-after-load library form

この関数は、ライブラリlibraryがロードされたら、 ロード終了時にformを評価するように調整します。 ライブラリlibraryがすでにロードされていたならば、 formを直ちに評価します。

ライブラリ名libraryloadの引数と完全に 一致しなければなりません。load-pathを検索してインストールされた ライブラリが見つかったときに正しい結果を得るには、library内に いかなるディレクトリ名も含めてはなりません。

form内でエラーが起きてもロードは取り消されませんが、 formの残り部分は実行されません。

一般的には、よく設計されたLispプログラムは本機能を使ってないはずです。 Lispライブラリとの、きれいでモジュール式の対話法は、 (1) ライブラリの変数(ライブラリ外での使用を意味する)を検査し設定する、 (2) ライブラリの関数を呼び出す、 です。(1)をやりたいときは、直ちに行なうことができます(ライブラリが ロードされるのを待つ必要がない)。(2)を行うには、 ライブラリをロードする必要があります(requireが望ましい)。

しかし、リリース用プログラムの設計標準に合わせる必要はないと 感じるのであれば、eval-after-loadを自分の個人的カスタマイズに 使用しても構いません

Variable: after-load-alist

特定のライブラリがロードされたならば、そのとき、評価すべき式のalistです。 各要素は、こんな感じになります:

 
(filename forms…)

関数loadは、eval-after-loadを実現するために after-load-alistをチェックします。


[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

This document was generated by Yasutaka SHINDOH on September, 29 2006 using texi2html 1.76.