Change:
Type: <bFeature Request</bFor screen reader users, terminal buffer is the great landing area where they can verify executed commands. Currently, the focus always moves to terminal input when we use the following command: Given the immediate need of accessing the terminal buffer for screen reader users, please add a custom setting to always move focus in terminal buffer area instead of the terminal input. This will greatly improve the accessibility, navigability, and alertability for screen reader users. VS Code version: Code - Insiders 1.82.0-insider (, 2023-08-04T05:35:09.023Z) OS version: Windows_NT x64 10.0. Modes: <!-- generated by issue reporter --
CC This benefit would be far reaching including Python repl and any terminal-based interpreters.
we have a new way to do this sort of thing. You can set up in a custom keybinding. For example: Note that I couldn't get this to work for me cc - maybe it's not yet supported
I have found that the following works: However, this is not novice-SR-user-friendly. Let's discuss further for better usability.
We could add a command that does the above with
would it suffice to focus the active terminal automatically for screen reader users after that command is run?
If you are referring to the current active terminal’s a11y buffer, I would say “Yes”. If you are talking about the active terminal input area, I would say, it might not be helpful.
I discussed with and we want to prevent the screen reader user's experience from diverging from the sighted user's experience. ATM, run selected text in active terminal keeps the focus in the editor so that a user can run additional lines of code. When I test this, the output gets announced via the screen reader. In the terminal buffer, we now have better support for reviewing the terminal input . What part of your flow is not well covered by this?
and -- Thank you for giving me the opportunity to expand on this topic: Configurable Setting: I propose the addition of a configurable setting for this feature. By default, the system could set the focus to move to the terminal input area. However, this behavior would be adjustable, allowing screen reader (SR) users to customize it according to their needs. This ensures that any divergence in user experience between sighted and visually impaired individuals is purely a matter of personal choice. Focus After Execution: Consider the following scenario—You have written your code in a scratch pad editor and then sent it to the terminal for execution. After the code has been executed, where does your focus naturally shift? Is it the input field or the output display? In most cases, it's the latter. Although 'aria-live' capabilities exist within the terminal input, these primarily provide instantaneous speech information that may be difficult to absorb, particularly if the output is complex or lengthy. For this reason, screen reader users often prefer to manually navigate through the terminal output, rather than relying on 'aria-live' alerts.
the way I think about it is that a user doesn't necessarily want to look at the accessible buffer immediately after running a command, the alerts will often be sufficient. So why wouldn't we treat this just like running a regular command where you type and press enter, ie. focus the terminal, but not the a11y buffer.
is fantastic for short and simple notifications, but it's not a one-size-fits-all solution. Imagine you're working in a data science context, and your output isn't just a single sentence but rather a complex data structure. It can be quite a challenge to remember all that information after hearing it just once, can't it? Another thing to consider is the buffer size of alerts. Longer outputs could get truncated, and that's definitely not ideal when the information is crucial. So, in scenarios like these, it might be more user-friendly to direct the focus straight to the terminal buffer. This would allow the user to navigate through the data at their own pace and comfort level. What do you think? Would love to hear your thoughts on this!
but we don't necessarily know whether the command will produce short or long output, and we don't know if the user will want to enter a command after, return to the editor, or view the accessible buffer. To me focusing the terminal and getting the regular behavior of running a command seems like the best compromise and most general behavior. Having said that, I've been on the fence for a setting for this behavior even when screen reader mode is disabled, so this is just another reason to add that. I would prefer if we kept the default to focus the terminal though because of the reasons above.
Yes, absolutely. I am not against keeping the default behavior. I was wondering if you could consider adding a custom user setting for those who want to change the default behavior.
If we add a setting, perhaps it could be "runTextInTerminalFocus": "terminal", "accessible buffer", or "none"
how about , where is terminal if in screen reader mode, otherwise ?
Your proposal sounds good except we'd want to go with for screen reader users as JooYoung has indicated that just focusing the terminal would not be helpful.
see and the comment below. That's preference but it's not necessarily the typical use case, so let's focus the terminal just like when running a command (typing and enter into shell).
To verify, enable screen reader mode and use the command . It should run the text then focus the terminal by default. Disable screen reader mode and do that again. The terminal shouldn't be focused. Change the setting with and without screen reader mode on and make sure it gets applied and that each setting description makes sense.
I get the following bug: screenreader mode. text in and then run terminal state, in terminal <img width="940" alt="image" src=""
the setting takes one of a few values:
sorry, I'm not sure why I said , I meant to say
yeah that's working for you in your screenshot above
Should be in the terminal though?
no, that's really odd and a different bug.
ok, I'll just mark this as and you can handle that separately

