Change:
Type: <bBug</bCC [I cannot easily find my authored issue so I am creating a new] Ctrl+LeftArrow and Ctrl+RightArrow does not work in the Output View (Ctrl+Shift+U) area. This happens on Windows. This means screen reader users cannot navigate word by word within the output view. Ctrl+Shift+U to focus in the Output View Choose any output (e.g., terminal) if you can navigate word by word via Ctrl+LeftArrow or Ctrl+RightArrow VS Code version: Code - Insiders 1.92.0-insider (, 2024-07-12T05:08:08.550Z) OS version: WindowsNT x64 10.0. Modes: <details<summarySystem Info</summary </details<details<summaryExtensions (125)</summaryExtensionVersion ------ vscode-openapi4.27.0 zotenote1.0.1 android-dev-ext1.4.0 aiprm-lang0.0.2 Bookmarks13.5.0 openscad1.2.2 spellright3.0.134 zoterolatex0.4.1 mermaid-markdown-syntax-highlighting1.6.0 external-pdf1.2.0 doxdocgen1.4.0 vscode-markdownlint0.53.0 vscode-eslint3.0.10 vscode-quick-select0.2.9 vscode-deno3.38.0 gitlens14.6.1 EditorConfig0.16.4 prettier-vscode10.1.0 figma-vscode-extension0.3.5 vscode-firefox-debug2.9.10 shell-format7.2.5 vscode-google-translate1.4.13 codespaces1.17.1 copilot1.213.0 copilot-chat0.18. remotehub0.62.0 vscode-github-actions0.26.2 vscode-pull-request-github0.93. cloudcode2.14.0 overleaf-workshop0.13.0 cslpreview0.2.2 path-autocomplete1.25.0 latex-workshop10.1.0 lilypond-syntax0.1.1 scheme0.2.0 better-cpp-syntax1.17.2 commitlint2.6.0 language-julia1.90.1 google-search0.0.1 vscode-lua-format1.3.8 lilypond-formatter0.2.3 lilypond-pdf-preview0.2.8 lilypond-snippets0.1.1 vslilypond1.7.3 language-matlab1.2.4 zotero0.1.11 git-graph1.30.0 azure-dev0.8.3 vscode-azureappservice0.25.2 vscode-azurecontainerapps0.6.1 vscode-azurefunctions1.15.1 vscode-azureresourcegroups0.8.3 vscode-azurestaticwebapps0.12.2 vscode-azurestorage0.16.0 vscode-azurevirtualmachines0.6.5 vscode-cosmosdb0.22.0 vscode-docker1.29.1 vscode-edge-devtools2.1.5 black-formatter2024.3. debugpy2024.9. flake82023.13. isort2023.13. python2024.11. vscode-pylance2024.7.1 jupyter2024.6. jupyter-keymap1.1.2 jupyter-renderers1.0.18 vscode-jupyter-cell-tags0.1.8 vscode-jupyter-slideshow0.1.5 remote-containers0.377.0 remote-ssh0.113. remote-ssh-edit0.86.0 remote-wsl0.81.8 vscode-remote-extensionpack0.25.0 azure-account0.12.0 azure-repos0.38.0 cmake-tools1.18.43 cpptools1.21.0 cpptools-extension-pack1.3.0 js-debug-nightly2024.7.517 powershell2024.3.2 remote-explorer0.5. remote-repositories0.40.0 remote-server1.6. vscode-github-issue-notebooks0.0.130 vscode-node-azure-pack1.2.0 vscode-selfhost-test-provider0.3.25 vscode-serial-monitor0.12.0 vscode-speech0.10.0 vscode-speech-language-pack-ko-kr0.4.0 vsliveshare1.0.5932 windows-ai-studio0.3.3 autodocstring0.6.1 pandocciter0.10.4 publisher1.1.3 shiny1.0.0 shinyuieditor0.5.0 quarto1.113.0 r-debugger0.5.4 java1.32.0 vscode-xml0.27.1 vscode-yaml1.14.0 r2.8.4 multi-command1.6.0 AudioQ0.0.2 vscode-deepl1.1.1 abc-music0.4.0 lua3.9.3 latex-utilities0.4.14 cmake0.0.17 vscode-terminal-here0.2.4 windows-terminal0.7.0 errorlens3.16.0 intellicode-api-usage-examples0.2.8 vscodeintellicode1.2.30 vscode-conventional-commits1.25.0 vscode-arduino0.6. vscode-java-debug0.58.0 vscode-java-dependency0.23.7 vscode-java-pack0.27.0 vscode-java-test0.41.1 vscode-maven0.44.0 zotero-cite0.8.6 markdown-all-in-one3.6.2 grammarly0.25.0 (1 theme extensions excluded) </details<details<summaryA/B Experiments</summary</details<!-- generated by issue reporter --
do you know why this isn't currently supported?
It seems to work for me in Mac, are you seeing it otherwise?
It does work for me, although sometimes with the screen reader enabled, it's reading the word then a whole chunk of text. I'll try on windows.
It’s not working in Windows.
Can reproduce on windows. I see that this is happening because there's a part of the when clause for and of for windows
Removing that from the clause fixes it. Looks like that condition was to fix this can you try removing that condition from the clause and seeing if you experience any consequences of doing so? Based on my testing, it seems fine.
will now also work to select the words

