[emacs-berlin] Understanding hooks
bitspook
bitspook at proton.me
Sat Sep 14 10:15:46 UTC 2024
Hello,
Your 'work goal' here seem to be:
> avoiding running a function in a specific buffer.
Your 'learning goal' seem to be:
> Gaining a better understanding of how Emacs hooks work.
---
There are multiple ways of achieving your 'work goal'. Off the top of my head:
*Create a custom hook callback*
Instead of calling =whitespace-cleanup= directly, you can create a custom callback which skips the actual work in certain modes.
Example: Following code won't do the work (printing a message) in =emacs-lisp-mode=
#+begin_src elisp
(defun my--custom-func ()
(unless (eq major-mode 'emacs-lisp-mode)
(message "Custom HOOK!")))
(add-hook 'before-save-hook #'my--custom-func)
#+end_src
---
(If you still have energy for your 'learning-goal')
I am not an expert, but through observation, it appears that buffer-local and global hooks are two distinct values.
#+begin_src elisp
(defun my--global-func ()
(message "GLOBAL HOOK!"))
(defun my--local-func ()
(message "LOCAL HOOK!"))
(defun my--emacs-lisp-mode-func ()
(add-hook 'before-save-hook #'my--local-func 0 t))
(add-hook 'before-save-hook #'my--global-func)
(add-hook 'emacs-lisp-mode-hook #'my--emacs-lisp-mode-func)
#+end_src
After running above snippet, checking =before-save-hook='s value in org-mode shows:
#+begin_quote
Its value is (my--global-func)
Original value was nil
#+end_quote
But in =emacs-lisp-mode=, it shows:
#+begin_quote
Its value is
(my--local-func t)
Original value was nil
Local in buffer *Org Src test[ elisp ]*; global value is (my--global-func)
#+end_quote
Removing a hook locally seem to not modify global-hook's value such that it changes for one particular buffer, but in fact changes the value of
a distinct local-hook value.
Trying to save file in org-mode and emacs-lisp-mode, there seem to be a precedence-order at play during hook evaluation:
1. Run local hooks
2. Run global hooks
Evidently, if you have a function in a global hook, it will run regardless of what you do to local hooks.
Hope it helps!
On Saturday, September 14th, 2024 at 11:03 AM, jman <emacs-berlin at city17.xyz> wrote:
>
>
> > If you add to the local hook, Emacs automatically adds the t entry to
> > the binding. And both the local and the global hook will be run.
>
>
> Ok, so what I am trying to do is avoiding running a function in a
> specific buffer.
>
> This code works does what I want:
> ``;; Trigger whitespace-cleanup everywhere when saving a buffer (add-hook 'before-save-hook 'whitespace-cleanup) (defun remove-whitespace-cleanup () ;; TODO: disable only for current buffer (remove-hook 'before-save-hook 'whitespace-cleanup)) (defun add-whitespace-cleanup () (add-hook 'before-save-hook 'whitespace-cleanup)) ;; Do not run `whitespace-cleanup` when composing emails (add-hook 'mu4e-compose-mode-hook 'remove-whitespace-cleanup) ;; Add again `whitespace-cleanup` after closing the composition buffer, ;; either by sending, postponing, exiting or killing it. (add-hook 'mu4e-compose-post-hook 'add-whitespace-cleanup)``
>
> but IIUC you point out this is not great because `remove-hook` rips
> away `whitespace-clean` from all buffers. 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.
>
> 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?
>
> Best,
> _______________________________________________
> emacs-berlin mailing list
> emacs-berlin at emacs-berlin.org
> https://mailb.org/mailman/listinfo/emacs-berlin
More information about the emacs-berlin
mailing list