1

I wanted to change the behavior of isearch in the minibuffer, making Return both accept a search result (isearch-exit) and submit it (minibuffer-complete-and-exit). This is the behavior I've grown to like with Ctrl-R in the shell.

(defun ivan/isearch-exit ()
  "Run isearch-exit, and if in the minibuffer, submit the search result as input."
  (interactive)
  (isearch-exit)
  (if (minibuffer-window-active-p (selected-window))
      (minibuffer-complete-and-exit)))

The first time isearch-mode is entered, it binds Return to isearch-exit in overriding-terminal-local-map (which takes precedence over all other keymaps). So I'm remapping isearch-exit to my custome ivan/isearch-exit in that keymap.

The problem is, I can't simply do the remapping in my init file, because overriding-terminal-local-map is nil at that point. To get around this, I've done the remapping in a hook:

(defun ivan/remap-isearch-exit ()
  (define-key
    overriding-terminal-local-map [remap isearch-exit] #'ivan/isearch-exit))

(add-hook 'isearch-mode-hook #'ivan/remap-isearch-exit)

This works, but it means I'm doing the remapping every time isearch starts, which is unnecessary. Not that it hurts anything (except maybe performance?), but I'd like to avoid doing so. Now I've added a variable to make sure the remap only occurs the first time isearch is entered.

(setq ivan/remapped-isearch-exit nil)

(defun ivan/remap-isearch-exit ()
  (unless ivan/remapped-isearch-exit
    (setq ivan/remapped-isearch-exit t)
    (define-key
      overriding-terminal-local-map [remap isearch-exit] #'ivan/isearch-exit)))

But it makes me wonder if there's a better way. Is there something I could hook into that's run when overriding-terminal-local-map is first created? Or is there another approach altogether that I'm not aware of?

Update: Thanks to lawlist's answer, I now have the following:

(eval-after-load "isearch"
  '(define-key isearch-mode-map [remap isearch-exit] #'ivan/isearch-exit))
2

Because certain components of isearch.el are autoloaded by default, Emacs recognizes the existence of the autoloaded functions when they are called during an Emacs session -- the entire library is loaded once an autoloaded function is called. The following are two different approaches to changing the settings -- . . . means to add your own additional stuff as needed -- the first approach will be slightly faster than the second approach when starting Emacs:

(eval-after-load "isearch" '(progn
  . . .))

or

(require 'isearch)
. . .
  • This didn't work quite as expected, but it did lead me to solution. Emacs was still complaining about the keymap being nil, and I noticed this line in the definition of isearch-mode-map: (setq overriding-terminal-local-map isearch-mode-map). So I tried the more obvious solution - remapping in isearch-mode-map. I thought I'd tried that already, but I must have tried minibuffer-local-isearch-map instead. Anyway, it works! – ivan Sep 11 '16 at 2:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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