Skip to content

Commit 3ae0b17

Browse files
yorkietjfontaine
authored andcommitted
repl: REPLServer inherits from readline.Interface
This exposes a setPrompt for and other readline features
1 parent 7589a00 commit 3ae0b17

File tree

5 files changed

+104
-39
lines changed

5 files changed

+104
-39
lines changed

doc/api/repl.markdown

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,9 @@ For example, you could add this to your bashrc file:
3232

3333
## repl.start(options)
3434

35-
Returns and starts a `REPLServer` instance. Accepts an "options" Object that
36-
takes the following values:
35+
Returns and starts a `REPLServer` instance, that inherits from
36+
[Readline Interface][]. Accepts an "options" Object that takes
37+
the following values:
3738

3839
- `prompt` - the prompt and `stream` for all I/O. Defaults to `> `.
3940

lib/repl.js

Lines changed: 28 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ var path = require('path');
4848
var fs = require('fs');
4949
var rl = require('readline');
5050
var Console = require('console').Console;
51-
var EventEmitter = require('events').EventEmitter;
5251
var domain = require('domain');
5352
var debug = util.debuglog('repl');
5453

@@ -82,8 +81,6 @@ function REPLServer(prompt, stream, eval_, useGlobal, ignoreUndefined) {
8281
return new REPLServer(prompt, stream, eval_, useGlobal, ignoreUndefined);
8382
}
8483

