Skip to content

Commit 8b258cb

Browse files
committed
#134: added support for terminal Save/Restore Position command (s/u)
1 parent c0c55ca commit 8b258cb

3 files changed

Lines changed: 79 additions & 5 deletions

File tree

web-src/js/components/terminal/terminal_model.js

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,6 @@ export class TerminalModel {
4141
this.listeners = [];
4242

4343
this.clear();
44-
45-
this.changedLines = [];
4644
}
4745

4846
addListener(listener) {
@@ -140,6 +138,10 @@ export class TerminalModel {
140138

141139
this.currentStyle = null;
142140

141+
this.changedLines = [];
142+
143+
this.savedCursorPosition = null;
144+
143145
for (const listener of this.listeners) {
144146
listener.cleared();
145147
}
@@ -504,6 +506,23 @@ class MoveCursorToPositionHandler extends CommandHandler {
504506
}
505507
}
506508

509+
class SaveCursorPositionHandler extends CommandHandler {
510+
handle(args, terminal) {
511+
terminal.savedCursorPosition = [terminal.currentLine, terminal.currentPosition];
512+
}
513+
}
514+
515+
class RestoreCursorPositionHandler extends CommandHandler {
516+
handle(args, terminal) {
517+
if (isNull(terminal.savedCursorPosition)) {
518+
console.log('WARN! trying to restore cursor position, but nothing is saved');
519+
return;
520+
}
521+
const [line, position] = terminal.savedCursorPosition;
522+
terminal.setCursorPosition(line, position);
523+
}
524+
}
525+
507526
class ClearLineHandler extends CommandHandler {
508527
constructor() {
509528
super();
@@ -534,8 +553,8 @@ COMMAND_HANDLERS.set('A', new MoveCursorVerticallyHandler(true));
534553
COMMAND_HANDLERS.set('B', new MoveCursorVerticallyHandler(false));
535554
COMMAND_HANDLERS.set('C', new MoveCursorHorizontallyHandler(true));
536555
COMMAND_HANDLERS.set('D', new MoveCursorHorizontallyHandler(false));
537-
COMMAND_HANDLERS.set('s', null);
538-
COMMAND_HANDLERS.set('u', null);
556+
COMMAND_HANDLERS.set('s', new SaveCursorPositionHandler());
557+
COMMAND_HANDLERS.set('u', new RestoreCursorPositionHandler());
539558

540559
const TEXT_COLOR_DICT = new Map();
541560
TEXT_COLOR_DICT.set(39, null);

web-src/tests/terminal_model_test.js

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ import {
1515
moveCursorLeft,
1616
moveCursorRight,
1717
moveCursorUp,
18-
moveToPosition
18+
moveToPosition,
19+
restorePosition,
20+
savePosition
1921
} from './terminal_test_utils';
2022

2123
chaiConfig.truncateThreshold = 0;
@@ -970,4 +972,49 @@ describe('Test terminal model', function () {
970972
assert.deepEqual([[0, 1, 2], [2]], this.changedLines);
971973
});
972974
});
975+
976+
describe('Save/restore cursor position', function () {
977+
beforeEach(function () {
978+
sinon.stub(console, 'log').returns(void 0);
979+
});
980+
981+
afterEach(function () {
982+
console.log.restore();
983+
});
984+
985+
it('Test restore in the first line', function () {
986+
this.model.write('1234' + savePosition() + '5678' + restorePosition() + 'abc');
987+
988+
assert.deepEqual(['1234abc8'], this.model.lines);
989+
});
990+
991+
it('Test restore in the first line, when 3 lines', function () {
992+
this.model.write('123' + savePosition() + '45\n678\n90' + restorePosition() + 'abc');
993+
994+
assert.deepEqual(['123abc', '678', '90'], this.model.lines);
995+
});
996+
997+
it('Test restore in the last line, when 3 lines', function () {
998+
this.model.write('123\n4567\n8' + savePosition() + '90' + moveCursorUp(2) + 'X'
999+
+ restorePosition() + 'abc');
1000+
1001+
assert.deepEqual(['123X', '4567', '8abc'], this.model.lines);
1002+
});
1003+
1004+
it('Test restore position without save', function () {
1005+
this.model.write('1234' + restorePosition() + 'abc');
1006+
1007+
assert.deepEqual(['1234abc'], this.model.lines);
1008+
expect(console.log.args[0][0]).to.equal('WARN! trying to restore cursor position, but nothing is saved');
1009+
});
1010+
1011+
it('Test restore position after clear', function () {
1012+
this.model.write('1234' + savePosition());
1013+
this.model.clear();
1014+
this.model.write('abc' + restorePosition() + 'XYZ');
1015+
1016+
assert.deepEqual(['abcXYZ'], this.model.lines);
1017+
expect(console.log.args[0][0]).to.equal('WARN! trying to restore cursor position, but nothing is saved');
1018+
});
1019+
})
9731020
});

web-src/tests/terminal_test_utils.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,14 @@ export function moveToPosition(line, column, command = 'H') {
2828
return escapePrefix + line + ';' + column + command;
2929
}
3030

31+
export function savePosition() {
32+
return escapePrefix + 's';
33+
}
34+
35+
export function restorePosition() {
36+
return escapePrefix + 'u';
37+
}
38+
3139
export function clearLineToRight() {
3240
return clearLine('');
3341
}

0 commit comments

Comments
 (0)