Ah yes. Isearch reads the keys you type, looks them up in isearch-mode-map
, and invokes them in the current buffer.
Isearch does not, in spite of appearances, use the minibuffer. It uses the echo area. That is, what you see there is actually output messages, including echoes of the characters you type.
This should do what you ask:
(defun mydelete ()
"Delete the failed portion of the search string, or the last char if successful."
(interactive)
(with-isearch-suspended
(setq isearch-new-string
(substring
isearch-string 0 (or (isearch-fail-pos) (1- (length isearch-string))))
isearch-new-message
(mapconcat 'isearch-text-char-description isearch-new-string ""))))
(define-key isearch-mode-map (kbd "DEL") 'mydelete)
(BTW, your question says the delete
character, but you wrote DEL
, which is the backspace character.)
As @Malabarba points out in a comment, when you set the new search string to ""
(empty string), with-isearch-suspended
resumes by searching for the last search string, instead starting with an empty search string.
This is a "feature" of with-isearch-suspended
, in general. But because you sometimes might really want to empty the search string for resumption,
in the version of with-isearch-suspended
in isearch+.el I've added variable isearchp-if-empty-prefer-resuming-with-last
, to control this. If you bind that to nil
and you set isearch-new-string
to ""
then search resumes with an empty search string.
So with Isearch+ you can do what you want with this definition:
(defun mydelete ()
"Delete the failed portion of the search string, or the last char if successful."
(interactive)
(let ((isearchp-if-empty-prefer-resuming-with-last nil))
(with-isearch-suspended
(setq isearch-new-string
(substring
isearch-string 0 (or (isearch-fail-pos) (1- (length isearch-string))))
isearch-new-message
(mapconcat 'isearch-text-char-description isearch-new-string "")))))
I notice too now that Emacs 24.4 introduced a regression, which I've filed Emacs bug #20466 for, which means that binding DEL
in isearch-mode-map
is not sufficient. They added a separate binding for <backspace>
, in addition to one for DEL
. That means that <backspace>
no longer gets translated to DEL
, for Isearch (but it does still get so translated for Emacs generally).
So if you want the Backspace key to do what you asked in Emacs 24.4 or later then you cannot just bind DEL
to mydelete
. You need to bind <backspace>
to mydelete
. Dumb, AFAICT, mais on n'arrete pas le progres...
I've added a similar command to Isearch+ and bound it to C-M-l
(the same key used to remove a completion mismatch in Icicles).
Be aware too that C-g
in Isearch will also, when there is a mismatch, remove the mismatched text. (But C-g
also has an effect when search is successful.)
I should have mentioned that Isearch+ has also had an optional behavior along similar lines for quite a while now. M-k
during Isearch toggles among 3 behaviors, which are controlled by the value of option isearchp-drop-mismatch
:
replace-last
- Your current input replaces the last mismatched
text. You can always see your last input, even
if it is a mismatch. And it is available for
editing using M-e
.
nil
- Your current input is appended, even if the
previous input has a mismatched portion.
anything else - Your current input is ignored (removed) if it
causes a mismatch. The search string always has successful matches.