abo-abo / swiper

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

virtual buffers usability: virtual buffers vs. candidate preselection and partial completion #132

Open tsdh opened 9 years ago

tsdh commented 9 years ago

Here's another concern about virtual buffers usability (#130): you get more matches, and thus you might need more keys to select an existing buffer. For example, I want to switch to *Group* but get offered *Group* and gnus-group.el where the latter is virtual. However, the latter is preselected (I think because I've selected it as current candidate earlier before killing that buffer).

In general, I think there should be a preference to using existing buffers. Right now, I thing that's already there with respect to the order of candidates but not with respect to preselection. I can imagine two solutions. (1) just preselect an existing buffer if there's one, or (2) make virtual buffers kick in only after some idle time (similar to ido's auto-merge feature), or (3) have a key binding which toggles virtual buffers on demand in a running buffer-completion session.

(1) is much simpler implementation-wise. However, (2) and (3) would also keep ivy-partial more functional. Depending on the size and contents of your recentf list, partial completion won't be able to do anything in certain cases when all recently opened files are considered from the start.

I think usability-wise, I'd want to have both (2) and (3) available where explicit toggling with (3) would cancel the timer of (2).

abo-abo commented 9 years ago

However, the latter is preselected (I think because I've selected it as current candidate earlier before killing that buffer).

I'll need a recipe to reproduce this. ivy-switch-buffer preselects (buffer-name (other-buffer (current-buffer))). Preselecting a virtual buffer is a bug.

In general, I think there should be a preference to using existing buffers.

I agree.

(1) just preselect an existing buffer if there's one,

That's what happens now.

or (2) make virtual buffers kick in only after some idle time (similar to ido's auto-merge feature),

I really dislike timers in almost any form. It's bad UX.

or (3) have a key binding which toggles virtual buffers on demand in a running buffer-completion session.

This can be done. While writing a command is easy, key bindings are precious. And if the command isn't bound by default, it's much less useful. For example, I've finally bound ivy-yank-word to M-j just to have a quick answer to issues about isearch-like C-w.

Maybe there should be a prefix key binding after which all possible situational commands can be bound. Do you have a preference for a prefix?

tsdh commented 9 years ago

Oleh Krehel notifications@github.com writes:

However, the latter is preselected (I think because I've selected it as current candidate earlier before killing that buffer).

I'll need a recipe to reproduce this. ivy-switch-buffer preselects (buffer-name (other-buffer (current-buffer))). Preselecting a virtual buffer is a bug.

Well, yes, that's the initial selection. But it will preselect virtual buffers once you start typing to restrict the matches. And then it seems to prefer virtual buffers over existing buffers when both have the same name. Or maybe it doesn't prefer them but at least it's possible that virtual buffers get selected.

Here's a recipe:

  1. emacs -Q -l ivy-init.el where the init file contains
(recentf-mode)
(add-to-list 'load-path "~/Repos/el/swiper/")
(require 'ivy)
(setq ivy-use-virtual-buffers t)
(ivy-mode)
  1. C-x C-f ~/test.file RET
  2. C-x C-f /tmp/test.file RET
  3. Kill the /tmp/test.file buffer
  4. C-x b test.file RET

Result: You are in a buffer associated with /tmp/test.file rather than ~/test.file for which a buffer already exists.

Actually, after step 4 you are already in the ~/test.file buffer so step 5 should be a no-op. But you can also try switching to scratch first and from there to test.file. It'll also switch to the virtual test.file buffer which implies that /tmp/test.file is found again.

(1) just preselect an existing buffer if there's one,

That's what happens now.

Yeah, I just wasn't clear enough. When doing C-x b test.f in the recipe above, the candidate test.file is selected. It is not shown in the virtual buffers face. But still if I select it with RET or TAB, the virtual buffer with the same name is opened rather than just switching to the existing buffer of that name.

or (2) make virtual buffers kick in only after some idle time (similar to ido's auto-merge feature),

I really dislike timers in almost any form. It's bad UX.

or (3) have a key binding which toggles virtual buffers on demand in a running buffer-completion session.

This can be done. While writing a command is easy, key bindings are precious. And if the command isn't bound by default, it's much less useful. For example, I've finally bound ivy-yank-word to M-j just to have a quick answer to issues about isearch-like C-w.

What's wrong with using C-w as in isearch?

BTW: ivy-yank-word moves point without setting it back.

Maybe there should be a prefix key binding after which all possible situational commands can be bound. Do you have a preference for a prefix?

No, not really. I think it should be a C-<something> binding because the most frequently used commands with completion also start with control, so your finger is already there. And it shouldn't be C-c or C-x because those are probably used up for global bindings of the user and emacs itself.

Bye, Tassilo

abo-abo commented 9 years ago

Result: You are in a buffer associated with /tmp/test.file rather than ~/test.file for which a buffer already exists.

Ah, I see. I added a work-around for this in bef708c. A better fix will come once the buffer names are uniquified. Please check if this fix works for you.

What's wrong with using C-w as in isearch?

C-w (kill-region) can actually be useful in the minibuffer. I'd like it to behave like a regular fundamental-mode buffer, except restricted to one line. So I can override only the bindings that work outside one line, like C-n or C-o, but not C-w or M-b.

BTW: ivy-yank-word moves point without setting it back.

I've mostly tested it for swiper, for which it works fine. But now I see that it misbehaves for other functions.

No, not really. I think it should be a C-<something> binding because the most frequently used commands with completion also start with control, so your finger is already there. And it shouldn't be C-c or C-x because those are probably used up for global bindings of the user and emacs itself.

I'm leaning towards C-o. There are also C-z, C-v and C-'.

tsdh commented 9 years ago

Oleh Krehel notifications@github.com writes:

Result: You are in a buffer associated with /tmp/test.file rather than ~/test.file for which a buffer already exists.

Ah, I see. I added a work-around for this in bef708c. A better fix will come once the buffer names are uniquified. Please check if this fix works for you.

Yes, it does. Thanks!

No, not really. I think it should be a C-<something> binding because the most frequently used commands with completion also start with control, so your finger is already there. And it shouldn't be C-c or C-x because those are probably used up for global bindings of the user and emacs itself.

I'm leaning towards C-o. There are also C-z, C-v and C-'.

C-v and M-v could also be used for commands which would scroll the candidate lists for about a page. Well, not sure if that's a must-have.

C-' is not so good because for many non-English keyboard layouts ' is accessible only with shift.

So that leaves C-o and C-z which are both fine to me.

abbioro commented 7 years ago

Looks like the workaround doesn't work when using ivy--regex-fuzzy.