This adds the `EnableScreenReaderMode` command-line switch which
defaults to true if an active screen reader is detected.
In screen reader mode, the existing `ForceRender()` function is replaced
by `RenderForScreenReader()` which uses a differential rendering
approach to minimize extraneous output to the terminal, allowing the use
of screen readers better than ever before.
The differential rendering relies on calculating the common prefix of
the `buffer` and `previousRender` strings. Nearly all necessary changes
are consolidated in the new rendering function.
Features known not to be supported:
* Colors: as this necessitates redrawing to insert color sequences after
the input is received and the AST parsed.
* Inline predictions: as this by definition changes the suffix and thus
requires endless redrawing.
* List view predictions: since the render implementation never calls
into the prediction engine, this is not available either.
* Menu completion: well, it "works" since it's not disabled and does its
own rendering, but no effort has been made to improve `DrawMenu()`, so
it's not accessible (and I'm not sure it could be given our current
constraints).
Features known to be partially supported:
* Text selection: mark and select commands work as intended, but provide
no visual indication.
* Multiple lines: as in newlines work fine, but there is no continuation
prompt.
* Visually wrapped lines: editing above a wrapped line redraws all
subsequent lines and hence is noisy.
* Status prompt based commands: what-is-key, digit-argument, and most
notably, forward/backward incremental history search all render a
"status prompt" on the line below the user's input buffer. This _is_
supported; however, it can be noisy since it necessarily has to render
the whole buffer when the input buffer changes, including the status
prompt (and search text). But what it's reading is almost always going
to be relevant.
Everything else should generally work, even Vi mode, and the tests pass.
That said, this isn't perfect, and moreover the approach specifically
doesn't attempt to enable things from the ground up. There may be
features that are available but turn out not to be accessible (like
`MenuComplete`) and I believe they should be left as-is.
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.
LanguagePrimitives.TryConvertTo raises (and catches) exceptions on
failed convertions to an enum type like ConsoleColor.
These exceptions were affecting debugging performance of the menu and we
never want exceptions if it's easy to avoid, which in this case it is.
To make it a bit easier to create themes, the various parameters to
Set-PSReadLineOption to set colors has been replaced with a single
parameter accepting a Hashtable.
The valid keys are:
-- ContinuationPrompt: The color of the continuation prompt.
-- Emphasis: The emphasis color, e.g. the matching text when searching history.
-- Error: The error color, e.g. in the prompt.
-- Default: The default token color.
-- Comment: The comment token color.
-- Keyword: The keyword token color.
-- String: The string token color.
-- Operator: The operator token color.
-- Variable: The variable token color.
-- Command: The command token color.
-- Parameter: The parameter token color.
-- Type: The type token color.
-- Number: The number token color.
-- Member: The member name token color.
I was terribly inconsistent.
This is a breaking change, though unlikely to cause troubles.
The apis are mostly used in PowerShell scripts which is not
case sensitive.
The cmdlet name change is also mostly safe.
At any rate, this is version 2.0 and breaking changes should be OK.
Fix selection to use escape sequence for invert - it doesn't look that
great when there are too many colors, but it will work with any
customization.
Also fix tests to work after previous commit.
With no portable way to scrape, displaying red in the prompt is harder.
To start, there is a new option to specify the end of the prompt text so
you can specify exactly what should turn red.
Many folks won't use this, so there are some smarts added at startup to
analyze the prompt function - if it's "pure", as in, doesn't call any
methods or commands, we call it and infer the invariant part of the
prompt, basically the last non-whitespace character plus the trailing
whitespace.