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

Add E (end of WORD), and fix up e (end of word). #160

Merged
merged 7 commits into from
Mar 1, 2016

Conversation

tma-isbx
Copy link

No description provided.

@johnfn
Copy link
Member

johnfn commented Feb 24, 2016

Hey @tma-isbx! This is looking pretty good, but one thing that I noticed is that in a case like this:

word word word|

word

With | being the cursor, if I press e, the cursor doesn't make it to the next word and actually the extension crashes! I left you a comment where I think this happens. Could you fix that case and add a test for it? Thanks!

regex.lastIndex = 0;
while (true) {
let result = regex.exec(currentLine.text);
if (result === null) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we get into an infinite loop.

Traversing empty lines/whitespace only lines should
match vim.
@tma-isbx
Copy link
Author

Fixed infinite loop occurring with w/b/e when trying to traverse empty lines.

Also made sure to match vim's behavior.

w/W stops on empty lines, but skips over whitespace only lines.
b/B stops on empty lines, but skips over whitespace only lines.
e/E skips over both empty lines and whitespace only lines.

@johnfn
Copy link
Member

johnfn commented Feb 26, 2016

Nice! Those are some bizarre edge cases...

You've got me wondering though. Your code seems a little complicated. The way I'd write this for word ends might look something like this (this is pseudocode, btw)

for (let line = currentLine(); line < maxLines; line++) {
    for (position of wordRegex.exec(currentLine.getText()).allPositions()) {
        if (position > currentPosition) { return position; }
    }
}

return endOfDocument();

It seems this could easily be generalized to all of wWeEbB. Is there any reason why such an approach wouldn't work here?

@tma-isbx
Copy link
Author

I've cleaned it up a little bit. It is fundamentally along the same lines as the psuedo code.

Fixed a bug in the regex that required the previous guards against empty lines (so was able to remove those). But still have the special case logic to stop on empty lines.

@johnfn
Copy link
Member

johnfn commented Feb 27, 2016

Hey @tma-isbx , check this out: 131bf4f

I was able to clean up your code a little bit by incorporating the empty line case in the regex that you use for matching. I also tightened up the outer loop by making it loop directly over current line rather than keeping track of that separately. Finally, I decomposed out the bit of code that turns regexes into positions that match because you use that in a couple different places.

Could you finish off the work I've done (I only did it for the 'w' motion so far) and then commit that? Then I think we can merge!

@tma-isbx
Copy link
Author

Looks good. I think it could be directly applied to wordLeft, but I think the regex change breaks e/E which doesn't stop on empty lines (maybe not breaks but e/E would probably need some special handling). And another version of allPositions will be needed for e/E (though it may be possible to use it with just different regexes -- something based off of \S\s+, though there are probably some corner cases there).

I'll take a look.

@johnfn
Copy link
Member

johnfn commented Feb 27, 2016

Yeah, the way I see it we could just use separate regex rules for the different motions - make e/E the base regex and then add ^$ onto it and make it the w/W regex. Ideally the regex could actually match the end of the word in the e/E case vs the beginning of the word in the w/W case. What's wrong with allPositions in the e/E case? Or is it the same issue?

@tma-isbx
Copy link
Author

Current implementation of e/E uses the same word/WORD regexes but uses match.position + match.length as the returned position to find the end of word/WORD.

@tma-isbx
Copy link
Author

Updated.

@johnfn
Copy link
Member

johnfn commented Mar 1, 2016

Ah, beautiful! :)

johnfn added a commit that referenced this pull request Mar 1, 2016
Add E (end of WORD), and fix up e (end of word).
@johnfn johnfn merged commit 663f3b5 into VSCodeVim:master Mar 1, 2016
This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants