brick-1.6: A declarative terminal user interface library
Safe HaskellSafe-Inferred
LanguageHaskell2010

Brick.Keybindings.KeyDispatcher

Description

This is the entry point into the keybinding infrastructure in this library. Note that usage of this API is not required to create working Brick applications; this API is provided for applications that need to support custom keybindings that are less tightly coupled to application behavior.

The workflow for this API is as follows:

  • Create a data type k with a constructor for each abstract application event that you want to trigger with an input key.
  • To each event k, assign a unique user-readable name (such as a name you could imagine using in a configuration file to refer to the event) and a list of default key bindings.
  • Use the resulting data to create a KeyConfig with newKeyConfig. If desired, provide custom keybindings to newKeyConfig from within the program or load them from an INI file with routines like keybindingsFromFile.
  • Optionally check for configuration-wide keybinding collisions with keyEventMappings.
  • Implement application event handlers that will be run in response to either specific hard-coded keys or events k, both in some monad m of your choosing, using constructors onKey and onEvent.
  • Use the created KeyConfig and handlers to create a KeyDispatcher with keyDispatcher, dealing with collisions if they arise.
  • As user input events arrive, dispatch them to the appropriate handler in the dispatcher using handleKey.
Synopsis

Key dispatching

data KeyDispatcher k m Source #

A dispatcher keys that map to abstract events k and whose handlers run in the monad m.

keyDispatcher :: Ord k => KeyConfig k -> [KeyEventHandler k m] -> Either [(Binding, [KeyHandler k m])] (KeyDispatcher k m) Source #

Build a KeyDispatcher to dispatch keys to handle events of type k using actions in a Monad m. If any collisions are detected, this fails with Left and returns the list of colliding event handlers for each overloaded binding. (Each returned KeyHandler contains the original KeyEventHandler that was used to build it so those can be inspected to understand which handlers are mapped to the same key, either via an abstract key event using onEvent or via a statically configured key using onKey.)

This works by taking a list of abstract KeyEventHandlers and building a KeyDispatcher of event handlers based on specific Vty keys using the provided KeyConfig to map between abstract key events of type k and Vty keys. Event handlers triggered by an event k are set up to be triggered by either the customized bindings for k in the KeyConfig, no bindings at all if the KeyConfig has marked k as Unbound, or the default bindings for k otherwise.

Once you have a KeyDispatcher, you can dispatch an input key event to it and invoke the corresponding handler (if any) with handleKey.

handleKey Source #

Arguments

:: Monad m 
=> KeyDispatcher k m

The dispatcher to use.

-> Key

The key to handle.

-> [Modifier]

The modifiers for the key, if any.

-> m Bool 

Handle a keyboard event by looking it up in the KeyDispatcher and invoking the matching binding's handler if one is found. Return True if the a matching handler was found and run; return False if no matching binding was found.

Building handlers

onEvent Source #

Arguments

:: k

The key event whose bindings should trigger this handler.

-> Text

The description of the handler.

-> m ()

The handler to invoke.

-> KeyEventHandler k m 

Specify a handler for the specified key event.

onKey Source #

Arguments

:: ToBinding a 
=> a

The binding that should trigger this handler.

-> Text

The description of the handler.

-> m ()

The handler to invoke.

-> KeyEventHandler k m 

Specify a handler for the specified key.

Handlers and triggers

data Handler m Source #

A Handler represents a handler implementation to be invoked in response to some event that runs in the monad m.

In general, you should never need to make one of these manually. Instead, use onEvent and onKey. This type's internals are exposed for easy inspection, not construction.

Constructors

Handler 

Fields

data KeyHandler k m Source #

A handler for a specific key.

In general, you should never need to create one of these manually. The internals are exposed to make inspection easy.

Constructors

KeyHandler 

Fields

  • khHandler :: KeyEventHandler k m

    The handler to invoke. Note that this maintains the original abstract key event handler; this allows us to obtain the original EventTrigger for the KeyEventHandler upon which this KeyHandler is built. This can be important for keybinding consistency checks or collision checks as well as help text generation.

  • khBinding :: Binding

    The specific key binding that should trigger this handler.

data KeyEventHandler k m Source #

A handler for an abstract key event.

In general, you should never need to create these manually. Instead, use onEvent and onKey. The internals of this type are exposed to allow inspection of handler data for e.g. custom help generation.

Constructors

KeyEventHandler 

Fields

data EventTrigger k Source #

A trigger for an event handler.

Constructors

ByKey Binding

The key event is always triggered by a specific key.

ByEvent k

The trigger is an abstract key event.

Misc

keyDispatcherToList :: KeyDispatcher k m -> [(Binding, KeyHandler k m)] Source #

Convert a key dispatcher to a list of pairs of bindings and their handlers.

lookupVtyEvent :: Key -> [Modifier] -> KeyDispatcher k m -> Maybe (KeyHandler k m) Source #

Find the key handler that matches a Vty key event, if any. Modifier order is unimportant since the lookup for a matching binding ignores modifier order.

This works by looking up an event handler whose binding is the specified key and modifiers based on the KeyConfig that was used to build the KeyDispatcher.

Ordinarily you will not need to use this function; use handleKey instead. This is provided for more direct access to the KeyDispatcher internals.