Skip to content

Commit 2a9de8f

Browse files
Trottrvagg
authored andcommitted
readline: allow tabs in input
If tab completion is not being used, allow user to enter tab characters. PR-URL: #1761 Reviewed-By: Brendan Ashworth <brendan.ashworth@me.com>
1 parent d77ae26 commit 2a9de8f

File tree

2 files changed

+67
-13
lines changed

2 files changed

+67
-13
lines changed

lib/readline.js

+14-13
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,7 @@ function Interface(input, output, completer, terminal) {
4949
}
5050
historySize = historySize || kHistorySize;
5151

52-
completer = completer || function() { return []; };
53-
54-
if (typeof completer !== 'function') {
52+
if (completer && typeof completer !== 'function') {
5553
throw new TypeError('Argument \'completer\' must be a function');
5654
}
5755

@@ -74,9 +72,11 @@ function Interface(input, output, completer, terminal) {
7472
this.historySize = historySize;
7573

7674
// Check arity, 2 - for async, 1 for sync
77-
this.completer = completer.length === 2 ? completer : function(v, callback) {
78-
callback(null, completer(v));
79-
};
75+
if (typeof completer === 'function') {
76+
this.completer = completer.length === 2 ? completer : function(v, cb) {
77+
cb(null, completer(v));
78+
};
79+
}
8080

8181
this.setPrompt('> ');
8282

@@ -346,9 +346,6 @@ Interface.prototype._normalWrite = function(b) {
346346
};
347347

348348
Interface.prototype._insertString = function(c) {
349-
//BUG: Problem when adding tabs with following content.
350-
// Perhaps the bug is in _refreshLine(). Not sure.
351-
// A hack would be to insert spaces instead of literal '\t'.
352349
if (this.cursor < this.line.length) {
353350
var beg = this.line.slice(0, this.cursor);
354351
var end = this.line.slice(this.cursor, this.line.length);
@@ -841,10 +838,6 @@ Interface.prototype._ttyWrite = function(s, key) {
841838
this._deleteRight();
842839
break;
843840

844-
case 'tab': // tab completion
845-
this._tabComplete();
846-
break;
847-
848841
case 'left':
849842
this._moveCursor(-1);
850843
break;
@@ -869,6 +862,14 @@ Interface.prototype._ttyWrite = function(s, key) {
869862
this._historyNext();
870863
break;
871864

865+
case 'tab':
866+
// If tab completion enabled, do that...
867+
if (typeof this.completer === 'function') {
868+
this._tabComplete();
869+
break;
870+
}
871+
// falls through
872+
872873
default:
873874
if (s instanceof Buffer)
874875
s = s.toString('utf-8');

test/parallel/test-readline-interface.js

+53
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,59 @@ function isWarned(emitter) {
175175
assert.equal(callCount, expectedLines.length);
176176
rli.close();
177177

178+
// \t when there is no completer function should behave like an ordinary
179+
// character
180+
fi = new FakeInput();
181+
rli = new readline.Interface({ input: fi, output: fi, terminal: true });
182+
called = false;
183+
rli.on('line', function(line) {
184+
assert.equal(line, '\t');
185+
assert.strictEqual(called, false);
186+
called = true;
187+
});
188+
fi.emit('data', '\t');
189+
fi.emit('data', '\n');
190+
assert.ok(called);
191+
rli.close();
192+
193+
// \t does not become part of the input when there is a completer function
194+
fi = new FakeInput();
195+
var completer = function(line) {
196+
return [[], line];
197+
};
198+
rli = new readline.Interface({
199+
input: fi,
200+
output: fi,
201+
terminal: true,
202+
completer: completer
203+
});
204+
called = false;
205+
rli.on('line', function(line) {
206+
assert.equal(line, 'foo');
207+
assert.strictEqual(called, false);
208+
called = true;
209+
});
210+
fi.emit('data', '\tfo\to\t');
211+
fi.emit('data', '\n');
212+
assert.ok(called);
213+
rli.close();
214+
215+
// constructor throws if completer is not a function or undefined
216+
fi = new FakeInput();
217+
assert.throws(function() {
218+
readline.createInterface({
219+
input: fi,
220+
completer: 'string is not valid'
221+
});
222+
}, function(err) {
223+
if (err instanceof TypeError) {
224+
if (/Argument \'completer\' must be a function/.test(err)) {
225+
return true;
226+
}
227+
}
228+
return false;
229+
});
230+
178231
// sending a multi-byte utf8 char over multiple writes
179232
var buf = Buffer('☮', 'utf8');
180233
fi = new FakeInput();

0 commit comments

Comments
 (0)