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: key interval delay for \r & \n #8109

Closed
wants to merge 7 commits into from

Conversation

princejwesley
Copy link
Contributor

Checklist
  • make -j4 test (UNIX), or vcbuild test nosign (Windows) passes
  • tests and/or benchmarks are included
  • commit message follows commit guidelines
Affected core subsystem(s)

readline

Description of change

Emit two line events when there is a delay between
CR('\r') and LF('\n')

@nodejs-github-bot nodejs-github-bot added the readline Issues and PRs related to the built-in readline module. label Aug 15, 2016
@@ -199,6 +199,27 @@ function isWarned(emitter) {
assert.equal(callCount, expectedLines.length);
rli.close();

// Emit two line events where there is a delay
// between \r and \n
(() => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you drop this style and just wrap this portion of the test in curly braces. That will provide the block scope you want.

@Fishrock123
Copy link
Contributor

@princejwesley Could you give an example as to how to induce the problem this fixes?

\r\n (\n after \r) is a grapheme iirc aka one character

@Fishrock123
Copy link
Contributor

@princejwesley
Copy link
Contributor Author

princejwesley commented Aug 15, 2016

@Fishrock123

This is how I reproduced in macOS. Run the below snippet and hit enter/return for (\r) and ctrl + j for (\n). You can try with repl too.

const readline = require('readline');

const rli = new readline.Interface({
    input: process.stdin,
    output: process.stdout,
    terminal: true
});
let count = 0;
rli.on('line', function(line) {
    count++;
    console.log(`line event triggered ${count}`);
});

Edit: \r\n - two characters. Here is the interesting history behind it

@jasnell
Copy link
Member

jasnell commented Aug 15, 2016

It may be better to make the delay period configurable

@mscdex
Copy link
Contributor

mscdex commented Aug 15, 2016

I think if we're going to add a delay, it should definitely be configurable (with some sensible default but allowing to opt out altogether -- perhaps with a 0 value).

@princejwesley
Copy link
Contributor Author

@mscdex Delay is introduced to differentiate whether its a system that emits \r\n for a single newline or a user or both. Setting delay as zero will nullify this fix.

In nutshell, this PR tries to figure out whether \n is an individual event or the tail of \r(emitted by the system for newline).

Current experience,

~ 🙈 node
> // I hit enter - that emits CR(\r)
> // now I hit `ctrl + j ` to emit LF(\n) - no newline

@mscdex
Copy link
Contributor

mscdex commented Aug 15, 2016

@princejwesley I understand, but I think it would be useful to be able to explicitly tell readline what to check for instead of trying to guess by adding a delay, whether that's setting 0 for the delay or setting some other option/flag.

@princejwesley
Copy link
Contributor Author

@mscdex I'll update the PR with configurable option. Shall I use crLfDelay or any better name?

}
return rl;
};


function Interface(input, output, completer, terminal) {
function Interface(input, output, completer, terminal,
crLfDelay = kCRLFDelayInMillis) {
Copy link
Contributor

Choose a reason for hiding this comment

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

IMHO this should line up with the input parameter.

@mscdex
Copy link
Contributor

mscdex commented Aug 15, 2016

@princejwesley I don't really have a preference on the name. Although personally I think if it starts with 'CRLF', that prefix would look better lowercased (crlf) instead of mixed cased (crLf).

@princejwesley
Copy link
Contributor Author

@Trott Trott added the semver-minor PRs that contain new features and should be released in the next minor version. label Aug 16, 2016
@@ -358,6 +358,9 @@ added: v0.1.98
only if `terminal` is set to `true` by the user or by an internal `output`
check, otherwise the history caching mechanism is not initialized at all.
* `prompt` - the prompt string to use. Default: `'> '`
* `crlfDelay` {number} If the delay between `\r` and `\n` exceeds
`crlfDelay`, both `\r` and `\n` will be treated as separate end-of-line
Copy link
Member

Choose a reason for hiding this comment

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

Suggestion: s/exceeds crlfDelay/exceeds crlfDelay milliseconds

Copy link
Member

@jasnell jasnell Aug 16, 2016

Choose a reason for hiding this comment

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

also... should there be a maximum delay? And how does one turn off the delay entirely? In other APIs, we've used setting the value explicitly to 0 or null or Infinity to turn it off.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I am not sure about the maximum delay but minimum delay should not be zero. the reason is subsequent events(\r followed by \n) may have latency greater than or equal to 1ms. It will obviously break windows system.
What do you suggest ? 10ms as minimum delay?

Copy link
Member

Choose a reason for hiding this comment

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

That should 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.

I am afraid to put 10ms (seems low because of context switches and other factors). Now I set [100, 2000] as range. It will go few more rounds to come up with better range 😄

@princejwesley
Copy link
Contributor Author

@princejwesley
Copy link
Contributor Author

Another attempt, CI: https://ci.nodejs.org/job/node-test-pull-request/3766/

rli = new readline.Interface({ input: fi, output: fi, crlfDelay: 1 << 30});
assert.strictEqual(rli.crlfDelay, 2000);
rli.close();
}
Copy link
Contributor

Choose a reason for hiding this comment

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

To 3 separate scopes?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@yorkie done

callCount++;
});
fi.emit('data', '\r');
setTimeout(() => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Wrap this function with common.mustCall?

@yorkie
Copy link
Contributor

yorkie commented Aug 24, 2016

LGTM :)

