つーさにブログ

つうさにのメモ用ブログ

recentf で最後に見たバッファを上位にする

ちょうどいいパッケージがあった。

recentf パッケージ

recentf パッケージは Emacs で最近使ったファイルを開くためのパッケージ。使うには init ファイルに(recentf-mode 1)と書くだけ。

メニューバーの [File] に [Open Recent] が追加される他、Helm や Ivy を使えば現在開いてるバッファを切り替えるのと同じインタフェースで、recentf に記録されたファイルを開くことができる。めちゃくちゃ便利。

recentf の問題

recentf パッケージでファイルを最近使ったと記録されるタイミングは、「ファイルを開いたとき (find-file-hook)」と「ファイルを保存したとき (write-file-functions)」に限られている。つまり、ファイルA、ファイルBの順番で開き、ファイルAのバッファに switch-to-buffer してファイルAを見た後に Emacs を終了したとき、recentf ではファイルBのほうがファイルAより最近使ったファイルと記録される。

開くバッファが2つくらいならいいけど、多くのバッファを開いて行き来していると、この挙動がどうも直感に反するため、最後に訪れたバッファを最近使ったファイルとするよう改良したい。

どうにか直す

見てるバッファが変わったときの hook...?

stackoverflow.com

実は Emacs では「見てるバッファが変わったときの hook」が提供されていない。post-command-hookでゴニョゴニョするしかないらしい。

困った。

switch-buffer-functions パッケージ

困ったかと思いきや、実はその機能を提供してるパッケージが存在した。switch-buffer-functions パッケージは、カレントバッファが変わった際に走る hook を提供する。中身を見たらpost-command-hookでゴニョゴニョしてるようだ。

github.com

MELPA に登録されているためインストールも簡単である。

ということで以下のように、switch-buffer-functionshook にmy-recentf-track-visited-file関数1recentf-add-fileしてrecentf-list変数にファイル名を追加する関数)を掛ける。こうしておけば、recentf-listは期待通り、最後に見たバッファが最上位になるようになった。

;;; switch-buffer-functions
(use-package switch-buffer-functions
  :defer t
  :after recentf
  :preface
  (defun my-recentf-track-visited-file (_prev _curr)
    (and buffer-file-name
         (recentf-add-file buffer-file-name)))
  :init
  (add-hook 'switch-buffer-functions #'my-recentf-track-visited-file))

おしまい

recentf パッケージがもっといい感じになったので嬉しい。


  1. やってることはrecentf-track-opened-file関数と同じ。ファイルに紐づいてないバッファ(Dired のバッファなど)では普通buffer-file-namenil であるため、recentf-add-fileの引数はファイル名となる。