kdb
kdb

Reputation: 4426

Emacs-lisp hooks for detecting change of active buffer?

I am trying to execute when the active buffer has changed by either

  1. Changing the buffer in the current window (e.g. C-x <left>).
  2. Switching to another window (C-x o).
  3. Switching to another frame.

Are their hooks suitable for detecting this?

What I figured out so far

Looking through the Standard Hooks I found the following options, none of which quite do what I want:

Upvotes: 22

Views: 5372

Answers (3)

CodeAwareness
CodeAwareness

Reputation: 21

It looks like other packages have already solved this problem, but I'm posting here for people who may arrive on this page in their search for answers.

The treemacs package uses a minor mode to toggle something called treemacs-follow-mode and a timer to call the desired update function after buffer-list-update-hook: https://github.com/Alexander-Miller/treemacs/blob/master/src/elisp/treemacs-follow-mode.el#L86C15-L86C15

And for #3: Update when changing frames, I used the after-focus-change-function like powerline does: https://github.com/milkypostman/powerline/blob/master/powerline.el#L575

Upvotes: 2

dingyi342
dingyi342

Reputation: 136

Emacs27.1 introduce a new variable called `window-buffer-change-functions'

Upvotes: 9

kdb
kdb

Reputation: 4426

Judging from the comments, the answer to this question is “No, there is no such hook.”

Additionally, some of the hooks mentioned in my question, are also triggered by changes, which are not user-visible, such as temporary changes due to with-current-buffer and with-selected-window.

However, using post-command-hook has proven to be a non-issue for performance, since the required state-check is cheap.

Alternative

Probably obvious, but stated for completeness.

  • Store state information in a global variable, in a frame-parameter, in a window-parameter or in a buffer-local variable, whichever is most applicable to the use-case. In my use-case, this necessary unique state is was defined by current-buffer, current-window, and in one case line-beginning-position.*

  • In post-command-hook, check if the state has changed, possibly skipping even that, if this-command is self-insert-command.

  • If it has, perform the intended action and update the stored state.

* line-number-at-pos is unsuitable, because it counts lines by iterating over the buffer from point-min to point, making it generally cheap, but not cheap enough to be executed after every typed character.

Upvotes: 11

Related Questions