ある変数に値をセットしてからEmacsを終了すると、その後に再起動してもその値が自動的に復元されることはありません。ユーザーが値を永続的にセットする場合には、通常の変数であればスタートアップファイル、ユーザーオプションであればCustomize(カスタマイゼーション設定を参照)を用いるのが普通です。更にデータを格納するためにさまざまなファイルをもつパッケージが沢山あります(例: Gnusはデータを.newsrc.eld、URLライブラリーはcookieを~/.emacs.d/url/cookiesに格納する)。
これらの2つの対極的な事項(スタートアップファイルに書き込まれる構成、あるいは大規模なアプリケーションが個別のファイルへ書き込む状態)にたいして、Emacsはセッションに跨がるデータを複製(replicate)するためのマルチセッション変数(multisession variables)と呼ばれる機能を提供しています(この機能はすべてのシステムで利用できる訳ではない)。これらがどのような利用を意図しているかヒントを与えるために、以下に小さな例を示しましょう:
(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はdoc文字列、argsにはいくつかのキーワード引数を使用できる:
:package package-symbol
マルチセッション変数がpackage-symbolで指定されたパッケージに属することを告げるキーワード。package-symbolとnameは一意な組み合わせであること。package-symbolが与えられない場合には、nameのシンボル名の1つ目の“セグメント”(シンボル名の最初の‘-’の手前までの部分)がデフォルトになる。たとえばnameがfoo
でpackage-symbolを与えなければ、package-symbolのデフォルトはfoo
。
:synchronized bool
boolが非nil
であればマルチセッション変数を同期(synchronized)できる。同時に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値のみ。
そのマルチセッション変数が同期化されている場合にセットすると、最初に値が更新されるかもしれない。たとえば:
(cl-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つにたいしてファイル1つという構造で値が格納されることを意味する。これがsqlite
なら値はSQLiteデータベースに格納される(SQLiteサポートつきでビルドされたEmacsでのみ利用可能)。
このディレクトリー配下にマルチセッション変数は格納される。デフォルトはuser-emacs-directory
のサブディレクトリーmultisession/
(通常なら~/.emacs.d/multisession/)。
このコマンドはすべてのマルチセッション変数をリストするバッファーをポップアップして、それらの値の削除や編集が行える特別なモードmultisession-edit-mode
にエンターする。