PSReadLine icon indicating copy to clipboard operation
PSReadLine copied to clipboard

Refactoring Key Chords Handling

Open springcomp opened this issue 2 years ago • 0 comments

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
Microsoft Reviewers: Open in CodeFlow

springcomp avatar Oct 31 '23 16:10 springcomp