Skip to content

Commit 4b3d493

Browse files
Trottbrendanashworth
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 6e78e5f commit 4b3d493

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
@@ -47,9 +47,7 @@ function Interface(input, output, completer, terminal) {
4747
}
4848
historySize = historySize || kHistorySize;
4949

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

@@ -72,9 +70,11 @@ function Interface(input, output, completer, terminal) {
7270
this.historySize = historySize;
7371

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

7979
this.setPrompt('> ');
8080

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

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

842-
case 'tab': // tab completion
843-
this._tabComplete();
844-
break;
845-
846839
case 'left':
847840
this._moveCursor(-1);
848841
break;
@@ -867,6 +860,14 @@ Interface.prototype._ttyWrite = function(s, key) {
867860
this._historyNext();
868861
break;
869862

863+
case 'tab':
864+
// If tab completion enabled, do that...
865+
if (typeof this.completer === 'function') {
866+
this._tabComplete();
867+
break;
868+
}
869+
// falls through
870+
870871
default:
871872
if (s instanceof Buffer)
872873
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)