7
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

EmacsAdvent Calendar 2023

Day 8

Emacsのセッション情報と履歴を保存する

Last updated at Posted at 2023-12-07

Emacsのセッション情報と履歴を保存する

Emacsを再起動すると通常は、ファイル自体のデータは保存されても、どのファイルを開いていたのかや、ウィンドウやフレームやバッファの状態、さまざまな履歴などの変数といったデータは消えてしまいます。そのため、Emacsを再起動した直後には不便な思いをすることも多くあります。というか、消えるのが当たり前で不便だと感じることさえなくなってるかもしれません。

こうした不便を解消するために使えるのが、Emacsに標準でついてくるdesktopライブラリーとsavehistライブラリーです。

このdesktopとsavehistについては、GNU Emacs Manual 29.1日本語版)の45 Saving Emacs Sessions日本語版)でdesktopを中心に紹介されています。

このうち、desktopでは開いているファイルや、ウィンドウやフレームやバッファの位置、変数の値などを保存できます。一方、savehistでは、変数の値を保存します。なので、変数の値だけを保存したい場合は、savehistを使い、開いているファイルやウィンドウ、フレームなどの状態を保存したい場合はdesktopを使うといいでしょう。ただしdesktopで保存されるファイルやウィンドウなどの情報は時々クリアする必要が生じるため、そうした場面も含めて変数の値をきちんと保存したい場合はdesktopとsavehistを併用した方がよさそうです。

desktopとsavehistを有効にする

desktopとsavehistを有効にするには、カスタム変数設定画面日本語版)から設定して保存する方法と、init.elなどの初期化ファイルに直接記述する方法があります。私は、初期化ファイルに直接記述した方がわかりやすくて便利だと思っています。

初期化ファイルでdesktopとsavehistを有効にする

次の記述を追加すると、desktop-save-modeとsavehist-modeをカスタム変数として設定します。

初期化ファイルに追加(1)
(custom-set-variables
 '(desktop-save-mode nil)
 '(savehist-mode nil)
)

あるいは、Emacs 29.1から登場したsetoptを使った次の記述でも同じ結果になります。

初期化ファイルに追加(2)
(setopt desktop-save-mode t)
(setopt savehist-mode t)

カスタム変数を使わずに、関数desktop-save-modeとsavehist-modeを使う記述もあります。

初期化ファイルに追加(3)
(desktop-save-mode 1)
(savehist-mode 1)

desktopとsavehistを無効にする

Emacsを使っている途中でdesktopとsavehistを無効にする場合は、M-xからdesktop-save-modesavehist-modeを実行するのがかんたんでしょう。無効にしたあともう一度同じコマンドを実行すると、desktopやsavehistが有効になります。

またカスタム変数設定画面を使い、M-x customize-variableからdesktop-save-modesavehist-modeを編集する方法もあります。
この方法は、状態を確認しながら設定できるメリットがありそうです。

すべての履歴変数を保存する

こうしたdesktopとsavehistの設定をして使っていたところ、ちょっと不満を覚えるようになりました。実はdesktopやsavehistが登場する前にsessionというパッケージを使って変数の保存をしていました。そのsessionとくれべて、desktopやsavehistでは限られた変数しか保存してくれなかったのです。ググると同じ不満を持っていた人がいて、鮮やかな解決方法を示していました。desktop-globals-to-saveにすべての履歴系変数を突っ込むです。個人的には、desktopの変数であるdesktop-globals-to-saveよりもsavehistの変数savehist-additional-variablesを使ったほうが良いと考え、次の処理を試してみました。

savehist-additional-variablesの設定:第1版
(setopt savehist-additional-variables (apropos-internal "-\\(\\(history\\)\\|\\(ring\\)\\)\\'" 'boundp))

ただし、これでも保存されない履歴変数があります。調べてみたら、あとからロードされたライブラリーの履歴変数が保存されていませんでした。そこで、上記の処理をmy-set-sevehist-additional-variablesという名前の関数にし、ファイルをロードしたあとに実行されるフックafter-load-functionsに追加するようにしました。

savehist-additional-variablesの設定:第2版
(defun my-set-sevehist-additional-variables (&optional file)
  (ignore file)
  (setopt savehist-additional-variables (apropos-internal "-\\(\\(history\\)\\|\\(ring\\)\\)\\'" 'boundp)))

(add-hook 'after-load-functions 'my-set-sevehist-additional-variables)

after-load-functionsは引数として引数1つ(file)が必要なので、関数に引数を設定します。ignoreは何もしない関数で、引数fileに対して何もしないことを明示しています。

また、savehistのsavehist-minibuffer-history-variablessavehist-ignored-variables、desktopを有効にした場合のdesktop-globals-to-savedesktop-locals-to-saveに含まれる変数を二重に保存することは無駄だし有害な場合もありそうなので、savehist-additional-variablesからは排除することにしました。この辺りになると、EmacsLispの本格的なリスト処理が必要になってきますね。

savehist-additional-variablesの設定:第3版
(defun my-set-savehist-additional-variables (&optional file)
  (let (histvars othervars)
    (ignore file)
    (setq histvars (apropos-internal "-\\(\\(history\\)\\|\\(ring\\)\\)\\'" 'boundp))
    (setq othervars
          (append othervars
                  (when desktop-save-mode
                    (append
                     desktop-globals-to-save
                     desktop-locals-to-save
                     ))
                  savehist-minibuffer-history-variables
                  savehist-ignored-variables
                  ))
    (dolist (ovar othervars)
      (setq histvars (delete ovar histvars)))
    (setopt savehist-additional-variables histvars)))

(add-hook 'after-load-functions 'my-set-sevehist-additional-variables)

まとめ

desktopとsavehistを有効にすると、Emacsを終了した場合でも様々な情報を保存できて便利です。savehist-additional-variablesなどの変数を適切に設定するとさらに便利になります。

7
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?