如何跟踪buffer的创建和关闭?

有个kill-buffer-hook可以跟踪buffer关闭(还不确定能否涵盖所有情况), 有没有跟它对称的hook, 可以跟踪buffer创建的?


应用场景:

想让一个frame绑定和管理一个project, 每个frame有一个独立的buffer-list, 只包含对应project的文件以及文件夹buffer,还有default-directory在project里的buffer,每次打开文件或者文件夹等, 自动将对应buffer加入到对应的project的frame的buffer-list里.


本来想找一个跟kill-buffer-hook对称的hook,该hook调用的时候,buffer已创建且对应的文件或文件夹已经打开,目前看major-mode-change-hook最接近,但要处理用户故意切换了major-mode的情况。

另外,frame有个buffer-predicate属性,如果emacs内部用它来判断一个buffer是否应该在当前frame显示就简单了,目前emacs好像只用它来判断other-buffer

buffer创建没有好方法,只有一个major-mode-change-hook。一般都是自己实现这个hook

buffer-list-update-hook

1 个赞

这个hook有可能是用户强制切换了某个buffer的major-mode, 如果用来更新每个frame的buffer列表, 则需要遍历每个frame保存的buffer列表, 代价较大.

如果能确定该buffer是全新创建且关联的文件(如果有的话)已经加载, 这样才好用

如果没有跟kill-buffer-hook对称的hook, 那就只能用这个了, 这个调用频率有点高

自己写一个:

(defun get-buffer-create@around (fn buffer-or-name)
  (or (get-buffer buffer-or-name)
      (prog1 (funcall fn buffer-or-name)
        (message ">>> buffer '%s' created" buffer-or-name))))

(advice-add 'get-buffer-create :around 'get-buffer-create@around)

UPDATE:

这种方也有待完善,company、helm 弹出菜单/窗口的时侯都会创建大量的临时 buffer:

可以在 company、helm 等弹出菜单/窗口的时侯暂时禁用,以减少干扰。

即使不做任何处理,响应次数也已经比 buffer-list-update-hook 少很多了,而且可以肯定当前是在「创建」 buffer、同时也知道 buffer 名称/对象。

2 个赞

你的使用场景是什么?

不确定能不能从 buffer-list-update-hook 中区分出 Buffer 的「创建」。

如果是打开文件的话,应该是在文件打开之前调用吧?这样没法获取文件名

每当打开文件的时候,根据条件判断该文件属于哪个frame,自动加入到该frame的buffer列表。

你如果只考虑打开文件的 buffer,不考虑其它方式创建的 buffer,确实在打开文件的时侯处理更方便。

buffer 名称/对象也是可以获取到文件名的 (buffer-file-name BUFFER-OR-NAME)


UPDATE

不是有个 find-file-hook 么?

直接在buffer.c中加个hook

不就行了吗?

我看有些配置/包都是用自制的hook,有人在emacs-devel提过这个问题吗?

这是什么意思?Frame 的 buffer-list 参数么?但这个然后怎么用?(不熟悉 Frame)

如果要不同文件用不同的 Frame 打开,或许可以试试 display-buffer-alist

不单是文件, 还有dired等, 用途是, 在打开文件的时候, 自动把该buffer放到指定分组里.

如果要等到buffer对应的文件或者文件夹(dired)打开之后呢? 现在感觉这种hook很难实现, 不再考虑这种方法了.

本来是想让一个frame绑定和管理一个project, 每个frame有一个独立的buffer-list, 每次打开文件, 自动将对应buffer加入到对应的project的frame的buffer-list里.

目前看major-mode-change-hook最合适, 配合一个buffer的hash map, 重复性也可以解决. 我看有插件就是这么用的

buffer.c

Emacs 用到 buffer 的地方非常多,你应该一开始就把需求描述清楚,而不是盖楼一点点追加。

通常 dired 和 find-file 最后都会调用 pop-to-window,但是在后台打开的,例如 find-file-noselect 就不会 pop 到 window。最然 revert-buffer 重新加载 buffer 内容,但它也不会调用 pop-to-window

你重复一遍自己干嘛…