Skip to content

Add screen reader support #4854

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: master
Choose a base branch
from

Conversation

andyleejordan
Copy link
Member

@andyleejordan andyleejordan commented Jul 19, 2025

A work-in-progress that utilizes a SafeRender abstraction that relies on checking the strings of buffer and previousRender to only re-render what's necessary when a screen reader is enabled. Predictions are disabled. Haven't tested Vi mode, Windows PowerShell 5.1, nor multi-line input. But visually wrapped lines and Windows and Emacs edit modes seem to be working as expected without any unnecessary re-rendering.

Specifically tested with NVDA on Windows and VoiceOver on macOS within VS Code's integrated terminal, with shell integration loaded, and Code's screen reader optimizations enabled.

Is a start to resolving #2504.

@andyleejordan andyleejordan force-pushed the screenreader branch 4 times, most recently from 8b8a080 to 9ba544b Compare July 23, 2025 17:56
@andyleejordan andyleejordan changed the title WIP: Prototype screen reader support Prototype screen reader support Jul 23, 2025
@andyleejordan andyleejordan marked this pull request as ready for review July 23, 2025 18:39
@andyleejordan andyleejordan requested a review from Copilot July 23, 2025 18:58
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces prototype screen reader support by implementing a SafeRender abstraction that uses ANSI control codes when screen reader mode is enabled. The changes modify rendering behavior throughout the application to provide better accessibility for screen reader users.

Key changes:

  • Introduces SafeRender method that outputs ANSI escape sequences instead of full re-rendering when screen reader support is enabled
  • Adds screen reader detection for Windows (including Narrator) and macOS VoiceOver
  • Replaces many Render() calls with SafeRender() calls across editing operations, undo/redo, history, and completion functionality

Reviewed Changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
PSReadLine/Accessibility.cs Enhanced screen reader detection for Windows and macOS platforms
PSReadLine/Cmdlets.cs Added ScreenReader option with automatic detection as default
PSReadLine/Options.cs Added logic to disable predictions when screen reader is enabled
PSReadLine/Render.cs Implemented SafeRender method using ANSI control codes
PSReadLine/UndoRedo.cs Replaced Render calls with SafeRender for undo/redo operations
PSReadLine/PublicAPI.cs Updated Insert and Replace methods to use SafeRender
PSReadLine/BasicEditing.cs Modified editing operations to use SafeRender with appropriate ANSI codes
PSReadLine/History.cs Updated history navigation and search to use SafeRender
PSReadLine/KillYank.cs Modified kill operations to use SafeRender
PSReadLine/Completion.cs Added TODO for menu completion screen reader testing
PSReadLine/KeyBindings.cs Added TODO for WhatIsKey screen reader evaluation
PSReadLine/ReadLine.cs Added TODOs for screen reader evaluation in various render calls
PSReadLine/PlatformWindows.cs Added IsMutexPresent method for detecting Windows Narrator

Copy link
Member

@daxian-dbw daxian-dbw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review in progress. Need to stop here today and want to share my comments so far.

@@ -533,6 +540,8 @@ public object ListPredictionTooltipColor

public bool TerminateOrphanedConsoleApps { get; set; }

public bool ScreenReader { get; set; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The property name doesn't indicate the Boolean type. How about renamed it to be ScreenReaderIsActive?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That seems awkward as a CLI option, you don't usually type -FooIsActive to enable something. What about -ScreenReaderMode?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The property name in PSConsoleReadLineOptions doesn't have to be the same as the parameter in the cmdlet SetPSReadLineOption. The former will be the one that is referenced a lot in the code base, so it would be better to make it more readable, such as UseScreenReader or ScreenReaderEnabled. The parameter name can be made -EnableScreenReadeMode or similar.

Should we use a different set of default key bindings when a Screen Reader is turned on? If so, then it may be better to add a new EditMode ScreenReaderMode, while defines its own set of default bindings.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me know which two names you'd like it to be.

I think let's not do a new EditMode but simply, for the very few that it seems to affect, disable the function by returning early if in screen reader mode. Otherwise we have to copy/paste the default bindings, and then we'd have different defaults for Windows/non-Windows, or we'd have to add new logic for unbinding by function name instead of key chord.

@andyleejordan andyleejordan force-pushed the screenreader branch 2 times, most recently from 175096b to d89f7ca Compare August 1, 2025 03:01
That should default to enabled when one is detected on startup,
but also allows the support to be forcibly enabled.
Borrows the "better" algorithm from Electron, with attribution.
Spawns a quick `defaults` process since in .NET
using the macOS events is difficult, but this is
quick and easy.
@andyleejordan andyleejordan force-pushed the screenreader branch 5 times, most recently from 0f93014 to 9090264 Compare August 5, 2025 18:28
@@ -533,6 +540,8 @@ public object ListPredictionTooltipColor

public bool TerminateOrphanedConsoleApps { get; set; }

public bool ScreenReader { get; set; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The property name in PSConsoleReadLineOptions doesn't have to be the same as the parameter in the cmdlet SetPSReadLineOption. The former will be the one that is referenced a lot in the code base, so it would be better to make it more readable, such as UseScreenReader or ScreenReaderEnabled. The parameter name can be made -EnableScreenReadeMode or similar.

Should we use a different set of default key bindings when a Screen Reader is turned on? If so, then it may be better to add a new EditMode ScreenReaderMode, while defines its own set of default bindings.

@andyleejordan andyleejordan changed the title Prototype screen reader support Add screen reader support Aug 5, 2025
@andyleejordan andyleejordan added Issue-Enhancement It's a feature request. Area-Accessibility Label for issues related to accessibility problems or improvements labels Aug 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Accessibility Label for issues related to accessibility problems or improvements Issue-Enhancement It's a feature request.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants