repl: REPLServer inherits from readline.Interface
This exposes a setPrompt for and other readline features
This commit is contained in:
parent
7589a0007c
commit
3ae0b17c76
@ -32,8 +32,9 @@ For example, you could add this to your bashrc file:
|
|||||||
|
|
||||||
## repl.start(options)
|
## repl.start(options)
|
||||||
|
|
||||||
Returns and starts a `REPLServer` instance. Accepts an "options" Object that
|
Returns and starts a `REPLServer` instance, that inherits from
|
||||||
takes the following values:
|
[Readline Interface][]. Accepts an "options" Object that takes
|
||||||
|
the following values:
|
||||||
|
|
||||||
- `prompt` - the prompt and `stream` for all I/O. Defaults to `> `.
|
- `prompt` - the prompt and `stream` for all I/O. Defaults to `> `.
|
||||||
|
|
||||||
|
58
lib/repl.js
58
lib/repl.js
@ -48,7 +48,6 @@ var path = require('path');
|
|||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
var rl = require('readline');
|
var rl = require('readline');
|
||||||
var Console = require('console').Console;
|
var Console = require('console').Console;
|
||||||
var EventEmitter = require('events').EventEmitter;
|
|
||||||
var domain = require('domain');
|
var domain = require('domain');
|
||||||
var debug = util.debuglog('repl');
|
var debug = util.debuglog('repl');
|
||||||
|
|
||||||
@ -82,8 +81,6 @@ function REPLServer(prompt, stream, eval_, useGlobal, ignoreUndefined) {
|
|||||||
return new REPLServer(prompt, stream, eval_, useGlobal, ignoreUndefined);
|
return new REPLServer(prompt, stream, eval_, useGlobal, ignoreUndefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
EventEmitter.call(this);
|
|
||||||
|
|
||||||
var options, input, output, dom;
|
var options, input, output, dom;
|
||||||
if (util.isObject(prompt)) {
|
if (util.isObject(prompt)) {
|
||||||
// an options object was given
|
// an options object was given
|
||||||
@ -109,6 +106,9 @@ function REPLServer(prompt, stream, eval_, useGlobal, ignoreUndefined) {
|
|||||||
self.useGlobal = !!useGlobal;
|
self.useGlobal = !!useGlobal;
|
||||||
self.ignoreUndefined = !!ignoreUndefined;
|
self.ignoreUndefined = !!ignoreUndefined;
|
||||||
|
|
||||||
|
// just for backwards compat, see github.com/joyent/node/pull/7127
|
||||||
|
self.rli = this;
|
||||||
|
|
||||||
eval_ = eval_ || defaultEval;
|
eval_ = eval_ || defaultEval;
|
||||||
|
|
||||||
function defaultEval(code, context, file, cb) {
|
function defaultEval(code, context, file, cb) {
|
||||||
@ -179,19 +179,18 @@ function REPLServer(prompt, stream, eval_, useGlobal, ignoreUndefined) {
|
|||||||
self.bufferedCommand = '';
|
self.bufferedCommand = '';
|
||||||
self.lines.level = [];
|
self.lines.level = [];
|
||||||
|
|
||||||
self.prompt = !util.isUndefined(prompt) ? prompt : '> ';
|
|
||||||
|
|
||||||
function complete(text, callback) {
|
function complete(text, callback) {
|
||||||
self.complete(text, callback);
|
self.complete(text, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
var rli = rl.createInterface({
|
rl.Interface.apply(this, [
|
||||||
input: self.inputStream,
|
self.inputStream,
|
||||||
output: self.outputStream,
|
self.outputStream,
|
||||||
completer: complete,
|
complete,
|
||||||
terminal: options.terminal
|
options.terminal
|
||||||
});
|
])
|
||||||
self.rli = rli;
|
|
||||||
|
self.setPrompt(!util.isUndefined(prompt) ? prompt : '> ');
|
||||||
|
|
||||||
this.commands = {};
|
this.commands = {};
|
||||||
defineDefaultCommands(this);
|
defineDefaultCommands(this);
|
||||||
@ -200,7 +199,7 @@ function REPLServer(prompt, stream, eval_, useGlobal, ignoreUndefined) {
|
|||||||
self.writer = options.writer || exports.writer;
|
self.writer = options.writer || exports.writer;
|
||||||
|
|
||||||
if (util.isUndefined(options.useColors)) {
|
if (util.isUndefined(options.useColors)) {
|
||||||
options.useColors = rli.terminal;
|
options.useColors = self.terminal;
|
||||||
}
|
}
|
||||||
self.useColors = !!options.useColors;
|
self.useColors = !!options.useColors;
|
||||||
|
|
||||||
@ -211,24 +210,24 @@ function REPLServer(prompt, stream, eval_, useGlobal, ignoreUndefined) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
rli.setPrompt(self.prompt);
|
self.setPrompt(self._prompt);
|
||||||
|
|
||||||
rli.on('close', function() {
|
self.on('close', function() {
|
||||||
self.emit('exit');
|
self.emit('exit');
|
||||||
});
|
});
|
||||||
|
|
||||||
var sawSIGINT = false;
|
var sawSIGINT = false;
|
||||||
rli.on('SIGINT', function() {
|
self.on('SIGINT', function() {
|
||||||
var empty = rli.line.length === 0;
|
var empty = self.line.length === 0;
|
||||||
rli.clearLine();
|
self.clearLine();
|
||||||
|
|
||||||
if (!(self.bufferedCommand && self.bufferedCommand.length > 0) && empty) {
|
if (!(self.bufferedCommand && self.bufferedCommand.length > 0) && empty) {
|
||||||
if (sawSIGINT) {
|
if (sawSIGINT) {
|
||||||
rli.close();
|
self.close();
|
||||||
sawSIGINT = false;
|
sawSIGINT = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
rli.output.write('(^C again to quit)\n');
|
self.output.write('(^C again to quit)\n');
|
||||||
sawSIGINT = true;
|
sawSIGINT = true;
|
||||||
} else {
|
} else {
|
||||||
sawSIGINT = false;
|
sawSIGINT = false;
|
||||||
@ -239,7 +238,7 @@ function REPLServer(prompt, stream, eval_, useGlobal, ignoreUndefined) {
|
|||||||
self.displayPrompt();
|
self.displayPrompt();
|
||||||
});
|
});
|
||||||
|
|
||||||
rli.on('line', function(cmd) {
|
self.on('line', function(cmd) {
|
||||||
debug('line %j', cmd);
|
debug('line %j', cmd);
|
||||||
sawSIGINT = false;
|
sawSIGINT = false;
|
||||||
var skipCatchall = false;
|
var skipCatchall = false;
|
||||||
@ -322,13 +321,13 @@ function REPLServer(prompt, stream, eval_, useGlobal, ignoreUndefined) {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
rli.on('SIGCONT', function() {
|
self.on('SIGCONT', function() {
|
||||||
self.displayPrompt(true);
|
self.displayPrompt(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
self.displayPrompt();
|
self.displayPrompt();
|
||||||
}
|
}
|
||||||
inherits(REPLServer, EventEmitter);
|
inherits(REPLServer, rl.Interface);
|
||||||
exports.REPLServer = REPLServer;
|
exports.REPLServer = REPLServer;
|
||||||
|
|
||||||
|
|
||||||
@ -340,7 +339,6 @@ exports.start = function(prompt, source, eval_, useGlobal, ignoreUndefined) {
|
|||||||
return repl;
|
return repl;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
REPLServer.prototype.createContext = function() {
|
REPLServer.prototype.createContext = function() {
|
||||||
var context;
|
var context;
|
||||||
if (this.useGlobal) {
|
if (this.useGlobal) {
|
||||||
@ -388,17 +386,17 @@ REPLServer.prototype.resetContext = function() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
REPLServer.prototype.displayPrompt = function(preserveCursor) {
|
REPLServer.prototype.displayPrompt = function(preserveCursor) {
|
||||||
var prompt = this.prompt;
|
var prompt = this._prompt;
|
||||||
if (this.bufferedCommand.length) {
|
if (this.bufferedCommand.length) {
|
||||||
prompt = '...';
|
prompt = '...';
|
||||||
var levelInd = new Array(this.lines.level.length).join('..');
|
var levelInd = new Array(this.lines.level.length).join('..');
|
||||||
prompt += levelInd + ' ';
|
prompt += levelInd + ' ';
|
||||||
|
} else {
|
||||||
|
this.setPrompt(prompt);
|
||||||
}
|
}
|
||||||
this.rli.setPrompt(prompt);
|
this.prompt(preserveCursor);
|
||||||
this.rli.prompt(preserveCursor);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// A stream to push an array into a REPL
|
// A stream to push an array into a REPL
|
||||||
// used in REPLServer.complete
|
// used in REPLServer.complete
|
||||||
function ArrayStream() {
|
function ArrayStream() {
|
||||||
@ -838,7 +836,7 @@ function defineDefaultCommands(repl) {
|
|||||||
repl.defineCommand('exit', {
|
repl.defineCommand('exit', {
|
||||||
help: 'Exit the repl',
|
help: 'Exit the repl',
|
||||||
action: function() {
|
action: function() {
|
||||||
this.rli.close();
|
this.close();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -879,7 +877,7 @@ function defineDefaultCommands(repl) {
|
|||||||
this.displayPrompt();
|
this.displayPrompt();
|
||||||
lines.forEach(function(line) {
|
lines.forEach(function(line) {
|
||||||
if (line) {
|
if (line) {
|
||||||
self.rli.write(line + '\n');
|
self.write(line + '\n');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -37,14 +37,23 @@ var r1 = repl.start({
|
|||||||
output: stream,
|
output: stream,
|
||||||
terminal: true
|
terminal: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
assert.equal(r1.input, stream);
|
||||||
|
assert.equal(r1.output, stream);
|
||||||
|
assert.equal(r1.input, r1.inputStream);
|
||||||
|
assert.equal(r1.output, r1.outputStream);
|
||||||
|
assert.equal(r1.terminal, true);
|
||||||
|
assert.equal(r1.useColors, r1.terminal);
|
||||||
|
assert.equal(r1.useGlobal, false);
|
||||||
|
assert.equal(r1.ignoreUndefined, false);
|
||||||
|
|
||||||
|
// test r1 for backwards compact
|
||||||
assert.equal(r1.rli.input, stream);
|
assert.equal(r1.rli.input, stream);
|
||||||
assert.equal(r1.rli.output, stream);
|
assert.equal(r1.rli.output, stream);
|
||||||
assert.equal(r1.rli.input, r1.inputStream);
|
assert.equal(r1.rli.input, r1.inputStream);
|
||||||
assert.equal(r1.rli.output, r1.outputStream);
|
assert.equal(r1.rli.output, r1.outputStream);
|
||||||
assert.equal(r1.rli.terminal, true);
|
assert.equal(r1.rli.terminal, true);
|
||||||
assert.equal(r1.useColors, r1.rli.terminal);
|
assert.equal(r1.useColors, r1.rli.terminal);
|
||||||
assert.equal(r1.useGlobal, false);
|
|
||||||
assert.equal(r1.ignoreUndefined, false);
|
|
||||||
|
|
||||||
// 2
|
// 2
|
||||||
function writer() {}
|
function writer() {}
|
||||||
@ -59,12 +68,20 @@ var r2 = repl.start({
|
|||||||
eval: evaler,
|
eval: evaler,
|
||||||
writer: writer
|
writer: writer
|
||||||
});
|
});
|
||||||
|
assert.equal(r2.input, stream);
|
||||||
|
assert.equal(r2.output, stream);
|
||||||
|
assert.equal(r2.input, r2.inputStream);
|
||||||
|
assert.equal(r2.output, r2.outputStream);
|
||||||
|
assert.equal(r2.terminal, false);
|
||||||
|
assert.equal(r2.useColors, true);
|
||||||
|
assert.equal(r2.useGlobal, true);
|
||||||
|
assert.equal(r2.ignoreUndefined, true);
|
||||||
|
assert.equal(r2.writer, writer);
|
||||||
|
|
||||||
|
// test r2 for backwards compact
|
||||||
assert.equal(r2.rli.input, stream);
|
assert.equal(r2.rli.input, stream);
|
||||||
assert.equal(r2.rli.output, stream);
|
assert.equal(r2.rli.output, stream);
|
||||||
assert.equal(r2.rli.input, r2.inputStream);
|
assert.equal(r2.rli.input, r2.inputStream);
|
||||||
assert.equal(r2.rli.output, r2.outputStream);
|
assert.equal(r2.rli.output, r2.outputStream);
|
||||||
assert.equal(r2.rli.terminal, false);
|
assert.equal(r2.rli.terminal, false);
|
||||||
assert.equal(r2.useColors, true);
|
|
||||||
assert.equal(r2.useGlobal, true);
|
|
||||||
assert.equal(r2.ignoreUndefined, true);
|
|
||||||
assert.equal(r2.writer, writer);
|
|
||||||
|
@ -28,6 +28,6 @@ var common = require('../common'),
|
|||||||
require.cache.something = 1;
|
require.cache.something = 1;
|
||||||
assert.equal(require.cache.something, 1);
|
assert.equal(require.cache.something, 1);
|
||||||
|
|
||||||
repl.start({ useGlobal: false }).rli.close();
|
repl.start({ useGlobal: false }).close();
|
||||||
|
|
||||||
assert.equal(require.cache.something, 1);
|
assert.equal(require.cache.something, 1);
|
||||||
|
49
test/simple/test-repl-setprompt.js
Normal file
49
test/simple/test-repl-setprompt.js
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
// 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'),
|
||||||
|
spawn = require('child_process').spawn,
|
||||||
|
os = require('os'),
|
||||||
|
util = require('util');
|
||||||
|
|
||||||
|
var args = [
|
||||||
|
'-e',
|
||||||
|
'var e = new (require("repl")).REPLServer("foo.. "); e.context.e = e;',
|
||||||
|
];
|
||||||
|
|
||||||
|
var p = "bar.. ";
|
||||||
|
|
||||||
|
var child = spawn(process.execPath, args);
|
||||||
|
|
||||||
|
child.stdout.setEncoding('utf8');
|
||||||
|
|
||||||
|
var data = '';
|
||||||
|
child.stdout.on('data', function(d) { data += d });
|
||||||
|
|
||||||
|
child.stdin.end(util.format("e.setPrompt('%s');%s", p, os.EOL));
|
||||||
|
|
||||||
|
child.on('close', function(code, signal) {
|
||||||
|
assert.strictEqual(code, 0);
|
||||||
|
assert.ok(!signal);
|
||||||
|
var lines = data.split(/\n/);
|
||||||
|
assert.strictEqual(lines.pop(), p);
|
||||||
|
});
|
Loading…
x
Reference in New Issue
Block a user