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

Implement quoted text objects #483

Merged
merged 1 commit into from
Jul 25, 2016

Conversation

ascandella
Copy link
Contributor

Fixes #471, #287


// Didn't find one behind us, the string may start ahead of us
for (let i = start; i < corpus.length; i++) {
const currentChar = corpus[i];
Copy link
Contributor Author

@ascandella ascandella Jul 20, 2016

Choose a reason for hiding this comment

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

I feel a bit bad (but not too bad) about copy-pasting the body of these loops. Really what I want is to have some thing that takes an iterator and returns Either<position **or** notfound> and then pass that iterator to the loops. But, I'm a total TypeScript noob and I didn't see an obvious way to do it.

@ascandella ascandella force-pushed the quoted-text-objects branch 2 times, most recently from 87e493b to 28f1c29 Compare July 20, 2016 03:25
// Didn't find one behind us, the string may start ahead of us
for (let i = start; i < corpus.length; i++) {
const currentChar = corpus[i];
if (currentChar === char && corpus[i - 1] !== this.escapeChar) {
Copy link
Member

Choose a reason for hiding this comment

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

I'm a little worried about the escape char, this can't handle \\", right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Correct, that is a limitation.

I looked at the algorithm used by other vim emulation stacks and this seemed to be the best one. I think we could handle that case by having another look-behind for another escape character? Or are there other pathological cases we'd still be missing?

Copy link
Member

Choose a reason for hiding this comment

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

We have handled escape char while parsing subsitute commands https://github.com/VSCodeVim/Vim/blob/master/src/cmd_line/subparsers/substitute.ts . The logic is reading char one by one and handling every \. I suppose we can do the same thing here?

For now I don't see any other case but I'll investigate.

@rebornix
Copy link
Member

Everything looks good to me except the \ escaping, it won't be too complex to handle as we already did that in substitute parsing :)

@ascandella ascandella force-pushed the quoted-text-objects branch 2 times, most recently from 5666361 to 977e7b5 Compare July 20, 2016 07:18
@ascandella
Copy link
Contributor Author

@rebornix updated with handling of escaped backslashes

@rebornix
Copy link
Member

@sectioneight I'm really sorry that I didn't think carefully about the escaping before I made suggestions. Checking double \ before " is somewhat not perfect, for example "abc\\\"def" will pass the validation

currentChar === char &&
(corpus[i - 1] !== this.escapeChar || corpus[i - 2] === this.escapeChar)

but it's not a true closing ". Now it turns out to be a text lexing problem, remind me of old school days...

@ascandella
Copy link
Contributor Author

Ah, right, of course it's not that easy :)

What do you guys think? Should we parse the whole line or stick with the
simpler (with known limitations) version?
On Wed, Jul 20, 2016 at 7:23 AM Peng Lyu [email protected] wrote:

@sectioneight https://github.com/sectioneight I'm really sorry that I
didn't think carefully about the escaping before I made suggestions.
Checking double \ before " is somewhat not perfect, for example
"abc\"def" will pass the validation

currentChar === char &&
(corpus[i - 1] !== this.escapeChar || corpus[i - 2] === this.escapeChar)

but it's not a true closing ". Now it turns out to be a text lexing
problem, remind me of old school days...


You are receiving this because you were mentioned.

Reply to this email directly, view it on GitHub
#483 (comment), or mute
the thread
https://github.com/notifications/unsubscribe-auth/AAF7P_es3k0heZUEREix08jSpRxb-gLVks5qXi95gaJpZM4JQYQq
.

@rebornix
Copy link
Member

I have a dirty but quick way to handle this, while iterating the text, skip all escaped chars then check whether it's a "

let i = 0;
while (i < text.length) {
  if (text[i] === "\") {
    i = i+2;
  }

  if (text[i] == "\"") {
    return i;
  }
}

I didn't handle corner cases carefully but I think you can get the idea.

Besides, I don't have a strong opinion about postpoing the escaping handling or not, if we don't have a perfect solution right now, we can fix it later. It's up to you and @johnfn .

@ascandella
Copy link
Contributor Author

OK, just pushed a new commit that pre-parses the line and handles your edge case properly. I'm not sure about performance implications, however -- is that something to be concerned about, or is that prematurely optimizing?

@ascandella
Copy link
Contributor Author

This one is ready to go

constructor(char: string, corpus: string, start: number) {
this.char = char;
this.start = start;
this.corpus = corpus;
Copy link
Member

Choose a reason for hiding this comment

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

seems this.corpus is never used?

@rebornix
Copy link
Member

only have some tiny suggestions. The logic and code look good to me so I'm willing to see it merged.

@ascandella
Copy link
Contributor Author

@rebornix great feedback, updated.

};
}
return {
start: new Position(position.line, start + (this.includeSurrounding ? 0 : 1)),
Copy link
Member

Choose a reason for hiding this comment

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

Can you use position objects and getRight()/getLeft() here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For sure.

@johnfn
Copy link
Member

johnfn commented Jul 23, 2016

The one big thing that we're missing here is i" in a situation like this:

"one " two |"three" (where | is the start of the block cursor)

You currently select the inner " two " rather than the "three" to the right. I'm pretty sure that Vim actually determines which of the two potential quote sections is inside the quotes rather than outside and selects that one. Could you add in that case?

This should be good to merge with that.

@ascandella
Copy link
Contributor Author

Sounds good. Master tests are currently broken, I'm going to wait until that's resolved to push anything else here.

@ascandella
Copy link
Contributor Author

@johnfn updated. Note that there are test cases that currently fail, as master is currently red.

@johnfn
Copy link
Member

johnfn commented Jul 25, 2016

Perfect! Thanks for the awesome work, @sectioneight!

@johnfn johnfn merged commit 0c18fa5 into VSCodeVim:master Jul 25, 2016
@ascandella ascandella deleted the quoted-text-objects branch July 25, 2016 01:41
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.

3 participants