Discussion:
EnableImages = 'terminal.integrated.enableImages', SmoothScrolling = 'terminal.integrated.smoothScrolling', IgnoreBracketedPasteMode = 'terminal.integrated.ignoreBracketedPasteMode', <ins> FocusAfterRun = 'terminal.integrated.focusAfterRun', </ins> // Debug settings that are hidden from user

onDidBlur: Event<ITerminalInstance>; onDidInputData: Event<ITerminalInstance>; onDidChangeSelection: Event<ITerminalInstance>; <ins> onDidRunText: Event<void>; </ins> /** * An event that fires when a terminal is dropped on this instance via drag and drop.

readonly onRequestAddInstanceToGroup = this._onRequestAddInstanceToGroup.event; private readonly _onDidChangeHasChildProcesses = this._register(new Emitter<boolean>()); readonly onDidChangeHasChildProcesses = this._onDidChangeHasChildProcesses.event; <ins> private readonly _onDidRunText = this._register(new Emitter<void>()); readonly onDidRunText = this._onDidRunText.event; </ins> constructor( private readonly _terminalShellTypeContextKey: IContextKey<string>,

this._onDidInputData.fire(this); this.xterm?.suggestController?.handleNonXtermData(text); this.xterm?.scrollToBottom(); <ins> this._onDidRunText.fire(); </ins> } async sendPath(originalPath: string | URI, addNewLine: boolean): Promise<void> {

type: 'boolean', default: true }, <ins> [TerminalSettingId.FocusAfterRun]: { markdownDescription: localize('terminal.integrated.focusAfterRun', "Controls whether the terminal, accessible buffer, or neither will be focused after `Terminal: Run Selected Text In Active Terminal` has been run."), enum: ['auto', 'terminal', 'accessible-buffer', 'none'], default: 'auto', tags: ['accessibility'], markdownEnumDescriptions: [ localize('terminal.integrated.focusAfterRun.auto', "Set to `terminal` when in screen reader optimized mode and `none` otherwise."), localize('terminal.integrated.focusAfterRun.terminal', "Always focus the terminal."), localize('terminal.integrated.focusAfterRun.accessible-buffer', "Always focus the accessible buffer."), localize('terminal.integrated.focusAfterRun.none', "Do nothing."), ] } </ins> } };

import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { localize } from 'vs/nls'; <del> import { CONTEXT_ACCESSIBILITY_MODE_ENABLED } from 'vs/platform/accessibility/common/accessibility'; </del> <ins> import { CONTEXT_ACCESSIBILITY_MODE_ENABLED, IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; </ins> import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { IQuickPick, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput'; <del> import { terminalTabFocusModeContextKey } from 'vs/platform/terminal/common/terminal'; </del> <ins> import { TerminalSettingId, terminalTabFocusModeContextKey } from 'vs/platform/terminal/common/terminal'; </ins> import { IAccessibleViewService } from 'vs/workbench/contrib/accessibility/browser/accessibleView'; import { AccessibilityHelpAction } from 'vs/workbench/contrib/accessibility/browser/accessibleViewActions'; import { ITerminalContribution, ITerminalInstance, ITerminalService, IXtermTerminal } from 'vs/workbench/contrib/terminal/browser/terminal';

private readonly _instance: ITerminalInstance, processManager: ITerminalProcessManager, widgetManager: TerminalWidgetManager, <del> @IInstantiationService private readonly _instantiationService: IInstantiationService </del> <ins> @IInstantiationService private readonly _instantiationService: IInstantiationService, @IConfigurationService configurationService: IConfigurationService, @IAccessibilityService accessibilityService: IAccessibilityService </ins> ) { super(); <ins> this.add(_instance.onDidRunText(() => { const focusAfterRun = configurationService.getValue(TerminalSettingId.FocusAfterRun); const focusTerminal = focusAfterRun === 'terminal' || (focusAfterRun === 'auto' && accessibilityService.isScreenReaderOptimized()); if (focusTerminal) { _instance.focus(true); } else if (focusAfterRun === 'accessible-buffer') { this.show(); } })); </ins> } layout(xterm: IXtermTerminal & { raw: Terminal }): void { this._xterm = xterm;