So I'm writing some custom functions to help me editing some guitar chords using LaTeX's songs package. I find convenient to rebind isearch-exit, so that when I press RET, the cursor is left at the beginning of the matched text (this speeds up in inserting chords in the right position). Since I do this only in some specific files, I thought to create a custom minor mode, and active that in those files using an eval in .dir-locals. The point is, I need to bind RET in isearch-mode-map (like with define-key), but only in a buffer local way (like with local-set-key). Can this be done?

Ideally, given this function:

(defun isearch-exit-other-end ()
  "Exit isearch, at the opposite end of the string."
  (goto-char isearch-other-end)
;; (define-key isearch-mode-map (kbd "M-<return>") #'isearch-exit-other-end)

(define-minor-mode chord-insertion-mode
  "Mode to help inserting chords with the LaTeX \"songs\" package, at the right spot."
  :lighter " chord"
  :keymap `((,(kbd "C-c C-c") . #'my--insert-chord)
        (,(kbd "C-c c") . #'my--insert-chord)
  :after-hook (???)) ;; <----- WHAT TO PLACE HERE?

I would like to do something similar to

(define-local-key isearch-mode-map (kbd "RET") #'isearch-exit-other-end)

How can I set a key buffer-locally, but in a keymap different from the active one? Thanks!

3 Answers 3


A couple possibilities I can think of. Both involve doing everything that's conditional in a command that's bound to what isearch-exit is normally bound to. Either modify isearch-exit itself or replace it with your own command.

  1. Just remap isearch-exit to a command you write that tests whether something is true in the current major mode. E.g.:

    (define-key [remap isearch-exit] 'my-isearch-exit)

    That "something is true" test could test a buffer local Boolean variable, or it could test whether some minor mode is enabled. You can use the mode hook for a major mode to set the local variable value or turn on the minor mode.

    In other words: just change RET and <return> to use your command, which does what you want and then does what isearch-exit does (or vice versa) - it can invoke isearch-exit.

  2. Just advise isearch-exit, to conditionally do what you want before or after it does its thing. The advice would test the value of some buffer-local variable or minor mode -- see #1 above.

  • 1
    Overkill solution: make isearch-mode-map buffer-local, and use copy-keymap, then set your binding in the copy
    – rpluim
    Jan 9, 2023 at 9:14
  • @rpluim Can this be done without changing the code of isearch-forward? Jan 9, 2023 at 12:27
  • I put it in as an answer, since those have nicer formatting and better permanence :-)
    – rpluim
    Jan 9, 2023 at 14:09

Here's a way to do it by making isearch-mode-map buffer-local:

(make-local-variable 'isearch-mode-map)
(setq isearch-mode-map (copy-keymap isearch-mode-map))
(define-key isearch-mode-map (kbd "RET") #'isearch-exit-other-end)

It's a little heavy-weight in that it ends up creating a copy of isearch-mode-map for every buffer, which you could possibly avoid by using keymap-inheritance, but I've not tested that.

  • Thanks! I don't get it one thing: what do you mean by "keymap-inheritance"? The possibility to have different keymaps active? Can it be done buffer-locally? Jan 9, 2023 at 14:51
  • 3
    Instead of creating the keymap with copy-keymap, you could create it with make-sparse-keymap (which would be an empty keymap), define your binding in it, and then set its parent to isearch-mode-map using set-keymap-parent. That way you'd only have buffer-local versions of your almost empty keymap, rather than the whole of isearch-mode-map. But it's something I haven't tested, so it might not work.
    – rpluim
    Jan 9, 2023 at 15:15

Here’s the code for rpluim’s key-map-inheritance suggestion. It does seem to work.

(let ((m (make-sparse-keymap)))
  ;; Make the key bindings of `isearch-mode-map` effectively buffer-local:
  (set-keymap-parent m isearch-mode-map)
  (setq-local isearch-mode-map m))
(define-key isearch-mode-map (kbd "RET") #'isearch-exit-other-end)

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.