3

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?

3

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-b runs the command backward-word (found in global-map), which is an interactive compiled Lisp function in simple.el.

It is bound to M-b, ESC left.

(backward-word &optional ARG)

Move backward until encountering the beginning of a word.

With argument ARG, do this that many times. If ARG is 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 char-script-table), but 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-strictly instead. See Info node (elisp) Word Motion for details.

  • M-b is not very useful here if search term is not in the beginning of the word. In such cases C-r will help: C-s acc C-r <RET>. – muffinmad Sep 8 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. – Drew Sep 9 at 1:24
  • I must say that I did find this answer very useful. It helped me to think about quitting isearch differently than I had before. – devcom Sep 10 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. – Drew Sep 10 at 22:48
  • You are correct. I failed to see that previously. – devcom Sep 11 at 13:04
3

As Drew pointed out in his answer you can also end the search with another key such as M-b or 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 use-package:

(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))))

Basically, map C-Ret to another function isearch-done-opposite which checks the variable isearch-other-end which is defined in isearch.el as:

(defvar isearch-other-end nil)  ; Start (end) of match if forward (backward).

This will work with forward and backward searches.

  • Is there some purpose to using use-package for a loaded-by-default library? I don't see any reason to introduce the dependency... a works-for-everyone answer would seem better. – phils Sep 8 at 11:21
  • No there's not, that's just how I have it in my config. – Anler Sep 8 at 11:29
1

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.

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.