From ae2622e5ce864a784b1faf43425106625a118a8e Mon Sep 17 00:00:00 2001 From: Jacob Bandes-Storch Date: Thu, 5 Dec 2024 18:00:18 -0800 Subject: [PATCH 1/4] Add reflowCursorLine option --- demo/client.ts | 21 +++++++++++++-------- demo/index.html | 1 + src/common/buffer/Buffer.ts | 15 +++++++++------ src/common/buffer/BufferReflow.ts | 15 +++++++++------ src/common/services/OptionsService.ts | 1 + src/common/services/Services.ts | 1 + typings/xterm-headless.d.ts | 6 ++++++ typings/xterm.d.ts | 6 ++++++ 8 files changed, 46 insertions(+), 20 deletions(-) diff --git a/demo/client.ts b/demo/client.ts index 49ba67438e..6e0be22f57 100644 --- a/demo/client.ts +++ b/demo/client.ts @@ -366,14 +366,19 @@ function createTerminal(): void { // Set terminal size again to set the specific dimensions on the demo updateTerminalSize(); - const res = await fetch('/terminals?cols=' + term.cols + '&rows=' + term.rows, { method: 'POST' }); - const processId = await res.text(); - pid = processId; - socketURL += processId; - socket = new WebSocket(socketURL); - socket.onopen = runRealTerminal; - socket.onclose = runFakeTerminal; - socket.onerror = runFakeTerminal; + const useRealTerminal = document.getElementById('use-real-terminal'); + if (useRealTerminal instanceof HTMLInputElement && !useRealTerminal.checked) { + runFakeTerminal(); + } else { + const res = await fetch('/terminals?cols=' + term.cols + '&rows=' + term.rows, { method: 'POST' }); + const processId = await res.text(); + pid = processId; + socketURL += processId; + socket = new WebSocket(socketURL); + socket.onopen = runRealTerminal; + socket.onclose = runFakeTerminal; + socket.onerror = runFakeTerminal; + } }, 0); } diff --git a/demo/index.html b/demo/index.html index 064518475b..3d46f61cab 100644 --- a/demo/index.html +++ b/demo/index.html @@ -81,6 +81,7 @@

Test

Lifecycle
+
diff --git a/src/common/buffer/Buffer.ts b/src/common/buffer/Buffer.ts index d5e057318a..dfdaefd32b 100644 --- a/src/common/buffer/Buffer.ts +++ b/src/common/buffer/Buffer.ts @@ -315,7 +315,7 @@ export class Buffer implements IBuffer { } private _reflowLarger(newCols: number, newRows: number): void { - const toRemove: number[] = reflowLargerGetLinesToRemove(this.lines, this._cols, newCols, this.ybase + this.y, this.getNullCell(DEFAULT_ATTR_DATA)); + const toRemove: number[] = reflowLargerGetLinesToRemove(this.lines, this._cols, newCols, this.ybase + this.y, this.getNullCell(DEFAULT_ATTR_DATA), this._optionsService.rawOptions.reflowCursorLine); if (toRemove.length > 0) { const newLayoutResult = reflowLargerCreateNewLayout(this.lines, toRemove); reflowLargerApplyNewLayout(this.lines, newLayoutResult.layout); @@ -347,6 +347,7 @@ export class Buffer implements IBuffer { } private _reflowSmaller(newCols: number, newRows: number): void { + const reflowCursorLine = this._optionsService.rawOptions.reflowCursorLine; const nullCell = this.getNullCell(DEFAULT_ATTR_DATA); // Gather all BufferLines that need to be inserted into the Buffer here so that they can be // batched up and only committed once @@ -367,11 +368,13 @@ export class Buffer implements IBuffer { wrappedLines.unshift(nextLine); } - // If these lines contain the cursor don't touch them, the program will handle fixing up - // wrapped lines with the cursor - const absoluteY = this.ybase + this.y; - if (absoluteY >= y && absoluteY < y + wrappedLines.length) { - continue; + if (!reflowCursorLine) { + // If these lines contain the cursor don't touch them, the program will handle fixing up + // wrapped lines with the cursor + const absoluteY = this.ybase + this.y; + if (absoluteY >= y && absoluteY < y + wrappedLines.length) { + continue; + } } const lastLineLength = wrappedLines[wrappedLines.length - 1].getTrimmedLength(); diff --git a/src/common/buffer/BufferReflow.ts b/src/common/buffer/BufferReflow.ts index af1c64738e..c127f3b091 100644 --- a/src/common/buffer/BufferReflow.ts +++ b/src/common/buffer/BufferReflow.ts @@ -20,8 +20,9 @@ export interface INewLayoutResult { * @param newCols The columns after resize. * @param bufferAbsoluteY The absolute y position of the cursor (baseY + cursorY). * @param nullCell The cell data to use when filling in empty cells. + * @param reflowCursorLine Whether to reflow the line containing the cursor. */ -export function reflowLargerGetLinesToRemove(lines: CircularList, oldCols: number, newCols: number, bufferAbsoluteY: number, nullCell: ICellData): number[] { +export function reflowLargerGetLinesToRemove(lines: CircularList, oldCols: number, newCols: number, bufferAbsoluteY: number, nullCell: ICellData,reflowCursorLine: boolean): number[] { // Gather all BufferLines that need to be removed from the Buffer here so that they can be // batched up and only committed once const toRemove: number[] = []; @@ -41,11 +42,13 @@ export function reflowLargerGetLinesToRemove(lines: CircularList, o nextLine = lines.get(++i) as BufferLine; } - // If these lines contain the cursor don't touch them, the program will handle fixing up wrapped - // lines with the cursor - if (bufferAbsoluteY >= y && bufferAbsoluteY < i) { - y += wrappedLines.length - 1; - continue; + if (!reflowCursorLine) { + // If these lines contain the cursor don't touch them, the program will handle fixing up + // wrapped lines with the cursor + if (bufferAbsoluteY >= y && bufferAbsoluteY < i) { + y += wrappedLines.length - 1; + continue; + } } // Copy buffer data to new locations diff --git a/src/common/services/OptionsService.ts b/src/common/services/OptionsService.ts index a757c17916..4b8ca82271 100644 --- a/src/common/services/OptionsService.ts +++ b/src/common/services/OptionsService.ts @@ -44,6 +44,7 @@ export const DEFAULT_OPTIONS: Readonly> = { allowTransparency: false, tabStopWidth: 8, theme: {}, + reflowCursorLine: false, rescaleOverlappingGlyphs: false, rightClickSelectsWord: isMac, windowOptions: {}, diff --git a/src/common/services/Services.ts b/src/common/services/Services.ts index 0ceff36c4e..0e5c518484 100644 --- a/src/common/services/Services.ts +++ b/src/common/services/Services.ts @@ -237,6 +237,7 @@ export interface ITerminalOptions { macOptionIsMeta?: boolean; macOptionClickForcesSelection?: boolean; minimumContrastRatio?: number; + reflowCursorLine?: boolean; rescaleOverlappingGlyphs?: boolean; rightClickSelectsWord?: boolean; rows?: number; diff --git a/typings/xterm-headless.d.ts b/typings/xterm-headless.d.ts index 3cbde44b2b..621b450bda 100644 --- a/typings/xterm-headless.d.ts +++ b/typings/xterm-headless.d.ts @@ -142,6 +142,12 @@ declare module '@xterm/headless' { */ minimumContrastRatio?: number; + /** + * Whether to reflow the line containing the cursor when the terminal is resized. Defaults to + * false, because shells usually handle this themselves. + */ + reflowCursorLine?: boolean; + /** * Whether to rescale glyphs horizontally that are a single cell wide but * have glyphs that would overlap following cell(s). This typically happens diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index f9cf14f9c7..a3ebadb06d 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -213,6 +213,12 @@ declare module '@xterm/xterm' { */ minimumContrastRatio?: number; + /** + * Whether to reflow the line containing the cursor when the terminal is resized. Defaults to + * false, because shells usually handle this themselves. + */ + reflowCursorLine?: boolean; + /** * Whether to rescale glyphs horizontally that are a single cell wide but * have glyphs that would overlap following cell(s). This typically happens From d7364faeee18768908df3fbc2664f8922e5ff7e8 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Thu, 12 Dec 2024 06:25:31 -0800 Subject: [PATCH 2/4] Update src/common/buffer/BufferReflow.ts --- src/common/buffer/BufferReflow.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/buffer/BufferReflow.ts b/src/common/buffer/BufferReflow.ts index c127f3b091..44aa0976fe 100644 --- a/src/common/buffer/BufferReflow.ts +++ b/src/common/buffer/BufferReflow.ts @@ -22,7 +22,7 @@ export interface INewLayoutResult { * @param nullCell The cell data to use when filling in empty cells. * @param reflowCursorLine Whether to reflow the line containing the cursor. */ -export function reflowLargerGetLinesToRemove(lines: CircularList, oldCols: number, newCols: number, bufferAbsoluteY: number, nullCell: ICellData,reflowCursorLine: boolean): number[] { +export function reflowLargerGetLinesToRemove(lines: CircularList, oldCols: number, newCols: number, bufferAbsoluteY: number, nullCell: ICellData, reflowCursorLine: boolean): number[] { // Gather all BufferLines that need to be removed from the Buffer here so that they can be // batched up and only committed once const toRemove: number[] = []; From 65899a9b50ced99098798b11354f0b5d3a4d8b25 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Thu, 12 Dec 2024 06:25:36 -0800 Subject: [PATCH 3/4] Update src/common/buffer/Buffer.ts --- src/common/buffer/Buffer.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/common/buffer/Buffer.ts b/src/common/buffer/Buffer.ts index dfdaefd32b..81ab156b57 100644 --- a/src/common/buffer/Buffer.ts +++ b/src/common/buffer/Buffer.ts @@ -315,7 +315,8 @@ export class Buffer implements IBuffer { } private _reflowLarger(newCols: number, newRows: number): void { - const toRemove: number[] = reflowLargerGetLinesToRemove(this.lines, this._cols, newCols, this.ybase + this.y, this.getNullCell(DEFAULT_ATTR_DATA), this._optionsService.rawOptions.reflowCursorLine); + const reflowCursorLine = this._optionsService.rawOptions.reflowCursorLine; + const toRemove: number[] = reflowLargerGetLinesToRemove(this.lines, this._cols, newCols, this.ybase + this.y, this.getNullCell(DEFAULT_ATTR_DATA), reflowCursorLine); if (toRemove.length > 0) { const newLayoutResult = reflowLargerCreateNewLayout(this.lines, toRemove); reflowLargerApplyNewLayout(this.lines, newLayoutResult.layout); From 0d673930721848418163df6f6da956d287d2b676 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Thu, 12 Dec 2024 06:30:17 -0800 Subject: [PATCH 4/4] Fix lint --- typings/xterm-headless.d.ts | 5 +++-- typings/xterm.d.ts | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/typings/xterm-headless.d.ts b/typings/xterm-headless.d.ts index 621b450bda..1085db9b43 100644 --- a/typings/xterm-headless.d.ts +++ b/typings/xterm-headless.d.ts @@ -143,8 +143,9 @@ declare module '@xterm/headless' { minimumContrastRatio?: number; /** - * Whether to reflow the line containing the cursor when the terminal is resized. Defaults to - * false, because shells usually handle this themselves. + * Whether to reflow the line containing the cursor when the terminal is + * resized. Defaults to false, because shells usually handle this + * themselves. */ reflowCursorLine?: boolean; diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index a3ebadb06d..15a0332789 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -214,8 +214,9 @@ declare module '@xterm/xterm' { minimumContrastRatio?: number; /** - * Whether to reflow the line containing the cursor when the terminal is resized. Defaults to - * false, because shells usually handle this themselves. + * Whether to reflow the line containing the cursor when the terminal is + * resized. Defaults to false, because shells usually handle this + * themselves. */ reflowCursorLine?: boolean;