@princejwesley
Copy link
Contributor Author

@princejwesley
Copy link
Contributor Author

@jasnell @Fishrock123 @mscdex PTAL

@jasnell
Copy link
Member

jasnell commented Aug 26, 2016

LGTM

1 similar comment
@mscdex
Copy link
Contributor

mscdex commented Aug 26, 2016

LGTM

@princejwesley
Copy link
Contributor Author

Trying again for green build: https://ci.nodejs.org/job/node-test-pull-request/3865/

@jasnell
Copy link
Member

jasnell commented Aug 30, 2016

build bot failure on the last CI run... trying one final time for green: https://ci.nodejs.org/job/node-test-pull-request/3897/

@princejwesley
Copy link
Contributor Author

@jasnell failed again 😞

@jasnell
Copy link
Member

jasnell commented Aug 31, 2016

@nodejs/build @jbergstroem ... can someone take a look to see what's happening with the arm build bot on this?

@princejwesley
Copy link
Contributor Author

princejwesley commented Sep 2, 2016

ping @nodejs/build

@princejwesley
Copy link
Contributor Author

@jasnell I see full of red & unstable CI jobs. I'll trigger build after few days to get green build

@jbergstroem
Copy link
Member

We've fixed the arm issues; disk-related. Please try again!

@princejwesley
Copy link
Contributor Author

princejwesley commented Sep 5, 2016

@princejwesley
Copy link
Contributor Author

@jbergstroem last two build attempts - unstable. can you take a look?

@jbergstroem
Copy link
Member

@princejwesley 3959,3960 looked good though! Flaky is fine -- it means a test is known to fail.

princejwesley added a commit that referenced this pull request Sep 8, 2016
Emit two line events when there is a delay between
CR('\r') and LF('\n').

Introduced a new option `crlfDelay`. If the delay between \r and \n
exceeds `crlfDelay` milliseconds, both \r and \n will be treated as
separate end-of-line input. Default to 100 milliseconds.
`crlfDelay` will be coerced to [100, 2000] range.

PR-URL: #8109
Reviewed-By: Yorkie Liu <yorkiefixer@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Brian White <mscdex@mscdex.net>
@princejwesley
Copy link
Contributor Author

Landed in a634554

Fishrock123 pushed a commit that referenced this pull request Sep 14, 2016
Emit two line events when there is a delay between
CR('\r') and LF('\n').

Introduced a new option `crlfDelay`. If the delay between \r and \n
exceeds `crlfDelay` milliseconds, both \r and \n will be treated as
separate end-of-line input. Default to 100 milliseconds.
`crlfDelay` will be coerced to [100, 2000] range.

PR-URL: #8109
Reviewed-By: Yorkie Liu <yorkiefixer@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Brian White <mscdex@mscdex.net>
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. semver-minor PRs that contain new features and should be released in the next minor version.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants