2

Having some command automatically populate the input string is a great thing (particularly, I refer to the feature that swiper-thing-at-point provides).

However, I would like to enhance this functionality even more by being able to have the input string automatically marked after running this command. The rationale behind it is that I find myself using swiper mostly for two things:

  1. Find other occurrences of the thing that I currently have at point;
  2. Find an arbitrary text in the current buffer, regardless of thing at point.

For each of these cases, having the input string automatically marked is optimal because I can, respectively, with a single command,

  1. Start searching other occurrences of the thing at point right away;
  2. Start typing the string I have in mind right away, knowing that, whatever input string there is, it will be completely replaced (assuming delete-selection-mode is enabled), without having to check if an initial input was populated in the minibuffer and deleting it in case it was.

I have tried creating a function to do so, but the problem is that the part of the function that tries to mark the input string (which should be whole line inside the minibuffer) is only executed when I finish the swiper search, i.e., I end up selecting a region in the buffer where I executed the function (not in the minibuffer), and the swiper input string is never selected (and so I have to delete it manually). What would be the best way to solve this problem?

2

I use helm-swoop just like what you described, so the same technique can work for you in swiper too. Helm-swoop picks up the input at point and I want it to be selected automatically, so I can instantly overtype it with delete selection mode. I push the selection keys to unread command events, so they are executed automatically when swoop is waiting for input. I used a zero idle timer to push the keys, because it did not work without it for some reason, so I use it to wait until emacs becomes idle and push the keys then:

(global-set-key (kbd "C-a") (lambda ()
                              (interactive)
                              (run-with-idle-timer
                               0 nil (lambda ()
                                       (push 'S-end unread-command-events)
                                       (push 'home unread-command-events)))
                              (helm-swoop)))
  • Thank you @Tom, it works perfectly and it is exactly what I wanted. I will post my own implementation for future reference in another answer. – Arthur Colombini Gusmão Oct 20 '19 at 10:50
1

I don't have an answer related to Swiper, sorry.

But FWIW, Icicles provides what (I think) you're describing.


  1. You can insert buffer text at point into the minibuffer (appending it to what's already there).

    You can take advantage of this feature for searching by using M-e when incremental-searching. That puts you in the minibuffer to edit the search string. (Then resume Isearch, e.g. C-s.)

    You insert text at point with M-..

    So for example, you use C-s M-e M-. C-s to search for something at point. The first C-s starts searching; M-e activates the minibuffer; M-. inserts a thing at point; and the second C-s searches for it.

    If you repeat M-. then you can either (1) grab more text from the buffer, appending it to what you've already grabbed, or (2) grab something different at the cursor (replacing the thing that you just grabbed).

    The first alternative is kind of like using C-w in Isearch - it grabs successive things of the same kind. The second alternative cycles among different kinds of thing-at-point, to get to the one you want.

    You can choose which of those two behaviors for repeated M-. to use by default, with option icicle-default-thing-insertion.

    And you can change the behavior on the fly using C-u: it flips from your chosen default behavior to the alternative behavior.

    You can customize what kinds of things can be grabbed using option icicle-thing-at-point-functions.

    This all explained here: Inserting Text from Cursor.


  1. Second, there's option icicle-default-value, which controls whether the default value provided by the current command is automatically inserted in the minibuffer, so you don't need to retrieve it with M-n. My own preference for the option value is insert-end, but it sounds like you might prefer, say, preselect-end.

    These are the possible values:

    • nil - Do not insert default value or add it to prompt.
    • t - Add default value to completing-read prompt. Do not insert it.
    • insert-start - Insert default value and leave cursor at start.
    • insert-end - Insert default value and leave cursor at end.
    • preselect-start - Insert and preselect default value; leave cursor at beginning.
    • preselect-end - Insert and preselect default value; leave cursor at end.

    .

    Preselection can be useful in Delete Selection mode. It makes it easy to replace the value by typing characters, or delete it by hitting C-d or DEL (backspace). However, all of the initial input is lost if you type or hit C-d or DEL. That is inconvenient if you want to keep most of it and edit it only slightly.

    Even without Delete Selection mode you can always completely empty the minibuffer using M-k. (I use Delete Selection mode all the time, including in the minibuffer, but to clear the minibuffer I use M-k - no need to select anything.)

  • Thank you for your very comprehensive answer @Drew! I ended up implementing @Tom's answer since it worked out of the box, and also I do not want to include a whole package for a single functionality, but Icicles seems quite impressive nevertheless. I plan to take a deeper look at it and reconsider adoption when I have more time – Arthur Colombini Gusmão Oct 20 '19 at 11:04
1

For completeness, here is what I ended up implementing, based on @Tom's answer:

(defun acg/with-marked-input (&rest args)
  "Mark input of minibuffer. To be used as advice before any
function that starts with an initial input in the minibuffer."
  (run-with-idle-timer
   0 nil (lambda ()
           (push 'C-S-right unread-command-events)
           (push 'C-left unread-command-events))))

(advice-add 'swiper-thing-at-point :before #'acg/with-marked-input)

Then I binded ESC to perform abort-recursive-edit instead of minibuffer-keyboard-quit (as I had before), since then I can quit the minibuffer right away with having to click it twice (where once would solely deselect text):

(define-key ivy-minibuffer-map [escape] 'abort-recursive-edit)

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.