Skip to content

Commit 90c72d4

Browse files
committed
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> Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
1 parent 197ba00 commit 90c72d4

File tree

2 files changed

+67
-13
lines changed

2 files changed

+67
-13
lines changed

lib/readline.js

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,7 @@ function Interface(input, output, completer, terminal) {
4848
}
4949
historySize = historySize || kHistorySize;
5050

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

@@ -73,9 +71,11 @@ function Interface(input, output, completer, terminal) {
7371
this.historySize = historySize;
7472

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

8080
this.setPrompt('> ');
8181

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

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

843-
case 'tab': // tab completion
844-
this._tabComplete();
845-
break;
846-
847840
case 'left':
848841
this._moveCursor(-1);
849842
break;
@@ -868,6 +861,14 @@ Interface.prototype._ttyWrite = function(s, key) {
868861
this._historyNext();
869862
break;
870863

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

test/parallel/test-readline-interface.js

Lines changed: 53 additions & 0 deletions
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)