4

The change-major-mode-hook appears to be running after the new major mode has already been enabled. How would one go about running a function just before the change of major mode occurs?

Example: A buffer with major-mode-abc has minor-mode-xyz active, and that minor-mode is responsible for placing certain overlays. When changing to major-mode-def, it is necessary to execute the function remove-overlays if minor-mode-xyz was active prior to changing major modes. The new major-mode-def also activates minor-mode-xyz again and immediately draws new overlays (this is a good thing); however, those new overlays (that I wanted to keep) get erased by the 'change-major-mode-hook 'remove-overlays nil t. I would rather that that the remove-overlays function be run with a hook associated with minor-mode-xyz, rather than as part of enabling major-mode-def.

lawlist
  • 13,099
  • 3
  • 49
  • 158

2 Answers2

4

I may have misunderstood your question, but I do not see any problem here, presuming that your minor mode is enabled from major mode hooks and adds its cleanup function to change-major-mode-hook.

change-major-mode-hook runs at the very beginning of a major mode function, before anything else, including the major mode hooks. Thus, the cleanup function of your minor mode is called before your minor mode is re-enabled by the hooks of the new major mode. If that doesn't work for you, there is likely a flaw in your minor mode implementation or setup.

Alternatively, you could delay adding the new overlays to post-command-hook rather than adding them directly in the minor mode function. Define a buffer-local variable, and set that variable to a non-nil value in your minor mode function. Then add a function to the buffer-local post-command-hook, that adds the overlays if the variable is non-nil.

This makes sure that the overlays are not drawn before the new major mode is completely setup, including the cleanup of any old overlays. An additional advantage of this approach is that the adding of the overlays has access to file-local and directory variables of the new major mode.

  • 2
    Thank you for helping me to better understand when the `change-major-mode-hook` is run when enabling a new major-mode. You are correct in that there was a flaw in my minor-mode setups. I had wrapped the overlay functions when enabling the minor-mode with `(when (called-interactively-p 'any) . . .` and erroneously blamed the `change-major-mode-hook` for erasing my new overlays, when in fact those new overlays never existed because the minor-mode was technically not enabled *interactively* (but was rather enabled as part of the new major mode hook). – lawlist Sep 12 '14 at 15:03
4

You say "The change-major-mode-hook appears to be running after ...": I wonder what makes you think so, because it is run before, i.e. it does exactly what you're asking (and is used precisely for this kind of situation).

Stefan
  • 27,908
  • 4
  • 53
  • 82
  • 1
    It ended up being a flaw in my minor mode implementation / setup and I erroneously blamed the `change-major-mode-hook` for my woes. Your help is greatly appreciated -- thank you. – lawlist Sep 12 '14 at 15:06