package inquire
An OCaml library to create beautiful interactive CLIs
Install
Dune Dependency
Authors
Maintainers
Sources
inquire-0.2.1.tbz
sha256=0b88d89e24d4cbc0560a7c8d8ec51388990e1b27f24685029997afa52a7c720f
sha512=8b62860a8d15e41528a404a6f1b9968c3d79755607b5ea319af2e3e45516e672a785361d278279910928db4054e1800e87bcee0210ff3eabfb330713b368c827
doc/src/inquire.lambda-term/lTerm_toplevel_impl.ml.html
Source file lTerm_toplevel_impl.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
open LTerm_geom open LTerm_key class t = LTerm_widget_base_impl.t (* About focus; widgets may specify an optional target widget in each direction. The focus specification is intepreted in two ways based on can_focus. can_focus=true If the currently focussed widget has a focus specification in the required direction that widget is jumped to. Otherwise a search is performed. can_focus=false Widgets with can_focus=false will never be the current focus, however, they can take part in search for a widget. When we search over such a widget, if it has an appropriate focus specification then we jump there. *) let get_focus x dir = let f = function None -> `none | Some(x) -> `set_focus(x) in match dir with | `left -> f x.left | `right -> f x.right | `up -> f x.up | `down -> f x.down let make_widget_matrix root dir = let { rows; cols } = LTerm_geom.size_of_rect root#allocation in let m = Array.make_matrix rows cols `none in let rec loop widget = let set rect widget = if widget <> `none then begin for r = rect.row1 to rect.row2 - 1 do for c = rect.col1 to rect.col2 - 1 do m.(r).(c) <- widget done done end in if widget#can_focus then begin set widget#allocation (`can_focus widget) end else begin set widget#allocation (get_focus widget#focus dir) end; List.iter loop widget#children in loop root; m let left coord = { coord with col = pred coord.col } let right coord = { coord with col = succ coord.col } let up coord = { coord with row = pred coord.row } let down coord = { coord with row = succ coord.row } let focus_to (dir,incr_dir) f root focused coord = let get_coord widget = let rect = widget#allocation in { col = (rect.col1 + rect.col2) / 2; row = (rect.row1 + rect.row2) / 2 } in match get_focus focused#focus dir with | `set_focus(widget) -> (* If the currently focused widget has a focus specification for the given direction jump directly to that widget *) Some(widget, get_coord widget) | `none -> (* Otherwise project a line in the appropriate direction until we hit a widget. *) let rect = root#allocation in let m = make_widget_matrix root dir in let rec loop coord = if coord.row < rect.row1 || coord.row >= rect.row2 || coord.col < rect.col1 || coord.col >= rect.col2 then None else match m.(coord.row).(coord.col) with | `none -> loop (incr_dir coord) | `can_focus widget when widget = focused -> loop (incr_dir coord) | `can_focus widget -> let rect = widget#allocation in Some (widget, f rect coord) | `set_focus widget -> (* note; this allows widget=focused, if specified *) Some (widget, get_coord widget) in loop coord let avg_col rect coord = { coord with col = (rect.col1 + rect.col2) / 2 } let avg_row rect coord = { coord with row = (rect.row1 + rect.row2) / 2 } let focus_left (* root focused coord *) = focus_to (`left,left) avg_col let focus_right (* root focused coord *) = focus_to (`right,right) avg_col let focus_up (* root focused coord *) = focus_to (`up,up) avg_row let focus_down (* root focused coord *) = focus_to (`down,down) avg_row class toplevel focused widget = object(self) inherit t "toplevel" as super val children = [widget] method! children = children method! draw ctx focused = widget#draw ctx focused val mutable coord = { row = 0; col = 0 } (* Coordinates of the cursor inside the screen. *) val mutable push_layer_handler = Lwt_react.E.never; val mutable pop_layer_handler = Lwt_react.E.never; method arm_layer_handlers (push_event : t Lwt_react.event) (push_handler : t -> unit) (pop_event : unit Lwt_react.event) (pop_handler : unit -> unit) = let open Lwt_react in push_layer_handler <- E.map push_handler push_event; pop_layer_handler <- E.map pop_handler pop_event method! set_allocation rect = super#set_allocation rect; widget#set_allocation rect; let rect = !focused#allocation in coord <- { row = (rect.row1 + rect.row2) / 2; col = (rect.col1 + rect.col2) / 2 } method move_focus_to = function | Some (widget, c) -> coord <- c; focused := widget; self#queue_draw | None -> () method private move_focus direction = self#move_focus_to @@ direction (self :> t) !focused coord method private process_arrows = function | LTerm_event.Key { control = false; meta = false; shift = false; code = Left } -> self#move_focus focus_left; true | LTerm_event.Key { control = false; meta = false; shift = false; code = Right } -> self#move_focus focus_right; true | LTerm_event.Key { control = false; meta = false; shift = false; code = Up } -> self#move_focus focus_up; true | LTerm_event.Key { control = false; meta = false; shift = false; code = Down } -> self#move_focus focus_down; true | _ -> false initializer widget#set_parent (Some (self :> t)); self#on_event self#process_arrows end
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>