) { super(); this._register(this._accessibilityService.onDidChangeScreenReaderOptimized(() => { <del> if (this._accessibilityService.isScreenReaderOptimized() && this._terminal) { this._refreshTextArea(); this._onCursorMoveListener.value = this._terminal.onCursorMove(() => this._refreshTextArea()); </del> <ins> if (this._accessibilityService.isScreenReaderOptimized()) { this._syncTextArea(); this._registerSyncListeners(); </ins> } else { <del> this._onCursorMoveListener.clear(); </del> <ins> this._listeners.clear(); </ins> } })); } <del> private _refreshTextArea(focusChanged?: boolean): void { </del> <ins> private _registerSyncListeners(): void { if (this._accessibilityService.isScreenReaderOptimized() && this._terminal?.textarea) { this._listeners.value = new DisposableStore(); this._listeners.value.add(this._terminal.onCursorMove(() => this._syncTextArea())); this._listeners.value.add(this._terminal.onData(() => this._syncTextArea())); this._listeners.value.add(addDisposableListener(this._terminal.textarea, 'focus', () => this._syncTextArea())); } } @debounce(50) private _syncTextArea(): void { this._logService.debug('TextAreaSyncAddon#syncTextArea'); const textArea = this._terminal?.textarea; if (!textArea) { this._logService.debug(`TextAreaSyncAddon#syncTextArea: no textarea`); return; } this._updateCommandAndCursor(); if (this._currentCommand !== textArea.value) { textArea.value = this._currentCommand || ''; this._logService.debug(`TextAreaSyncAddon#syncTextArea: text changed to "${this._currentCommand}"`); } else if (!this._currentCommand) { textArea.value = ''; this._logService.debug(`TextAreaSyncAddon#syncTextArea: text cleared`); } if (this._cursorX !== textArea.selectionStart) { textArea.selectionStart = this._cursorX ?? 0; textArea.selectionEnd = this._cursorX ?? 0; this._logService.debug(`TextAreaSyncAddon#syncTextArea: selection start/end changed to ${this._cursorX}`); } } private _updateCommandAndCursor(): void { </ins> if (!this._terminal) { return; } <del> this._logService.debug('TextAreaSyncAddon#refreshTextArea'); </del> const commandCapability = this._capabilities.get(TerminalCapability.CommandDetection); const currentCommand = commandCapability?.currentCommand; if (!currentCommand) { <del> this._logService.debug(`TextAreaSyncAddon#refreshTextArea: no currentCommand`); </del> <ins> this._logService.debug(`TextAreaSyncAddon#updateCommandAndCursor: no current command`); </ins> return; } const buffer = this._terminal.buffer.active; const line = buffer.getLine(buffer.cursorY)?.translateToString(true); <del> let commandStartX: number | undefined; </del> if (!line) { <del> this._logService.debug(`TextAreaSyncAddon#refreshTextArea: no line`); </del> <ins> this._logService.debug(`TextAreaSyncAddon#updateCommandAndCursor: no line`); </ins> return; } <del> let content: string | undefined; if (currentCommand.commandStartX) { </del> <ins> if (currentCommand.commandStartX !== undefined) { </ins> // Left prompt <del> content = line.substring(currentCommand.commandStartX); commandStartX = currentCommand.commandStartX; } else if (currentCommand.commandRightPromptStartX) { </del> <ins> this._currentCommand = line.substring(currentCommand.commandStartX); this._cursorX = buffer.cursorX - currentCommand.commandStartX; } else if (currentCommand.commandRightPromptStartX !== undefined) { </ins> // Right prompt <del> content = line.substring(0, currentCommand.commandRightPromptStartX); commandStartX = 0; } if (!content) { this._logService.debug(`TextAreaSyncAddon#refreshTextArea: no content`); return; } if (commandStartX === undefined) { this._logService.debug(`TextAreaSyncAddon#refreshTextArea: no commandStartX`); return; } const textArea = this._terminal.textarea; if (!textArea) { this._logService.debug(`TextAreaSyncAddon#refreshTextArea: no textarea`); return; } this._logService.debug(`TextAreaSyncAddon#refreshTextArea: content is "${content}"`); this._logService.debug(`TextAreaSyncAddon#refreshTextArea: textContent is "${textArea.textContent}"`); if (focusChanged || content !== textArea.textContent) { textArea.textContent = content; this._logService.debug(`TextAreaSyncAddon#refreshTextArea: textContent changed to "${content}"`); } const cursorX = buffer.cursorX - commandStartX; this._logService.debug(`TextAreaSyncAddon#refreshTextArea: cursorX is ${cursorX}`); this._logService.debug(`TextAreaSyncAddon#refreshTextArea: selectionStart is ${textArea.selectionStart}`); if (focusChanged || cursorX !== textArea.selectionStart) { textArea.selectionStart = cursorX; textArea.selectionEnd = cursorX; this._logService.debug(`TextAreaSyncAddon#refreshTextArea: selectionStart changed to ${cursorX}`); </del> <ins> this._currentCommand = line.substring(0, currentCommand.commandRightPromptStartX); this._cursorX = buffer.cursorX; } else { this._currentCommand = undefined; this._cursorX = undefined; this._logService.debug(`TextAreaSyncAddon#updateCommandAndCursor: neither commandStartX nor commandRightPromptStartX`); </ins> } <del> // TODO: cursorY? </del> } }