Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Quickmatch feature #569

Closed

Conversation

mykola-hrebenyuk
Copy link

@mykola-hrebenyuk mykola-hrebenyuk commented May 8, 2016

Fixes #124.

PR provides an alternative to navigation of candidates.

Instead of pressing consecutively a key for up and down action to iterate candidates, you can now pick any candidate by hit quickmatch (new action in --bind) toggle key and a label appeared on screen next to the candidate of choice.
In other words it's O(1) for any candidate on screen:

gifrecord_2016-05-08_191443
gifrecord_2016-05-08_193943

How to enable

  • bind an easy-reached key to quickmatch action
  • provide set of labels you want to pick up from. optional

export FZF_DEFAULT_OPTS="--bind \':quickmatch --quickmatch-labels=bgtasdfqwerzxcvhjklmnyuop12345,."

@justinmk
Copy link
Contributor

justinmk commented May 9, 2016

This pretty much defeats the purpose of a fuzzy-finder.

@mykola-hrebenyuk
Copy link
Author

Not really. This rather defeats navigating of narrowed list of candidates.
If your eyes already spotted the right candidate on the screen
you don't need to waste further your time with:

  • narrowing down it more
  • or picking it by up, up, up, Enter

Just press two keys to select it instead. (quickmatch trigger + a letter)
No Enter, no ctrl-p/ctrl-n workflow anymore.

Maybe it's just me, but it's much convenient to use home row keys for picking up.
Finally, it doesn't replace anything but provides additional way of selecting a candidate.

@junegunn
Copy link
Owner

I'm assuming this PR is a proof of concept prototype to open up a discussion as it lacks new test cases and documentation. I also noticed a couple of bugs in your implementation and there are some points I'd do slightly differently both implementation-wise and interface-wise, don't quite like the name "quickmatch" in the first place.

I rejected the idea the last time since I felt it was not really needed. It's probably a matter of personal preference so I'm not trying to make a point. I'm just providing another perspective.

Most of the time, I don't move my cursor upwards at all. I don't even try to browse the screen to find the item of my interest. My focus is pinned on the first few lines, and I type in the query until the one ends up in there. I prefer this way since there isn't any mental context switches in the process. Type in the query until one match is left, enter, it's simple. The process usually does not take more than a couple seconds for me. Now compare that to

  • Look through the whole screen to find the right one that I'm trying to pick
  • Decide whether if I'm going to use ctrl-p (ctrl-k) or to use this new feature
  • Press the key to enable the new feature
  • Check the label for the line that I should press
    • Make sure to press the right key, as there's no turning back when you mess up

