···2525 | None ->
2626 let key_map = (Lwd.peek ui_state.config).key_map.file in
2727 let registry = FileCommands.get_command_registry active_files get_command_mapping in
2828- let mapping = build_command_list key_map registry in
2828+ let mapping = build_command_keymap key_map registry in
2929 command_mapping := Some mapping;
3030 mapping
3131 ;;
+1-1
jj_tui/bin/graph_view.ml
···4040 | None ->
4141 let key_map = (Lwd.peek ui_state.config).key_map.graph in
4242 let registry = GraphCommands.get_command_registry get_command_mapping in
4343- let mapping = build_command_list key_map registry in
4343+ let mapping = build_command_keymap key_map registry in
4444 command_mapping := Some mapping;
4545 mapping
4646 ;;
+3-2
jj_tui/bin/jj_commands.ml
···285285 match key with
286286 | `ASCII k, modifiers ->
287287 let key = { key = k; modifiers } in
288288+ (*remember that the key map here has been processed so it directly maps the keys to commands not to command ids*)
288289 let cmd = keymap |> Key_Map.find_opt key in
289290 (match cmd with
290291 | Some cmd ->
···447448 command_input ~is_sub:false command_mapping
448449 ;;
449450450450- (* Function to build command list from key_map and a command registry *)
451451- let build_command_list key_map command_registry =
451451+ (* Function to build key=>command keymap from a key=>command_id map and a command registry *)
452452+ let build_command_keymap key_map command_registry =
452453 (* Process a key_map item *)
453454 let rec process_key_map_item key item =
454455 match item with
+21-2
jj_tui/bin/jj_ui.ml
···3838 W.button (Printf.sprintf "quit ") (fun () -> Vars.quit $= true) |> Lwd.pure
3939 ;;
40404141+ (** Forward an event to a list of handlers until one of them returns `Handled *)
4142 let rec forward_events handlers event =
4243 match handlers with
4344 | h :: rest ->
···4647 `Unhandled
4748 ;;
48495050+ (** Handle inputs for the UI.
5151+ @param custom A custom handler that can be used to handle inputs that are not part of the default key bindings.
5252+ @param ui The UI to handle inputs for.
5353+ *)
4954 let inputs ?(custom = fun _ -> `Unhandled) ui =
5055 ui
5156 |>$ Ui.keyboard_area @@ fun event ->
5257 event
5358 |> forward_events
5459 [
5555- custom
6060+ custom;
6161+ (fun x->
6262+ (*Try to remap the key if needed *)
6363+ match x with
6464+ | `ASCII k, modifiers ->
6565+ let key = Key.{ key = k; modifiers } in
6666+ let key=Key_map.Key_Map.find_opt key (Lwd.peek ui_state.config).key_map.remap in
6767+ ( match key with
6868+ | Some remap ->
6969+ (** This needs to be type converted so our limited variants get upcast into a full nottui event*)
7070+ (`Remap (remap.remap, modifiers):> Nottui.Ui.may_handle)
7171+ | None ->
7272+ `Unhandled)
7373+ | _ ->
7474+ `Unhandled)
5675 ; (function
5776 | `ASCII 'q', _ ->
5877 Vars.quit $= true;
···93112 ]
94113 ;;
951149696- (* shows a pretty box in the middle of the screen with our error in it*)
115115+ (** Shows a pretty box in the middle of the screen with our error in it*)
97116 let render_startup_error error =
98117 let message =
99118 match error with
+1-1
jj_tui/lib/key.ml
···3434 in
3535 process_parts [] parts
36363737-let key_of_string_exn str= key_of_string str|>Result.get_ok
3737+let key_of_string_exn str= match key_of_string str with Ok k -> k | Error msg -> failwith ("Invalid key: " ^ msg)
38383939let key_to_string { key; modifiers } =
4040 let modifier_str =
+147-47
jj_tui/lib/key_map.ml
···1313 ;;
1414end
15151616+module Nottui_remap = struct
1717+ (** Currently this only supports arrow remapping, but we could support any other keys/events *)
1818+1919+ (** Extraction of the nottui arrow keys event type for remapping*)
2020+ type t = [ `Arrow of [ `Down | `Left | `Right | `Up ] ] [@@deriving show]
2121+2222+ let of_string remap =
2323+ match remap with
2424+ | "up" ->
2525+ Ok (`Arrow `Up)
2626+ | "down" ->
2727+ Ok (`Arrow `Down)
2828+ | "left" ->
2929+ Ok (`Arrow `Left)
3030+ | "right" ->
3131+ Ok (`Arrow `Right)
3232+ | _ ->
3333+ Error (`Msg ("Invalid remap: " ^ remap))
3434+ ;;
3535+3636+ let of_string_exn remap =
3737+ match of_string remap with
3838+ | Ok remap ->
3939+ remap
4040+ | Error (`Msg msg) ->
4141+ failwith ("Invalid remap: " ^ msg)
4242+ ;;
4343+4444+ let to_string = function
4545+ | `Arrow `Up ->
4646+ "up"
4747+ | `Arrow `Down ->
4848+ "down"
4949+ | `Arrow `Left ->
5050+ "left"
5151+ | `Arrow `Right ->
5252+ "right"
5353+ ;;
5454+end
5555+5656+(**A functor to make a usable keymap module from a given item type*)
5757+module MakeKeyMap (Item : sig
5858+ type t [@@deriving show]
5959+6060+ val of_yaml : string * Yaml.value -> (Key.t * t, [ `Msg of string ]) result
6161+ val to_yaml : (t Key_Map.t -> Yaml.value) -> Key.t * t -> string * Yaml.value
6262+ end) =
6363+struct
6464+ type t = Item.t Key_Map.t [@@deriving show]
6565+ type t_update_t = t
6666+6767+ let of_yaml (yaml : Yaml.value) =
6868+ match yaml with
6969+ | `O top_level ->
7070+ List.map Item.of_yaml top_level
7171+ |> Base.Result.all
7272+ |> Result.map (fun x -> Key_Map.of_seq (List.to_seq x))
7373+ | _ ->
7474+ Error (`Msg "Invalid YAML structure")
7575+ ;;
7676+7777+ let of_yaml_exn yaml =
7878+ match of_yaml yaml with
7979+ | Ok key_map ->
8080+ key_map
8181+ | Error (`Msg msg) ->
8282+ failwith ("Invalid YAML structure: " ^ msg)
8383+ ;;
8484+8585+ open Yaml.Util
8686+8787+ let rec to_yaml (key_map : Item.t Key_Map.t) : Yaml.value =
8888+ obj (key_map |> Key_Map.to_seq |> Seq.map (Item.to_yaml to_yaml) |> List.of_seq)
8989+ ;;
9090+ let t_update_t_to_yaml (key_map : t) : Yaml.value =
9191+ to_yaml key_map
9292+ ;;
9393+9494+ let t_update_t_of_yaml (yaml : Yaml.value) = of_yaml yaml
9595+9696+ (**Merge two key maps, checking for duplicate keys*)
9797+let t_apply_update override og =
9898+ Key_Map.merge
9999+ (fun k v1 v2 ->
100100+ match v1, v2 with
101101+ | Some og, Some override ->
102102+ Some override
103103+ | Some v, None | None, Some v ->
104104+ Some v
105105+ | None, None ->
106106+ None)
107107+ og
108108+ override
109109+;;
110110+end
111111+16112type command = { command : string } [@@deriving show]
113113+type remap = { remap : Nottui_remap.t } [@@deriving show]
1711418115type sub_menu = {
19116 title : string
20117 ; subcommands : key_map
21118}
119119+[@@deriving show]
2212023121and key_map_item =
24122 | Sub_menu of sub_menu
25123 | Command of command
2612427125and key_map = key_map_item Key_Map.t [@@deriving show]
2828-and key_map_update_t = key_map
126126+and remap_key_map = remap Key_Map.t [@@deriving show]
2912730128let ( let* ) = Base.Result.Let_syntax.( >>= )
31129let ( let+ ) = Base.Result.Let_syntax.( >>| )
···53151 Error (`Msg "Invalid YAML structure")
54152;;
551535656-let key_map_of_yaml (yaml : Yaml.value) =
5757- match yaml with
5858- | `O top_level ->
5959- List.map key_map_item_of_yaml top_level
6060- |> Base.Result.all
6161- |> Result.map (fun x -> Key_Map.of_seq (List.to_seq x))
154154+let remap_key_map_item_of_yaml (value : string * Yaml.value) =
155155+ match value with
156156+ | key, `O [ ("remap", `String remap) ] ->
157157+ let* key =
158158+ Key.key_of_string key |> Result.map_error (fun msg -> `Msg ("Invalid key: " ^ msg))
159159+ in
160160+ let+ remap = Nottui_remap.of_string remap in
161161+ key, { remap }
62162 | _ ->
63163 Error (`Msg "Invalid YAML structure")
6464-;;
6565-6666-let key_map_of_yaml_exn yaml =
6767- match key_map_of_yaml yaml with
6868- | Ok key_map ->
6969- key_map
7070- | Error (`Msg msg) ->
7171- failwith ("Invalid YAML structure: " ^ msg)
72164;;
7316574166open Yaml.Util
751677676-let rec key_map_item_to_yaml = function
168168+let key_map_item_to_yaml key_map_to_yaml key_map_item =
169169+ match key_map_item with
77170 | key, Sub_menu { title; subcommands } ->
78171 let sub_yaml = key_map_to_yaml subcommands in
79172 let key = Key.key_to_string key in
···81174 | key, Command { command } ->
82175 let key = Key.key_to_string key in
83176 key, string command
177177+;;
841788585-and key_map_to_yaml (key_map : key_map) : Yaml.value =
8686- obj (key_map |> Key_Map.to_seq |> Seq.map key_map_item_to_yaml |> List.of_seq)
179179+let remap_key_map_item_to_yaml _key_map_to_yaml key_map_item =
180180+ match key_map_item with
181181+ | key, { remap } ->
182182+ let key = Key.key_to_string key in
183183+ key, obj [ "remap", string (Nottui_remap.to_string remap) ]
87184;;
881858989-let key_map_update_t_to_yaml (key_map : key_map_update_t) : Yaml.value =
9090- key_map_to_yaml key_map
9191-;;
186186+module Main_Key_Map = MakeKeyMap (struct
187187+ type t = key_map_item [@@deriving show]
188188+189189+ let of_yaml = key_map_item_of_yaml
190190+ let to_yaml = key_map_item_to_yaml
191191+ end)
192192+193193+module Remap_Key_Map = MakeKeyMap (struct
194194+ type t = remap [@@deriving show]
195195+196196+ let of_yaml = remap_key_map_item_of_yaml
197197+ let to_yaml = remap_key_map_item_to_yaml
198198+ end)
199199+922009393-let key_map_update_t_of_yaml (yaml : Yaml.value) = key_map_of_yaml yaml
9420195202(* let rec key_map_merge (key_map1 : key_map) (key_map2 : key_map) : key_map =
96203 let merged = Key_Map.create (Key_Map.length key_map1 + Key_Map.length key_map2) in
···114221 merged
115222;; *)
116223117117-(**Merge two key maps, checking for duplicate keys*)
118118-let key_map_apply_update override og =
119119- Key_Map.merge
120120- (fun k v1 v2 ->
121121- match v1, v2 with
122122- | Some og, Some override ->
123123- Some override
124124- | Some v, None | None, Some v ->
125125- Some v
126126- | None, None ->
127127- None)
128128- og
129129- override
130130-;;
224224+131225132226let cmd key id =
133227 let key = Key.key_of_string_exn key in
···139233 key, Sub_menu { title; subcommands = sub |> List.to_seq |> Key_Map.of_seq }
140234;;
141235236236+let remap key remap =
237237+ let key = Key.key_of_string_exn key in
238238+ key, { remap = Nottui_remap.of_string_exn remap }
239239+;;
240240+142241let k_map list = list |> List.to_seq |> Key_Map.of_seq
143242144243type key_config = {
145145- global : key_map [@updater]
146146- ; graph : key_map [@updater]
147147- ; file : key_map [@updater]
244244+ global : Main_Key_Map.t [@updater]
245245+ ; graph : Main_Key_Map.t [@updater]
246246+ ; file : Main_Key_Map.t [@updater]
247247+ ; remap : Remap_Key_Map.t [@updater]
148248}
149249[@@deriving yaml, record_updater ~derive:yaml]
150250···152252let default : key_config =
153253 let open Key in
154254 {
155155- global =
156156- k_map
157157- [ cmd "y" "confirm"; cmd "n" "decline"; cmd "h" "left_alt"; cmd "l" "right_alt" ]
255255+ remap =
256256+ k_map [ remap "h" "left"; remap "j" "down"; remap "k" "up"; remap "l" "right" ]
257257+ ; global = k_map [ cmd "y" "confirm"; cmd "n" "decline" ]
158258 ; graph =
159259 k_map
160260 [
···270370271371let%expect_test "parse yaml" =
272372 let yaml = Yaml.of_string_exn sample in
273273- let key_map = key_map_of_yaml_exn yaml in
274274- print_endline (Yaml.to_string_exn (key_map_to_yaml key_map));
373373+ let key_map = Main_Key_Map.of_yaml_exn yaml in
374374+ print_endline (Yaml.to_string_exn (Main_Key_Map.to_yaml key_map));
275375 [%expect
276376 {|
277377 c:
···292392293393let%expect_test "merge" =
294394 let yaml = Yaml.of_string_exn sample in
295295- let key_map = key_map_of_yaml_exn yaml in
395395+ let key_map = Main_Key_Map.of_yaml_exn yaml in
296396 let overrides =
297397 k_map [ cmd "c" "override"; sub "s" "Squash" [ cmd "c" "override2" ] ]
298398 in
299299- let merged = key_map_apply_update overrides key_map in
300300- print_endline (Yaml.to_string_exn (key_map_to_yaml merged));
399399+ let merged = Main_Key_Map.t_apply_update overrides key_map in
400400+ print_endline (Yaml.to_string_exn (Main_Key_Map.to_yaml merged));
301401 [%expect
302402 {|
303403 c: override