Refactoring Key Chords Handling
PR Summary
This PR refactors, the handling of key chords and consolidates the behaviour from Emacs and VI modes into a single consistent function.
This PR addresses freedback made on #3791 following #2059 which has been merged a bit too optimistically.
PR Content
In order to achieve a consistent behaviour, the Chord Dispatch Table structures are refactored using a KeyHandlerOrChordDispatchTable class that can hold either a regular KeyHandler or a nested ChordDispatchTable. This means that chord dispatch tables are organized in a tree structure and looking up a key handler is a simple matter of walking down the tree structure.
This allows to greatly simplify the handling of VI-mode three key-chord commands, such as d, g, g (<d,g,g> delete relative lines) or d, i, w (<d,i,w> delete inner word)
This allows to remove all the references to a secondary dispatch table when handling key chords in favor of a more consistent algorithm that walks through the chord dispatch table tree structure and identifies whether the next node is a leaf (i.e a KeyHandler) or another nested node (i.e an inner-level chord dispatch table).
Note in #3791 was discussed the fact that we may want to limit key chords to a maximum of three keys. This PR does not enforce any limit. Maybe such a limit could be hardcoded in the PSConsoleReadLine.SetKeyHandler() CmdLet implementation.
This PR consolidates handling of key chords in the ProcessOneKey function – which could be renamed ProcessKeyChord. Most of the current implementations were using recursive code – albeit, indirectly by calling either the Chord or the ViChord method. In contrast, this PR almost eliminates recursive code in favor of walking the tree structure. However, handling of VI-mode digit-arguments is a bit complex and I was not able to solve this without resorting to recursive code. This make the ProcessOneKey function a bit hard to understand. I have tried adding as much comments as I could think of.
The unit-tests sometimes randomly fail on my machine, but that was already the case with the current code in the master branch before this PR. Sometimes, unit-tests fail as part of running the whole test suite. When running one failing test again it then succeeds. Finally, most tests around history fail on my machine but – again – that is already the case with the current code in the master branch 🤔.
PR Checklist
- [x] PR has a meaningful title
- Use the present tense and imperative mood when describing your changes
- [x] Summarized changes
- [x] Make sure you've added one or more new tests
- [x] Make sure you've tested these changes in terminals that PowerShell is commonly used in (i.e. conhost.exe, Windows Terminal, Visual Studio Code Integrated Terminal, etc.)
- User-facing changes
- [x] Documentation needed at PowerShell-Docs
- [ ] Doc Issue filed:
- [x] Documentation needed at PowerShell-Docs