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:
Родитель
f8f283b8f3
Коммит
5bef38b627
|
@ -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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче