12.18 Multisession Variables

When you set a variable to a value and then close Emacs and restart it, that value won’t be automatically restored. Users usually set normal variables in their startup files, or use Customize (see Customization Settings) to set user options permanently, and various packages have various files where they store the data (e.g., Gnus stores this in .newsrc.eld and the URL library stores cookies in ~/.emacs.d/url/cookies).

For things in between these two extremes (i.e., configuration which goes in the startup file, and massive application state that goes into separate files), Emacs provides a facility to replicate data between sessions called multisession variables. (This facility may not be available on all systems.) To give you an idea of how these are meant to be used, here’s a small example:

(define-multisession-variable foo-var 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)))

This defines the variable foo-var and binds it to a special multisession object which is initialized with the value ‘0’ (if the variable doesn’t already exist from a previous session). The my-adder command queries the user for a number, adds this to the old (possibly saved value), and then saves the new value.

This facility isn’t meant to be used for huge data structures, but should be performant for most values.

Macro: define-multisession-variable name initial-value &optional doc &rest args

This macro defines name as a multisession variable, and gives it the initial-value if this variable hasn’t been assigned a value earlier. doc is the doc string, and several keyword arguments can be used in args:

:package package-symbol

This keyword says that a multisession variable belongs to the package specified by package-symbol. The combination of package-symbol and name has to be unique. If package-symbol isn’t given, this will default to the first “segment” of the name symbol’s name, which is the part of its name up to and excluding the first ‘-’. For instance, if name is foo-var and package-symbol isn’t given, package-symbol will default to foo.

:synchronized bool

Multisession variables can be synchronized if bool is non-nil. This means that if there’re two concurrent Emacs instances running, and the other Emacs changes the multisession variable foo-var, the current Emacs instance will retrieve that modified data when accessing the value. If synchronized is nil or missing, this won’t happen, and the values in all Emacs sessions using the variable will be independent of each other.

:storage storage

Use the specified storage method. This can be either sqlite (in Emacs compiled with SQLite support) or files. If not given, this defaults to the value of the multisession-storage variable, described below.

Function: multisession-value variable

This function returns the current value of variable. If this variable hasn’t been accessed before in this Emacs session, or if it’s changed externally, it will be read in from external storage. If not, the current value in this session is returned as is. It is an error to call this function for a variable that is not a multisession variable.

Values retrieved via multisession-value may or may not be eq to each other, but they will always be equal.

This is a generalized variable (see Generalized Variables), so the way to update such a variable is to say, for instance:

(setf (multisession-value foo-bar) 'zot)

Only Emacs Lisp values that have a readable print syntax (see Printed Representation and Read Syntax) can be saved this way.

If the multisession variable is synchronized, setting it may update the value first. For instance:

(cl-incf (multisession-value foo-bar))

This first checks whether the value has changed in a different Emacs instance, retrieves that value, and then adds 1 to that value and stores it. But note that this is done without locking, so if many instances are updating the value at the same time, it’s unpredictable which instance “wins”.

Function: multisession-delete object

This function deletes object and its value from its persistent storage.

Function: make-multisession

You can also make persistent values that aren’t tied to a specific variable, but are tied to an explicit package and key.

(setq foo (make-multisession :package "mail"
                             :key "friends"))
(setf (multisession-value foo) 'everybody)

This supports the same keywords as define-multisession-variable, but also supports a :initial-value keyword, which specifies the default value.

User Option: multisession-storage

This variable controls how the multisession variables are stored. It value defaults to files, which means that the values are stored in a one-file-per-variable structure inside the directory specified by multisession-directory. If this value is sqlite instead, the values are stored in an SQLite database; this is only available if Emacs was built with SQLite support.

User Option: multisession-directory

The multisession variables are stored under this directory, which defaults to multisession/ subdirectory of the user-emacs-directory, which is typically ~/.emacs.d/multisession/.

Command: list-multisession-values

This command pops up a buffer listing all the multisession variables, and enters a special mode multisession-edit-mode which allows you to delete them and edit their values.