putty-style ED2 sequence handling as terminal option

This commit is contained in:
blashaq
2024-11-21 18:16:19 +00:00
parent 41e8ae3959
commit 9aba07f8f8
5 changed files with 68 additions and 6 deletions
+31
View File
@@ -438,6 +438,37 @@ describe('InputHandler', () => {
inputHandler.eraseInLine(Params.fromArray([2]));
assert.equal(bufferService.buffer.lines.get(2)!.isWrapped, false);
});
it('ED2 with scrollOnDisplayErase turned on', async () => {
const inputHandler = new TestInputHandler(
bufferService,
new MockCharsetService(),
new MockCoreService(),
new MockLogService(),
new MockOptionsService({ scrollOnDisplayErase: true }),
new MockOscLinkService(),
new MockCoreMouseService(),
new MockUnicodeService()
);
const aLine = Array(bufferService.cols + 1).join('a');
// add 2 full lines of text.
await inputHandler.parseP(aLine);
await inputHandler.parseP(aLine);
inputHandler.eraseInDisplay(Params.fromArray([2]));
// those 2 lines should have been pushed to scrollback.
assert.equal(bufferService.rows + 2, bufferService.buffer.lines.length);
assert.equal(bufferService.buffer.ybase, 2);
assert.equal(bufferService.buffer.lines.get(0)?.translateToString(), aLine);
assert.equal(bufferService.buffer.lines.get(1)?.translateToString(), aLine);
// Move to last line and add more text.
bufferService.buffer.y = bufferService.rows - 1;
bufferService.buffer.x = 0;
await inputHandler.parseP(aLine);
inputHandler.eraseInDisplay(Params.fromArray([2]));
// Screen should have been scrolled by a full screen size.
assert.equal(bufferService.rows * 2 + 2, bufferService.buffer.lines.length);
});
it('eraseInDisplay', async () => {
const bufferService = new MockBufferService(80, 7);
const inputHandler = new TestInputHandler(
+23 -5
View File
@@ -1220,12 +1220,30 @@ export class InputHandler extends Disposable implements IInputHandler {
this._dirtyRowTracker.markDirty(0);
break;
case 2:
j = this._bufferService.rows;
this._dirtyRowTracker.markDirty(j - 1);
while (j--) {
this._resetBufferLine(j, respectProtect);
if (this._optionsService.rawOptions.scrollOnDisplayErase) {
let fouldLastLineToKeep = false;
j = this._bufferService.rows;
const x = this._activeBuffer.getBlankLine(this._eraseAttrData());
while (j > 0 && !fouldLastLineToKeep) {
j--;
const currentLine = this._activeBuffer.lines.get(this._activeBuffer.ybase + j);
if (currentLine?.translateToString() !== x.translateToString()) {
fouldLastLineToKeep = true;
this._dirtyRowTracker.markRangeDirty(0, j);
}
}
for (; j >= 0; j--) {
this._bufferService.scroll(this._eraseAttrData());
}
}
else {
j = this._bufferService.rows;
this._dirtyRowTracker.markDirty(j - 1);
while (j--) {
this._resetBufferLine(j, respectProtect);
}
this._dirtyRowTracker.markDirty(0);
}
this._dirtyRowTracker.markDirty(0);
break;
case 3:
// Clear scrollback (everything not in viewport)
+2 -1
View File
@@ -54,7 +54,8 @@ export const DEFAULT_OPTIONS: Readonly<Required<ITerminalOptions>> = {
convertEol: false,
termName: 'xterm',
cancelEvents: false,
overviewRuler: {}
overviewRuler: {},
scrollOnDisplayErase: false
};
const FONT_WEIGHT_OPTIONS: Extract<FontWeight, string>[] = ['normal', 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900'];
+6
View File
@@ -248,6 +248,12 @@ declare module '@xterm/headless' {
* All features are disabled by default for security reasons.
*/
windowOptions?: IWindowOptions;
/**
* If enabled ED2 (clear screen) escape sequence will push erased text to scrollback.
* This emulates PuTTY default clear screen behaviour.
*/
scrollOnDisplayErase?: boolean
}
/**
+6
View File
@@ -331,6 +331,12 @@ declare module '@xterm/xterm' {
* decorations underneath the scroll bar.
*/
overviewRuler?: IOverviewRulerOptions;
/**
* If enabled ED2 (clear screen) escape sequence will push erased text to scrollback.
* This emulates PuTTY default clear screen behaviour.
*/
scrollOnDisplayErase?: boolean
}
/**