6

I am looking for an example, please, to programmatically control the order of functions within a particular hook:

  • First in time, which is easy -- i.e., don't append using add-hook.

  • Last in time, which is easy -- i.e., append using add-hook.

  • Second to last -- not so easy?

In the context of this particular question, there are three (3) functions assigned to the post-command-hook.

  • An overlay removal function, which must always be first in time.

  • A flyspell-post-command-hook function that must always be last in time -- if flyspell-mode is active.

  • A overlay placement function that must be last in time when flyspell-mode is not active, or second to last when flyspell-mode is active.

Essentially, I would like to control the overlay placement function to programmatically check to see whether flyspell-mode is active, and if so, then place it second to last. If flyspell-mode is not active, then just append so that the overlay placement function becomes the last in the hook.

  • 2
    Not sure I completely understand your question, but a hook is just a list of functions, so if they get evaluated in order, you can manipulate the list as with any other. Here's a quick little function that appends a new element to the second-to-last position in a list. (defun append-butlast (elt list) (append (butlast list) (list elt) (last list))). – Dan Dec 22 '14 at 21:57
  • 1
    @Dan -- How do I handle the t that sometimes appears inside the hook when I inspect the post-command-hook? I think add-hook may place that t somewhere specifically, but I'm not sure how that is determined or under what circumstance a t is added. Here is a specific example: (vr-remove-vertical-ruler t pch-hr-function parens flyspell-post-command-hook) – lawlist Dec 22 '14 at 22:05
  • Not sure where that t comes from. I imagine you could inspect post-command-hook for that t in deciding where to assign your function (last, second-to-last, etc., either counting t or not). – Dan Dec 22 '14 at 22:12
  • @Dan -- thanks -- I'll work on it a bit to see if I can figure that out, because I may need to simultaneously add the t (if applicable) somewhere when adding the second to the last. – lawlist Dec 22 '14 at 22:14
  • 2
    The t stands for the global part of the hook (i.e. the list of functions kept on (default-value <hook>). – Stefan Dec 23 '14 at 13:58
3

As others have pointed out a hook variable is just a list of hook functions that can be manipulated in anyway you see fit. There are two complications however; the t element that has already been mentioned, and instead of a list the variable value may also be a single symbol.

For Magit I have a "add-hook" variant, magit-add-section-hook, which is able to inserted after or before any existing member of the list, but which ignores the two mentioned complications because I though they are not relevant for the intended usecase (but I might fix that at some point, and then make this available separately).

3

There is "right" answer for that, sadly. Typically, what packages do when they need to care about the ordering, is that they try to detect the wrong ordering and manually set it back the way it should be.

In electric.el we tried to do it "more or less cleanly" with a somewhat generic approach, where each hook function can have a priority property, and we call electric--sort-post-self-insertion-hook every time we think we may have gotten the order wrong.

In add-function (and advice-add) I provided a similar solution but with direct support, so it should work reliably.

We could extend the electric--sort-post-self-insertion-hook and move it into add-hook so it works for all hooks. Patch welcome.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.