Skip to content

Commit 1771825

Browse files
authored
Merge pull request #5224 from Blashaq/master
putty-style ED2 sequence handling as terminal option
2 parents a260f7d + e5b838a commit 1771825

File tree

6 files changed

+67
-5
lines changed

6 files changed

+67
-5
lines changed

src/common/InputHandler.test.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,37 @@ describe('InputHandler', () => {
438438
inputHandler.eraseInLine(Params.fromArray([2]));
439439
assert.equal(bufferService.buffer.lines.get(2)!.isWrapped, false);
440440
});
441+
it('ED2 with scrollOnEraseInDisplay turned on', async () => {
442+
const inputHandler = new TestInputHandler(
443+
bufferService,
444+
new MockCharsetService(),
445+
new MockCoreService(),
446+
new MockLogService(),
447+
new MockOptionsService({ scrollOnEraseInDisplay: true }),
448+
new MockOscLinkService(),
449+
new MockCoreMouseService(),
450+
new MockUnicodeService()
451+
);
452+
const aLine = Array(bufferService.cols + 1).join('a');
453+
// add 2 full lines of text.
454+
await inputHandler.parseP(aLine);
455+
await inputHandler.parseP(aLine);
456+
457+
inputHandler.eraseInDisplay(Params.fromArray([2]));
458+
// those 2 lines should have been pushed to scrollback.
459+
assert.equal(bufferService.rows + 2, bufferService.buffer.lines.length);
460+
assert.equal(bufferService.buffer.ybase, 2);
461+
assert.equal(bufferService.buffer.lines.get(0)?.translateToString(), aLine);
462+
assert.equal(bufferService.buffer.lines.get(1)?.translateToString(), aLine);
463+
464+
// Move to last line and add more text.
465+
bufferService.buffer.y = bufferService.rows - 1;
466+
bufferService.buffer.x = 0;
467+
await inputHandler.parseP(aLine);
468+
inputHandler.eraseInDisplay(Params.fromArray([2]));
469+
// Screen should have been scrolled by a full screen size.
470+
assert.equal(bufferService.rows * 2 + 2, bufferService.buffer.lines.length);
471+
});
441472
it('eraseInDisplay', async () => {
442473
const bufferService = new MockBufferService(80, 7);
443474
const inputHandler = new TestInputHandler(

src/common/InputHandler.ts

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1220,12 +1220,27 @@ export class InputHandler extends Disposable implements IInputHandler {
12201220
this._dirtyRowTracker.markDirty(0);
12211221
break;
12221222
case 2:
1223-
j = this._bufferService.rows;
1224-
this._dirtyRowTracker.markDirty(j - 1);
1225-
while (j--) {
1226-
this._resetBufferLine(j, respectProtect);
1223+
if (this._optionsService.rawOptions.scrollOnEraseInDisplay) {
1224+
j = this._bufferService.rows;
1225+
this._dirtyRowTracker.markRangeDirty(0, j - 1);
1226+
while (j--) {
1227+
const currentLine = this._activeBuffer.lines.get(this._activeBuffer.ybase + j);
1228+
if (currentLine?.getTrimmedLength()) {
1229+
break;
1230+
}
1231+
}
1232+
for (; j >= 0; j--) {
1233+
this._bufferService.scroll(this._eraseAttrData());
1234+
}
1235+
}
1236+
else {
1237+
j = this._bufferService.rows;
1238+
this._dirtyRowTracker.markDirty(j - 1);
1239+
while (j--) {
1240+
this._resetBufferLine(j, respectProtect);
1241+
}
1242+
this._dirtyRowTracker.markDirty(0);
12271243
}
1228-
this._dirtyRowTracker.markDirty(0);
12291244
break;
12301245
case 3:
12311246
// Clear scrollback (everything not in viewport)

src/common/services/OptionsService.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ export const DEFAULT_OPTIONS: Readonly<Required<ITerminalOptions>> = {
3232
logLevel: 'info',
3333
logger: null,
3434
scrollback: 1000,
35+
scrollOnEraseInDisplay: false,
3536
scrollOnUserInput: true,
3637
scrollSensitivity: 1,
3738
screenReaderMode: false,

src/common/services/Services.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ export interface ITerminalOptions {
254254
windowOptions?: IWindowOptions;
255255
wordSeparator?: string;
256256
overviewRuler?: IOverviewRulerOptions;
257+
scrollOnEraseInDisplay?: boolean;
257258

258259
[key: string]: any;
259260
cancelEvents: boolean;

typings/xterm-headless.d.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,13 @@ declare module '@xterm/headless' {
186186
*/
187187
scrollback?: number;
188188

189+
/**
190+
* If enabled the Erase in Display All (ED2) escape sequence will push
191+
* erased text to scrollback, instead of clearing only the viewport portion.
192+
* This emulates PuTTY's default clear screen behavior.
193+
*/
194+
scrollOnEraseInDisplay?: boolean;
195+
189196
/**
190197
* The scrolling speed multiplier used for adjusting normal scrolling speed.
191198
*/

typings/xterm.d.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,13 @@ declare module '@xterm/xterm' {
257257
*/
258258
scrollback?: number;
259259

260+
/**
261+
* If enabled the Erase in Display All (ED2) escape sequence will push
262+
* erased text to scrollback, instead of clearing only the viewport portion.
263+
* This emulates PuTTY's default clear screen behavior.
264+
*/
265+
scrollOnEraseInDisplay?: boolean;
266+
260267
/**
261268
* Whether to scroll to the bottom whenever there is some user input. The
262269
* default is true.

0 commit comments

Comments
 (0)