readline: should not require an output stream.
Passing null as the output stream to readline.Interface()'s constructor is now supported. Any output written by readline is just discarded. It makes it easier to use readline just as a line parser. Fixes: https://github.com/joyent/node/issues/4408 Reviewed-by: Trevor Norris <trev.norris@gmail.com>
This commit is contained in:
parent
8dc6be1747
commit
862cc28183
@ -30,7 +30,7 @@ the following values:
|
||||
|
||||
- `input` - the readable stream to listen to (Required).
|
||||
|
||||
- `output` - the writable stream to write readline data to (Required).
|
||||
- `output` - the writable stream to write readline data to (Optional).
|
||||
|
||||
- `completer` - an optional function that is used for Tab autocompletion. See
|
||||
below for an example of using this.
|
||||
@ -100,6 +100,9 @@ to `true` to prevent the cursor placement being reset to `0`.
|
||||
This will also resume the `input` stream used with `createInterface` if it has
|
||||
been paused.
|
||||
|
||||
If `output` is set to `null` or `undefined` when calling `createInterface`, the
|
||||
prompt is not written.
|
||||
|
||||
### rl.question(query, callback)
|
||||
|
||||
Prepends the prompt with `query` and invokes `callback` with the user's
|
||||
@ -109,6 +112,9 @@ with the user's response after it has been typed.
|
||||
This will also resume the `input` stream used with `createInterface` if
|
||||
it has been paused.
|
||||
|
||||
If `output` is set to `null` or `undefined` when calling `createInterface`,
|
||||
nothing is displayed.
|
||||
|
||||
Example usage:
|
||||
|
||||
interface.question('What is your favorite food?', function(answer) {
|
||||
@ -130,8 +136,9 @@ Closes the `Interface` instance, relinquishing control on the `input` and
|
||||
|
||||
### rl.write(data[, key])
|
||||
|
||||
Writes `data` to `output` stream. `key` is an object literal to represent a key
|
||||
sequence; available if the terminal is a TTY.
|
||||
Writes `data` to `output` stream, unless `output` is set to `null` or
|
||||
`undefined` when calling `createInterface`. `key` is an object literal to
|
||||
represent a key sequence; available if the terminal is a TTY.
|
||||
|
||||
This will also resume the `input` stream if it has been paused.
|
||||
|
||||
|
@ -68,7 +68,7 @@ function Interface(input, output, completer, terminal) {
|
||||
|
||||
// backwards compat; check the isTTY prop of the output stream
|
||||
// when `terminal` was not specified
|
||||
if (util.isUndefined(terminal)) {
|
||||
if (util.isUndefined(terminal) && !util.isNullOrUndefined(output)) {
|
||||
terminal = !!output.isTTY;
|
||||
}
|
||||
|
||||
@ -142,11 +142,15 @@ function Interface(input, output, completer, terminal) {
|
||||
this.history = [];
|
||||
this.historyIndex = -1;
|
||||
|
||||
output.on('resize', onresize);
|
||||
if (!util.isNullOrUndefined(output))
|
||||
output.on('resize', onresize);
|
||||
|
||||
self.once('close', function() {
|
||||
input.removeListener('keypress', onkeypress);
|
||||
input.removeListener('end', ontermend);
|
||||
output.removeListener('resize', onresize);
|
||||
if (!util.isNullOrUndefined(output)) {
|
||||
output.removeListener('resize', onresize);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -156,7 +160,10 @@ function Interface(input, output, completer, terminal) {
|
||||
inherits(Interface, EventEmitter);
|
||||
|
||||
Interface.prototype.__defineGetter__('columns', function() {
|
||||
return this.output.columns || Infinity;
|
||||
var columns = Infinity;
|
||||
if (this.output && this.output.columns)
|
||||
columns = this.output.columns;
|
||||
return columns;
|
||||
});
|
||||
|
||||
Interface.prototype.setPrompt = function(prompt) {
|
||||
@ -177,7 +184,7 @@ Interface.prototype.prompt = function(preserveCursor) {
|
||||
if (!preserveCursor) this.cursor = 0;
|
||||
this._refreshLine();
|
||||
} else {
|
||||
this.output.write(this._prompt);
|
||||
this._writeToOutput(this._prompt);
|
||||
}
|
||||
};
|
||||
|
||||
@ -207,6 +214,13 @@ Interface.prototype._onLine = function(line) {
|
||||
}
|
||||
};
|
||||
|
||||
Interface.prototype._writeToOutput = function _writeToOutput(stringToWrite) {
|
||||
if (!util.isString(stringToWrite))
|
||||
throw new TypeError('stringToWrite must be a string');
|
||||
|
||||
if (!util.isNullOrUndefined(this.output))
|
||||
this.output.write(stringToWrite);
|
||||
};
|
||||
|
||||
Interface.prototype._addHistory = function() {
|
||||
if (this.line.length === 0) return '';
|
||||
@ -245,11 +259,11 @@ Interface.prototype._refreshLine = function() {
|
||||
exports.clearScreenDown(this.output);
|
||||
|
||||
// Write the prompt and the current buffer content.
|
||||
this.output.write(line);
|
||||
this._writeToOutput(line);
|
||||
|
||||
// Force terminal to allocate a new line
|
||||
if (lineCols === 0) {
|
||||
this.output.write(' ');
|
||||
this._writeToOutput(' ');
|
||||
}
|
||||
|
||||
// Move cursor to original position.
|
||||
@ -351,7 +365,7 @@ Interface.prototype._insertString = function(c) {
|
||||
if (this._getCursorPos().cols === 0) {
|
||||
this._refreshLine();
|
||||
} else {
|
||||
this.output.write(c);
|
||||
this._writeToOutput(c);
|
||||
}
|
||||
|
||||
// a hack to get the line refreshed if it's needed
|
||||
@ -378,7 +392,7 @@ Interface.prototype._tabComplete = function() {
|
||||
if (completions.length === 1) {
|
||||
self._insertString(completions[0].slice(completeOn.length));
|
||||
} else {
|
||||
self.output.write('\r\n');
|
||||
self._writeToOutput('\r\n');
|
||||
var width = completions.reduce(function(a, b) {
|
||||
return a.length > b.length ? a : b;
|
||||
}).length + 2; // 2 space padding
|
||||
@ -422,17 +436,17 @@ function handleGroup(self, group, width, maxColumns) {
|
||||
break;
|
||||
}
|
||||
var item = group[idx];
|
||||
self.output.write(item);
|
||||
self._writeToOutput(item);
|
||||
if (col < maxColumns - 1) {
|
||||
for (var s = 0, itemLen = item.length; s < width - itemLen;
|
||||
s++) {
|
||||
self.output.write(' ');
|
||||
self._writeToOutput(' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
self.output.write('\r\n');
|
||||
self._writeToOutput('\r\n');
|
||||
}
|
||||
self.output.write('\r\n');
|
||||
self._writeToOutput('\r\n');
|
||||
}
|
||||
|
||||
function commonPrefix(strings) {
|
||||
@ -525,7 +539,7 @@ Interface.prototype._deleteLineRight = function() {
|
||||
|
||||
Interface.prototype.clearLine = function() {
|
||||
this._moveCursor(+Infinity);
|
||||
this.output.write('\r\n');
|
||||
this._writeToOutput('\r\n');
|
||||
this.line = '';
|
||||
this.cursor = 0;
|
||||
this.prevRows = 0;
|
||||
@ -1168,6 +1182,9 @@ function emitKeys(stream, s) {
|
||||
*/
|
||||
|
||||
function cursorTo(stream, x, y) {
|
||||
if (util.isNullOrUndefined(stream))
|
||||
return;
|
||||
|
||||
if (!util.isNumber(x) && !util.isNumber(y))
|
||||
return;
|
||||
|
||||
@ -1188,6 +1205,9 @@ exports.cursorTo = cursorTo;
|
||||
*/
|
||||
|
||||
function moveCursor(stream, dx, dy) {
|
||||
if (util.isNullOrUndefined(stream))
|
||||
return;
|
||||
|
||||
if (dx < 0) {
|
||||
stream.write('\x1b[' + (-dx) + 'D');
|
||||
} else if (dx > 0) {
|
||||
@ -1211,6 +1231,9 @@ exports.moveCursor = moveCursor;
|
||||
*/
|
||||
|
||||
function clearLine(stream, dir) {
|
||||
if (util.isNullOrUndefined(stream))
|
||||
return;
|
||||
|
||||
if (dir < 0) {
|
||||
// to the beginning
|
||||
stream.write('\x1b[1K');
|
||||
@ -1230,6 +1253,9 @@ exports.clearLine = clearLine;
|
||||
*/
|
||||
|
||||
function clearScreenDown(stream) {
|
||||
if (util.isNullOrUndefined(stream))
|
||||
return;
|
||||
|
||||
stream.write('\x1b[0J');
|
||||
}
|
||||
exports.clearScreenDown = clearScreenDown;
|
||||
|
@ -307,5 +307,36 @@ function isWarned(emitter) {
|
||||
assert.equal(isWarned(process.stdout._events), false);
|
||||
}
|
||||
|
||||
//can create a new readline Interface with a null output arugument
|
||||
fi = new FakeInput();
|
||||
rli = new readline.Interface({input: fi, output: null, terminal: terminal });
|
||||
|
||||
called = false;
|
||||
rli.on('line', function(line) {
|
||||
called = true;
|
||||
assert.equal(line, 'asdf');
|
||||
});
|
||||
fi.emit('data', 'asdf\n');
|
||||
assert.ok(called);
|
||||
|
||||
assert.doesNotThrow(function() {
|
||||
rli.setPrompt("ddd> ");
|
||||
});
|
||||
|
||||
assert.doesNotThrow(function() {
|
||||
rli.prompt();
|
||||
});
|
||||
|
||||
assert.doesNotThrow(function() {
|
||||
rli.write('really shouldnt be seeing this');
|
||||
});
|
||||
|
||||
assert.doesNotThrow(function() {
|
||||
rli.question("What do you think of node.js? ", function(answer) {
|
||||
console.log("Thank you for your valuable feedback:", answer);
|
||||
rli.close();
|
||||
})
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user