Browse Source

repl: make ^D emit an 'end' event on the readline instance

Also emit 'exit' on the repl when 'end' is emitted on the readline.

Fixes `node debug test/fixtures/breakpoints.js` when ^D is pressed.
v0.9.1-release
Nathan Rajlich 13 years ago
parent
commit
f41901cdf6
  1. 8
      doc/api/readline.markdown
  2. 3
      doc/api/repl.markdown
  3. 4
      lib/readline.js
  4. 5
      lib/repl.js
  5. 77
      test/simple/test-repl-end-emits-exit.js

8
doc/api/readline.markdown

@ -160,6 +160,14 @@ Example of listening for `resume`:
console.log('Readline resumed.'); console.log('Readline resumed.');
}); });
### Event: 'end'
`function () {}`
Emitted when the `input` stream receives its "end" event, or when `^D` is
pressed by the user. It's generally a good idea to consider this `Interface`
instance as completed after this is emitted.
### Event: 'SIGINT' ### Event: 'SIGINT'
`function () {}` `function () {}`

3
doc/api/repl.markdown

@ -116,7 +116,8 @@ see: https://gist.github.com/2053342
`function () {}` `function () {}`
Emitted when the user exits the REPL in any of the defined ways. Namely, typing Emitted when the user exits the REPL in any of the defined ways. Namely, typing
`.exit` at the repl, or pressing Ctrl+C twice to signal SIGINT. `.exit` at the repl, pressing Ctrl+C twice to signal SIGINT, or pressing Ctrl+D
to signal "end" on the `input` stream.
Example of listening for `exit`: Example of listening for `exit`:

4
lib/readline.js

@ -90,6 +90,9 @@ function Interface(input, output, completer, terminal) {
input.on('data', function(data) { input.on('data', function(data) {
self._normalWrite(data); self._normalWrite(data);
}); });
input.on('end', function() {
self.emit('end');
});
} else { } else {
@ -575,6 +578,7 @@ Interface.prototype._ttyWrite = function(s, key) {
case 'd': // delete right or EOF case 'd': // delete right or EOF
if (this.cursor === 0 && this.line.length === 0) { if (this.cursor === 0 && this.line.length === 0) {
this.pause(); this.pause();
this.emit('end');
} else if (this.cursor < this.line.length) { } else if (this.cursor < this.line.length) {
this._deleteRight(); this._deleteRight();
} }

5
lib/repl.js

@ -168,6 +168,11 @@ function REPLServer(prompt, stream, eval, useGlobal, ignoreUndefined) {
rli.setPrompt(self.prompt); rli.setPrompt(self.prompt);
rli.on('end', function() {
self.rli.output.write('\n');
self.emit('exit');
});
var sawSIGINT = false; var sawSIGINT = false;
rli.on('SIGINT', function() { rli.on('SIGINT', function() {
var empty = rli.line.length === 0; var empty = rli.line.length === 0;

77
test/simple/test-repl-end-emits-exit.js

@ -0,0 +1,77 @@
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
var common = require('../common'),
assert = require('assert'),
Stream = require('stream'),
repl = require('repl'),
gotTerminalExit = false,
gotRegularExit = false;
// create a dummy stream that does nothing
var stream = new Stream();
stream.write = stream.pause = stream.resume = function(){};
stream.readable = stream.writable = true;
function testTerminalMode() {
var r1 = repl.start({
input: stream,
output: stream,
terminal: true
});
process.nextTick(function() {
// manually fire a ^D keypress
stream.emit('data', '\u0004');
});
r1.on('exit', function() {
// should be fired from the simulated ^D keypress
gotTerminalExit = true;
testRegularMode();
});
}
function testRegularMode() {
var r2 = repl.start({
input: stream,
output: stream,
terminal: false
});
process.nextTick(function() {
stream.emit('end');
});
r2.on('exit', function() {
// should be fired from the simulated 'end' event
gotRegularExit = true;
});
}
process.on('exit', function() {
assert(gotTerminalExit);
assert(gotRegularExit);
});
// start
testTerminalMode();
Loading…
Cancel
Save