tednaleid / sublime-EasyMotion

Sublime Text 2 plugin to quickly jump to any character in the visible area of the active view.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Allow multiple letters for target selection

lamnatos opened this issue · comments

(This is not an issue but an enhancement idea. I could not find a way to mark it as such, sorry about that)

I think it would be useful to make it work more like the Vimium extension for Chrome works.

Vimum can mark targets with more than one letters, so instead of having only single letter targets, you get targets marked as AA, C0A etc. This has two benefits:

  • You avoid running out of targets like it happens with the current implementation
  • You can cover more targets with less characters, for example restricting the needed keys on the home row

A big disadvantage I see is in the case of targets that are too close to each other. Since the target markers are in the place of the actual text (instead of inside a pop over like in Vimium), the target markers can overlap. If for example you have two targets right next to each other and you must use two letters to address each, the first's targets mark will overlap with the second one. I'm not sure how this could be averted with the current implementation.

I like that kind of idea, but unfortunately, I don't think it's viable with the way that ST2 works. THere's no real way to do a "popup" or an overlay on top of the screen. All changes are embedded in the text (and need to be reversed). Doing multi-letter replacements would have the effect of moving the text so that if the user was looking at the 10th item, it's likely that the one they want to go to has shifted, maybe to another line or possibly even off the screen.

I'm guessing that it's because of the cross-platform nature of ST2 that it doesn't have an overlay API like that.

You could just fill the remaining chars with spaces or repeat the "hot letter" a few times until the replacement string is as long as the original.

@FichteFoll I'm not sure I'm fully understanding the behavior you're suggesting by "fill the remaining characters with spaces", can you give me a more concrete example?

Also, @lamnatos did you know that the plugin does currently support getting to any character via a different method? If there are more than 62 instances of the character you want to jump to on the page, it will decorate the first 62. If you hit "enter" without typing a character, it'll decorate the next batch of 62 characters, so if there are 124 matches, and the character you want to jump to is in the 2nd batch, just hit enter and you'll get to it with only a single extra keystroke.

After looking at Vimium I now understand that @lamnatos initially meant to use multiple characters for the "hot letters" (I'll continue to use this term). Just as @tednaleid I do not see the viability in this with ST2 or at least with how this plugin works because you specify a letter you want to go to and the plugin then highlights occurences. Vimium instead already hat a few patterns from the links it highlights and chooses key letters (e.g. initials) from them as hot letters. And with multiple pages there won't be an issue of you getting out of targets.

Well, this is what I understood:
I thought about specifying multiple letters (a sequence) which should be searched for in the current viewport.
So, with a code like this (which I had in some test file):

class TestCommandCommand(sublime_lib.WindowAndTextCommand):
    def is_checked(self):
        return True

    def run(self, param):
        string = "abcdefghijklmnopqrstuvwxyz"
        quick_panel(self.window, [c * 3 for c in string], self.on_done)

    def on_done(self, result):
        print("result", result)

you could run EasyMotion, enter "op" and it will only highlight the op in the string - you could also just go to that position, I don't know if you already do this. Or you enter "se" and then replace all the "self"s with "aalf" or "a lf" to fill the replaced characters. I think this is a different feature request but what do you think about it?

@FichteFoll that's an interesting idea, but I think there are a couple of limitations to it. The first is that it seems to be pretty close to the existing incremental find behavior.

I'm also not sure how it would know the difference between when you're typing se in self or s and that you then want to go to the 5th ("e") s on the page.

The biggest limitation is that the way that you capture characters in ST2 doesn't let you get a variable number of input characters before reacting, it only lets you get a single one as far as I can tell, so this mapping:

{ 
    "keys": ["ctrl+,", "<character>"], 
    "command": "easy_motion",
    "args": {"select_text": false} 
}

It then calls the command after the first character is typed with the first character in the character parameter of the run method:

   def run(self, character=None, select_text=False):

AFAIK there isn't any way to get 2 or more characters in that variable.

My experience with the code that I've been working with has been that 80-90% of the EasyMotion searches that I do highlight the chosen letter in the first batch of a-z0-9A-Z and 99+% of the time I can get to the character I want to get with only 1 extra enter if it isn't highlighted in the first batch. That feels like the smallest number of keystrokes possible to get just about anywhere, but I'd be interested to hear what kinds of searches people are doing where they need more than just cmd-;+a+enter+q (if we're looking for an a and it ends up being the qth item in the second batch).

I looked into the code for running the plugin and apparently I did not know of a <character> key.

Anyway, what I was thinking of is using an input panel for the sequence to search and cmd-; would call the command directly. This would add one enter but would probably remove the enter you listed above because it should not be necessary to search in a second batch/page. Btw, since you are already using an input panel for submitting the hot letter you forgot an enter at the end.
Results would be: cmd-; + ac + enter + q + enter

What came to my mind just now was using contexts in key bindings similar to jonfinerty/sublime-snake#12. You could make the cmd-; binding set a flag and bind <character> with a context to another command that would catch these characters. Binding enter with the same context would let you switch another flag, highlight the found regions and pressing a key after this would trigger the context from above where you unset both flags. This actually removes the last enter and maybe even allows live-higlighting inbetween <character> matches. To make the user be able to know whether he is typing the to-search-sequence or the hot letter you could use a different background color (scope) for live-highlighting and actual hot-linking. Furthermore, binding backspace with the context would also work. Oh, and the enter context binding from before can be used for going to the next batch/page if necessary.
Results would be: cmd-; + a + c + enter + q
or cmd-; + a + d + backspace + c + enter + q

Another compromise is to use the input panel for entering the sequence to search and then a "" context binding for the hot letter (with enter). This would only lack the live-highlighting and is slightly simpler to implement. Key input results are the same as above.

I hope you understand it even though I have problems expressing my thoughts. And no, this is not too close to incremental find, imo, because it searches onwards from the current selection and you need to press f3 or shift+f3 a bunch of times.

Edit: After I remembered that the input panel supports an on_change callback it is actually the best and most simple solution to use the last proposal.

I'm not sure if I understand 100% of what you're proposing above, but I'm wondering if, with the latest code that doesn't require an enter at the end you think it'd still be useful.

I think you're saying that you want to be able to type more than just a single character for the search term, to help it get scoped down a bit more. An enter would end the search term and would then decorate the visible targets with the normal a-z0-9A-Z stuff that EasyMotion does now.

Are you finding that you need that level of precision in the visible area with the latest code? For most code I write, I can get to my character in what I think would be fewer keystrokes than I'd need with this method. I think it's interesting, but I'm not sure I see enough variety in the visible text for it to be worth the extra complexity.

This is pretty much what I wanted to say, yeah. To be honest I never actually used this plugin a single time so I have no real "experience", even though I certainly plan to use it. I just thought that I'd use it this way so I mentioned it here.