Reputation: 4426
I am trying to execute when the active buffer has changed by either
C-x <left>
).C-x o
). Are their hooks suitable for detecting this?
Looking through the Standard Hooks I found the following options, none of which quite do what I want:
buffer-list-update-hook
is called for both (1) and (2). It is however unsuitable, because it is run before the buffer is changed, while I want to know what the current-buffer
after the change is.
window-configuration-change-hook
can be used to detect a change of the buffer displayed in the current window, and it is run after the change, as needed. It is however not run for M-x other-window
.
mouse-leave-buffer-hook
seems viable for detecting mouse-based window switching, but it gets called a bit often (for me four times upon switching windows with the mouse, three times before and once after switching), which requires additional logical to prevent multiple execution.
post-command-hook
would be viable but a bit heavy handed, risking significant slow-down of the editor by even minor bugs.
Since my action would need to use with-selected-window
, which triggers these hooks, care has to be taken to avoid endless loops where the hook triggers itself.
Upvotes: 22
Views: 5372
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
Reputation: 136
Emacs27.1 introduce a new variable called `window-buffer-change-functions'
Upvotes: 9
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.
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
.
* 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