If I use isearch to search for the word "accommodating" in my document, I have to type acc before the cursor jumps to the word. When I press enter the cursor is on the the second "c" as in acCommodating. This strikes me as rather unintuitive because I have to go back two characters to begin editing the word. In Vim, search puts the cursor at the start of the word. Can I replicate this behaviour in Emacs?
There's really nothing to replicate, I think. You somehow have to tell Isearch that you're done typing text for the search string - you have to hit some key to tell it that. So at a minimum you have
C-s acc <SOME KEY>.
You can end Isearch with any key that is not already bound to something in
isearch-mode-map. (And even then, you can rebind any keys that are already bound.) And the key that ends Isearch can do whatever you like, including move back to a word beginning.
So you can end it with
M-b (that key isn't bound for Isearch, by default), which goes back to the beginning of the current word:
C-s acc M-b
That's not so hard. Whether you find it "intuitive" probably has to do with what you're already used to. There are a zillion use cases for Isearch, only one of which is wanting to move to the beginning of a matching word.
C-h k M-b tells you:
M-bruns the command
global-map), which is an interactive compiled Lisp function in
It is bound to
(backward-word &optional ARG)
Move backward until encountering the beginning of a word.
ARG, do this that many times. If
ARGis omitted or
nil, move point backward one word.
The word boundaries are normally determined by the buffer’s syntax table and character script (according to
find-word-boundary-function-table, such as set up by
subword-mode, can change that. If a Lisp program needs to move by words determined strictly by the syntax table, it should use
backward-word-strictlyinstead. See Info node (elisp) Word Motion for details.
M-bis not very useful here if search term is not in the beginning of the word. In such cases
C-s acc C-r <RET>. Sep 8, 2019 at 19:44
@muffinmad: You seem to be saying that if the search string matches, say, the middle of a word, then point should be returned to the match beginning, not the word beginning. That would do what dangom's answer does. But that's not what was requested. Maybe the OP prefers that, dunno, the request was to put point at the word beginning.– DrewSep 9, 2019 at 1:24
1I must say that I did find this answer very useful. It helped me to think about quitting isearch differently than I had before.– EdmanSep 10, 2019 at 19:21
(OP) FYI: The answer you accepted does not answer the question that you posed. You said you wanted to go back to the beginning of the word that Isearch ended at. The answer you accepted goes back to the beginning of the search-string match. That coincides with the beginning of the word only if your search string matches also the beginning of the word. If it matches in the middle of the word, that answer doesn't take you to the word beginning.– DrewSep 10, 2019 at 22:48
1You are correct. I failed to see that previously.– EdmanSep 11, 2019 at 13:04
As Drew pointed out in his answer you can also end the search with another key such as
M-f, which for words boundaries works good, but my solution is kind of more general: define a key to put the cursor at the beginning (or end) of the pattern I'm searching:
(use-package isearch :bind (:map isearch-mode-map ("C-<return>" . isearch-done-opposite)) :init (defun isearch-done-opposite (&optional nopush edit) "End current search in the opposite side of the match." (interactive) (funcall #'isearch-done nopush edit) (when isearch-other-end (goto-char isearch-other-end))))
UPDATE: or in case you don't use
(define-key isearch-mode-map (kbd "<C-return>") (defun isearch-done-opposite (&optional nopush edit) "End current search in the opposite side of the match." (interactive) (funcall #'isearch-done nopush edit) (when isearch-other-end (goto-char isearch-other-end))))
C-Ret to another function
isearch-done-opposite which checks the variable
isearch-other-end which is defined in
(defvar isearch-other-end nil) ; Start (end) of match if forward (backward).
This will work with forward and backward searches.
Luckily this has been studied by Malabarba and published in his blog, Endless. I have the following in my config:
(use-package isearch :no-require t :demand t ;; Go to the start of current isearch match. (adapted from Endless) :hook (isearch-mode-end . (lambda () (when (and isearch-forward (number-or-marker-p isearch-other-end) (not mark-active) (not isearch-mode-end-hook-quit)) (goto-char isearch-other-end)))))
Check the blog entry for other solutions as well.