Discussion:
import { ICodeEditor } from '../../../browser/editorBrowser.js'; import { EditorAction, EditorCommand, ICommandOptions, registerEditorAction, registerEditorCommand, ServicesAccessor } from '../../../browser/editorExtensions.js'; import { ReplaceCommand } from '../../../common/commands/replaceCommand.js'; <del> import { EditorOption } from '../../../common/config/editorOptions.js'; </del> <ins> import { EditorOption, EditorOptions } from '../../../common/config/editorOptions.js'; </ins> import { CursorState } from '../../../common/cursorCommon.js'; import { CursorChangeReason } from '../../../common/cursorEvents.js'; import { DeleteWordContext, WordNavigationType, WordOperations } from '../../../common/cursor/cursorWordOperations.js';

} } <ins> // Accessibility navigation commands should only be enabled on windows since they are tuned to what NVDA expects export class CursorWordAccessibilityLeft extends WordLeftCommand { constructor() { super({ inSelectionMode: false, wordNavigationType: WordNavigationType.WordAccessibility, id: 'cursorWordAccessibilityLeft', precondition: undefined }); } protected override _move(wordCharacterClassifier: WordCharacterClassifier, model: ITextModel, position: Position, wordNavigationType: WordNavigationType, hasMulticursor: boolean): Position { return super._move(getMapForWordSeparators(EditorOptions.wordSeparators.defaultValue, wordCharacterClassifier.intlSegmenterLocales), model, position, wordNavigationType, hasMulticursor); } } export class CursorWordAccessibilityLeftSelect extends WordLeftCommand { constructor() { super({ inSelectionMode: true, wordNavigationType: WordNavigationType.WordAccessibility, id: 'cursorWordAccessibilityLeftSelect', precondition: undefined }); } protected override _move(wordCharacterClassifier: WordCharacterClassifier, model: ITextModel, position: Position, wordNavigationType: WordNavigationType, hasMulticursor: boolean): Position { return super._move(getMapForWordSeparators(EditorOptions.wordSeparators.defaultValue, wordCharacterClassifier.intlSegmenterLocales), model, position, wordNavigationType, hasMulticursor); } } </ins> export class CursorWordStartRight extends WordRightCommand { constructor() { super({

} } <ins> export class CursorWordAccessibilityRight extends WordRightCommand { constructor() { super({ inSelectionMode: false, wordNavigationType: WordNavigationType.WordAccessibility, id: 'cursorWordAccessibilityRight', precondition: undefined }); } protected override _move(wordCharacterClassifier: WordCharacterClassifier, model: ITextModel, position: Position, wordNavigationType: WordNavigationType, hasMulticursor: boolean): Position { return super._move(getMapForWordSeparators(EditorOptions.wordSeparators.defaultValue, wordCharacterClassifier.intlSegmenterLocales), model, position, wordNavigationType, hasMulticursor); } } export class CursorWordAccessibilityRightSelect extends WordRightCommand { constructor() { super({ inSelectionMode: true, wordNavigationType: WordNavigationType.WordAccessibility, id: 'cursorWordAccessibilityRightSelect', precondition: undefined }); } protected override _move(wordCharacterClassifier: WordCharacterClassifier, model: ITextModel, position: Position, wordNavigationType: WordNavigationType, hasMulticursor: boolean): Position { return super._move(getMapForWordSeparators(EditorOptions.wordSeparators.defaultValue, wordCharacterClassifier.intlSegmenterLocales), model, position, wordNavigationType, hasMulticursor); } } </ins> export interface DeleteWordOptions extends ICommandOptions { whitespaceHeuristics: boolean; wordNavigationType: WordNavigationType;

registerEditorCommand(new CursorWordStartRightSelect()); registerEditorCommand(new CursorWordEndRightSelect()); registerEditorCommand(new CursorWordRightSelect()); <ins> registerEditorCommand(new CursorWordAccessibilityLeft()); registerEditorCommand(new CursorWordAccessibilityLeftSelect()); registerEditorCommand(new CursorWordAccessibilityRight()); registerEditorCommand(new CursorWordAccessibilityRightSelect()); </ins> registerEditorCommand(new DeleteWordStartLeft()); registerEditorCommand(new DeleteWordEndLeft()); registerEditorCommand(new DeleteWordLeft());

import { ILanguageService } from '../../../../common/languages/language.js'; import { ILanguageConfigurationService } from '../../../../common/languages/languageConfigurationRegistry.js'; import { ViewModel } from '../../../../common/viewModel/viewModelImpl.js'; <del> import { CursorWordEndLeft, CursorWordEndLeftSelect, CursorWordEndRight, CursorWordEndRightSelect, CursorWordLeft, CursorWordLeftSelect, CursorWordRight, CursorWordRightSelect, CursorWordStartLeft, CursorWordStartLeftSelect, CursorWordStartRight, CursorWordStartRightSelect, DeleteInsideWord, DeleteWordEndLeft, DeleteWordEndRight, DeleteWordLeft, DeleteWordRight, DeleteWordStartLeft, DeleteWordStartRight } from '../../browser/wordOperations.js'; </del> <ins> import { CursorWordAccessibilityLeft, CursorWordAccessibilityLeftSelect, CursorWordAccessibilityRight, CursorWordAccessibilityRightSelect, CursorWordEndLeft, CursorWordEndLeftSelect, CursorWordEndRight, CursorWordEndRightSelect, CursorWordLeft, CursorWordLeftSelect, CursorWordRight, CursorWordRightSelect, CursorWordStartLeft, CursorWordStartLeftSelect, CursorWordStartRight, CursorWordStartRightSelect, DeleteInsideWord, DeleteWordEndLeft, DeleteWordEndRight, DeleteWordLeft, DeleteWordRight, DeleteWordStartLeft, DeleteWordStartRight } from '../../browser/wordOperations.js'; </ins> import { deserializePipePositions, serializePipePositions, testRepeatedActionAndExtractPositions } from './wordTestUtils.js'; import { createCodeEditorServices, instantiateTestCodeEditor, withTestCodeEditor } from '../../../../test/browser/testCodeEditor.js'; import { instantiateTextModel } from '../../../../test/common/testTextModel.js';

const _cursorWordStartRightSelect = new CursorWordStartRightSelect(); const _cursorWordEndRightSelect = new CursorWordEndRightSelect(); const _cursorWordRightSelect = new CursorWordRightSelect(); <ins> const _cursorWordAccessibilityLeft = new CursorWordAccessibilityLeft(); const _cursorWordAccessibilityLeftSelect = new CursorWordAccessibilityLeftSelect(); const _cursorWordAccessibilityRight = new CursorWordAccessibilityRight(); const _cursorWordAccessibilityRightSelect = new CursorWordAccessibilityRightSelect(); </ins> const _deleteWordLeft = new DeleteWordLeft(); const _deleteWordStartLeft = new DeleteWordStartLeft(); const _deleteWordEndLeft = new DeleteWordEndLeft();

function cursorWordLeft(editor: ICodeEditor, inSelectionMode: boolean = false): void { runEditorCommand(editor, inSelectionMode ? _cursorWordLeftSelect : _cursorWordLeft); } <ins> function cursorWordAccessibilityLeft(editor: ICodeEditor, inSelectionMode: boolean = false): void { runEditorCommand(editor, inSelectionMode ? _cursorWordAccessibilityLeft : _cursorWordAccessibilityLeftSelect); } function cursorWordAccessibilityRight(editor: ICodeEditor, inSelectionMode: boolean = false): void { runEditorCommand(editor, inSelectionMode ? _cursorWordAccessibilityRightSelect : _cursorWordAccessibilityRight); } </ins> function cursorWordStartLeft(editor: ICodeEditor, inSelectionMode: boolean = false): void { runEditorCommand(editor, inSelectionMode ? _cursorWordStartLeftSelect : _cursorWordStartLeft); }

assert.deepStrictEqual(actual, EXPECTED); }); <ins> test('cursorWordAccessibilityLeft', () => { const EXPECTED = ['|   /* |Just |some   |more   |text |a+= |3 +|5-|3 + |7 */  '].join('n'); const [text,] = deserializePipePositions(EXPECTED); const actualStops = testRepeatedActionAndExtractPositions( text, new Position(1000, 1000), ed => cursorWordAccessibilityLeft(ed), ed => ed.getPosition()!, ed => ed.getPosition()!.equals(new Position(1, 1)) ); const actual = serializePipePositions(text, actualStops); assert.deepStrictEqual(actual, EXPECTED); }); test('cursorWordAccessibilityRight', () => { const EXPECTED = ['   /* |Just |some   |more   |text |a+= |3 +|5-|3 + |7 */  |'].join('n'); const [text,] = deserializePipePositions(EXPECTED); const actualStops = testRepeatedActionAndExtractPositions( text, new Position(1, 1), ed => cursorWordAccessibilityRight(ed), ed => ed.getPosition()!, ed => ed.getPosition()!.equals(new Position(1, 50)) ); const actual = serializePipePositions(text, actualStops); assert.deepStrictEqual(actual, EXPECTED); }); </ins> test('deleteWordLeft for non-empty selection', () => { withTestCodeEditor([ '    tMy First Linet ',

import { AccessibilitySignal, IAccessibilitySignalService } from '../../../../platform/accessibilitySignal/browser/accessibilitySignalService.js'; import { ILoggerService, LogLevel, LogLevelToLocalizedString, LogLevelToString } from '../../../../platform/log/common/log.js'; import { IDefaultLogLevelsService } from '../../logs/common/defaultLogLevels.js'; <del> import { EditorOptions } from '../../../../editor/common/config/editorOptions.js'; import { WordCharacterClassifier, getMapForWordSeparators } from '../../../../editor/common/core/wordCharacterClassifier.js'; import { WordNavigationType } from '../../../../editor/common/cursor/cursorWordOperations.js'; </del> <ins> import { KeybindingsRegistry, KeybindingWeight } from '../../../../platform/keybinding/common/keybindingsRegistry.js'; </ins> import { EditorContextKeys } from '../../../../editor/common/editorContextKeys.js'; <del> import { ITextModel } from '../../../../editor/common/model.js'; import { WordLeftCommand, WordRightCommand } from '../../../../editor/contrib/wordOperations/browser/wordOperations.js'; </del> import { CONTEXT_ACCESSIBILITY_MODE_ENABLED } from '../../../../platform/accessibility/common/accessibility.js'; import { IsWindowsContext } from '../../../../platform/contextkey/common/contextkeys.js'; <del> import { KeybindingWeight } from '../../../../platform/keybinding/common/keybindingsRegistry.js'; import { Position } from '../../../../editor/common/core/position.js'; import { registerEditorCommand } from '../../../../editor/browser/editorExtensions.js'; </del> import { FocusedViewContext } from '../../../common/contextkeys.js'; // Register Service

} }); <del> // Accessibility navigation commands should only be enabled on windows since they are tuned to what NVDA expects export class CursorWordAccessibilityLeft extends WordLeftCommand { constructor() { super({ inSelectionMode: false, wordNavigationType: WordNavigationType.WordAccessibility, id: 'cursorWordAccessibilityLeft', precondition: undefined, kbOpts: { kbExpr: ContextKeyExpr.and(EditorContextKeys.textInputFocus, CONTEXT_ACCESSIBILITY_MODE_ENABLED, IsWindowsContext, ContextKeyExpr.equals(FocusedViewContext.key, OUTPUT_VIEW_ID)), primary: KeyMod.CtrlCmd | KeyCode.LeftArrow, weight: KeybindingWeight.EditorContrib } }); } protected override _move(wordCharacterClassifier: WordCharacterClassifier, model: ITextModel, position: Position, wordNavigationType: WordNavigationType, hasMulticursor: boolean): Position { return super._move(getMapForWordSeparators(EditorOptions.wordSeparators.defaultValue, wordCharacterClassifier.intlSegmenterLocales), model, position, wordNavigationType, hasMulticursor); } } export class CursorWordAccessibilityLeftSelect extends WordLeftCommand { constructor() { super({ inSelectionMode: true, wordNavigationType: WordNavigationType.WordAccessibility, id: 'cursorWordAccessibilityLeftSelect', precondition: undefined, kbOpts: { kbExpr: ContextKeyExpr.and(EditorContextKeys.textInputFocus, CONTEXT_ACCESSIBILITY_MODE_ENABLED, IsWindowsContext, ContextKeyExpr.equals(FocusedViewContext.key, OUTPUT_VIEW_ID)), primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.LeftArrow, weight: KeybindingWeight.EditorContrib } }); } protected override _move(wordCharacterClassifier: WordCharacterClassifier, model: ITextModel, position: Position, wordNavigationType: WordNavigationType, hasMulticursor: boolean): Position { return super._move(getMapForWordSeparators(EditorOptions.wordSeparators.defaultValue, wordCharacterClassifier.intlSegmenterLocales), model, position, wordNavigationType, hasMulticursor); } } export class CursorWordAccessibilityRight extends WordRightCommand { constructor() { super({ inSelectionMode: false, wordNavigationType: WordNavigationType.WordAccessibility, id: 'cursorWordAccessibilityRight', precondition: undefined, kbOpts: { kbExpr: ContextKeyExpr.and(EditorContextKeys.textInputFocus, CONTEXT_ACCESSIBILITY_MODE_ENABLED, IsWindowsContext, ContextKeyExpr.equals(FocusedViewContext.key, OUTPUT_VIEW_ID)), primary: KeyMod.CtrlCmd | KeyCode.RightArrow, weight: KeybindingWeight.EditorContrib } }); } protected override _move(wordCharacterClassifier: WordCharacterClassifier, model: ITextModel, position: Position, wordNavigationType: WordNavigationType, hasMulticursor: boolean): Position { return super._move(getMapForWordSeparators(EditorOptions.wordSeparators.defaultValue, wordCharacterClassifier.intlSegmenterLocales), model, position, wordNavigationType, hasMulticursor); } } export class CursorWordAccessibilityRightSelect extends WordRightCommand { constructor() { super({ inSelectionMode: true, wordNavigationType: WordNavigationType.WordAccessibility, id: 'cursorWordAccessibilityRightSelect', precondition: undefined, kbOpts: { kbExpr: ContextKeyExpr.and(EditorContextKeys.textInputFocus, CONTEXT_ACCESSIBILITY_MODE_ENABLED, IsWindowsContext, ContextKeyExpr.equals(FocusedViewContext.key, OUTPUT_VIEW_ID)), primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.RightArrow, weight: KeybindingWeight.EditorContrib } }); } protected override _move(wordCharacterClassifier: WordCharacterClassifier, model: ITextModel, position: Position, wordNavigationType: WordNavigationType, hasMulticursor: boolean): Position { return super._move(getMapForWordSeparators(EditorOptions.wordSeparators.defaultValue, wordCharacterClassifier.intlSegmenterLocales), model, position, wordNavigationType, hasMulticursor); } } registerEditorCommand(new CursorWordAccessibilityLeft()); registerEditorCommand(new CursorWordAccessibilityLeftSelect()); registerEditorCommand(new CursorWordAccessibilityRight()); registerEditorCommand(new CursorWordAccessibilityRightSelect()); </del> <ins> KeybindingsRegistry.registerKeybindingRule({ id: 'cursorWordAccessibilityLeft', when: ContextKeyExpr.and(EditorContextKeys.textInputFocus, CONTEXT_ACCESSIBILITY_MODE_ENABLED, IsWindowsContext, ContextKeyExpr.equals(FocusedViewContext.key, OUTPUT_VIEW_ID)), primary: KeyMod.CtrlCmd | KeyCode.LeftArrow, weight: KeybindingWeight.WorkbenchContrib }); KeybindingsRegistry.registerKeybindingRule({ id: 'cursorWordAccessibilityLeftSelect', when: ContextKeyExpr.and(EditorContextKeys.textInputFocus, CONTEXT_ACCESSIBILITY_MODE_ENABLED, IsWindowsContext, ContextKeyExpr.equals(FocusedViewContext.key, OUTPUT_VIEW_ID)), primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.LeftArrow, weight: KeybindingWeight.WorkbenchContrib }); KeybindingsRegistry.registerKeybindingRule({ id: 'cursorWordAccessibilityRight', when: ContextKeyExpr.and(EditorContextKeys.textInputFocus, CONTEXT_ACCESSIBILITY_MODE_ENABLED, IsWindowsContext, ContextKeyExpr.equals(FocusedViewContext.key, OUTPUT_VIEW_ID)), primary: KeyMod.CtrlCmd | KeyCode.RightArrow, weight: KeybindingWeight.WorkbenchContrib }); KeybindingsRegistry.registerKeybindingRule({ id: 'cursorWordAccessibilityRightSelect', when: ContextKeyExpr.and(EditorContextKeys.textInputFocus, CONTEXT_ACCESSIBILITY_MODE_ENABLED, IsWindowsContext, ContextKeyExpr.equals(FocusedViewContext.key, OUTPUT_VIEW_ID)), primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.RightArrow, weight: KeybindingWeight.WorkbenchContrib }); </ins>