[emacs-berlin] Understanding hooks
Michael Heerdegen
michael_heerdegen at web.de
Sun Sep 15 19:19:47 UTC 2024
jman <emacs-berlin at city17.xyz> writes:
> This code works does what I want:
> ``` [...] ``
> but IIUC you point out this is not great because `remove-hook` rips
> away `whitespace-clean` from all buffers.
Indeed. You would regret it.
> So let's try removing it only from
> the current buffer, documentation for `remove-hook` says:
>
> If local is non-nil, that says to remove function from the
> buffer-local hook list instead of from the global hook list.
>
> So:
>
> (remove-hook 'before-save-hook 'whitespace-cleanup t))
>
> When I compose an email, `before-save-hook` is now described as:
>
> Its value is (mu4e--compose-before-save t)
> Original value was nil
> Local in buffer "No subject"; global value is
> (whitespace-cleanup)
>
> but now whitespace-clean runs when saving this buffer.
Expected, yes. For "conventional" variables this would make sense. But
remember: Hook variables have special semantics - the local _and_ the
global value is executed. Both matter. So, if the global binding
contains a certain function, it will run whatever you do with the local
hook binding (unless you deactivate the global hook entirely - see
below).
> I am really confused by all this. Is this something I should bring to
> the mu4e mailing list or am I just missing something due to me not
> inexperience withabout how hooks work?
Feel free to ask anywhere, but I think so far we are in the expected
well running learning process. You asked about understanding how it
works (I appreciate that!), so I didn't want to pull a solution out of a
hat in my first answer.
Ok - how to proceed? Using only local hooks would be cumbersome if what
you want is more "having a blacklist" like. Using a global hook
variable doesn't let you deactivate the thing for certain cases, without
deactivating the global hook completely for certain modes, which you
obviously should avoid: for other global hook functions you may still
want to run the global hook.
So... obviously, "hooks only" is not the solution for your problem,
conceptually. Sometimes you need a screw driver and a hammer. You need
a (simple) combination of concepts.
One solution: define a function that calls `whitespace-cleanup' if and
only if the buffer is in a certain mode. Or certain conditions are met.
Add _that_ function to the global hook.
Or something similar. You could also use a local variable that this
function evaluates. The varialbe could be used to inhibit calling
`whitespace-cleanup' when non-nil. You would then set this variable's
(buffer-local) value in the mode hooks, for example.
What I left out is the question whether running whitespace-cleanup in so
many cases is a good idea. I dunno. I don't use it often - maybe it is
even too slow for large buffers? Note that Emacs also uses a lot of
buffer saving in the background (custom files, desktop files, bookmarks,
files created by your Emacs mail program, ...). Most of the time the
"white list" approach is less full of surprises.
Personally I am using `whitespace-mode' to see any whitespace
weirdnesses I create while working. And avoid automatic magic
completely.
Ok - that was a long answer. Please tell about your chosen solution!
Or do you need further advice?
Michael.
More information about the emacs-berlin
mailing list