変数に値を代入した後、Emacsを終了して再起動しても、その値は自動的に復元されません。通常、ユーザーはスタートアップファイルで通常変数を設定するか、Customize(カスタマイズ設定を参照)を使用してユーザーオプションを永続的に設定します。また、各種パッケージにはデータを保存するためのさまざまなファイルがあります(例えば、Gnusは.newsrc.eldに、URLライブラリは~/.emacs.d/url/cookiesにCookieを保存します)。
これら2つの極端な例の中間にあたるケース(すなわち、スタートアップファイルに記述する設定と、別ファイルに記述する大規模なアプリケーション状態)向けに、Emacsではマルチセッション変数と呼ばれる、セッション間でデータを再現するための機能が提供されています。(この機能はすべてのシステムで利用できるとは限りません。)これらがどのように使われるのかイメージを掴んでいただくために、簡単な例を以下に示します。
(define-multisession-variable foo 0)
(defun my-adder (num)
(interactive "nAdd number: ")
(setf (multisession-value foo)
(+ (multisession-value foo) num))
(message "The new number is: %s" (multisession-value foo)))
これにより変数 foo が定義され、値 ‘0’
で初期化された特殊なマルチセッションオブジェクトにバインドされます(前回のセッションから変数が既に存在していない場合)。my-adder
コマンドはユーザーに数値の入力を求め、それを以前の(保存されている可能性のある)値に加算した上で、新しい値を保存します。
この機能は巨大なデータ構造向けに設計されたものではありませんが、ほとんどの値に対して高いパフォーマンスを発揮するはずです。
このマクロは name をマルチセッション変数として定義し、この変数に事前に値が代入されていない場合は initial-value を割り当てます。doc はドキュメント文字列であり、args では複数のキーワード引数を使用できます:
:package package-symbolこのキーワードは、マルチセッション変数が package-symbol
で指定されたパッケージに属することを示します。package-symbol と name の組み合わせは一意である必要があります。package-symbol が指定されていない場合、name
シンボル名の最初の「セグメント」(名前のうち、最初の「-」に至るまでの部分)がデフォルトとなります。例えば、name が
foo で package-symbol
が指定されていない場合、package-symbol は foo がデフォルトとなります。
:synchronized bool
¶bool が nil
でない場合、マルチセッション変数を同期させることができます。つまり、2つの Emacs
インスタンスが並行して動作しており、もう一方の Emacs がマルチセッション変数 foo
を変更した場合、現在の Emacs インスタンスが値にアクセスする際に、その変更されたデータが取得されます。synchronized が nil
であるか、あるいは欠落している場合はこの動作は起こらず、その変数を使用しているすべての Emacs セッションの値は互いに独立します。
:storage storage指定された storage メソッドを使用してください。これは sqlite(SQLite サポート付きでコンパイルされた Emacs の場合)または files のいずれかになります。指定されない場合は、後述する multisession-storage 変数の値がデフォルトとなります。
この関数は variable の現在の値を返します。この変数が今回の Emacs セッションでこれまで参照されていない場合、あるいは外部から変更されている場合は、外部ストレージから読み込まれます。そうでない場合は、このセッションにおける現在の値がそのまま返されます。マルチセッション変数ではない variable に対してこの関数を呼び出すとエラーになります。
multisession-value 経由で取得した値は、互いに eq である場合もあればそうでない場合もありますが、常に equal となります。
これは一般化変数(一般化変数を参照)であるため、このような変数を更新する方法は、例えば次のように記述します。
(setf (multisession-value foo-bar) 'zot)
この方法で保存できるのは、可読なプリント構文(プリント表現と読み取り構文を参照)を持つEmacs Lispの値のみです。
マルチセッション変数が同期されている場合、その値を設定するとまず値が更新されることがあります。例えば:
(incf (multisession-value foo-bar))
まず、別のEmacsインスタンスで値が変更されたかどうかを確認し、その値を取得した上で、さらにその値に1を加算して保存します。ただし、これはロックなしで行われているため、多くのインスタンスが同時に値を更新している場合、どのインスタンスが「勝つ」かは予測できません。
この関数は、object とその値を永続ストレージから削除します。
また、特定の変数に紐づかず、明示的なパッケージとキーに紐づく永続的な値を作成することもできます。
(setq foo (make-multisession :package "mail"
:key "friends"))
(setf (multisession-value foo) 'everybody)
これは define-multisession-variable
と同じキーワードをサポートしているほか、デフォルト値を指定する :initial-value
キーワードもサポートしています。
この変数は、マルチセッション変数の保存方法を制御します。デフォルト値は files で、これは値が
multisession-directory
で指定されたディレクトリ内に、変数ごとに1ファイルという形式で保存されることを意味します。この値が代わりに sqlite である場合、値は SQLite データベースに保存されます。これは、Emacs が SQLite
サポート付きでビルドされている場合にのみ利用可能です。
マルチセッション変数はこのディレクトリ配下に格納されます。このディレクトリは、通常は~/.emacs.d/multisession/であるuser-emacs-directoryのサブディレクトリmultisession/がデフォルトとなります。
このコマンドを実行すると、すべてのマルチセッション変数が一覧表示されたバッファがポップアップし、それらの削除や値の編集が可能な特殊モード multisession-edit-mode に入ります。