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:
parent
f8f283b8f3
commit
5bef38b627
@ -41,6 +41,7 @@ function Interface(input, output, completer, terminal) {
|
|||||||
|
|
||||||
this._sawReturn = false;
|
this._sawReturn = false;
|
||||||
this.isCompletionEnabled = true;
|
this.isCompletionEnabled = true;
|
||||||
|
this._sawKeyPress = false;
|
||||||
this._previousKey = null;
|
this._previousKey = null;
|
||||||
|
|
||||||
EventEmitter.call(this);
|
EventEmitter.call(this);
|
||||||
@ -247,6 +248,9 @@ Interface.prototype._addHistory = function() {
|
|||||||
// if the history is disabled then return the line
|
// if the history is disabled then return the line
|
||||||
if (this.historySize === 0) return this.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) {
|
if (this.history.length === 0 || this.history[0] !== this.line) {
|
||||||
this.history.unshift(this.line);
|
this.history.unshift(this.line);
|
||||||
|
|
||||||
@ -947,6 +951,10 @@ function emitKeypressEvents(stream, iface) {
|
|||||||
if (r) {
|
if (r) {
|
||||||
clearTimeout(timeoutId);
|
clearTimeout(timeoutId);
|
||||||
|
|
||||||
|
if (iface) {
|
||||||
|
iface._sawKeyPress = r.length === 1;
|
||||||
|
}
|
||||||
|
|
||||||
for (var i = 0; i < r.length; i++) {
|
for (var i = 0; i < r.length; i++) {
|
||||||
if (r[i] === '\t' && typeof r[i + 1] === 'string' && iface) {
|
if (r[i] === '\t' && typeof r[i + 1] === 'string' && iface) {
|
||||||
iface.isCompletionEnabled = false;
|
iface.isCompletionEnabled = false;
|
||||||
|
@ -471,6 +471,15 @@ function REPLServer(prompt,
|
|||||||
|
|
||||||
if (self.editorMode) {
|
if (self.editorMode) {
|
||||||
self.bufferedCommand += cmd + '\n';
|
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);
|
self.memory(cmd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ const repl = require('repl');
|
|||||||
// \u001b[3G - Moves the cursor to 3rd column
|
// \u001b[3G - Moves the cursor to 3rd column
|
||||||
const terminalCode = '\u001b[1G\u001b[0J> \u001b[3G';
|
const terminalCode = '\u001b[1G\u001b[0J> \u001b[3G';
|
||||||
|
|
||||||
function run(input, output, event) {
|
function run({input, output, event}) {
|
||||||
const stream = new common.ArrayStream();
|
const stream = new common.ArrayStream();
|
||||||
let found = '';
|
let found = '';
|
||||||
|
|
||||||
@ -49,7 +49,59 @@ const tests = [
|
|||||||
input: 'var i = 1;\ni + 3',
|
input: 'var i = 1;\ni + 3',
|
||||||
output: '\n4',
|
output: '\n4',
|
||||||
event: {ctrl: true, name: 'd'}
|
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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user