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

readline: turn emitKeys into a streaming parser #1601

Closed
wants to merge 6 commits into from

Conversation

rlidwka
Copy link
Contributor

@rlidwka rlidwka commented May 3, 2015

see #1403

I changed emitKeys to a generator that receives data character by character and emits keypress event whenever an escape sequence is complete.

So now behavior is similar to bash and python shells I tested so far. For example, you can sequentally press ESC + [ + D, and it will be handled the same as "left arrow", because the data that's coming to node.js is the same in both cases: \x1b[D.

Possible side effect: escape key itself will never be emitted. If we get \x1b, parser will treat it as a start of an escape sequence no matter what. Our REPL never rely on that, but maybe other readline users are (xkcd spacebar heating yep).

@mscdex mscdex added the readline Issues and PRs related to the built-in readline module. label May 3, 2015
@mscdex
Copy link
Contributor

mscdex commented May 3, 2015

What about having a timer that starts when you see \x1b and after 1-2 seconds or whatever of no additional input, it is interpreted as an escape by itself. This is what I've seen in other console-based programs.

@rlidwka
Copy link
Contributor Author

rlidwka commented May 3, 2015

This is what I've seen in other console-based programs.

I think readline behavior should be consistent with other shells. I just tested bash, irb (ruby shell) and python, and didn't see a timer-based approach.

@mscdex
Copy link
Contributor

mscdex commented May 3, 2015

Sorry, I was referring to ncurses-based programs and such, not so much shells or other REPLs.


if (ch === '\x1b') {
s += (ch = yield);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe use a while (ch === '\x1b'), so it will catch as many escapes as one could possibly feed into it?

@Fishrock123
Copy link
Contributor

Clever use of a generator here. I like it.

Would prefer if someone who better understands the parsing requirements could also take a look though.

@Fishrock123
Copy link
Contributor

@silverwind
Copy link
Contributor

There're a few unused consts after this commit, probaby best to remove these (unless there's future use for them):

metaKeyCodeRe
functionKeyCodeRe
escapeCodeReAnywhere

@silverwind
Copy link
Contributor

Tested it a bit. Escape sequences all work as expected, the code looks well documented, nice work!

} else {
s = s.toString(stream.encoding || 'utf-8');
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Does all the existing Buffer functionality still work?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No, it's not, and it didn't work before either.

I'd appreciate another look at this, but I think this Buffer handling was a dead code since this commit: 3c91a7a.

Function emitKeys never receives any buffers in the first place, because string_decoder.write() returns strings only.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah true. Makes sense.

@Fishrock123
Copy link
Contributor

LGTM, but maybe cc @piscisaureus?

@rlidwka
Copy link
Contributor Author

rlidwka commented May 7, 2015

There're a few unused consts after this commit, probaby best to remove these

Done. Some of rhe consts are used in stripVTControlCharacters below, so I removed other ones.

if ((match = cmd.match(/^(\d\d?)(;(\d))?([~^$])$/))) {
code += match[1] + match[4];
modifier = (match[3] || 1) - 1;
} else if ((match = cmd.match(/^((\d;)?(\d))?([A-Za-z])$/))) {
Copy link
Contributor

Choose a reason for hiding this comment

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

should we put these into consts then? Does it make a difference?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Are you talking about regular expressions?

I think the only difference is readability, so if regexps are large enough, it'd make sense to move them out (or get rid of them since large regular expressions are a source of trouble usually).

But those are small, so they could be inlined.

V8 should create each regexp from regexp literal only once anyway.

In certain environments escape sequences could be splitted into
multiple chunks. For example, when user presses left arrow,
`\x1b[D` sequence could appear as two keypresses (`\x1b` + `[D`).

Fixes: nodejs#1403
@rlidwka
Copy link
Contributor Author

rlidwka commented May 9, 2015

Rebased on top of master branch and added generators to .eslintrc so it would lint successfully.

@silverwind
Copy link
Contributor

LGTM

silverwind pushed a commit that referenced this pull request May 10, 2015
In certain environments escape sequences could be splitted into
multiple chunks. For example, when user presses left arrow,
`\x1b[D` sequence could appear as two keypresses (`\x1b` + `[D`).

PR-URL: #1601
Fixes: #1403
Reviewed-By: Jeremiah Senkpiel <[email protected]>
Reviewed-By: Roman Reiss <[email protected]>
@silverwind
Copy link
Contributor

Thanks! Landed in aed6bce

@silverwind silverwind closed this May 10, 2015
Fishrock123 pushed a commit to Fishrock123/node that referenced this pull request May 19, 2015
In certain environments escape sequences could be splitted into
multiple chunks. For example, when user presses left arrow,
`\x1b[D` sequence could appear as two keypresses (`\x1b` + `[D`).

PR-URL: nodejs#1601
Fixes: nodejs#1403
Reviewed-By: Jeremiah Senkpiel <[email protected]>
Reviewed-By: Roman Reiss <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
readline Issues and PRs related to the built-in readline module.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants