Brad Wright
Brad Wright

Reputation: 5852

How can I apply a hook to multiple Emacs modes at once?

I was reading an article about well-formatted Git commits, and I was wondering how I could apply some of the rules to the Magit log mode.

It seems to use 3 major modes simultaneously: Magit, Log, Edit.

So how would I get just those modes, when used together, to hard-wrap at 72 characters automatically?

Upvotes: 8

Views: 7449

Answers (6)

Bruce Wen
Bruce Wen

Reputation: 121

(dolist (mode-hook '(org-mode-hook
               term-mode-hook))
  (add-hook mode-hook (lambda () (display-line-numbers-mode 0))))

Upvotes: -2

Lindydancer
Lindydancer

Reputation: 26094

In general, you could define your own function, say my-common-hook and add it to all the major modes, for example:

(defun my-common-hook ()
   ... do stuff ...
   )
(add-hook 'one-mode-hook 'my-common-hook)
(add-hook 'another-mode-hook 'my-common-hook)
(add-hook 'a-third-mode-hook 'my-common-hook)

Upvotes: 4

dpsutton
dpsutton

Reputation: 101

Just seeing this now, but here's what I've done. The end result is that i want to do the following: (hook-up-modes my-lisps 'standard-lisp-environment).

To do this, i define the following defvars.

(defvar my-lisps  "clojure lisp emacs-lisp cider-repl")
(defun standard-lisp-environment ()
  (paredit-mode 1)
  (rainbow-delimiters-mode 1)
  (eldoc-mode 1))

I want to have lisp append -mode-hook to the lisps i use so i have the following:

(defun append-suffix (suffix phrases)
  "take SUFFIX and append it to each of the PHRASES."
  (mapcar #'(lambda (phrase) (concat phrase suffix)) phrases))

so that ("clojure" "lisp") => ("clojure-mode-hook" "lisp-mode-hook").

Now that we could easily have these, we need their reader symbols, which we easily get from

(defun symbols-from-strings (strings)
  "Given a list of strings, get their symbol values"
  (mapcar #'intern strings))

And then finally we have the similar form posted above:

(defun multiple-mode-add-hook (modes hook)
  "Given a list of x-mode-hook symbols in MODE, add the HOOK to them."
  (mapc (lambda (mode) (add-hook mode hook)) modes))

These all operate on the type that makes sense for them, list of strings, list of symbols 'blah-mode-hook, etc. So now we need a nice user facing function that we can work with.

(defun hook-up-modes (strings hook)
  (let ((modes (symbols-from-strings
                (append-suffix "-mode-hook" (split-string strings)))))
    (multiple-mode-add-hook modes hook)))

Now this should be pretty legible: We create our modes from a space delimited list of strings and apply the hook to it. Also, since I've defined a standard-lisp-environment, all my lisps behave similarly, and I can easily remove the hook later if I like. Then the code that actually does work is the super simple phrase (hook-up-modes my-lisps 'standard-lisp-environment).

Upvotes: 1

Ross Patterson
Ross Patterson

Reputation: 5742

Emacs modes have "base modes" which is to say bade modes. For example python-mode extends prog-mode which itself extends fundamental-mode. All modes extend fundamental-mode. So to hook python-mode plus c-mode but not text-mode, you could hook prog-mode.

Upvotes: 6

phils
phils

Reputation: 73246

In answer to the original stated question, if you have a single function to add to numerous hook variables, you could do it like this:

(defun my-add-to-multiple-hooks (function hooks)
  (mapc (lambda (hook)
          (add-hook hook function))
        hooks))

(defun my-turn-on-auto-fill ()
  (setq fill-column 72)
  (turn-on-auto-fill))

(my-add-to-multiple-hooks
 'my-turn-on-auto-fill
 '(text-mode-hook
   magit-log-edit-mode-hook
   change-log-mode-hook))

Not the best example, perhaps, but I have something similar for some common behaviours I want enabled in programming modes, of which there are a great many more to list.

Upvotes: 10

Victor Deryagin
Victor Deryagin

Reputation: 12215

There can be only one major mode in Emacs buffer (unless you are using something like MMM or MuMaMo). In your case that one major mode is magit-log-edit-mode, whose name consists of three words ("Magit Log Edit"). You can just add to it whatever hook you like:

(defun my-turn-on-auto-fill ()
  (setq fill-column 72)
  (turn-on-auto-fill))

(add-hook 'magit-log-edit-mode-hook 'my-turn-on-auto-fill)

Upvotes: 4

Related Questions