85-
EventEmitter.call(this);
86-
8784
var options, input, output, dom;
8885
if (util.isObject(prompt)) {
8986
// an options object was given
@@ -109,6 +106,9 @@ function REPLServer(prompt, stream, eval_, useGlobal, ignoreUndefined) {
109106
self.useGlobal = !!useGlobal;
110107
self.ignoreUndefined = !!ignoreUndefined;
111108

109+
// just for backwards compat, see github.com/joyent/node/pull/7127
110+
self.rli = this;
111+
112112
eval_ = eval_ || defaultEval;
113113

114114
function defaultEval(code, context, file, cb) {
@@ -179,19 +179,18 @@ function REPLServer(prompt, stream, eval_, useGlobal, ignoreUndefined) {
179179
self.bufferedCommand = '';
180180
self.lines.level = [];
181181

182-
self.prompt = !util.isUndefined(prompt) ? prompt : '> ';
183-
184182
function complete(text, callback) {
185183
self.complete(text, callback);
186184
}
187185

188-
var rli = rl.createInterface({
189-
input: self.inputStream,
190-
output: self.outputStream,
191-
completer: complete,
192-
terminal: options.terminal
193-
});
194-
self.rli = rli;
186+
rl.Interface.apply(this, [
187+
self.inputStream,
188+
self.outputStream,
189+
complete,
190+
options.terminal
191+
])
192+
193+
self.setPrompt(!util.isUndefined(prompt) ? prompt : '> ');
195194

196195
this.commands = {};
197196
defineDefaultCommands(this);
@@ -200,7 +199,7 @@ function REPLServer(prompt, stream, eval_, useGlobal, ignoreUndefined) {
200199
self.writer = options.writer || exports.writer;
201200

202201
if (util.isUndefined(options.useColors)) {
203-
options.useColors = rli.terminal;
202+
options.useColors = self.terminal;
204203
}
205204
self.useColors = !!options.useColors;
206205

@@ -211,24 +210,24 @@ function REPLServer(prompt, stream, eval_, useGlobal, ignoreUndefined) {
211210
};
212211
}
213212

214-
rli.setPrompt(self.prompt);
213+
self.setPrompt(self._prompt);
215214

216-
rli.on('close', function() {
215+
self.on('close', function() {
217216
self.emit('exit');
218217
});
219218

220219
var sawSIGINT = false;
221-
rli.on('SIGINT', function() {
222-
var empty = rli.line.length === 0;
223-
rli.clearLine();
220+
self.on('SIGINT', function() {
221+
var empty = self.line.length === 0;
222+
self.clearLine();
224223

225224
if (!(self.bufferedCommand && self.bufferedCommand.length > 0) && empty) {
226225
if (sawSIGINT) {
227-
rli.close();
226+
self.close();
228227
sawSIGINT = false;
229228
return;
230229
}
231-
rli.output.write('(^C again to quit)\n');
230+
self.output.write('(^C again to quit)\n');
232231
sawSIGINT = true;
233232
} else {
234233
sawSIGINT = false;
@@ -239,7 +238,7 @@ function REPLServer(prompt, stream, eval_, useGlobal, ignoreUndefined) {
239238
self.displayPrompt();
240239
});
241240

242-
rli.on('line', function(cmd) {
241+
self.on('line', function(cmd) {
243242
debug('line %j', cmd);
244243
sawSIGINT = false;
245244
var skipCatchall = false;
@@ -322,13 +321,13 @@ function REPLServer(prompt, stream, eval_, useGlobal, ignoreUndefined) {
322321
};
323322
});
324323

325-
rli.on('SIGCONT', function() {
324+
self.on('SIGCONT', function() {
326325
self.displayPrompt(true);
327326
});
328327

329328
self.displayPrompt();
330329
}
331-
inherits(REPLServer, EventEmitter);
330+
inherits(REPLServer, rl.Interface);
332331
exports.REPLServer = REPLServer;
333332

334333

@@ -340,7 +339,6 @@ exports.start = function(prompt, source, eval_, useGlobal, ignoreUndefined) {
340339
return repl;
341340
};
342341

343-
344342
REPLServer.prototype.createContext = function() {
345343
var context;
346344
if (this.useGlobal) {
@@ -388,17 +386,17 @@ REPLServer.prototype.resetContext = function() {
388386
};
389387

390388
REPLServer.prototype.displayPrompt = function(preserveCursor) {
391-
var prompt = this.prompt;
389+
var prompt = this._prompt;
392390
if (this.bufferedCommand.length) {
393391
prompt = '...';
394392
var levelInd = new Array(this.lines.level.length).join('..');
395393
prompt += levelInd + ' ';
394+
} else {
395+
this.setPrompt(prompt);
396396
}
397-
this.rli.setPrompt(prompt);
398-
this.rli.prompt(preserveCursor);
397+
this.prompt(preserveCursor);
399398
};
400399

401-
402400
// A stream to push an array into a REPL
403401
// used in REPLServer.complete
404402
function ArrayStream() {
@@ -838,7 +836,7 @@ function defineDefaultCommands(repl) {
838836
repl.defineCommand('exit', {
839837
help: 'Exit the repl',
840838
action: function() {
841-
this.rli.close();
839+
this.close();
842840
}
843841
});
844842

@@ -879,7 +877,7 @@ function defineDefaultCommands(repl) {
879877
this.displayPrompt();
880878
lines.forEach(function(line) {
881879
if (line) {
882-
self.rli.write(line + '\n');
880+
self.write(line + '\n');
883881
}
884882
});
885883
}

test/simple/test-repl-options.js

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,23 @@ var r1 = repl.start({
3737
output: stream,
3838
terminal: true
3939
});
40+
41+
assert.equal(r1.input, stream);
42+
assert.equal(r1.output, stream);
43+
assert.equal(r1.input, r1.inputStream);
44+
assert.equal(r1.output, r1.outputStream);
45+
assert.equal(r1.terminal, true);
46+
assert.equal(r1.useColors, r1.terminal);
47+
assert.equal(r1.useGlobal, false);
48+
assert.equal(r1.ignoreUndefined, false);
49+
50+
// test r1 for backwards compact
4051
assert.equal(r1.rli.input, stream);
4152
assert.equal(r1.rli.output, stream);
4253
assert.equal(r1.rli.input, r1.inputStream);
4354
assert.equal(r1.rli.output, r1.outputStream);
4455
assert.equal(r1.rli.terminal, true);
4556
assert.equal(r1.useColors, r1.rli.terminal);
46-
assert.equal(r1.useGlobal, false);
47-
assert.equal(r1.ignoreUndefined, false);
4857

4958
// 2
5059
function writer() {}
@@ -59,12 +68,20 @@ var r2 = repl.start({
5968
eval: evaler,
6069
writer: writer
6170
});
71+
assert.equal(r2.input, stream);
72+
assert.equal(r2.output, stream);
73+
assert.equal(r2.input, r2.inputStream);
74+
assert.equal(r2.output, r2.outputStream);
75+
assert.equal(r2.terminal, false);
76+
assert.equal(r2.useColors, true);
77+
assert.equal(r2.useGlobal, true);
78+
assert.equal(r2.ignoreUndefined, true);
79+
assert.equal(r2.writer, writer);
80+
81+
// test r2 for backwards compact
6282
assert.equal(r2.rli.input, stream);
6383
assert.equal(r2.rli.output, stream);
6484
assert.equal(r2.rli.input, r2.inputStream);
6585
assert.equal(r2.rli.output, r2.outputStream);
6686
assert.equal(r2.rli.terminal, false);
67-
assert.equal(r2.useColors, true);
68-
assert.equal(r2.useGlobal, true);
69-
assert.equal(r2.ignoreUndefined, true);
70-
assert.equal(r2.writer, writer);
87+

test/simple/test-repl-require-cache.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,6 @@ var common = require('../common'),
2828
require.cache.something = 1;
2929
assert.equal(require.cache.something, 1);
3030

31-
repl.start({ useGlobal: false }).rli.close();
31+
repl.start({ useGlobal: false }).close();
3232

3333
assert.equal(require.cache.something, 1);

test/simple/test-repl-setprompt.js

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Copyright Joyent, Inc. and other Node contributors.
2+
//
3+
// Permission is hereby granted, free of charge, to any person obtaining a
4+
// copy of this software and associated documentation files (the
5+
// "Software"), to deal in the Software without restriction, including
6+
// without limitation the rights to use, copy, modify, merge, publish,
7+
// distribute, sublicense, and/or sell copies of the Software, and to permit
8+
// persons to whom the Software is furnished to do so, subject to the
9+
// following conditions:
10+
//
11+
// The above copyright notice and this permission notice shall be included
12+
// in all copies or substantial portions of the Software.
13+
//
14+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15+
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16+
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17+
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18+
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19+
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20+
// USE OR OTHER DEALINGS IN THE SOFTWARE.
21+
22+
var common = require('../common'),
23+
assert = require('assert'),
24+
spawn = require('child_process').spawn,
25+
os = require('os'),
26+
util = require('util');
27+
28+
var args = [
29+
'-e',
30+
'var e = new (require("repl")).REPLServer("foo.. "); e.context.e = e;',
31+
];
32+
33+
var p = "bar.. ";
34+
35+
var child = spawn(process.execPath, args);
36+
37+
child.stdout.setEncoding('utf8');
38+
39+
var data = '';
40+
child.stdout.on('data', function(d) { data += d });
41+
42+
child.stdin.end(util.format("e.setPrompt('%s');%s", p, os.EOL));
43+
44+
child.on('close', function(code, signal) {
45+
assert.strictEqual(code, 0);
46+
assert.ok(!signal);
47+
var lines = data.split(/\n/);
48+
assert.strictEqual(lines.pop(), p);
49+
});

0 commit comments

Comments
 (0)