···7575 , fun str ->
7676 let curr_msg, prev_msg = get_messages () in
7777 let new_msg = prev_msg ^ curr_msg in
7878- Dynamic_r(fun rev->Cmd [ "squash"; "--quiet"; "-m"; new_msg;"--from";rev; "--into"; str ] ))
7878+ Dynamic_r
7979+ (fun rev ->
8080+ Cmd
8181+ [
8282+ "squash"
8383+ ; "--quiet"
8484+ ; "-m"
8585+ ; new_msg
8686+ ; "--from"
8787+ ; rev
8888+ ; "--into"
8989+ ; str
9090+ ]) )
7991 }
8092 ; {
8193 key = 'u'
···246258 |> Array.map (fun x ->
247259 match x with
248260 | `Selectable x ->
249249- let ui is_focused =
250250- (*hightlight blue when selection is true*)
251251- let prefix =
252252- if is_focused then I.char A.(bg A.blue) '>' 1 2 else I.char A.empty ' ' 1 2
253253- in
254254- I.hcat
255255- [
256256- prefix
257257- ; x ^ "\n"
258258- (* TODO This won't work if we are on a branch, because that puts the @ further out*)
259259- |> Jj_tui.AnsiReverse.colored_string
260260- ]
261261- |> Ui.atom
261261+ let ui =
262262+ Wd.selectable_item
263263+ (x ^ "\n"
264264+ (* TODO This won't work if we are on a branch, because that puts the @ further out*)
265265+ |> Jj_tui.AnsiReverse.colored_string
266266+ |> Ui.atom)
262267 in
263268 let data = Wd.{ ui; data = rev_ids.(!selectable_idx) } in
264269 selectable_idx := !selectable_idx + 1;
···2020let selectable_item ui is_focused =
2121 let height = Ui.layout_height ui in
2222 let prefix =
2323- if is_focused then I.char A.(bg A.blue) '>' 1 height else I.char A.empty ' ' 1 height
2323+ if is_focused
2424+ then I.char A.(st bold++ bg (blue)) '>' 1 height
2525+ else I.char A.empty ' ' 1 height
2426 in
2527 Ui.hcat [ prefix |> Ui.atom; ui ]
2628;;
2929+27302831(** Selection list that allows for custom handling of keyboard events.
2932 Scrolls when the selection reaches the lower third
···124127 (*
125128 The rough overview is:
126129 1. Make a lookup list that has the indexes of all the selectable items within the overall list, we will be selecting from those
127127- 2. Render the items, making sure to tell the selected one to render as selected.
128128- 3. Calculate how much we should scroll by.
130130+ 2. Render the items, making sure to tell the selected one to render as selected.
131131+ 3. Calculate how much we should scroll by.
129132 4. offset by the scroll amount, apply size sensors and output final ui
130133 *)
131134 let selected_var = Lwd.var 0 in
+42
jj_tui/lib/widgets/widgets.ml
···325325let is_focused ~focus f ui =
326326 Lwd.map2 ui (focus |> Focus.status) ~f:(fun ui focus -> f ui (focus |> Focus.has_focus))
327327;;
328328+329329+(** Gets an int that a char represents*)
330330+let char_to_int c =
331331+ if c >= '0' && c <= '9' then Some (int_of_char c - int_of_char '0') else None
332332+;;
333333+334334+(** Tab view, where exactly one element of [l] is shown at a time. *)
335335+let mouse_tabs (tabs : (string * (unit -> Ui.t Lwd.t)) list) : Ui.t Lwd.t =
336336+ match tabs with
337337+ | [] ->
338338+ Lwd.return Ui.empty
339339+ | _ ->
340340+ let cur = Lwd.var 0 in
341341+ let$* idx_sel = Lwd.get cur in
342342+ let _, f = List.nth tabs idx_sel in
343343+ let tab_bar =
344344+ tabs
345345+ |> List.mapi (fun i (s, _) ->
346346+ let attr = if i = idx_sel then A.(st underline) else A.empty in
347347+ let tab_annot = W.printf ~attr "%s [%d]" s (i + 1) in
348348+ tab_annot)
349349+ |> Base.List.intersperse ~sep:(W.string " | ")
350350+ |> Ui.hcat
351351+ |> Ui.resize ~sw:1 ~mw:10000
352352+ |> Lwd.pure
353353+ |> border_box ~pad_w:1 ~pad_h:0
354354+ in
355355+ W.vbox [ tab_bar; f () ]
356356+ |>$ Ui.keyboard_area (function
357357+ | `ASCII key, _ ->
358358+ key
359359+ |> char_to_int
360360+ |> Option.map (fun i ->
361361+ if i >= 1 && i <= List.length tabs
362362+ then (
363363+ cur $= i-1;
364364+ `Handled)
365365+ else `Unhandled)
366366+ |> Option.value ~default:`Unhandled
367367+ | _ ->
368368+ `Unhandled)
369369+;;