-
Notifications
You must be signed in to change notification settings - Fork 5
Handling Keyboard Inputs with Active Patterns
MIkE edited this page Sep 20, 2018
·
6 revisions
An active pattern lets you define match expressions with different number of Keys to analyse keyboard input.
Define active pattern:
let (|ContainsKeys|_|) (keys : List<Keys>) (pressedKeys : Set<Keys>) : unit option =
match containsKeys pressedKeys keys with
| true -> Some ()
| false -> None
Example match expression:
match pressedKeys with
| ContainsKeys [ Keys.P; Keys.LeftCtrl ]
| ContainsKeys [ Keys.P; Keys.RightCtrl ] -> ()
| ContainsKey Keys.OemPeriod -> ()
| ContainsKeys [ Keys.LeftCtrl; Keys.LeftAlt; Keys.Delete ] -> ()
With boolean expressions, the active pattern could analyse even more complex inputs, like:
| Fulfills (Keys.X && Keys.c && (Keys.LeftShift || Keys.RightShift)) ->
Infix functions seem not to work with pattern matching, but member functions should allow the following code:
| Fulfills (Keys.X .And Keys.c .And (Keys.LeftShift .Or Keys.RightShift)) ->
The query tree structure could look like this:
type Node =
| Key of Keys
| And of Node * Node
| Or of Node * Node
let rec fulfills (keys : Set<Keys>) (query : Node) : bool =
match query with
| Key k -> keys |> Set.contains k
| And (k1, k2) -> (fulfills keys k1) && (fulfills keys k2)
| Or (k1, k2) -> (fulfills keys k1) || (fulfills keys k2)
let (|Fulfills|_|) (query : Node) (keys : Set<Keys>) : unit option =
match fulfills keys query with
| true -> Some ()
| false -> None
By using List instead of Set for the pressed keys you can make queries on the order of pressed keys, like:
| [ Keys.V; Keys.X ] -> ()
| [ Keys.X; Keys.V ] -> ()