From: Rich Trott Date: Thu, 21 May 2015 04:17:10 +0000 (-0700) Subject: readline: allow tabs in input X-Git-Tag: v2.3.0~46 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4b3d493c4b5996d00dc6eac3a7600b124ed4c5b7;p=platform%2Fupstream%2Fnodejs.git readline: allow tabs in input If tab completion is not being used, allow user to enter tab characters. PR-URL: https://github.com/nodejs/io.js/pull/1761 Reviewed-By: Brendan Ashworth --- diff --git a/lib/readline.js b/lib/readline.js index 5782eb8..4107c99 100644 --- a/lib/readline.js +++ b/lib/readline.js @@ -47,9 +47,7 @@ function Interface(input, output, completer, terminal) { } historySize = historySize || kHistorySize; - completer = completer || function() { return []; }; - - if (typeof completer !== 'function') { + if (completer && typeof completer !== 'function') { throw new TypeError('Argument \'completer\' must be a function'); } @@ -72,9 +70,11 @@ function Interface(input, output, completer, terminal) { this.historySize = historySize; // Check arity, 2 - for async, 1 for sync - this.completer = completer.length === 2 ? completer : function(v, callback) { - callback(null, completer(v)); - }; + if (typeof completer === 'function') { + this.completer = completer.length === 2 ? completer : function(v, cb) { + cb(null, completer(v)); + }; + } this.setPrompt('> '); @@ -344,9 +344,6 @@ Interface.prototype._normalWrite = function(b) { }; Interface.prototype._insertString = function(c) { - //BUG: Problem when adding tabs with following content. - // Perhaps the bug is in _refreshLine(). Not sure. - // A hack would be to insert spaces instead of literal '\t'. if (this.cursor < this.line.length) { var beg = this.line.slice(0, this.cursor); var end = this.line.slice(this.cursor, this.line.length); @@ -839,10 +836,6 @@ Interface.prototype._ttyWrite = function(s, key) { this._deleteRight(); break; - case 'tab': // tab completion - this._tabComplete(); - break; - case 'left': this._moveCursor(-1); break; @@ -867,6 +860,14 @@ Interface.prototype._ttyWrite = function(s, key) { this._historyNext(); break; + case 'tab': + // If tab completion enabled, do that... + if (typeof this.completer === 'function') { + this._tabComplete(); + break; + } + // falls through + default: if (s instanceof Buffer) s = s.toString('utf-8'); diff --git a/test/parallel/test-readline-interface.js b/test/parallel/test-readline-interface.js index 6ee9ad2..2e08264 100644 --- a/test/parallel/test-readline-interface.js +++ b/test/parallel/test-readline-interface.js @@ -175,6 +175,59 @@ function isWarned(emitter) { assert.equal(callCount, expectedLines.length); rli.close(); + // \t when there is no completer function should behave like an ordinary + // character + fi = new FakeInput(); + rli = new readline.Interface({ input: fi, output: fi, terminal: true }); + called = false; + rli.on('line', function(line) { + assert.equal(line, '\t'); + assert.strictEqual(called, false); + called = true; + }); + fi.emit('data', '\t'); + fi.emit('data', '\n'); + assert.ok(called); + rli.close(); + + // \t does not become part of the input when there is a completer function + fi = new FakeInput(); + var completer = function(line) { + return [[], line]; + }; + rli = new readline.Interface({ + input: fi, + output: fi, + terminal: true, + completer: completer + }); + called = false; + rli.on('line', function(line) { + assert.equal(line, 'foo'); + assert.strictEqual(called, false); + called = true; + }); + fi.emit('data', '\tfo\to\t'); + fi.emit('data', '\n'); + assert.ok(called); + rli.close(); + + // constructor throws if completer is not a function or undefined + fi = new FakeInput(); + assert.throws(function() { + readline.createInterface({ + input: fi, + completer: 'string is not valid' + }); + }, function(err) { + if (err instanceof TypeError) { + if (/Argument \'completer\' must be a function/.test(err)) { + return true; + } + } + return false; + }); + // sending a multi-byte utf8 char over multiple writes var buf = Buffer('☮', 'utf8'); fi = new FakeInput();