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

Better integration with `find-file` and friends without `counsel-find-file` #2353

Open Alexander-Shukaev opened 4 years ago

Alexander-Shukaev commented 4 years ago

The problem with counsel-find-file is that it can only be used by remapping find-file to it. There are other sister functions like find-file-other-window, find-file-other-frame, and etc. To cover them, corresponding counsel-* functions have to be implemented and remapped. This quickly gets tedious and error-prone.

AFAIK, either counsel-find-file or find-file (with ivy enabled) will both boil down to simple ivy-read invocation albeit with different arguments of course. So is there already a hooking mechanism already available (or otherwise worth implementing), where instead of implementing something like counsel-find-file, we'd rather intercept/enhance/modify arguments to ivy-read based on :caller (which, for example, in case of find-file would be read-file-name-internal itself).

For example, to teach find-file and all other functions internally using read-file-name-internal to do what counsel-find-file does, one would intercept ivy-read (e.g. with advice-add), see that :caller is read-file-name-internal, and in this case apply ivy-read as

ivy-read prompt #'read-file-name-internal
            :matcher #'counsel--find-file-matcher
            :initial-input initial-input
            :action #'counsel-find-file-action
            :preselect (counsel--preselect-file)
            :require-match 'confirm-after-completion
            :history 'file-name-history
            :keymap counsel-find-file-map
            :caller #'read-file-name-internal

similar to how counsel-find-file does that explicitly.

basil-conto commented 4 years ago

The problem with counsel-find-file is that it can only be used by remapping find-file to it.

No, it can be used just like any other command, via custom key bindings or otherwise.

To cover them, corresponding counsel-* functions have to be implemented and remapped. This quickly gets tedious and error-prone.

I think that's an exaggeration, as it's the approach that vanilla Emacs has followed until now, and it seems to work fine in practice.

So is there already a hooking mechanism already available (or otherwise worth implementing), where instead of implementing something like counsel-find-file, we'd rather intercept/enhance/modify arguments to ivy-read based on :caller

Not the same thing, but FWIW many Ivy and Counsel functions, including counsel-find-file, already take a j action for opening in another window and an f action for opening in another frame.

For example, to teach find-file and all other functions internally using read-file-name-internal to do what counsel-find-file does, one would intercept ivy-read (e.g. with advice-add)

Sounds pretty invasive for a library to do without built-in support from Emacs in the form of a variable/hook.

What use case do you have in mind for which the current j/k actions or counsel-find-file-other-window and counsel-find-file-other-frame commands don't cut it?

dgutov commented 3 years ago

IIUC, you want to set read-file-name-function to some alternative that delegates to Ivy.