Description
I had some ideas about how to flesh out some of the extensibility APIs. The original motivation was to allow context specific key handler assignments in menus like MenuComplete
. As I was looking into how PSRL might be changed to allow this, I came up with some ideas that would make extending PSRL a lot easier in general.
I do realize that the changes I'm about to propose would be unavoidably less performant, but I'd like to hear your thoughts. Here's a rough draft of what I have in mind.
Stories
As a user I want to
- Customize input handling of menus created by key handlers (both default and custom)
As a writer of custom key handlers I want to
-
Temporarily take over a default action when I present a menu, regardless of what key that action is assigned to
-
Allow PSRL to handle string manipulation of a custom input buffer
Bind keys to "dispatch" codes instead of delegates
Assigning keys
// Enum-like for default commands, borrowing a little from the
// design of System.Reflection.Emit.OpCodes.
class KeyHandlerCommand
{
// Default dispatch codes
static ListMoveDown { get; }
static ListMoveUp { get; }
static Accept { get; }
static SearchHistoryBackward { get; }
...
// Registering custom dispatch codes
static KeyHandlerCommand RegisterCustomCommand(
string dispatchCode,
Action<ConsoleKeyInfo?, object> defaultHandler);
static KeyHandlerCommand GetCustomCommand(
string dispatchCode);
// Instance properties
string DispatchCode { get; }
Action<ConsoleKeyInfo?, object> DefaultHandler { get; }
}
void SetKeyHandler(
string[] key,
KeyHandlerCommand command);
Assigning dispatch
IDisposable RegisterAction(
KeyHandlerCommand command,
Action<ConsoleKeyInfo?, object> handler);
The idea here is that a key handler that implements a menu would take over a command using this API and dispose of the return value to relinquish control back to PSRL. If this was a public API it would allow external custom menus to use existing key bindings.
Nested input buffers
This one in particular might be a long shot, but the ability tap into PSRL's string manipulation would greatly reduce the barrier of entry for custom menu creators.
IDisposable EnterNestedInputBuffer(
StringBuilder buffer,
Action<Edit> onBufferChange,
Action<int> onCursorMove);
Accepting dispatch
class KeyHandlerDispatch
{
KeyHandlerCommand Command { get; }
Action<ConsoleKeyInfo?, object> CurrentHandler { get; }
ConsoleKeyInfo? Key { get; }
object Argument { get; }
}
KeyHandlerDispatch ReadDispatch(
string contextName,
CancellationToken cancellationToken);
This would be the last piece needed to fully enable both context specific key bindings and extending PSRL's input loop.