From 7adddadd58d58636f534a62ea16614a40f4b50ac Mon Sep 17 00:00:00 2001 From: meganrogge Date: Tue, 7 Mar 2023 11:06:15 -0600 Subject: [PATCH 01/23] fix #172582 --- .../browser/terminalAccessibleBuffer.ts | 42 +++++++++++++++---- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts index 03886143442e3..34871f340e761 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts @@ -39,6 +39,7 @@ export class AccessibleBufferWidget extends DisposableStore { private _lastContentLength: number = 0; private _font: ITerminalFont; private _xtermElement: HTMLElement; + private _content: string = ''; constructor( private readonly _xterm: IXtermTerminal & { raw: Terminal }, @@ -87,6 +88,11 @@ export class AccessibleBufferWidget extends DisposableStore { this._font = _xterm.getFont(); } })); + this.add(this._xterm.raw.onData(() => { + if (this._accessibleBuffer.classList.contains('active')) { + this._refresh(); + } + })); } private _hide(): void { @@ -95,10 +101,32 @@ export class AccessibleBufferWidget extends DisposableStore { this._xterm.raw.focus(); } + private async _refresh(): Promise { + const sb = new StringBuilder(10000); + sb.appendString(this._content); + sb.appendString(this._getContent(this._lastContentLength)); + this._content = sb.build(); + const model = await this._getTextModel(URI.from({ scheme: AccessibleBufferConstants.Scheme, fragment: this._content })); + if (model) { + this._bufferEditor.setModel(model); + } + let lineNumber = 1; + const lineCount = model?.getLineCount(); + if (lineCount && model) { + lineNumber = lineCount > 2 ? lineCount - 2 : 1; + } + this._bufferEditor.setSelection({ startLineNumber: lineNumber, startColumn: 1, endLineNumber: lineNumber, endColumn: 1 }); + this._bufferEditor.setScrollTop(this._bufferEditor.getScrollHeight()); + this._refreshSelection = false; + this._lastContentLength = this._content.length; + this._accessibleBuffer.replaceChildren(this._editorContainer); + this._bufferEditor.focus(); + } + async show(): Promise { const commandDetection = this._capabilities.get(TerminalCapability.CommandDetection); - const fragment = !!commandDetection ? this._getShellIntegrationContent() : this._getAllContent(); - const model = await this._getTextModel(URI.from({ scheme: AccessibleBufferConstants.Scheme, fragment })); + this._content = !!commandDetection ? this._getShellIntegrationContent() : this._getContent(); + const model = await this._getTextModel(URI.from({ scheme: AccessibleBufferConstants.Scheme, fragment: this._content })); if (model) { this._bufferEditor.setModel(model); } @@ -118,7 +146,7 @@ export class AccessibleBufferWidget extends DisposableStore { this._accessibleBuffer.tabIndex = -1; this._accessibleBuffer.classList.add('active'); this._xtermElement.classList.add('hide'); - if (this._lastContentLength !== fragment.length || this._refreshSelection) { + if (this._lastContentLength !== this._content.length || this._refreshSelection) { let lineNumber = 1; const lineCount = model?.getLineCount(); if (lineCount && model) { @@ -127,7 +155,7 @@ export class AccessibleBufferWidget extends DisposableStore { this._bufferEditor.setSelection({ startLineNumber: lineNumber, startColumn: 1, endLineNumber: lineNumber, endColumn: 1 }); this._bufferEditor.setScrollTop(this._bufferEditor.getScrollHeight()); this._refreshSelection = false; - this._lastContentLength = fragment.length; + this._lastContentLength = this._content.length; } this._accessibleBuffer.replaceChildren(this._editorContainer); this._bufferEditor.focus(); @@ -146,7 +174,7 @@ export class AccessibleBufferWidget extends DisposableStore { const commands = this._capabilities.get(TerminalCapability.CommandDetection)?.commands; const sb = new StringBuilder(10000); if (!commands?.length) { - return this._getAllContent(); + return this._getContent(); } for (const command of commands) { sb.appendString(command.command.replace(new RegExp(' ', 'g'), '\xA0')); @@ -159,7 +187,7 @@ export class AccessibleBufferWidget extends DisposableStore { return sb.build(); } - private _getAllContent(): string { + private _getContent(startLine?: number): string { const lines: string[] = []; let currentLine: string = ''; const buffer = this._xterm?.raw.buffer.active; @@ -167,7 +195,7 @@ export class AccessibleBufferWidget extends DisposableStore { return ''; } const end = buffer.length; - for (let i = 0; i < end; i++) { + for (let i = startLine ?? 0; i < end; i++) { const line = buffer.getLine(i); if (!line) { continue; From d69927bdcf935def592f23daa4e4401864c2b16e Mon Sep 17 00:00:00 2001 From: meganrogge Date: Tue, 7 Mar 2023 12:01:31 -0600 Subject: [PATCH 02/23] clean up --- .../browser/terminalAccessibleBuffer.ts | 76 +++++++++---------- 1 file changed, 37 insertions(+), 39 deletions(-) diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts index 34871f340e761..7487652d5c7ab 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts @@ -90,6 +90,7 @@ export class AccessibleBufferWidget extends DisposableStore { })); this.add(this._xterm.raw.onData(() => { if (this._accessibleBuffer.classList.contains('active')) { + this._refreshSelection = true; this._refresh(); } })); @@ -101,64 +102,61 @@ export class AccessibleBufferWidget extends DisposableStore { this._xterm.raw.focus(); } - private async _refresh(): Promise { + private async _updateContent(refresh?: boolean): Promise { const sb = new StringBuilder(10000); - sb.appendString(this._content); - sb.appendString(this._getContent(this._lastContentLength)); + if (refresh) { + sb.appendString(this._content); + sb.appendString(this._getContent(this._lastContentLength)); + } else { + const commandDetection = this._capabilities.get(TerminalCapability.CommandDetection); + sb.appendString(!!commandDetection ? this._getShellIntegrationContent() : this._getContent()); + } this._content = sb.build(); const model = await this._getTextModel(URI.from({ scheme: AccessibleBufferConstants.Scheme, fragment: this._content })); if (model) { this._bufferEditor.setModel(model); + } else { + throw new Error('Could not create model'); } - let lineNumber = 1; - const lineCount = model?.getLineCount(); - if (lineCount && model) { - lineNumber = lineCount > 2 ? lineCount - 2 : 1; + return model; + } + + private async _refresh(): Promise { + const model = await this._updateContent(); + const lineNumber = model.getLineCount() - 1; + if (this._lastContentLength !== this._content.length || this._refreshSelection) { + this._bufferEditor.setSelection({ startLineNumber: lineNumber, startColumn: 1, endLineNumber: lineNumber, endColumn: 1 }); + this._bufferEditor.setScrollTop(this._bufferEditor.getScrollHeight()); + this._refreshSelection = false; + this._lastContentLength = this._content.length; } - this._bufferEditor.setSelection({ startLineNumber: lineNumber, startColumn: 1, endLineNumber: lineNumber, endColumn: 1 }); - this._bufferEditor.setScrollTop(this._bufferEditor.getScrollHeight()); - this._refreshSelection = false; - this._lastContentLength = this._content.length; this._accessibleBuffer.replaceChildren(this._editorContainer); this._bufferEditor.focus(); } async show(): Promise { - const commandDetection = this._capabilities.get(TerminalCapability.CommandDetection); - this._content = !!commandDetection ? this._getShellIntegrationContent() : this._getContent(); - const model = await this._getTextModel(URI.from({ scheme: AccessibleBufferConstants.Scheme, fragment: this._content })); - if (model) { - this._bufferEditor.setModel(model); - } if (!this._registered) { - this._bufferEditor.layout({ width: this._xtermElement.clientWidth, height: this._xtermElement.clientHeight }); - this._bufferEditor.onKeyDown((e) => { - if (e.keyCode === KeyCode.Escape || e.keyCode === KeyCode.Tab) { - this._hide(); - } - }); - if (commandDetection) { - this._commandFinishedDisposable = commandDetection.onCommandFinished(() => this._refreshSelection = true); - this.add(this._commandFinishedDisposable); - } - this._registered = true; + this._registerListeners(); } + await this._refresh(); this._accessibleBuffer.tabIndex = -1; this._accessibleBuffer.classList.add('active'); this._xtermElement.classList.add('hide'); - if (this._lastContentLength !== this._content.length || this._refreshSelection) { - let lineNumber = 1; - const lineCount = model?.getLineCount(); - if (lineCount && model) { - lineNumber = commandDetection ? lineCount - 1 : lineCount > 2 ? lineCount - 2 : 1; + } + + private _registerListeners(): void { + const commandDetection = this._capabilities.get(TerminalCapability.CommandDetection); + this._bufferEditor.layout({ width: this._xtermElement.clientWidth, height: this._xtermElement.clientHeight }); + this._bufferEditor.onKeyDown((e) => { + if (e.keyCode === KeyCode.Escape || e.keyCode === KeyCode.Tab) { + this._hide(); } - this._bufferEditor.setSelection({ startLineNumber: lineNumber, startColumn: 1, endLineNumber: lineNumber, endColumn: 1 }); - this._bufferEditor.setScrollTop(this._bufferEditor.getScrollHeight()); - this._refreshSelection = false; - this._lastContentLength = this._content.length; + }); + if (commandDetection) { + this._commandFinishedDisposable = commandDetection.onCommandFinished(() => this._refreshSelection = true); + this.add(this._commandFinishedDisposable); } - this._accessibleBuffer.replaceChildren(this._editorContainer); - this._bufferEditor.focus(); + this._registered = true; } private async _getTextModel(resource: URI): Promise { From 3cf756e13f3d6664babb06a98f69f32be9ac3666 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Tue, 7 Mar 2023 12:14:19 -0600 Subject: [PATCH 03/23] fix issues --- .../accessibility/browser/terminalAccessibleBuffer.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts index 7487652d5c7ab..ee9c92345fc38 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts @@ -37,6 +37,7 @@ export class AccessibleBufferWidget extends DisposableStore { private _refreshSelection: boolean = true; private _registered: boolean = false; private _lastContentLength: number = 0; + private _lastBufferLine: number = 0; private _font: ITerminalFont; private _xtermElement: HTMLElement; private _content: string = ''; @@ -106,7 +107,7 @@ export class AccessibleBufferWidget extends DisposableStore { const sb = new StringBuilder(10000); if (refresh) { sb.appendString(this._content); - sb.appendString(this._getContent(this._lastContentLength)); + sb.appendString(this._getContent(this._lastBufferLine)); } else { const commandDetection = this._capabilities.get(TerminalCapability.CommandDetection); sb.appendString(!!commandDetection ? this._getShellIntegrationContent() : this._getContent()); @@ -122,7 +123,7 @@ export class AccessibleBufferWidget extends DisposableStore { } private async _refresh(): Promise { - const model = await this._updateContent(); + const model = await this._updateContent(true); const lineNumber = model.getLineCount() - 1; if (this._lastContentLength !== this._content.length || this._refreshSelection) { this._bufferEditor.setSelection({ startLineNumber: lineNumber, startColumn: 1, endLineNumber: lineNumber, endColumn: 1 }); @@ -205,6 +206,7 @@ export class AccessibleBufferWidget extends DisposableStore { currentLine = ''; } } + this._lastBufferLine = end; return lines.join('\n'); } } From 6782f4524b008a3562ae0717477c6c136c456c50 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Tue, 7 Mar 2023 12:21:48 -0600 Subject: [PATCH 04/23] clear content and last buffer line on command finished --- .../accessibility/browser/terminalAccessibleBuffer.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts index ee9c92345fc38..94a2441947f7e 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts @@ -154,7 +154,10 @@ export class AccessibleBufferWidget extends DisposableStore { } }); if (commandDetection) { - this._commandFinishedDisposable = commandDetection.onCommandFinished(() => this._refreshSelection = true); + this._commandFinishedDisposable = commandDetection.onCommandFinished(() => { + this._refreshSelection = true; + this._lastBufferLine = 0; + }); this.add(this._commandFinishedDisposable); } this._registered = true; From 1626e8de54f7aeab7f20160c42e54f1e2b048b4d Mon Sep 17 00:00:00 2001 From: meganrogge Date: Tue, 7 Mar 2023 13:10:54 -0600 Subject: [PATCH 05/23] still not working quite right --- .../browser/terminalAccessibleBuffer.ts | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts index 94a2441947f7e..ffd326936eaf8 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts @@ -89,10 +89,9 @@ export class AccessibleBufferWidget extends DisposableStore { this._font = _xterm.getFont(); } })); - this.add(this._xterm.raw.onData(() => { + this.add(this._xterm.raw.onWriteParsed(async () => { if (this._accessibleBuffer.classList.contains('active')) { - this._refreshSelection = true; - this._refresh(); + await this._refresh(); } })); } @@ -107,18 +106,22 @@ export class AccessibleBufferWidget extends DisposableStore { const sb = new StringBuilder(10000); if (refresh) { sb.appendString(this._content); - sb.appendString(this._getContent(this._lastBufferLine)); + const additionalLines = this._getContent(this._lastBufferLine); + sb.appendString(additionalLines); } else { const commandDetection = this._capabilities.get(TerminalCapability.CommandDetection); sb.appendString(!!commandDetection ? this._getShellIntegrationContent() : this._getContent()); } this._content = sb.build(); - const model = await this._getTextModel(URI.from({ scheme: AccessibleBufferConstants.Scheme, fragment: this._content })); - if (model) { + let model = this._bufferEditor.getModel(); + if (!model) { + model = await this._getTextModel(URI.from({ scheme: AccessibleBufferConstants.Scheme })); this._bufferEditor.setModel(model); - } else { - throw new Error('Could not create model'); } + if (!model) { + throw new Error('Could not create accessible buffer editor model'); + } + model.setValue(this._content); return model; } @@ -197,7 +200,7 @@ export class AccessibleBufferWidget extends DisposableStore { return ''; } const end = buffer.length; - for (let i = startLine ?? 0; i < end; i++) { + for (let i = startLine ?? 0; i <= end; i++) { const line = buffer.getLine(i); if (!line) { continue; From 0e73aa4f684d999544241540c9fca6084ef853a9 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Tue, 7 Mar 2023 14:47:26 -0600 Subject: [PATCH 06/23] get it to work --- .../browser/terminalAccessibleBuffer.ts | 32 ++++--------------- 1 file changed, 6 insertions(+), 26 deletions(-) diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts index ffd326936eaf8..a3c00f2e275cd 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts @@ -36,11 +36,8 @@ export class AccessibleBufferWidget extends DisposableStore { private _commandFinishedDisposable: IDisposable | undefined; private _refreshSelection: boolean = true; private _registered: boolean = false; - private _lastContentLength: number = 0; - private _lastBufferLine: number = 0; private _font: ITerminalFont; private _xtermElement: HTMLElement; - private _content: string = ''; constructor( private readonly _xterm: IXtermTerminal & { raw: Terminal }, @@ -103,36 +100,23 @@ export class AccessibleBufferWidget extends DisposableStore { } private async _updateContent(refresh?: boolean): Promise { - const sb = new StringBuilder(10000); - if (refresh) { - sb.appendString(this._content); - const additionalLines = this._getContent(this._lastBufferLine); - sb.appendString(additionalLines); - } else { - const commandDetection = this._capabilities.get(TerminalCapability.CommandDetection); - sb.appendString(!!commandDetection ? this._getShellIntegrationContent() : this._getContent()); - } - this._content = sb.build(); - let model = this._bufferEditor.getModel(); - if (!model) { - model = await this._getTextModel(URI.from({ scheme: AccessibleBufferConstants.Scheme })); - this._bufferEditor.setModel(model); - } + const commandDetection = this._capabilities.get(TerminalCapability.CommandDetection); + const value = !!commandDetection && !refresh ? this._getShellIntegrationContent() : this._getContent(); + const model = await this._getTextModel(URI.from({ scheme: AccessibleBufferConstants.Scheme, fragment: value })); if (!model) { throw new Error('Could not create accessible buffer editor model'); } - model.setValue(this._content); + this._bufferEditor.setModel(model); return model; } private async _refresh(): Promise { const model = await this._updateContent(true); const lineNumber = model.getLineCount() - 1; - if (this._lastContentLength !== this._content.length || this._refreshSelection) { + if (this._refreshSelection) { this._bufferEditor.setSelection({ startLineNumber: lineNumber, startColumn: 1, endLineNumber: lineNumber, endColumn: 1 }); this._bufferEditor.setScrollTop(this._bufferEditor.getScrollHeight()); this._refreshSelection = false; - this._lastContentLength = this._content.length; } this._accessibleBuffer.replaceChildren(this._editorContainer); this._bufferEditor.focus(); @@ -157,10 +141,7 @@ export class AccessibleBufferWidget extends DisposableStore { } }); if (commandDetection) { - this._commandFinishedDisposable = commandDetection.onCommandFinished(() => { - this._refreshSelection = true; - this._lastBufferLine = 0; - }); + this._commandFinishedDisposable = commandDetection.onCommandFinished(() => this._refreshSelection = true); this.add(this._commandFinishedDisposable); } this._registered = true; @@ -212,7 +193,6 @@ export class AccessibleBufferWidget extends DisposableStore { currentLine = ''; } } - this._lastBufferLine = end; return lines.join('\n'); } } From 55e59cb6afc96445f06ca9fbcd6524963541aa71 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Tue, 7 Mar 2023 14:49:06 -0600 Subject: [PATCH 07/23] rm shell integration content --- .../browser/terminalAccessibleBuffer.ts | 22 +------------------ 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts index a3c00f2e275cd..e54a6edc657ad 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts @@ -9,7 +9,6 @@ import { URI } from 'vs/base/common/uri'; import { IEditorConstructionOptions } from 'vs/editor/browser/config/editorConfiguration'; import { EditorExtensionsRegistry } from 'vs/editor/browser/editorExtensions'; import { CodeEditorWidget, ICodeEditorWidgetOptions } from 'vs/editor/browser/widget/codeEditorWidget'; -import { StringBuilder } from 'vs/editor/common/core/stringBuilder'; import { ITextModel } from 'vs/editor/common/model'; import { IModelService } from 'vs/editor/common/services/model'; import { LinkDetector } from 'vs/editor/contrib/links/browser/links'; @@ -100,9 +99,7 @@ export class AccessibleBufferWidget extends DisposableStore { } private async _updateContent(refresh?: boolean): Promise { - const commandDetection = this._capabilities.get(TerminalCapability.CommandDetection); - const value = !!commandDetection && !refresh ? this._getShellIntegrationContent() : this._getContent(); - const model = await this._getTextModel(URI.from({ scheme: AccessibleBufferConstants.Scheme, fragment: value })); + const model = await this._getTextModel(URI.from({ scheme: AccessibleBufferConstants.Scheme, fragment: this._getContent() })); if (!model) { throw new Error('Could not create accessible buffer editor model'); } @@ -156,23 +153,6 @@ export class AccessibleBufferWidget extends DisposableStore { return this._modelService.createModel(resource.fragment, null, resource, false); } - private _getShellIntegrationContent(): string { - const commands = this._capabilities.get(TerminalCapability.CommandDetection)?.commands; - const sb = new StringBuilder(10000); - if (!commands?.length) { - return this._getContent(); - } - for (const command of commands) { - sb.appendString(command.command.replace(new RegExp(' ', 'g'), '\xA0')); - if (command.exitCode !== 0) { - sb.appendString(` exited with code ${command.exitCode}`); - } - sb.appendString('\n'); - sb.appendString(command.getOutput()?.replace(new RegExp(' ', 'g'), '\xA0') || ''); - } - return sb.build(); - } - private _getContent(startLine?: number): string { const lines: string[] = []; let currentLine: string = ''; From defcb3a04cabcc493ee3d156360263088597899d Mon Sep 17 00:00:00 2001 From: meganrogge Date: Tue, 7 Mar 2023 14:52:36 -0600 Subject: [PATCH 08/23] rm more shellintegration --- .../browser/terminal.accessibility.contribution.ts | 4 ++-- .../accessibility/browser/terminalAccessibleBuffer.ts | 10 +--------- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminal.accessibility.contribution.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminal.accessibility.contribution.ts index 467a7c89db807..2ace27281784c 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminal.accessibility.contribution.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminal.accessibility.contribution.ts @@ -33,7 +33,7 @@ class AccessibleBufferContribution extends DisposableStore implements ITerminalC private _accessibleBufferWidget: AccessibleBufferWidget | undefined; constructor( - private readonly _instance: ITerminalInstance, + instance: ITerminalInstance, processManager: ITerminalProcessManager, widgetManager: TerminalWidgetManager, @IInstantiationService private readonly _instantiationService: IInstantiationService @@ -42,7 +42,7 @@ class AccessibleBufferContribution extends DisposableStore implements ITerminalC } xtermReady(xterm: IXtermTerminal & { raw: Terminal }): void { - this._accessibleBufferWidget = this._instantiationService.createInstance(AccessibleBufferWidget, xterm, this._instance.capabilities); + this._accessibleBufferWidget = this._instantiationService.createInstance(AccessibleBufferWidget, xterm); } show(): void { this._accessibleBufferWidget?.show(); diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts index e54a6edc657ad..7aeee49973bc6 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { KeyCode } from 'vs/base/common/keyCodes'; -import { DisposableStore, IDisposable } from 'vs/base/common/lifecycle'; +import { DisposableStore } from 'vs/base/common/lifecycle'; import { URI } from 'vs/base/common/uri'; import { IEditorConstructionOptions } from 'vs/editor/browser/config/editorConfiguration'; import { EditorExtensionsRegistry } from 'vs/editor/browser/editorExtensions'; @@ -15,7 +15,6 @@ import { LinkDetector } from 'vs/editor/contrib/links/browser/links'; import { localize } from 'vs/nls'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { ITerminalCapabilityStore, TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities'; import { TerminalSettingId } from 'vs/platform/terminal/common/terminal'; import { SelectionClipboardContributionID } from 'vs/workbench/contrib/codeEditor/browser/selectionClipboard'; import { getSimpleEditorOptions } from 'vs/workbench/contrib/codeEditor/browser/simpleEditorOptions'; @@ -32,7 +31,6 @@ export class AccessibleBufferWidget extends DisposableStore { private _accessibleBuffer: HTMLElement; private _bufferEditor: CodeEditorWidget; private _editorContainer: HTMLElement; - private _commandFinishedDisposable: IDisposable | undefined; private _refreshSelection: boolean = true; private _registered: boolean = false; private _font: ITerminalFont; @@ -40,7 +38,6 @@ export class AccessibleBufferWidget extends DisposableStore { constructor( private readonly _xterm: IXtermTerminal & { raw: Terminal }, - private readonly _capabilities: ITerminalCapabilityStore, @IInstantiationService private readonly _instantiationService: IInstantiationService, @IModelService private readonly _modelService: IModelService, @IConfigurationService private readonly _configurationService: IConfigurationService @@ -130,17 +127,12 @@ export class AccessibleBufferWidget extends DisposableStore { } private _registerListeners(): void { - const commandDetection = this._capabilities.get(TerminalCapability.CommandDetection); this._bufferEditor.layout({ width: this._xtermElement.clientWidth, height: this._xtermElement.clientHeight }); this._bufferEditor.onKeyDown((e) => { if (e.keyCode === KeyCode.Escape || e.keyCode === KeyCode.Tab) { this._hide(); } }); - if (commandDetection) { - this._commandFinishedDisposable = commandDetection.onCommandFinished(() => this._refreshSelection = true); - this.add(this._commandFinishedDisposable); - } this._registered = true; } From b9b3360b00d31b8e5bd070e48a6b927f6603d1e5 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Tue, 7 Mar 2023 14:57:12 -0600 Subject: [PATCH 09/23] rm more code --- .../accessibility/browser/terminalAccessibleBuffer.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts index 7aeee49973bc6..1a8115d626a75 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts @@ -95,7 +95,7 @@ export class AccessibleBufferWidget extends DisposableStore { this._xterm.raw.focus(); } - private async _updateContent(refresh?: boolean): Promise { + private async _updateContent(): Promise { const model = await this._getTextModel(URI.from({ scheme: AccessibleBufferConstants.Scheme, fragment: this._getContent() })); if (!model) { throw new Error('Could not create accessible buffer editor model'); @@ -105,7 +105,7 @@ export class AccessibleBufferWidget extends DisposableStore { } private async _refresh(): Promise { - const model = await this._updateContent(true); + const model = await this._updateContent(); const lineNumber = model.getLineCount() - 1; if (this._refreshSelection) { this._bufferEditor.setSelection({ startLineNumber: lineNumber, startColumn: 1, endLineNumber: lineNumber, endColumn: 1 }); From 796d1a46bf196efcc95d6ab173afa0978c1df173 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Tue, 7 Mar 2023 15:00:33 -0600 Subject: [PATCH 10/23] place cursor at the end --- .../accessibility/browser/terminalAccessibleBuffer.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts index 1a8115d626a75..54c4513b2d5f2 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts @@ -31,7 +31,6 @@ export class AccessibleBufferWidget extends DisposableStore { private _accessibleBuffer: HTMLElement; private _bufferEditor: CodeEditorWidget; private _editorContainer: HTMLElement; - private _refreshSelection: boolean = true; private _registered: boolean = false; private _font: ITerminalFont; private _xtermElement: HTMLElement; @@ -107,11 +106,8 @@ export class AccessibleBufferWidget extends DisposableStore { private async _refresh(): Promise { const model = await this._updateContent(); const lineNumber = model.getLineCount() - 1; - if (this._refreshSelection) { - this._bufferEditor.setSelection({ startLineNumber: lineNumber, startColumn: 1, endLineNumber: lineNumber, endColumn: 1 }); - this._bufferEditor.setScrollTop(this._bufferEditor.getScrollHeight()); - this._refreshSelection = false; - } + this._bufferEditor.setSelection({ startLineNumber: lineNumber, startColumn: 1, endLineNumber: lineNumber, endColumn: 1 }); + this._bufferEditor.setScrollTop(this._bufferEditor.getScrollHeight()); this._accessibleBuffer.replaceChildren(this._editorContainer); this._bufferEditor.focus(); } From e470e3914eb476d3df52c3714233d3747350eaaf Mon Sep 17 00:00:00 2001 From: meganrogge Date: Wed, 8 Mar 2023 10:40:01 -0600 Subject: [PATCH 11/23] polish --- .../browser/terminalAccessibleBuffer.ts | 35 ++++++++----------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts index 54c4513b2d5f2..2a53b2b976bf9 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts @@ -23,7 +23,9 @@ import { IXtermTerminal } from 'vs/workbench/contrib/terminal/browser/terminal'; import type { Terminal } from 'xterm'; const enum AccessibleBufferConstants { - Scheme = 'terminal-accessible-buffer' + Scheme = 'terminal-accessible-buffer', + Active = 'active', + Hide = 'hide' } export class AccessibleBufferWidget extends DisposableStore { @@ -31,7 +33,6 @@ export class AccessibleBufferWidget extends DisposableStore { private _accessibleBuffer: HTMLElement; private _bufferEditor: CodeEditorWidget; private _editorContainer: HTMLElement; - private _registered: boolean = false; private _font: ITerminalFont; private _xtermElement: HTMLElement; @@ -76,21 +77,28 @@ export class AccessibleBufferWidget extends DisposableStore { } this._editorContainer = document.createElement('div'); this._bufferEditor = this._instantiationService.createInstance(CodeEditorWidget, this._editorContainer, editorOptions, codeEditorWidgetOptions); + this._bufferEditor.layout({ width: this._xtermElement.clientWidth, height: this._xtermElement.clientHeight }); + this.add(this._bufferEditor); + this.add(this._bufferEditor.onKeyDown((e) => { + if (e.keyCode === KeyCode.Escape || e.keyCode === KeyCode.Tab) { + this._hide(); + } + })); this.add(this._configurationService.onDidChangeConfiguration(e => { if (e.affectedKeys.has(TerminalSettingId.FontFamily)) { this._font = _xterm.getFont(); } })); this.add(this._xterm.raw.onWriteParsed(async () => { - if (this._accessibleBuffer.classList.contains('active')) { + if (this._accessibleBuffer.classList.contains(AccessibleBufferConstants.Active)) { await this._refresh(); } })); } private _hide(): void { - this._accessibleBuffer.classList.remove('active'); - this._xtermElement.classList.remove('hide'); + this._accessibleBuffer.classList.remove(AccessibleBufferConstants.Active); + this._xtermElement.classList.remove(AccessibleBufferConstants.Hide); this._xterm.raw.focus(); } @@ -113,23 +121,10 @@ export class AccessibleBufferWidget extends DisposableStore { } async show(): Promise { - if (!this._registered) { - this._registerListeners(); - } await this._refresh(); this._accessibleBuffer.tabIndex = -1; - this._accessibleBuffer.classList.add('active'); - this._xtermElement.classList.add('hide'); - } - - private _registerListeners(): void { - this._bufferEditor.layout({ width: this._xtermElement.clientWidth, height: this._xtermElement.clientHeight }); - this._bufferEditor.onKeyDown((e) => { - if (e.keyCode === KeyCode.Escape || e.keyCode === KeyCode.Tab) { - this._hide(); - } - }); - this._registered = true; + this._accessibleBuffer.classList.add(AccessibleBufferConstants.Active); + this._xtermElement.classList.add(AccessibleBufferConstants.Hide); } private async _getTextModel(resource: URI): Promise { From 6ab87c7189814956a028538d5f3ae179c05a27db Mon Sep 17 00:00:00 2001 From: meganrogge Date: Wed, 8 Mar 2023 10:57:52 -0600 Subject: [PATCH 12/23] use pushEditOperations --- .../browser/terminalAccessibleBuffer.ts | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts index 2a53b2b976bf9..11b54e34ac988 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts @@ -35,6 +35,7 @@ export class AccessibleBufferWidget extends DisposableStore { private _editorContainer: HTMLElement; private _font: ITerminalFont; private _xtermElement: HTMLElement; + private _previousLines: number = 0; constructor( private readonly _xterm: IXtermTerminal & { raw: Terminal }, @@ -102,8 +103,17 @@ export class AccessibleBufferWidget extends DisposableStore { this._xterm.raw.focus(); } - private async _updateContent(): Promise { - const model = await this._getTextModel(URI.from({ scheme: AccessibleBufferConstants.Scheme, fragment: this._getContent() })); + private async _updateContent(refresh?: boolean): Promise { + let model = this._bufferEditor.getModel(); + if (model && this._previousLines === this._xterm.raw.buffer.active.length) { + return model; + } + if (refresh && model) { + const selection = this._bufferEditor.getSelection(); + model.pushEditOperations(selection !== null ? [selection] : null, [{ range: model.getFullModelRange(), text: this._getContent(this._previousLines) }], () => []); + return model; + } + model = await this._getTextModel(URI.from({ scheme: AccessibleBufferConstants.Scheme, fragment: this._getContent() })); if (!model) { throw new Error('Could not create accessible buffer editor model'); } @@ -156,6 +166,7 @@ export class AccessibleBufferWidget extends DisposableStore { currentLine = ''; } } + this._previousLines = lines.length; return lines.join('\n'); } } From b880a31caccc4746288dbbb0834a424c6c7b868d Mon Sep 17 00:00:00 2001 From: meganrogge Date: Wed, 8 Mar 2023 14:22:55 -0600 Subject: [PATCH 13/23] pushEditOperations --- .../terminal.accessibility.contribution.ts | 4 +-- .../browser/terminalAccessibleBuffer.ts | 34 ++++++++++--------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminal.accessibility.contribution.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminal.accessibility.contribution.ts index 2ace27281784c..543541bc2b981 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminal.accessibility.contribution.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminal.accessibility.contribution.ts @@ -33,7 +33,7 @@ class AccessibleBufferContribution extends DisposableStore implements ITerminalC private _accessibleBufferWidget: AccessibleBufferWidget | undefined; constructor( - instance: ITerminalInstance, + private readonly _instance: ITerminalInstance, processManager: ITerminalProcessManager, widgetManager: TerminalWidgetManager, @IInstantiationService private readonly _instantiationService: IInstantiationService @@ -42,7 +42,7 @@ class AccessibleBufferContribution extends DisposableStore implements ITerminalC } xtermReady(xterm: IXtermTerminal & { raw: Terminal }): void { - this._accessibleBufferWidget = this._instantiationService.createInstance(AccessibleBufferWidget, xterm); + this._accessibleBufferWidget = this._instantiationService.createInstance(AccessibleBufferWidget, this._instance.instanceId, xterm); } show(): void { this._accessibleBufferWidget?.show(); diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts index 11b54e34ac988..b09a229b517e2 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts @@ -35,9 +35,9 @@ export class AccessibleBufferWidget extends DisposableStore { private _editorContainer: HTMLElement; private _font: ITerminalFont; private _xtermElement: HTMLElement; - private _previousLines: number = 0; constructor( + private readonly _instanceId: number, private readonly _xterm: IXtermTerminal & { raw: Terminal }, @IInstantiationService private readonly _instantiationService: IInstantiationService, @IModelService private readonly _modelService: IModelService, @@ -78,6 +78,7 @@ export class AccessibleBufferWidget extends DisposableStore { } this._editorContainer = document.createElement('div'); this._bufferEditor = this._instantiationService.createInstance(CodeEditorWidget, this._editorContainer, editorOptions, codeEditorWidgetOptions); + this._accessibleBuffer.replaceChildren(this._editorContainer); this._bufferEditor.layout({ width: this._xtermElement.clientWidth, height: this._xtermElement.clientHeight }); this.add(this._bufferEditor); this.add(this._bufferEditor.onKeyDown((e) => { @@ -92,7 +93,7 @@ export class AccessibleBufferWidget extends DisposableStore { })); this.add(this._xterm.raw.onWriteParsed(async () => { if (this._accessibleBuffer.classList.contains(AccessibleBufferConstants.Active)) { - await this._refresh(); + await this._refresh(true); } })); } @@ -103,30 +104,32 @@ export class AccessibleBufferWidget extends DisposableStore { this._xterm.raw.focus(); } - private async _updateContent(refresh?: boolean): Promise { + private async _updateContent(refresh?: boolean): Promise { let model = this._bufferEditor.getModel(); - if (model && this._previousLines === this._xterm.raw.buffer.active.length) { - return model; - } - if (refresh && model) { + const lineCount = model?.getLineCount() ?? 0; + if (refresh && model && lineCount > this._xterm.raw.rows) { const selection = this._bufferEditor.getSelection(); - model.pushEditOperations(selection !== null ? [selection] : null, [{ range: model.getFullModelRange(), text: this._getContent(this._previousLines) }], () => []); - return model; + const lineNumber = lineCount + 1; + const column = 1; + model.pushEditOperations(selection !== null ? [selection] : null, [{ range: { startLineNumber: lineNumber, endLineNumber: lineNumber, startColumn: column, endColumn: column }, text: await this._getContent(lineNumber - 1) }], () => []); + return; } - model = await this._getTextModel(URI.from({ scheme: AccessibleBufferConstants.Scheme, fragment: this._getContent() })); + model = await this._getTextModel(URI.from({ scheme: `${AccessibleBufferConstants.Scheme}-${this._instanceId}`, fragment: await this._getContent() })); if (!model) { throw new Error('Could not create accessible buffer editor model'); } this._bufferEditor.setModel(model); - return model; } - private async _refresh(): Promise { - const model = await this._updateContent(); + private async _refresh(refresh?: boolean): Promise { + await this._updateContent(refresh); + const model = this._bufferEditor.getModel(); + if (!model) { + return; + } const lineNumber = model.getLineCount() - 1; this._bufferEditor.setSelection({ startLineNumber: lineNumber, startColumn: 1, endLineNumber: lineNumber, endColumn: 1 }); this._bufferEditor.setScrollTop(this._bufferEditor.getScrollHeight()); - this._accessibleBuffer.replaceChildren(this._editorContainer); this._bufferEditor.focus(); } @@ -146,7 +149,7 @@ export class AccessibleBufferWidget extends DisposableStore { return this._modelService.createModel(resource.fragment, null, resource, false); } - private _getContent(startLine?: number): string { + private async _getContent(startLine?: number): Promise { const lines: string[] = []; let currentLine: string = ''; const buffer = this._xterm?.raw.buffer.active; @@ -166,7 +169,6 @@ export class AccessibleBufferWidget extends DisposableStore { currentLine = ''; } } - this._previousLines = lines.length; return lines.join('\n'); } } From 28d5c10636ee25a8f66adc1980fabadd57409b78 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Wed, 8 Mar 2023 14:29:29 -0600 Subject: [PATCH 14/23] revert async --- .../accessibility/browser/terminalAccessibleBuffer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts index b09a229b517e2..35f7cbae9870b 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts @@ -149,7 +149,7 @@ export class AccessibleBufferWidget extends DisposableStore { return this._modelService.createModel(resource.fragment, null, resource, false); } - private async _getContent(startLine?: number): Promise { + private _getContent(startLine?: number): string { const lines: string[] = []; let currentLine: string = ''; const buffer = this._xterm?.raw.buffer.active; From 0c394e888171769bf6e0360f58bbfbcfd780b75b Mon Sep 17 00:00:00 2001 From: meganrogge Date: Wed, 8 Mar 2023 14:31:24 -0600 Subject: [PATCH 15/23] clean up --- .../accessibility/browser/terminalAccessibleBuffer.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts index 35f7cbae9870b..717de69f59efd 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts @@ -110,8 +110,7 @@ export class AccessibleBufferWidget extends DisposableStore { if (refresh && model && lineCount > this._xterm.raw.rows) { const selection = this._bufferEditor.getSelection(); const lineNumber = lineCount + 1; - const column = 1; - model.pushEditOperations(selection !== null ? [selection] : null, [{ range: { startLineNumber: lineNumber, endLineNumber: lineNumber, startColumn: column, endColumn: column }, text: await this._getContent(lineNumber - 1) }], () => []); + model.pushEditOperations(selection ? [selection] : null, [{ range: { startLineNumber: lineNumber, endLineNumber: lineNumber, startColumn: 1, endColumn: 1 }, text: await this._getContent(lineNumber - 1) }], () => []); return; } model = await this._getTextModel(URI.from({ scheme: `${AccessibleBufferConstants.Scheme}-${this._instanceId}`, fragment: await this._getContent() })); From ed76cfe8e24780c053d211c6383826b075634535 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Wed, 8 Mar 2023 14:47:51 -0600 Subject: [PATCH 16/23] tweak names --- .../browser/terminalAccessibleBuffer.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts index 717de69f59efd..2d51d0e8b515d 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts @@ -93,7 +93,7 @@ export class AccessibleBufferWidget extends DisposableStore { })); this.add(this._xterm.raw.onWriteParsed(async () => { if (this._accessibleBuffer.classList.contains(AccessibleBufferConstants.Active)) { - await this._refresh(true); + await this._updateEditor(true); } })); } @@ -104,10 +104,10 @@ export class AccessibleBufferWidget extends DisposableStore { this._xterm.raw.focus(); } - private async _updateContent(refresh?: boolean): Promise { + private async _updateModel(insertion?: boolean): Promise { let model = this._bufferEditor.getModel(); const lineCount = model?.getLineCount() ?? 0; - if (refresh && model && lineCount > this._xterm.raw.rows) { + if (insertion && model && lineCount > this._xterm.raw.rows) { const selection = this._bufferEditor.getSelection(); const lineNumber = lineCount + 1; model.pushEditOperations(selection ? [selection] : null, [{ range: { startLineNumber: lineNumber, endLineNumber: lineNumber, startColumn: 1, endColumn: 1 }, text: await this._getContent(lineNumber - 1) }], () => []); @@ -120,8 +120,8 @@ export class AccessibleBufferWidget extends DisposableStore { this._bufferEditor.setModel(model); } - private async _refresh(refresh?: boolean): Promise { - await this._updateContent(refresh); + private async _updateEditor(insertion?: boolean): Promise { + await this._updateModel(insertion); const model = this._bufferEditor.getModel(); if (!model) { return; @@ -133,7 +133,7 @@ export class AccessibleBufferWidget extends DisposableStore { } async show(): Promise { - await this._refresh(); + await this._updateEditor(); this._accessibleBuffer.tabIndex = -1; this._accessibleBuffer.classList.add(AccessibleBufferConstants.Active); this._xtermElement.classList.add(AccessibleBufferConstants.Hide); From c3d3166b3aa730aec1971e416c84a715abf8de3f Mon Sep 17 00:00:00 2001 From: meganrogge Date: Wed, 8 Mar 2023 14:55:30 -0600 Subject: [PATCH 17/23] fix cursor issue --- .../accessibility/browser/terminalAccessibleBuffer.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts index 2d51d0e8b515d..348080785d0a0 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts @@ -127,7 +127,11 @@ export class AccessibleBufferWidget extends DisposableStore { return; } const lineNumber = model.getLineCount() - 1; - this._bufferEditor.setSelection({ startLineNumber: lineNumber, startColumn: 1, endLineNumber: lineNumber, endColumn: 1 }); + const selection = this._bufferEditor.getSelection(); + // If the selection is at the top of the buffer, IE the default when not set, move it to the bottom + if (selection?.startColumn === 1 && selection.endColumn === 1 && selection.startLineNumber === 1 && selection.endLineNumber === 1) { + this._bufferEditor.setSelection({ startLineNumber: lineNumber, startColumn: 1, endLineNumber: lineNumber, endColumn: 1 }); + } this._bufferEditor.setScrollTop(this._bufferEditor.getScrollHeight()); this._bufferEditor.focus(); } From a345cebf48556e723c5d1d5674657fe6a76445dd Mon Sep 17 00:00:00 2001 From: meganrogge Date: Wed, 8 Mar 2023 15:23:23 -0600 Subject: [PATCH 18/23] await container opening --- src/vs/workbench/contrib/terminal/browser/terminal.ts | 4 ++++ .../workbench/contrib/terminal/browser/terminalInstance.ts | 1 + .../browser/terminal.accessibility.contribution.ts | 4 +++- .../accessibility/browser/terminalAccessibleBuffer.ts | 6 ++---- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/terminal.ts b/src/vs/workbench/contrib/terminal/browser/terminal.ts index 2a077aad66f24..a6d962901fa3b 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminal.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminal.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Dimension } from 'vs/base/browser/dom'; import { Orientation } from 'vs/base/browser/ui/splitview/splitview'; +import { AutoOpenBarrier } from 'vs/base/common/async'; import { Color } from 'vs/base/common/color'; import { Event } from 'vs/base/common/event'; import { IDisposable } from 'vs/base/common/lifecycle'; @@ -601,6 +602,9 @@ export interface ITerminalInstance { /** A promise that resolves when the terminal's pty/process have been created. */ readonly processReady: Promise; + /** A barrier that opens when the terminal's container is ready */ + readonly containerReadyBarrier: AutoOpenBarrier; + /** Whether the terminal's process has child processes (ie. is dirty/busy). */ readonly hasChildProcesses: boolean; diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts index 2c1a9e4179208..e7b64da65eda2 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts @@ -189,6 +189,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { private _areLinksReady: boolean = false; private _initialDataEvents: string[] | undefined = []; private _containerReadyBarrier: AutoOpenBarrier; + get containerReadyBarrier(): AutoOpenBarrier { return this._containerReadyBarrier; } private _attachBarrier: AutoOpenBarrier; private _icon: TerminalIcon | undefined; private _messageTitleDisposable: IDisposable | undefined; diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminal.accessibility.contribution.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminal.accessibility.contribution.ts index 543541bc2b981..f7cf5a010476a 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminal.accessibility.contribution.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminal.accessibility.contribution.ts @@ -42,7 +42,9 @@ class AccessibleBufferContribution extends DisposableStore implements ITerminalC } xtermReady(xterm: IXtermTerminal & { raw: Terminal }): void { - this._accessibleBufferWidget = this._instantiationService.createInstance(AccessibleBufferWidget, this._instance.instanceId, xterm); + this._instance.containerReadyBarrier.wait().then(() => { + this._accessibleBufferWidget = this._instantiationService.createInstance(AccessibleBufferWidget, this._instance.instanceId, xterm); + }); } show(): void { this._accessibleBufferWidget?.show(); diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts index 348080785d0a0..94a3897695c71 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts @@ -49,6 +49,7 @@ export class AccessibleBufferWidget extends DisposableStore { contributions: EditorExtensionsRegistry.getSomeEditorContributions([LinkDetector.ID, SelectionClipboardContributionID]) }; this._font = _xterm.getFont(); + // this will be defined because we await the container opening this._xtermElement = _xterm.raw.element!; const editorOptions: IEditorConstructionOptions = { ...getSimpleEditorOptions(), @@ -72,13 +73,10 @@ export class AccessibleBufferWidget extends DisposableStore { this._accessibleBuffer.setAttribute('role', 'document'); this._accessibleBuffer.ariaRoleDescription = localize('terminal.integrated.accessibleBuffer', 'Terminal buffer'); this._accessibleBuffer.classList.add('accessible-buffer'); - const elt = _xterm.raw.element; - if (elt) { - elt.insertAdjacentElement('beforebegin', this._accessibleBuffer); - } this._editorContainer = document.createElement('div'); this._bufferEditor = this._instantiationService.createInstance(CodeEditorWidget, this._editorContainer, editorOptions, codeEditorWidgetOptions); this._accessibleBuffer.replaceChildren(this._editorContainer); + this._xtermElement.insertAdjacentElement('beforebegin', this._accessibleBuffer); this._bufferEditor.layout({ width: this._xtermElement.clientWidth, height: this._xtermElement.clientHeight }); this.add(this._bufferEditor); this.add(this._bufferEditor.onKeyDown((e) => { From a39a500909190b88c23e3e4677b1057ee4778f1e Mon Sep 17 00:00:00 2001 From: meganrogge Date: Fri, 10 Mar 2023 11:25:19 -0600 Subject: [PATCH 19/23] reintroduce hide --- .../contrib/terminal/browser/media/xterm.css | 4 ++++ .../accessibility/browser/terminalAccessibleBuffer.ts | 11 +++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/media/xterm.css b/src/vs/workbench/contrib/terminal/browser/media/xterm.css index 30fdf93feb648..8a6a8f392fed5 100644 --- a/src/vs/workbench/contrib/terminal/browser/media/xterm.css +++ b/src/vs/workbench/contrib/terminal/browser/media/xterm.css @@ -208,3 +208,7 @@ z-index: 2; position: relative; } + +.hide { + opacity: 0; +} diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts index a58c13d7df4d7..d78d3d982fd43 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts @@ -24,7 +24,8 @@ import type { Terminal } from 'xterm'; const enum AccessibleBufferConstants { Scheme = 'terminal-accessible-buffer', - Active = 'active' + Active = 'active', + Hide = 'hide' } export class AccessibleBufferWidget extends DisposableStore { @@ -102,6 +103,7 @@ export class AccessibleBufferWidget extends DisposableStore { private _hide(): void { this._accessibleBuffer.classList.remove(AccessibleBufferConstants.Active); + this._xtermElement.classList.remove(AccessibleBufferConstants.Hide); this._xterm.raw.focus(); } @@ -109,12 +111,12 @@ export class AccessibleBufferWidget extends DisposableStore { let model = this._bufferEditor.getModel(); const lineCount = model?.getLineCount() ?? 0; if (insertion && model && lineCount > this._xterm.raw.rows) { - const selection = this._bufferEditor.getSelection(); const lineNumber = lineCount + 1; - model.pushEditOperations(selection ? [selection] : null, [{ range: { startLineNumber: lineNumber, endLineNumber: lineNumber, startColumn: 1, endColumn: 1 }, text: await this._getContent(lineNumber - 1) }], () => []); + model.pushEditOperations(null, [{ range: { startLineNumber: lineNumber, endLineNumber: lineNumber, startColumn: 1, endColumn: 1 }, text: await this._getContent(lineNumber - 1) }], () => []); return; + } else { + model = await this._getTextModel(URI.from({ scheme: `${AccessibleBufferConstants.Scheme}-${this._instanceId}`, fragment: await this._getContent() })); } - model = await this._getTextModel(URI.from({ scheme: `${AccessibleBufferConstants.Scheme}-${this._instanceId}`, fragment: await this._getContent() })); if (!model) { throw new Error('Could not create accessible buffer editor model'); } @@ -141,6 +143,7 @@ export class AccessibleBufferWidget extends DisposableStore { await this._updateEditor(); this._accessibleBuffer.tabIndex = -1; this._accessibleBuffer.classList.add(AccessibleBufferConstants.Active); + this._xtermElement.classList.add(AccessibleBufferConstants.Hide); } private async _getTextModel(resource: URI): Promise { From 0053a850b352bd23415aec0c9156a8d1d5ffba6e Mon Sep 17 00:00:00 2001 From: meganrogge Date: Fri, 10 Mar 2023 11:59:47 -0600 Subject: [PATCH 20/23] call layout more --- src/vs/workbench/contrib/terminal/browser/media/xterm.css | 2 +- src/vs/workbench/contrib/terminal/browser/terminalInstance.ts | 2 +- .../accessibility/browser/terminalAccessibleBuffer.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/media/xterm.css b/src/vs/workbench/contrib/terminal/browser/media/xterm.css index 8a6a8f392fed5..a437b197ce4da 100644 --- a/src/vs/workbench/contrib/terminal/browser/media/xterm.css +++ b/src/vs/workbench/contrib/terminal/browser/media/xterm.css @@ -210,5 +210,5 @@ } .hide { - opacity: 0; + visibility: hidden; } diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts index e7b64da65eda2..900e9875b72c0 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts @@ -491,7 +491,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { this._register(toDisposable(() => this._dndObserver?.dispose())); this._containerReadyBarrier = new AutoOpenBarrier(Constants.WaitForContainerThreshold); - this._attachBarrier = new AutoOpenBarrier(1000); + this._attachBarrier = new AutoOpenBarrier(3000); this._xtermReadyPromise = this._createXterm(); this._xtermReadyPromise.then(async () => { // Wait for a period to allow a container to be ready diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts index d78d3d982fd43..586adbe0431c7 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts @@ -113,7 +113,6 @@ export class AccessibleBufferWidget extends DisposableStore { if (insertion && model && lineCount > this._xterm.raw.rows) { const lineNumber = lineCount + 1; model.pushEditOperations(null, [{ range: { startLineNumber: lineNumber, endLineNumber: lineNumber, startColumn: 1, endColumn: 1 }, text: await this._getContent(lineNumber - 1) }], () => []); - return; } else { model = await this._getTextModel(URI.from({ scheme: `${AccessibleBufferConstants.Scheme}-${this._instanceId}`, fragment: await this._getContent() })); } @@ -142,6 +141,7 @@ export class AccessibleBufferWidget extends DisposableStore { async show(): Promise { await this._updateEditor(); this._accessibleBuffer.tabIndex = -1; + this._bufferEditor.layout({ width: this._xtermElement.clientWidth, height: this._xtermElement.clientHeight }); this._accessibleBuffer.classList.add(AccessibleBufferConstants.Active); this._xtermElement.classList.add(AccessibleBufferConstants.Hide); } From e5d6d2a139d03f50f67df2f0707fc8a2b32b054a Mon Sep 17 00:00:00 2001 From: meganrogge Date: Fri, 10 Mar 2023 12:34:24 -0600 Subject: [PATCH 21/23] increase specificity --- src/vs/workbench/contrib/terminal/browser/media/xterm.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/terminal/browser/media/xterm.css b/src/vs/workbench/contrib/terminal/browser/media/xterm.css index a437b197ce4da..e9d326036d080 100644 --- a/src/vs/workbench/contrib/terminal/browser/media/xterm.css +++ b/src/vs/workbench/contrib/terminal/browser/media/xterm.css @@ -209,6 +209,6 @@ position: relative; } -.hide { +.xterm.terminal.hide { visibility: hidden; } From 0a868be0fd2a4324b4a733c0788cd47019c0217c Mon Sep 17 00:00:00 2001 From: meganrogge Date: Fri, 10 Mar 2023 17:43:31 -0600 Subject: [PATCH 22/23] Revert change --- src/vs/workbench/contrib/terminal/browser/terminalInstance.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts index 900e9875b72c0..e7b64da65eda2 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts @@ -491,7 +491,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { this._register(toDisposable(() => this._dndObserver?.dispose())); this._containerReadyBarrier = new AutoOpenBarrier(Constants.WaitForContainerThreshold); - this._attachBarrier = new AutoOpenBarrier(3000); + this._attachBarrier = new AutoOpenBarrier(1000); this._xtermReadyPromise = this._createXterm(); this._xtermReadyPromise.then(async () => { // Wait for a period to allow a container to be ready From 058f557d36fec3e69cda8f7a365ef6d4dc2a3d5b Mon Sep 17 00:00:00 2001 From: meganrogge Date: Fri, 10 Mar 2023 17:44:39 -0600 Subject: [PATCH 23/23] rename constant --- .../browser/terminalAccessibleBuffer.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts index 586adbe0431c7..e83de74f9867f 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts @@ -22,14 +22,14 @@ import { ITerminalFont } from 'vs/workbench/contrib/terminal/common/terminal'; import { IXtermTerminal } from 'vs/workbench/contrib/terminal/browser/terminal'; import type { Terminal } from 'xterm'; -const enum AccessibleBufferConstants { +const enum Constants { Scheme = 'terminal-accessible-buffer', Active = 'active', Hide = 'hide' } export class AccessibleBufferWidget extends DisposableStore { - public static ID: string = AccessibleBufferConstants.Scheme; + public static ID: string = Constants.Scheme; private _accessibleBuffer: HTMLElement; private _bufferEditor: CodeEditorWidget; private _editorContainer: HTMLElement; @@ -94,7 +94,7 @@ export class AccessibleBufferWidget extends DisposableStore { } })); this.add(this._xterm.raw.onWriteParsed(async () => { - if (this._accessibleBuffer.classList.contains(AccessibleBufferConstants.Active)) { + if (this._accessibleBuffer.classList.contains(Constants.Active)) { await this._updateEditor(true); } })); @@ -102,8 +102,8 @@ export class AccessibleBufferWidget extends DisposableStore { } private _hide(): void { - this._accessibleBuffer.classList.remove(AccessibleBufferConstants.Active); - this._xtermElement.classList.remove(AccessibleBufferConstants.Hide); + this._accessibleBuffer.classList.remove(Constants.Active); + this._xtermElement.classList.remove(Constants.Hide); this._xterm.raw.focus(); } @@ -114,7 +114,7 @@ export class AccessibleBufferWidget extends DisposableStore { const lineNumber = lineCount + 1; model.pushEditOperations(null, [{ range: { startLineNumber: lineNumber, endLineNumber: lineNumber, startColumn: 1, endColumn: 1 }, text: await this._getContent(lineNumber - 1) }], () => []); } else { - model = await this._getTextModel(URI.from({ scheme: `${AccessibleBufferConstants.Scheme}-${this._instanceId}`, fragment: await this._getContent() })); + model = await this._getTextModel(URI.from({ scheme: `${Constants.Scheme}-${this._instanceId}`, fragment: await this._getContent() })); } if (!model) { throw new Error('Could not create accessible buffer editor model'); @@ -142,8 +142,8 @@ export class AccessibleBufferWidget extends DisposableStore { await this._updateEditor(); this._accessibleBuffer.tabIndex = -1; this._bufferEditor.layout({ width: this._xtermElement.clientWidth, height: this._xtermElement.clientHeight }); - this._accessibleBuffer.classList.add(AccessibleBufferConstants.Active); - this._xtermElement.classList.add(AccessibleBufferConstants.Hide); + this._accessibleBuffer.classList.add(Constants.Active); + this._xtermElement.classList.add(Constants.Hide); } private async _getTextModel(resource: URI): Promise {