0

Let's say I want to write a mode which updates the display (e.g. adds some annotation) when the user edits the buffer or just moves around.

What is the recommended way to implement this?

Using post-command-hook with sit-for, so my function does its work when the user becomes idle after a command:

(defun my-post-command ()
  (when (sit-for 0.3)
    ....

Or an idle timer:

(run-with-idle-timer 0.3 t 'my-post-command)

The drawback of post-command-hook is that it holds up the hook with the delay if some other hook function comes after it.

The drawback of idle timer is that it's global, so there can be no buffer local timer, so if one implements some minor mode then the timer has to be deactivated/activated when the user switches buffers.

Is there a better/recommended method for this?

Tom
  • 1,190
  • 7
  • 16

2 Answers2

0

Do you not want the action taken, if the user switches buffer? If so, just use this in the timer:

(when (derived-mode-p 'THE-MODE-WHERE-IT-SHOULD-BE-DONE)
  <your code to do it>)

or:

(when (eq (current-buffer) <the buffer where it should be done>)
  <your code to do it>)

or something else similar (e.g. conditional on a given file or whatever).

If you expect the action to be taken when the user comes back to the buffer or whatever, then you'll need some more elaborate handling.

Are you sure you need/want to do this kind of thing? E.g., what's the real problem you're trying to solve?

Drew
  • 75,699
  • 9
  • 109
  • 225
  • "It's also the case that as soon as the user does anything the sit-for is quit and the following code invoked immediately. " sit-for returns t if it waited the full time otherwise nil, so using it like (when (sit-for 0.3) ...) the body is only executed if the delay elapsed otherwise it's skipped. That's why it can be used in post-command-hook: when the user keeps typing, moving, the delayed code is not executed. it only executes if the user stops for a while. – Tom Jan 04 '21 at 22:10
  • Oh, right. Thanks for the correction. I've removed that part of my answer. – Drew Jan 05 '21 at 02:27
0

I think you hit the nail on the head with:

The drawback of post-command-hook is that it holds up the hook with the delay if some other hook function comes after it.

Packages like follow-mode that use post-command-hook will not work properly if you add a post-command hook with a sit-for.

I would say that run-with-idle-timer is the way to go for the code that should update the display. (Maybe you can combine this with a quick post-command-hook that only register the buffers that should be updated.)

Regardless of solution you pick, you have to ensure that your code is applied to the correct buffer or buffers. Remember that the last command could change the current buffer or selected window, so you have to ensure that test this case.

Lindydancer
  • 6,095
  • 1
  • 13
  • 25