4

This has been driving me crazy, I can't get this to work. I want to link the on-off status of a handful of minor modes, in particular evil-mode, evil-quickscope-mode, hl-paren-mode, and a few others. I don't necessarily want evil globally, but once I turn on evil-mode I want the other modes to also turn on (and correspondingly turn off once evil turns off).

Is there a way to accomplish this cleanly? The closest I've come involved using mode-hooks, but somehow the modes always got out of sync (evil on, others off. others on, evil off. etc.)

edit: Posting the relevant mode-hooks section of my init.el:

;; Evil Mode Setup
(require 'evil-leader)
(evil-leader/set-leader ",")
(evil-leader/set-key "q" 'kill-buffer-and-window)
(evil-leader/set-key "b" 'ibuffer)

(defun after-all-loads () (require 'evil))
(add-hook 'after-init-hook 'after-all-loads)
(define-key global-map "\C-xv" 'evil-mode)
(add-hook 'evil-mode-hook 'hl-paren-mode)
(add-hook 'evil-mode-hook 'evil-visual-mark-mode)
(add-hook 'evil-mode-hook 'evil-quickscope-mode)
(add-hook 'evil-mode-hook 'evil-leader-mode)
3
  • It sounds like you are on the right track with using mode-hooks. Can you post the relevant portions of your init file? Commented Apr 15, 2016 at 17:46
  • E.g., evil-quickscope-mode is defined via define-minor-mode. The doc for define-minor-mode says: "When called from Lisp, the mode command toggles the mode if the argument is `toggle', disables the mode if the argument is a non-positive integer, and enables the mode otherwise (including if the argument is omitted or nil or a positive integer)."
    – Tobias
    Commented Apr 15, 2016 at 18:00
  • I've edited the relevant portion of my init.el into my question. The issue I have specifically is that it works fine the first time I invoke evil, then I switch to a new buffer and evil stays on but the other modes all turn off. Then I have to toggle evil back off and on again to get the other modes back.
    – Kyle Rush
    Commented Apr 15, 2016 at 18:44

2 Answers 2

1

You need to be aware of whether a minor mode is global or buffer-local before you can reliably enable or disable it along with other modes. (See the list of mode types at the bottom of https://emacs.stackexchange.com/a/20915 )

(FYI, all of the following information was ascertained by checking the definitions of the various functions with M-x find-function -- although it helps to know what you're looking for, of course.)

evil-quickscope-mode and evil-leader-mode are buffer-local, so you can enable or disable them along with other buffer-local minor modes. I'm not sure where your hl-paren-mode is from, but I'll assume that's also buffer-local.

evil-visual-mark-mode is a global minor mode, so attempting to toggle it in specific buffers is wrong. You can probably enable this once and then not touch it (being a global mode, I would presume that it knows when evil is or isn't active). Assuming it's autoloaded:

(eval-after-load 'evil
  '(evil-visual-mark-mode 1))

evil-mode itself is a globalized minor mode. That means it's a global mode which controls a buffer-local mode (this one is named evil-local-mode), and probably all of the interesting functionality is managed by the buffer-local mode. As such, I imagine you actually want to tie your other buffer-local minor modes to evil-local-mode.

(defcustom my-evil-minor-modes
  '(evil-leader-mode
    evil-quickscope-mode
    hl-paren-mode)
  "Buffer-local minor modes to enable or disable with `evil-local-mode'."
  :type  '(repeat symbol)
  :group 'evil)

(defun my-evil-local-mode-hook ()
  "Enable or disable all of `my-evil-minor-modes' with `evil-local-mode'."
  (let ((state (if evil-local-mode 1 0)))
    (mapc (lambda (mode) (funcall mode state))
          my-evil-minor-modes)))

(add-hook 'evil-local-mode-hook 'my-evil-local-mode-hook)

You could copy and modify that for evil-mode-hook in order to enable/disable the global evil-visual-mark-mode along with the also-global evil-mode, but I don't think you actually want that, because you can enable evil-local-mode without enabling evil-mode.

2

Just define your own minor mode that does what you want. It can turn on/off any number of modes when you turn it on/off. It can set variables, set up key bindings, and do pretty much anything you want.

IOW, you make a super-minor-mode that encapsulates whatever you want, including a bunch of other minor modes.

Turn on your new minor mode whenever you want - in your init file or on some hook or just interactively.

C-h f define-minor-mode

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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