Skip to content

Commit cc62029

Browse files
committed
enable tabs for readline if tab completion is not enabled
documentation updates add test
1 parent 2b1c01c commit cc62029

File tree

3 files changed

+35
-12
lines changed

3 files changed

+35
-12
lines changed

doc/api/readline.markdown

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ the following values:
4141

4242
- `historySize` - maximum number of history lines retained. Defaults to `30`.
4343

44+
If a `completer` function is supplied, the user will not be able to enter tab
45+
characters as part of their input. If no `completer` function is supplied, tabs
46+
will be permitted in user input.
47+
4448
The `completer` function is given the current line entered by the user, and
4549
is supposed to return an Array with 2 entries:
4650

lib/readline.js

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,9 @@ function Interface(input, output, completer, terminal) {
4747
}
4848
historySize = historySize || kHistorySize;
4949

50-
completer = completer || function() { return []; };
50+
completer = completer || undefined;
5151

52-
if (typeof completer !== 'function') {
52+
if (! typeof completer in ['function', 'undefined']) {
5353
throw new TypeError('Argument \'completer\' must be a function');
5454
}
5555

@@ -72,9 +72,12 @@ function Interface(input, output, completer, terminal) {
7272
this.historySize = historySize;
7373

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

7982
this.setPrompt('> ');
8083

@@ -344,9 +347,6 @@ Interface.prototype._normalWrite = function(b) {
344347
};
345348

346349
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'.
350350
if (this.cursor < this.line.length) {
351351
var beg = this.line.slice(0, this.cursor);
352352
var end = this.line.slice(this.cursor, this.line.length);
@@ -839,10 +839,6 @@ Interface.prototype._ttyWrite = function(s, key) {
839839
this._deleteRight();
840840
break;
841841

842-
case 'tab': // tab completion
843-
this._tabComplete();
844-
break;
845-
846842
case 'left':
847843
this._moveCursor(-1);
848844
break;
@@ -868,6 +864,14 @@ Interface.prototype._ttyWrite = function(s, key) {
868864
break;
869865

870866
default:
867+
if (key.name === 'tab') {
868+
// If tab completion enabled, do that...
869+
if (typeof this.completer === 'function') {
870+
this._tabComplete();
871+
break;
872+
}
873+
}
874+
871875
if (s instanceof Buffer)
872876
s = s.toString('utf-8');
873877

test/parallel/test-readline-interface.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,21 @@ 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+
expectedLines = ['\t'];
183+
callCount = 0;
184+
rli.on('line', function(line) {
185+
assert.equal(line, expectedLines[callCount]);
186+
callCount++;
187+
});
188+
fi.emit('data', '\t');
189+
fi.emit('data', '\n');
190+
assert.equal(callCount, expectedLines.length);
191+
rli.close();
192+
178193
// sending a multi-byte utf8 char over multiple writes
179194
var buf = Buffer('☮', 'utf8');
180195
fi = new FakeInput();

0 commit comments

Comments
 (0)