1

Edit: Highlight text that matches the marked region, without the use of any key, but just by having a region marked. Then have two commands to directly move across the highlighted text, forward and backward.

Edit: For example if I mark "hello", automatically highlight all the occurrences that are equal to "hello". If I mark "hello w", highlight all the occurrences equal to "hello w". Then use two keys to move forward and backward respectively.

A third key to toggle between three options:

  1. Search (default): take marked region as the search for parameter.

  2. Search and replace: preserve search for parameter and prompt for the replace with parameter.

  3. Search and replace with regexp: preserve replace with parameter and prompt the search for parameter as the starting point of the regexp.

A basic option would be a command to turn on/off the "on the fly" behavior. A more advanced option would be to use the "on the fly" behavior only for words/symbols/expressions marked in its entirety, or tweak minimum/maximum criteria required to perform automatic search, so that for example making it necessary that the mark have three or more characters, and no more than one line.

I already use such tool, but not to work the way mentioned ("on the fly"). Such tool is isearch. The best solution would be to use that same tool, but if not, then maybe there is a package or code that implement it in another way?

Hopefully it does not mess up with multiple cursors, so that multiple cursors have the highlight precedence.

If there is no complete solution, the most approaching is welcomed.

mikl
  • 413
  • 3
  • 19
  • Does [`highlight-symbol`](https://github.com/nschum/highlight-symbol.el) meet your needs? Check out its readme page on github, or even better.. try it out by installing from Melpa. – Kaushal Modi May 04 '16 at 02:58
  • No because it only highlight symbols, not other semantic expressions or partial strings. – mikl May 04 '16 at 03:01
  • You might then want to try out the `swiper` package which has very good integration with multiple-cursors and occur. You can choose to use the marked region as initial swiper search pattern, but wrapping `(swiper (buffer-substring-no-properties (region-beginning) (region-end)))` in an interactive function. The interface or the search flow is quite different from the traditional Isearch, but it might suit your needs. Again, try it out to decide. – Kaushal Modi May 04 '16 at 03:13
  • 1
    I think the term "search" is misleading. In my mind at least, it refers to moving point (cursor) to the text being searched for. IIUC, what you want is highlighting first, and then possibly act on the text upon pressing keys. – YoungFrog May 04 '16 at 08:53
  • Edited to make it more clear – mikl May 04 '16 at 19:29

2 Answers2

2

I'm mostly trying to address the "automatically highlight text matching region" part in this answer : I don't know if it exists, but it seemed pretty straightforward to write an initial rudimentary version, so I did just that. The idea is simply to use activate-mark-hook to highlight region when mark gets activated using highlight-region. Here's the result :

(also available at https://github.com/YoungFrog/highlight-region -- updates to the code, if any, will only go to the repo)

(defvar-local highlight-region--highlighted-text "")

(define-minor-mode highlight-region-mode
  "Automatically highlight current region when mark is active."
  nil nil nil
  (highlight-region--unhighlight-region)
  (remove-hook 'activate-mark-hook #'highlight-region--highlight-region t)
  ;; as for GNU Emacs 25.0.93.1 (i686-pc-linux-gnu, X toolkit, Xaw scroll bars) of 2016-05-03
  ;; it seems that the following behaviour of activate-mark-hook described in its dosctring :
  ;; >> It is also run at the end of a command, if the mark is active and
  ;; >> it is possible that the region may have changed.
  ;; actually doesn't work. Thus let's add ourselves to post-command-hook...
  (remove-hook 'post-command-hook #'highlight-region--highlight-region t)
  (remove-hook 'deactivate-mark-hook #'highlight-region--unhighlight-region t)
  (when highlight-region-mode
    (add-hook 'activate-mark-hook #'highlight-region--highlight-region nil t)
    (add-hook 'post-command-hook #'highlight-region--highlight-region nil t)
    (add-hook 'deactivate-mark-hook #'highlight-region--unhighlight-region nil t)))

(defun highlight-region--highlight-region ()
  "Highlight currently active region"
  (when (use-region-p)
    (let ((str (buffer-substring-no-properties (region-beginning) (region-end))))
      (unless (or (string= "" str)
                  (string= str highlight-region--highlighted-text))
        (highlight-region--unhighlight-region)
        (setq highlight-region--highlighted-text str)
        ;; TODO: add a face `highlight-region' and use it.
        (highlight-regexp (regexp-quote str))))))

(defun highlight-region--unhighlight-region nil
  (unhighlight-regexp (regexp-quote highlight-region--highlighted-text))
  (setq highlight-region--highlighted-text ""))

I'd like to also mention selected.el (https://github.com/Kungsgeten/selected.el) which defines a keymap that is active when the region is active. This will let you define key bindings that act on the region specifically.

YoungFrog
  • 3,496
  • 15
  • 27
  • It does just what I wanted combined with selected and isearch. Also thanks to Drew's function which I used with selected.el to directly move forward and backward with C-s and C-r, but being careful to use ´(deactivate-mark)´ if neccessary. – mikl May 05 '16 at 08:49
1

Isearch+ provides these features.

  • Optional restriction of search to the active region, controlled by option isearchp-restrict-to-region-flag. Deactivation of the active region is controlled by option isearchp-deactivate-region-flag. Both of these are available for Emacs 24.3 and later. You can use C-x n (command isearchp-toggle-region-restriction) during search to toggle isearchp-restrict-to-region-flag.

  • That applies literal search and regexp search.

  • If you also use library Mode-Line Position (modeline-posn.el) then not only can you restrict Isearch to the active region but you can keep that restriction when you invoke a query-replacement command from Isearch (e.g. M-% from Isearch, to use query-replace). The main job of that library is to show information about the active region in the mode line. And whenever you invoke a replacement command or Isearch for the active region, that region information is highlighted specially. See Mode-Line Position for screenshots and more info.

  • With just Isearch+, you can replace on demand while searching.

    When you visit a search hit, you can perform an action on it. Use C-M-RET (command isearchp-act-on-demand) to invoke the action function that is the value of option isearchp-on-demand-action-function. That function is passed the current search-hit string and its start and end positions in the buffer. Search moves to the next hit in the same search direction, so just repeating C-M-RET carries out the action on subsequent hits.

    The default value of isearchp-on-demand-action-function is function isearchp-replace-on-demand, which replaces the search hit. This means that you can replace (or delete) chosen search hits on demand. By default, the replacement string is empty, so with no prefix argument the action is to delete the search hit (replace it with nothing).

  • With a prefix argument, isearchp-replace-on-demand (C-M-RET) prompts for the replacement, which is used thereafter until you again use a prefix arg. Since you can use a prefix arg at any time, you can provide different replacements for different search hits. When prompted, if you clear the minibuffer and hit RET, hit replacement just becomes search-hit deletion. [NOTE: To use a prefix arg within Isearch, you must set isearch-allow-prefix (if available) or isearch-allow-scroll to non-nil.]

    • With a plain prefix arg (C-u) or a numeric prefix arg of value 1 (e.g. C-1), isearchp-replace-on-demand replaces only the current search hit.

    • With a negative prefix arg (e.g. M-- or C--), isearchp-replace-on-demand toggles automatic replacement by just searching. Automatic replacement means that each time you use a search key (e.g. C-s) to visit a search hit, the hit is automatically replaced, without your needing to hit C-M-RET. Using a prefix arg again with C-M-RET cancels this (as does quitting and restarting Isearch).

    • With a positive prefix arg N (e.g. C-8 or C-u 200), isearchp-replace-on-demand replaces N search hits (but it stops at the search limit, if reached).

    • With a zero prefix arg (e.g. C-0), isearchp-replace-on-demand replaces all remaining search hits (up to the search limit).

  • When you use on-demand replacement (with C-M-RET) the replacement text can be either inserted literally, as is, or interpreted as in query-replace-regexp. In the latter case, you can use \&, \=\N, \#, \, and \?.

    • For example, suppose you use a regexp-search pattern of \(e\)\|a and a replacement pattern of \,(if \1 "a" "e"). Each C-M-RET will then swap e for a and vice versa.

    • See the doc for query-replace-regexp and node Regexp Replace of the Emacs manual for more information.

    • (Note that \? is supported, but it is not very useful in this context, because it prompts you to edit the result each time you hit C-M-RET. Instead, use C-u C-M-RET whenever you want to change (edit) the replacement pattern.)

  • You can use C-M-` (isearchp-toggle-literal-replacement) anytime during Isearch to toggle whether replacement text is used literally or interpreted per the special regexp-replacement constructs.

    • Note that the use of the special regexp replacement patterns is unrelated to the kind of incremental search: literal string search or regexp search. Just remember that the way to switch on/off the special behavior of \& and so on is to use C-M-`.

Sorry, but I don't understand this part of your request:

If the marked region changes, start over with search (default). This is the automatic aspect that I mean.

Also, perhaps I misunderstand your requested use of the region. If you do not mean that you want to search only the region, but you instead want to search (the whole buffer) for the text that is in the region, then that is easily accomplished (even in vanilla Isearch), by using M-w to save the region to the kill-ring and then M-y during Isearch to yank it onto the search string.


After your comment and your edit, to clarify what you want -

This command will give you what you are apparently looking for: automatically search for the text that is in the active region. Just bind it to a key.

(defun foo ()
  (interactive)
  (let ((str  (if mark-active
                  (buffer-substring (region-beginning) (region-end))
                "")))
    (isearch-forward nil 1)
    (isearch-yank-string str)))
Drew
  • 75,699
  • 9
  • 109
  • 225
  • By searching the marked region automatically I mean that as one is editing normally, each time text is marked, perform a search and highlight occurrences. I do not mean to search inside a region. These features are what I expect, but the main feature I am looking for is to "search automatically the marked region", is that what you mean too? – mikl May 04 '16 at 02:42
  • I mean take the marked region as the argument for the search function. For example if I mark "car", automatically highlight all he occurrences of "car". – mikl May 04 '16 at 02:46
  • In that case, as I said, use `M-w` to save (copy) the region text to the `kill-ring`, and then when you are in incremental search (`C-s` or `C-M-s`), use `M-y` to yank (paste) that copied text to the search string. Then hit `C-s` or `C-M-s` again to search for it (and temporarily highlight all occurrences). See the Emacs manual, node [Incremental Search](http://www.gnu.org/software/emacs/manual/html_node/emacs/Incremental-Search.html). See also [this](https://www.emacswiki.org/emacs/IsearchPlus#isearchp-kill-ring-save) for info about copying text at or near the cursor to the search string. – Drew May 04 '16 at 02:54
  • The function helped a big deal, combined with YoungFrog's answer – mikl May 05 '16 at 08:54