2

counsel-git-grep is nice to search git repository, but by default it can't show the candidate lively. Meaning if I use down arrow to select the next candidate, the buffer doesn't change, and one solution is to use the hydra C-o and then press C to toggle "calling" from off to on. But looks like the default one is off, so every time I use this command, I have to do the same toggle again and again. Is there a way to set the default value of "calling" to on?

Update

Looks like the default value shouldn't change, otherwise other ivy commands don't work as well, so I am using

(defun my-counsel-git-grep ()
  (interactive)
  (let ((ivy-calling t))
    (counsel-git-grep)))
  • 1
    For live updates I press C-M-n and C-M-p in place of C-n and C-p. The default bindings (and also C-v) are useful for making sure the correct file is found, instead of opening 100 random files. – abo-abo Jun 15 '17 at 17:46
1

N.B. See abo-abo's comment for the quickest and IMO best (most idiomatic) solution.

I believe the variable responsible for this behaviour of counsel-git-grep is ivy-calling, whose documentation states

When non-nil, call the current action when ‘ivy--index’ changes.

So when the value of this variable is non-nil, moving to a different candidate in any ivy-based command will call the current action on the new candidate (in counsel-git-grep, this defaults to jumping to the location of the selected candidate).

You can enable this behaviour by default for all ivy-based commands with

(setq-default ivy-calling t)

Update

As OP correctly points out, setting ivy-calling globally, as I previously proposed, will usually be unfavourable. Although (1) OP's custom command is a perfectly good solution, and (2) advising functions is discouraged where avoidable, my personal preference in this case would be the following advice:

(defun my-counsel-git-grep--advice (grep &rest args)
  "Call `counsel-git-grep' with `ivy-calling' enabled."
  (let* ((sym 'ivy-calling)
         (def (default-value sym)))
    (unwind-protect
        (progn
          (set-default sym t)
          (apply grep args))
      (set-default sym def))))

(advice-add #'counsel-git-grep :around #'my-counsel-git-grep--advice)

Similarly in Emacs 25 or newer:

(define-advice counsel-git-grep
    (:around (grep &rest args) my-turn-on-ivy-calling)
  "Temporarily enable `ivy-calling'."
  (let* ((sym 'ivy-calling)
         (def (default-value sym)))
    (unwind-protect
        (progn
          (set-default sym t)
          (apply grep args))
      (set-default sym def))))

The benefit of using advice over a custom function in this case is that counsel-git-grep gets to keep any optional arguments and its interactive spec for free (i.e. without the user needing to maintain the custom function to match upstream).

  • Looks like ivy-calling is a global setting, and is it possible to only set it for counsel-git-grep? I checked the code of ivy-occur-next-line (or previous line), if we could get the the current command, then I might skip the calling of ivy-calling, some thing like if current-command == counsel-git-grep or ivy-calling ==t then call the action (I am not using elisp here). Is there any method to know the current calling command? – Daniel Wu Jun 14 '17 at 1:24
  • @DanielWu The current command, or "caller" in ivy terminology, can be determined via (ivy-state-caller ivy-last). For example, you can check (eq (ivy-state-caller ivy-last) 'counsel-git-grep). I don't think the ivy-occur-* commands are relevant in this case, however. If you really intend to check the current caller I think the function ivy-set-index is the place to do that. – Basil Jun 14 '17 at 17:41
  • @Basil I am using emacs 25.1 (spacemacs) After I added your define-advice counsel-git-grep to .spacemacs, it doesn't work. Did you test it? – Daniel Wu Aug 2 '17 at 9:02
  • @DanielWu I thought I had, but I must have been mistaken. I'll see if I can come up with a workaround, though I've noted in my answer that abo-abo's approach is the correct one. – Basil Oct 13 '17 at 23:43
  • @DanielWu Should work now; the problem was that ivy would reset the buffer-local variable ivy-calling to nil internally after the let-binding in our advice. – Basil Oct 14 '17 at 0:02

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.