(Also this can't be used when you want to multi-select (--multi) items.)

So basically I'm not convinced that fzf needs this. But like I said it's a matter of personal preference and I can see some would find it useful and of course I have zero evidence to prove objective superiority or inferiority of one method over the other. And you have made a good point that the new feature is only complementary and does not require a huge change to the code base.

We're in no rush. I'll sleep over it for a few days and give you feedbacks.

@justinmk
Copy link
Contributor

justinmk commented May 10, 2016

Press the key to enable the new feature

An alternative to consider: instead of a "label selection mode", always show the labels, and treat label-selection as a "special query" (like the ' modifier), so that labels can be used to narrow results. Say that , is the "label pseudo-query" prefix, then given a result list:

a /foo/bar1
b /foo/bar2
c /foo/bar3
d /foo/bar4
e /foo/bar5

Appending ,c to the query narrows the results to a single item:

c /foo/bar3

That avoids the "no turning back" problem, and achieves some UI consistency (query-driven, no new "modes").

@mykola-hrebenyuk
Copy link
Author

mykola-hrebenyuk commented May 10, 2016

I'm assuming this PR is a proof of concept prototype to open up a discussion as it lacks new test cases and documentation.

Correct. I'll add/correct what are left if PR will be accepted otherwise it's suits my needs.

Most of the time, I don't move my cursor upwards at all. I don't even try to browse the screen to find the item of my interest. My focus is pinned on the first few lines, and I type in the query until the one ends up in there. I prefer this way since there isn't any mental context switches in the process. Type in the query until one match is left, enter, it's simple.

And what if one did not end up? Or ended up wrong one?
Then you should backspace couple of times to correct your query.

Sometimes, I found myself in situation when I don't know exactly what I looking for. So I can't just type till it yields the only one candidate. Instead I type a little waiting for result to come up then type again then enter or ctrl-p, ctrl-p depending on where I ended up.

Imagine, you want to peek into css file in a web project. What you vaguely remember is that it's something related to main styles. So you type main css$ and wait a bit to results show up then you can found that main.css is scattered across exploded/, src/, core/, html/ etc. Starting from this point you can either narrow down it further by struggling to exclude some uninterested paths or nail it with quickmatch to pick what you see.

Also it would be useful with any sort of a short list. When you know your choice will be already present on screen in recent entries even without narrowing. Bcommits, oldfiles, mru, recent shell commands, tmux windows/session, vim buffers come to mind. There it competes with ctrl-p.

Remember in all possible cases what you're needed is just to type two easy-reached keys usually from home row. Two keys to rule them all. That's it.

@mykola-hrebenyuk
Copy link
Author

mykola-hrebenyuk commented May 10, 2016

"No turning back" is not the problem if you're touch typing. That I believe most of vim/cli users are.
If you aren't than quickmatch makes no sense.

The key point is the feature let you select what you want in speedy and convenient way when you really need it.

@junegunn
Copy link
Owner

And what if one did not end up? Or ended up wrong one?
Then you should backspace couple of times to correct your query.

Naturally, yes. I don't see how the new feature is different in that regard except for very small input that fits in one screen. Anyway the point is that the whole process is strictly "query-driven" as @justinmk pointed out.

"No turning back" is not the problem if you're touch typing.

Touch typing does not completely prevent typos. But that was not my point anyway, we can be looking at the two far ends of the screen.

hadoop

I guess you see my point. It's easy to get confused while moving one's focus from the far right to the far left.

And as I mentioned earlier, the method cannot be used when we want to select multiple items with tab and shift-tab since it exits immediately. One thing we can consider is to make it only jump to the target. So that 1. we can check if the cursor is positioned on the right item, 2. and we're given a choice to either press tab or enter. The obvious downside is that it requires an extra keystroke.

@mykola-hrebenyuk
Copy link
Author

mykola-hrebenyuk commented May 11, 2016

I guess you see my point. It's easy to get confused while moving one's focus from the far right to the far left.

Of course it's not a holy grail but a triggered feature you can summon when you need it.

One thing we can consider is to make it only jump to the target. So that 1. we can check if the cursor is positioned on the right item, 2. and we're given a choice to either press tab or enter. The obvious downside is that it requires an extra keystroke.

It feels like a bit of overingeneering. I'd rather go with simplicity and unobtrusiveness of take&exit (trigger + home row key) over bloating it with support of mulitselect (separation of concerns). Anyway multiselect is not what it made for. Finally we can consider one in future iterations if it will be requested.

@mykola-hrebenyuk
Copy link
Author

I forgot to mention that in current implementation it actually toggle. (Maybe it's not obvious looking at provided screencasts and description)

if you triggered it and then change your mind you can un-toggle it and continue playing around with your query.

@justinmk
Copy link
Contributor

justinmk commented May 11, 2016

The UX described in #569 (comment) could support multiselect by allowing multiple labels to be specified after the pseudo-query modifier.

E.g. given the pseudo-query ,ac instead of narrowing, it would highlight the corresponding items:

[a /foo/bar1]
 b /foo/bar2
[c /foo/bar3]
 d /foo/bar4
 e /foo/bar5

@junegunn
Copy link
Owner

junegunn commented May 12, 2016

@mhrebenyuk Well, speaking of "separation of concern", I would argue that the alternative approach suggested above provides exactly that by just being another way of moving your cursor instead of being a new mode of operation that is a combination of two actions (move + accept). It blends well with the rest of the interface.

  • CTRL-P / CTRL-K / Mouse wheel-up
    • Move cursor up
  • CTRL-N / CTRL-J / Mouse wheel-down
    • Move cursor down
  • PgUp
    • Move cursor up by a page
  • PgDn
    • Move cursor down by a page
  • <trigger key><label> / Mouse-click
    • Move cursor to the designated position

It acts like <line no>G movement of Vim. It allows you to move around the screen and do whatever you want to do. It doesn't suffer the aforementioned "no turning back" problem. In my opininon, combining it with accept action should be considered as the next step that builds upon this new "movement". And I'm not against the direction per se.

Anyway multiselect is not what it made for.

We're discussing pros and cons of different approaches and trying to come up with a better, more flexible solution. I shared my concerns about your proposal and you agreed that it has limitations. I hope you don't dismiss suggestions to tackle those very problems saying that they are overengineered, overbloated or not on the point because they don't meet your specific requirement or you don't care about the problems. fzf is a hugely popular tool that is used by many users with different preferences. We don't add new features without careful consideration beforehand. Like I said, we're in no rush. We're still in the process of brainstorming. You can always use your fork until we reach the conclusion (or after that).

@justinmk Interesting idea. It's a bit unclear though what should happen when you press enter after ,ac, or tab when multi-select is not enabled. Another concern is that as it's a part of the query and we can type in more characters, the mappings between the labels and the items will change (foo ,ac -> foo ,ac bar) and then a and c may no longer point the items we want.

@mykola-hrebenyuk
Copy link
Author

mykola-hrebenyuk commented May 12, 2016

instead of a "label selection mode", always show the labels, and treat label-selection as a "special query"

Permanently shown labels are kind of distraction.

As the last argument for original implementation, I'd like to remember that fzf is based on premise of being as effective as possible with the less time is spent on fzf the better it is.

From that perspective it's difficult to compete with <trigger> + <label> approach. As it operates in constant time and requires only two key to be pressed.

Compare that to other suggestions where you have to hit at least extra Enter to finish.

@junegunn junegunn closed this in 6d235bc May 17, 2016
@deathmaz
Copy link

Hi @junegunn, first of all thank you very much for your work, can't imagine my life without fzf.
Can you please explain how this feature can be used?

@balta2ar
Copy link

Maybe it's worth updating the docs and adding demo gifs as well.

@junegunn
Copy link
Owner

junegunn commented May 18, 2016

@deathmaz The feature will be included in the next version (0.12.2) and the man page will be updated accordingly at that point to avoid confusion. The specification is not final until then. Anyway if you build the binary from the source, you can bind a key to jump or jump-accept action.

fzf --bind ';:jump,::jump-accept'

screen shot 2016-05-19 at 12 48 01 am

@deathmaz
Copy link

Thank you very much!

@justinmk
Copy link
Contributor

The striping is a nice touch. And the non-chorded activation with ; feels nice.

@mykola-hrebenyuk
Copy link
Author

mykola-hrebenyuk commented May 18, 2016

Any chance to combine jump with jump-accept?

For example, if a bind key for jump is the same as for jump-accept (i.e. fzf --bind ';:jump,;:jump-accept') then start selection in single mode (like in suggested implementation), otherwise go with multiselect and jump-accept.

If fzf is not intended to be used in multiselect mode that will save one keystroke to be pressed.

@junegunn
Copy link
Owner

I can understand the motivation but that breaks the contract where the last binding for a key overrides the earlier bindings. It's not a dynamic change of behavior while fzf is running so I guess it's better to leave it up to the caller to choose the right set of options.

fzf --no-multi --bind ';:jump-accept'
fzf --multi --bind ';:jump'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants