emacsminor-mode

Almost-global Emacs minor mode


I'm working on an Emacs minor mode, and I'd like it to apply only when the major mode is a certain mode (i.e. js-mode). In other words, when I activate my-super-mode, I'd like the keymap it defines to be available in all JS buffers (like it was global) but without affecting non-js buffers.

I know it's possible via hooks but I'd like to avoid this solution. Ideally my minor mode would be activated only when needed via M-x (and when activated it should be in effect in all JS buffers). Possible?


Solution

  • One solution that comes to mind is to define a buffer-local minor mode that implements the actual functionality, but is not invoked directly by the user and its name prefixed by an internal prefix to prevent accidental triggering:

    (define-minor-mode my--mode
      "Mode implementing blah, invoke it with M-x my-super-mode."
      nil " Super" nil
      ;; mode definition goes here, including keymaps, etc.
      )
    

    The public mode invoked by the user is global. When switched on or off, it automatically switches the internal mode in all existing and future JS buffers:

    (defun my--mode-set-maybe ()
      (my--mode (if my-super-mode 1 0)))
    
    (define-minor-mode my-super-mode
      "Super mode, only in effect in JS buffers."
      nil "" nil
      :global t
      (dolist (buf (buffer-list))
        (with-current-buffer buf
          (my--mode-set-maybe))))
    
    (add-hook 'js-mode-hook 'my--mode-set-maybe)