repl: Auto alignment for .editor mode

When in `.editor` mode, current line whitespace prefixes
are preserved in the subsequent line. User can hit backspace
to clean the whitespace

```js
node 🙈 ₹ node
> .editor
// Entering editor mode (^D to finish, ^C to cancel)
function test() {
  console.log('tested!'); //On enter, cursor will be after 2 spaces
  _
```

PR-URL: https://github.com/nodejs/node/pull/8241
Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
Prince J Wesley 2016-08-24 00:05:59 +05:30
Родитель f8f283b8f3
Коммит 5bef38b627
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 9D76A33B02A4C46B
3 изменённых файлов: 71 добавлений и 2 удалений

Просмотреть файл

@ -41,6 +41,7 @@ function Interface(input, output, completer, terminal) {
this._sawReturn = false;
this.isCompletionEnabled = true;
this._sawKeyPress = false;
this._previousKey = null;
EventEmitter.call(this);
@ -247,6 +248,9 @@ Interface.prototype._addHistory = function() {
// if the history is disabled then return the line
if (this.historySize === 0) return this.line;
// if the trimmed line is empty then return the line
if (this.line.trim().length === 0) return this.line;
if (this.history.length === 0 || this.history[0] !== this.line) {
this.history.unshift(this.line);
@ -947,6 +951,10 @@ function emitKeypressEvents(stream, iface) {
if (r) {
clearTimeout(timeoutId);
if (iface) {
iface._sawKeyPress = r.length === 1;
}
for (var i = 0; i < r.length; i++) {
if (r[i] === '\t' && typeof r[i + 1] === 'string' && iface) {
iface.isCompletionEnabled = false;

Просмотреть файл

@ -471,6 +471,15 @@ function REPLServer(prompt,
if (self.editorMode) {
self.bufferedCommand += cmd + '\n';
// code alignment
const matches = self._sawKeyPress ? cmd.match(/^\s+/) : null;
if (matches) {
const prefix = matches[0];
self.inputStream.write(prefix);
self.line = prefix;
self.cursor = prefix.length;
}
self.memory(cmd);
return;
}

Просмотреть файл

@ -9,7 +9,7 @@ const repl = require('repl');
// \u001b[3G - Moves the cursor to 3rd column
const terminalCode = '\u001b[1G\u001b[0J> \u001b[3G';
function run(input, output, event) {
function run({input, output, event}) {
const stream = new common.ArrayStream();
let found = '';
@ -49,7 +49,59 @@ const tests = [
input: 'var i = 1;\ni + 3',
output: '\n4',
event: {ctrl: true, name: 'd'}
},
{
input: ' var i = 1;\ni + 3',
output: '\n4',
event: {ctrl: true, name: 'd'}
}
];
tests.forEach(({input, output, event}) => run(input, output, event));
tests.forEach(run);
// Auto code alignment for .editor mode
function testCodeAligment({input, cursor = 0, line = ''}) {
const stream = new common.ArrayStream();
const replServer = repl.start({
prompt: '> ',
terminal: true,
input: stream,
output: stream,
useColors: false
});
stream.emit('data', '.editor\n');
input.split('').forEach((ch) => stream.emit('data', ch));
// Test the content of current line and the cursor position
assert.strictEqual(line, replServer.line);
assert.strictEqual(cursor, replServer.cursor);
replServer.write('', {ctrl: true, name: 'd'});
replServer.close();
// Ensure that empty lines are not saved in history
assert.notStrictEqual(replServer.history[0].trim(), '');
}
const codeAlignmentTests = [
{
input: 'var i = 1;\n'
},
{
input: ' var i = 1;\n',
cursor: 2,
line: ' '
},
{
input: ' var i = 1;\n',
cursor: 5,
line: ' '
},
{
input: ' var i = 1;\n var j = 2\n',
cursor: 2,
line: ' '
}
];
codeAlignmentTests.forEach(testCodeAligment);