-
-
Notifications
You must be signed in to change notification settings - Fork 31
feat(leaves): Add module for defining user customizable keybindings #22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 3 commits
bbe2e73
c3f470e
fd1d808
5939704
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| (executable | ||
| (name main) | ||
| (libraries minttea spices leaves)) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| open Leaves | ||
| open Minttea | ||
|
|
||
| type msg = CursorUp | CursorDown | CursorLeft | ||
|
|
||
| let defaults = | ||
| let open Key_map in | ||
| make [ | ||
| on | ||
| ~help:{ key = "up"; desc = "↑/k" } | ||
| [ Minttea.Event.Up; Minttea.Event.Key "k" ] | ||
| CursorUp; | ||
| on | ||
| ~help:{ key = "down"; desc = "↓/j" } | ||
| [ Minttea.Event.Down; Minttea.Event.Key "j" ] | ||
| CursorDown; | ||
| on ~disabled:true | ||
| ~help:{ key = "left"; desc = "←/h" } | ||
| [ Minttea.Event.Left; Minttea.Event.Key "h" ] | ||
| CursorLeft; | ||
| ] | ||
|
|
||
| let custom_key_map = | ||
| let open Key_map in | ||
| [ | ||
| on | ||
| ~help:{ key = "up"; desc = "↑/k" } | ||
| [ Minttea.Event.Up; Minttea.Event.Key "k"; Minttea.Event.Key "u" ] | ||
| CursorUp; | ||
| ] | ||
|
|
||
| let () = | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Almost forgot, all the examples should be working Minttea app to showcase how this component fits into an application. This also helps you see if the API really figs the way you'd use it in an app. In this case we can also refactor an existing example that uses several keys (like the views example) so use one or more key maps. This should also expose the component to the use cases of:
We don't have to have those answers in this PR but they would definitely inform the design you go for.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, so in this case should I remove the key_map example and refactor say the views example to use the key map feature?
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Up to you :) either making this one a complete tiny app, or refactoring one of the others. |
||
| List.iter | ||
| (fun k -> | ||
| match Key_map.find_match ~custom_key_map k defaults with | ||
| | Some CursorUp -> print_endline "up" | ||
| | Some CursorDown -> print_endline "down" | ||
| | Some CursorLeft -> print_endline "left" | ||
| | None -> print_endline "Not Found") | ||
| [ | ||
| Event.Up; | ||
| Event.Key "k"; | ||
| Event.Key "u"; | ||
| Event.Down; | ||
| Event.Key "j"; | ||
| Event.Left; | ||
| Event.Enter; | ||
| ] | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| type help = { key : string; desc : string } | ||
|
|
||
| type binding = { | ||
| keys : Minttea.Event.key list; | ||
| help : help option; | ||
| disabled : bool; | ||
| } | ||
|
|
||
| type 'a t = ('a * binding) list | ||
|
|
||
| let on ?help ?(disabled = false) keys msg = (msg, { keys; help; disabled }) | ||
|
|
||
| let find_match ?(custom_key_map : 'a t option) key (default_key_map : 'a t) = | ||
| let key_map = | ||
| match custom_key_map with | ||
| | Some k_map -> | ||
| List.fold_left | ||
| (fun acc (k, b) -> | ||
| if List.mem_assoc k acc then acc else List.cons (k, b) acc) | ||
| k_map default_key_map | ||
| | None -> default_key_map | ||
| in | ||
|
|
||
| let f (_, (binding : binding)) = | ||
| if binding.disabled then false | ||
| else List.exists (fun k -> k == key) binding.keys | ||
| in | ||
| List.find_opt f key_map |> Option.map (fun (msg, _) -> msg) | ||
|
|
||
| (* INFO: This is just for future proofing, in case the underlying type changes *) | ||
| let make (key_map : ('a * binding) list) = key_map | ||
| let to_list (key_map : 'a t) = key_map |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| type help = { key : string; desc : string } | ||
|
|
||
| type binding = { | ||
| keys : Minttea.Event.key list; | ||
| help : help option; | ||
| disabled : bool; | ||
| } | ||
|
|
||
| type 'a t = ('a * binding) list | ||
|
|
||
| val on : | ||
| ?help:help -> | ||
| ?disabled:bool -> | ||
| Minttea.Event.key list -> | ||
| 'a -> | ||
| 'a * binding | ||
|
|
||
| val find_match : | ||
| ?custom_key_map:'a t -> | ||
| Minttea.Event.key -> | ||
| 'a t -> | ||
| 'a option | ||
|
|
||
| val make : ('a * binding) list -> 'a t | ||
| val to_list : 'a t -> ('a * binding) list | ||
|
|
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think about deriving these from the events and using the
~helpfor writing more about what the keymap is supposed to do?For example:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can see how with this information we can put together a bindings help view: