abo-abo / swiper

Ivy - a generic completion frontend for Emacs, Swiper - isearch with an overview, and more. Oh, man!
https://oremacs.com/swiper/
2.31k stars 338 forks source link

`ivy-set-actions` and `ivy-with-window` #2746

Open zimoun opened 3 years ago

zimoun commented 3 years ago

Dear,

This snippet

(defun ivy-git-grep-current-directory-action (x)
  (with-ivy-window
    (message default-directory)    
    (counsel-git-grep (word-at-point) default-directory)))

(ivy-set-actions
 t
 '(("G" ivy-git-grep-current-directory-action "git grep")))

is not producing the expected and I do not know if it is a bug or a misuse from my side.

I expect that default-directory is set to current directory from where I call the action. But it is not, probably because probably the (ivy--get-window ivy-last) is the minibuffer running "git grep" and not the initial window.

Concretely, if I am editing the buffer foo/bar/baz/file then M-x counsel-git-grep M-o G in that file should be run in the subdirectory foo/bar/baz only and not in the Git root.

Do I miss something?

All the best, simon

nbfalcon commented 3 years ago

This is a misuse of ivy on your part: with-ivy-window causes the minibuffer window to be selected, so the current-buffer from which default-directory is taken becomes that of the minibuffer, not the buffer you originally called your function from. From my limited experience in debugging problems with ivy, I know that it tries very hard to invoke actions in the context of the original buffer, so you needn't save the old default-directory in a lambda or anything.

Removing with-ivy-window and just directly executing (counsel-git-grep (word-at-point) default-directory) should fix this.

basil-conto commented 3 years ago

with-ivy-window causes the minibuffer window to be selected

Its docstring says otherwise:

with-ivy-window is a Lisp macro in `ivy.el'.

(with-ivy-window &rest BODY)

Execute BODY in the window from which `ivy-read' was called.
zimoun commented 3 years ago

The docstring Execute BODY in the window from which 'ivy-read' was called. seems ambiguous. Somehow ivy-read is always called from the minibuffer, therefore by specifying in the window from which, I understand window as the initial window.

Moreover, the manual about Actions, says: (section 7.3)

Currently, the action is executed in the minibuffer window context. This means e.g. that if you call insert the text will be inserted into the minibuffer.

If you want to execute the action in the initial window from which the completion started, use the with-ivy-window wrapper macro.

(defun ivy-insert-action (x)
(with-ivy-window
(insert x)))

I do not have access to my desktop computer, so I do not know the Emacs+Ivy versions, but on my laptop with GNU Emacs 27.1 and Ivy 0.13.1, both from Guix f6dfe42, it is works as expected, i.e, the previous action snippet is doing what I am expecting.

basil-conto commented 3 years ago

Somehow ivy-read is always called from the minibuffer

No, it's called from wherever it's called. ;) Most of the time this is a normal non-minibuffer window; sometimes ivy-read is called recursively within the minibuffer window.

zimoun commented 3 years ago

@basil-conto I do not have an example in my workflow where I am doing "actions" without calling them from the minibuffer, somehow. :-) Anyway, thanks for the explanation. :-)

basil-conto commented 3 years ago

I do not have an example in my workflow where I am doing "actions" without calling them from the minibuffer

Right, but where ivy-read is called from need not be the same place that actions are called from.

zimoun commented 3 years ago

Right, but where ivy-read is called from need not be the same place that actions are called from.

Yes, for sure. But the report is about "actions". ;-)

Anyway, my point is 1. the documentation says that ivy-with-window allows to execute the action in the initial window and 2. it is not the case as I am reproducing with the minimal example.

Therefore, if I am not misusing Ivy, then it seems a bug. Could you confirm ?

basil-conto commented 3 years ago

Yes, for sure. But the report is about "actions". ;-)

Sure, but I was replying not to the OP, but to the spinoff confusion about ivy-read, its actions, and ivy-with-window.

Anyway, my point is 1. the documentation says that ivy-with-window allows to execute the action in the initial window and 2. it is not the case as I am reproducing with the minimal example.

Therefore, if I am not misusing Ivy, then it seems a bug. Could you confirm ?

If the documentation doesn't agree with the behaviour, then of course there's a bug somewhere. :)