···3434 "squash"
3535 ; "-u"
3636 ; "--from"
3737- ; get_selected_rev()
3737+ ; get_selected_rev ()
3838 ; "--into"
3939 ; rev
4040 ; Lwd.peek selected_file
···7373 (**Get the status for the currently selected file*)
7474 let file_status () =
7575 let$ selected = Lwd.get selected_file
7676- and$ rev = Vars.get_selected_rev_lwd()in
7676+ and$ rev = Vars.get_selected_rev_lwd () in
7777 if selected != "" then jj_no_log [ "diff"; "-r"; rev; selected ] else ""
7878 ;;
7979end
+1-1
jj_tui/bin/global_funcs.ml
···4646 This should be called after any command that performs a change *)
4747let update_views ?(cause_snapshot = false) () =
4848 safe_jj (fun () ->
4949- let rev = Vars.get_selected_rev() in
4949+ let rev = Vars.get_selected_rev () in
5050 Eio.Switch.run @@ fun sw ->
5151 let log_res =
5252 jj_no_log ~snapshot:cause_snapshot [ "show"; "-s"; "--color-words"; "-r"; rev ]
+23-13
jj_tui/bin/jj_commands.ml
···99 (** Regular jj command *)
1010 type command_variant =
1111 | Cmd of cmd_args (** Regular jj command *)
1212- | Cmd_r of cmd_args (** Regular jj command that should operate on the selected revison *)
1212+ | Cmd_r of cmd_args
1313+ (** Regular jj command that should operate on the selected revison *)
1314 | Dynamic of (unit -> command_variant)
1414- | Dynamic_r of (string-> command_variant)
1515+ | Dynamic_r of (string -> command_variant)
1516 (** Wraps a command so that the content will be regenerated each time it's run. Usefull if you wish to read some peice of ui state *)
1617 | Cmd_I of cmd_args
1718 (** Command that will open interactively. Used for diff editing to hand control over to the jj process *)
···4748 open! Jj_tui.Util
4849 module Wd = Jj_tui.Widgets
49505050-5151 exception Handled
52525353 let render_command_line ~indent_level key desc =
···6868 | {
6969 key
7070 ; description
7171- ; cmd = Cmd _ | Cmd_I _ | Prompt _ | Prompt_I _ | Fun _ | PromptThen _ | Dynamic _ |Cmd_r _|Prompt_r _|Dynamic_r _
7171+ ; cmd =
7272+ ( Cmd _
7373+ | Cmd_I _
7474+ | Prompt _
7575+ | Prompt_I _
7676+ | Fun _
7777+ | PromptThen _
7878+ | Dynamic _
7979+ | Cmd_r _
8080+ | Prompt_r _
8181+ | Dynamic_r _ )
7282 } ->
7383 [ render_command_line ~indent_level [| key |> Uchar.of_char |] description ]
7484 | { key; description; cmd = SubCmd subs } ->
···7686 :: render_commands ~indent_level:(indent_level + 1) subs
7787 ;;
78887979-8080-8189 let commands_list_ui commands =
8290 let move_command =
8391 render_command_line
···132140 raise Handled
133141 | Cmd_r args ->
134142 ui_state.show_popup $= None;
135135- noOut (args@["-r";Vars.get_selected_rev()]);
143143+ noOut (args @ [ "-r"; Vars.get_selected_rev () ]);
136144 raise Handled
137145 | Prompt (str, args) ->
138146 ui_state.show_popup $= None;
···140148 raise Handled
141149 | Prompt_r (str, args) ->
142150 ui_state.show_popup $= None;
143143- prompt str (`Cmd (args@["-r";Vars.get_selected_rev()]));
151151+ prompt str (`Cmd (args @ [ "-r"; Vars.get_selected_rev () ]));
144152 raise Handled
145153 | PromptThen (label, next) ->
146154 ui_state.show_popup $= None;
···163171 | Dynamic f ->
164172 f () |> handleCommand description
165173 | Dynamic_r f ->
166166- f (Vars.get_selected_rev()) |> handleCommand description
174174+ f (Vars.get_selected_rev ()) |> handleCommand description
167175168176 (** Try mapching the command mapping to the provided key and run the command if it matches *)
169177 and command_input ~is_sub keymap key =
···177185 | Handled ->
178186 if is_sub then ui_state.input $= `Normal;
179187 `Handled
180180- | JJError (cmd,error) ->
188188+ | JJError (cmd, error) ->
181189 handle_jj_error cmd error;
182190 `Unhandled
183191···204212 open Intern (Vars)
205213 module Wd = Jj_tui.Widgets
206214 include Shared
207207-(** A handy command_list that just has this help command for areas that don't have any commands to still show help*)
208208- let rec default_list=
215215+216216+ (** A handy command_list that just has this help command for areas that don't have any commands to still show help*)
217217+ let rec default_list =
209218 [
210219 {
211220 key = 'h'
···216225 ui_state.show_popup $= Some (commands_list_ui default_list, "Help");
217226 ui_state.input $= `Mode (fun _ -> `Unhandled))
218227 }
219219- ]
228228+ ]
229229+ ;;
220230221231 (**Generate a UI object with all the commands nicely formatted and layed out. Useful for help text*)
222232 let commands_list_ui = commands_list_ui
+22-12
jj_tui/bin/jj_process.ml
···6060 Mutex.lock access_lock;
6161 true)
6262 else false
6363- in
6363+ in
6464 let res =
6565 cmdArgs
6666 "jj"
···7575 res
7676 ;;
77777878- exception JJError of string*string
7878+ exception JJError of string * string
79798080 (** Run a jj command without outputting to the command_log.
8181 @param ?snapshot=true
8282 When true snapshots the state when running the command and also aquires a lock before running it. Set to false for commands you wish to run concurrently. like those for generating content in the UI
8383 @param ?color=true When true output will have terminal escape codes for color *)
8484 let jj_no_log ?(snapshot = true) ?(color = true) args =
8585-8685 match jj_no_log_errorable ~snapshot ~color args with
8786 | Ok a ->
8887 a
8988 | Error (`BadExit (code, str)) ->
9090- raise (JJError( "jj"::args|>String.concat " " ,Printf.sprintf "Exited with code %i; Message:\n%s" code str))
8989+ raise
9090+ (JJError
9191+ ( "jj" :: args |> String.concat " "
9292+ , Printf.sprintf "Exited with code %i; Message:\n%s" code str ))
9193 | Error (`EioErr a) ->
9292- raise (JJError ("jj"::args|>String.concat " ",Printf.sprintf
9393- "Error running jj process:\n%a"
9494- (fun _ -> Base.Error.to_string_hum)
9595- a))
9494+ raise
9595+ (JJError
9696+ ( "jj" :: args |> String.concat " "
9797+ , Printf.sprintf
9898+ "Error running jj process:\n%a"
9999+ (fun _ -> Base.Error.to_string_hum)
100100+ a ))
96101 ;;
9710298103 let jj args =
···115120 ; "-T"
116121 ; {|"::"++current_working_copy++"::\n"++description++"\n::end::\n"|}
117122 ]
118118- |>String.trim
123123+ |> String.trim
124124+ in
125125+ let current, prev =
126126+ output |> Jj_tui.OutputParsing.parse_descriptions |> Result.get_ok
119127 in
120120- let current, prev = output |>Jj_tui.OutputParsing.parse_descriptions|>Result.get_ok in
121128 current |> String.concat "", prev |> String.concat ""
122129 ;;
130130+123131 open Vars
124132 open Nottui
125133 open Lwd_infix
134134+126135 (*handle exception from jj*)
127136 let handle_jj_error cmd error =
128137 ui_state.show_prompt $= None;
···133142 |> Ui.atom
134143 |> Ui.resize ~sw:1 ~sh:1
135144 |> Lwd.pure
136136- , Printf.sprintf"An error occured running %s" cmd );
145145+ , Printf.sprintf "An error occured running %s" cmd );
137146 ui_state.input $= `Mode (fun _ -> `Unhandled)
138147 ;;
148148+139149 (*catch any exceptions from jj*)
140140- let safe_jj f = try f () with JJError (cmd,error) -> handle_jj_error cmd error
150150+ let safe_jj f = try f () with JJError (cmd, error) -> handle_jj_error cmd error
141151end
+5-4
jj_tui/bin/jj_ui.ml
···7979 ~pad:Wd.neutral_grav
8080 |> inputs
8181 ;;
8282+8283 (** The primary view for the UI with the file_view graph_view and summary*)
8384 let main_view ~sw =
8485 let file_focus = Focus.make () in
···135136136137 (** Shows the op log *)
137138 let log_view () =
138138- jj_no_log [ "op"; "log"; "--limit";"200" ]
139139+ jj_no_log [ "op"; "log"; "--limit"; "200" ]
139140 |> AnsiReverse.colored_string
140141 |> Ui.atom
141141-|>Ui.resize ~mh:1000 ~mw:10000
142142+ |> Ui.resize ~mh:1000 ~mw:10000
142143 |> Lwd.pure
143143- |>Wd.scroll_area
144144+ |> Wd.scroll_area
144145 |> Wd.border_box ~pad_w:1 ~pad_h:0
145145- |>inputs
146146+ |> inputs
146147 ;;
147148148149 let mainUi ~sw env =
+19-17
jj_tui/bin/jj_widgets.ml
···145145 (* else () *))
146146 ;;
147147148148-(** Function to tag duplicated items in a list *)
149149-let tag_duplicates lst =
150150- (* Create a frequency map to count occurrences of each element *)
151151- let freq_map =
152152- List.fold_left (fun acc {change_id;_} ->
153153- let count = try List.assoc change_id acc with Not_found -> 0 in
154154- (change_id, count + 1) :: List.remove_assoc change_id acc
155155- ) [] lst
156156- in
157157- (* Tag each item in the list based on the frequency map *)
158158- List.map (fun ({change_id;_} as x) ->
159159- if List.assoc change_id freq_map > 1 then Duplicate x else Unique x
160160- ) lst
148148+ (** Function to tag duplicated items in a list *)
149149+ let tag_duplicates lst =
150150+ (* Create a frequency map to count occurrences of each element *)
151151+ let freq_map =
152152+ List.fold_left
153153+ (fun acc { change_id; _ } ->
154154+ let count = try List.assoc change_id acc with Not_found -> 0 in
155155+ (change_id, count + 1) :: List.remove_assoc change_id acc)
156156+ []
157157+ lst
158158+ in
159159+ (* Tag each item in the list based on the frequency map *)
160160+ List.map
161161+ (fun ({ change_id; _ } as x) ->
162162+ if List.assoc change_id freq_map > 1 then Duplicate x else Unique x)
163163+ lst
164164+ ;;
161165162166 (**Returns a list of revs with both the change_id and commit_id*)
163167 let get_revs () =
164164- jj_no_log
165165- ~color:false
166166- [ "log"; "-T"; {|"|"++change_id++"|"++commit_id++"\n"|} ]
168168+ jj_no_log ~color:false [ "log"; "-T"; {|"|"++change_id++"|"++commit_id++"\n"|} ]
167169 |> String.split_on_char '\n'
168170 |> List.filter_map (fun x ->
169171 let items = x |> String.split_on_char '|' in
···172174 Some { change_id; commit_id }
173175 | _ ->
174176 None)
175175- |>tag_duplicates
177177+ |> tag_duplicates
176178 |> Array.of_list
177179 ;;
178180
+9-5
jj_tui/lib/ansiReverse.ml
···140140;;
141141142142let string_to_image ?(extra_attr = A.empty) str =
143143- let str=
143143+ let str =
144144 (* replace any carrriage returns becasue notty doesn't know what to do with them*)
145145- Base.String.Search_pattern.replace_all (Base.String.Search_pattern.create "\r\n") ~in_:str ~with_:"\n"
146146- |>
147147- Base.String.Search_pattern.replace_all (Base.String.Search_pattern.create "\r") ~with_:"\n"
148148- in
145145+ Base.String.Search_pattern.replace_all
146146+ (Base.String.Search_pattern.create "\r\n")
147147+ ~in_:str
148148+ ~with_:"\n"
149149+ |> Base.String.Search_pattern.replace_all
150150+ (Base.String.Search_pattern.create "\r")
151151+ ~with_:"\n"
152152+ in
149153 match parse_ansi_escape_codes str with
150154 | Error a ->
151155 Printf.printf "restut: %s" a;
-263
jj_tui/lib/box_widget.ml
···11-open Notty
22-open Nottui
33-open Lwd_infix
44-open! Util
55-open! Widgets_citty
66-module W = Nottui_widgets
77-88-(** This is for shifting something away from the edge it is pushed against *)
99-let pad_edge x_pad y_pad grav ui =
1010- let y_pad =
1111- match grav |> Gravity.v with
1212- | `Negative ->
1313- -y_pad
1414- | `Neutral ->
1515- 0
1616- | `Positive ->
1717- y_pad
1818- in
1919- match grav |> Gravity.h with
2020- | `Negative ->
2121- ui |> Ui.shift_area (-x_pad) y_pad
2222- | `Neutral ->
2323- ui
2424- | `Positive ->
2525- ui |> Ui.shift_area x_pad y_pad
2626-;;
2727-2828-let neutral_grav = Gravity.make ~h:`Neutral ~v:`Neutral
2929-3030-module Intern = struct
3131- let make_even num = num + (num mod 2 * 1)
3232- let upPipe = Uchar.of_int 0x2503
3333- let tlPipe = Uchar.of_int 0x250f
3434- let trPipe = Uchar.of_int 0x2513
3535- let blPipe = Uchar.of_int 0x2517
3636- let brPipe = Uchar.of_int 0x251b
3737- let sidePipe = Uchar.of_int 0x2501
3838-3939- (** makes a line of chars with a specific start , midlle and end*)
4040- let make_with_ends start mid ending width =
4141- Array.init width (fun i ->
4242- let lastIdx = width - 1 in
4343- match i with 0 -> start | a when a == lastIdx -> ending | _ -> mid)
4444- |> I.uchars A.empty
4545- ;;
4646-4747- let make_top width = make_with_ends tlPipe sidePipe trPipe width
4848- let make_bot width = make_with_ends blPipe sidePipe brPipe width
4949- let grid xxs = xxs |> List.map I.hcat |> I.vcat
5050-5151- (** Truncate a string to a given length, adding an ellipsis if truncated. *)
5252- let truncate_string len str =
5353- if String.length str > len
5454- then if len <= 3 then "" else String.sub str 0 (len - 3) ^ "..."
5555- else str
5656- ;;
5757-5858- (** top border*)
5959- let outline_top attr w label =
6060- let chr x = I.uchar attr (Uchar.of_int x) 1 1 in
6161- let hbar = I.uchar attr (Uchar.of_int 0x2500) w 1
6262- and label = if label |> I.width > w - 2 then I.empty else label |> I.hpad 2 0
6363- and a, b = chr 0x256d, chr 0x256e in
6464- I.zcat [ label; I.hcat [ a; hbar; b ]; label ]
6565- ;;
6666-6767- (** bottom border*)
6868- let outline_bot attr w label =
6969- let chr x = I.uchar attr (Uchar.of_int x) 1 1 in
7070- let hbar = I.uchar attr (Uchar.of_int 0x2500) w 1 in
7171- let label =
7272- if label |> I.width > w - 2
7373- then I.empty
7474- else label |> I.hpad (w - (label |> I.width |> ( + ) 1)) 0
7575- in
7676- let c, d = chr 0x256f, chr 0x2570 in
7777- I.zcat [ label; I.hcat [ d; hbar; c ] ]
7878- ;;
7979-8080- let make_label max_width label_str =
8181- I.strf " %s " (truncate_string (max_width - 2) label_str)
8282- ;;
8383-8484-end
8585-8686-open Intern
8787- (** Internal function for rendering a border box with known dimensions and padding.*)
8888- let border_box_intern
8989- ?(border_attr = A.empty)
9090- ?(label_top = I.empty)
9191- ?(label_bottom = I.empty)
9292- w
9393- h
9494- pad
9595- pad_w
9696- pad_h
9797- input
9898- =
9999- (*can't go below 1 internal width or things get weird*)
100100- let h = if pad_h < 1 then Int.max h 1 else h in
101101- let w = if pad_w < 1 then Int.max w 1 else w in
102102- (* this is a weird quirk, but we have to be careful of runaway size expansion.
103103- If we increase the width of the space by making the vbar longer than the input ui element it will be able to expand to fill that space.
104104- That will then increase the vbar and increase the height etc etc untill the max height is reached*)
105105- let vbar =
106106- I.uchar border_attr (Uchar.of_int 0x2502) 1 (h + (pad_h * 2))
107107- |> Ui.atom
108108- |> Ui.resize ~h:0
109109- in
110110- Ui.vcat
111111- [
112112- outline_top border_attr w label_top |> Ui.atom |> Ui.resize ~w:0
113113- ; Ui.hcat
114114- [
115115- vbar
116116- ; I.void pad_w 1 |> Ui.atom
117117- ; Ui.vcat
118118- [
119119- I.void 1 pad_h |> Ui.atom
120120- ; input |> Ui.resize ~pad
121121- ; I.void 1 pad_h |> Ui.atom
122122- ]
123123- ; I.void pad_w 1 |> Ui.atom
124124- ; vbar
125125- ]
126126- ; outline_bot border_attr w label_bottom |> Ui.atom |> Ui.resize ~w:0
127127- ]
128128- ;;
129129-130130-let border_box_custom_border
131131- ?(scaling = `Static)
132132- ?(pad = neutral_grav)
133133- ?(pad_w = 2)
134134- ?(pad_h = 1)
135135- ?label_top
136136- ?label_bottom
137137- get_border
138138- input
139139- =
140140- let max_width, min_width, sw =
141141- match scaling with
142142- | `Static ->
143143- None, None, None
144144- (* This allows the input to expand to fill space*)
145145- | `Expand sw ->
146146- Some 1000, None, Some sw
147147- in
148148- let size = Lwd.var (0, 0) in
149149- let layout_width = Lwd.var 0 in
150150- let input =
151151- let$ input = input |>$ Ui.resize ?sw ?mw:max_width ?sh:sw ?mh:max_width in
152152- (*We need this later to determine the max with*)
153153- layout_width $= (input |> Ui.layout_width);
154154- input
155155- (*This lets us tell the input to be a flexible size*)
156156- |> Ui.size_sensor (fun ~w ~h -> if Lwd.peek size <> (w, h) then Lwd.set size (w, h))
157157- in
158158- (*This is original width and height of the input before padding or anything *)
159159- let$ o_w, o_h = Lwd.get size
160160- and$ input = input
161161- and$ border_attr = get_border in
162162- let w, h = o_w + (pad_w * 2), o_h in
163163- let h = h in
164164- let bbox =
165165- border_box_intern
166166- ~border_attr
167167- ?label_top:(label_top |> Option.map (make_label (w - 2)))
168168- ?label_bottom:(label_bottom |> Option.map (make_label (w - 2)))
169169- (* ~label_bottom:(if has_focus then I.strf "focused" else I.strf "unfocused") *)
170170- w
171171- h
172172- pad
173173- pad_w
174174- pad_h
175175- input
176176- in
177177- (*If we want the input to be shrinkable we make it expandable, set it's width to something small and then set a max width for the whole box*)
178178- bbox
179179-;;
180180-181181-(** Creates a bordered box around the given [input] widget. This box will change colour when focused
182182-183183- @param scaling
184184- Controls how the input widget is sized within the border box. Can be:
185185- - [`Static] - The input widget is not resized.
186186- - [`Expand sw] - The input widget is allowed to expand to fill the available space, with a stretch width [sw].
187187- - [`Shrinkable (min_width, sw)] - The input widget is allowed to shrink to a minimum width of [min_width], and expand with a stretch width [sw].
188188- @param pad The padding around the input widget within the border box.
189189- @param pad_w The horizontal padding around the input widget.
190190- @param pad_h The vertical padding around the input widget.
191191- @param label An optional label to display within the border box.
192192- @param input The input widget to be bordered.
193193- @param border_attr Style for the border, defaults to [A.empty].
194194- @param focus Focus handle for the box .
195195- @param focus_attr Style for the border when focused, defaults to [A.fg A.blue].
196196- @param on_key Callback called when a key is pressed while the box is focused. Useful for performing actions when the box is selected .
197197- *)
198198-let border_box_focusable
199199- ?scaling
200200- ?pad
201201- ?pad_w
202202- ?pad_h
203203- ?label_top
204204- ?label_bottom
205205- ?(border_attr = A.empty)
206206- ?(focus_attr = A.fg A.blue)
207207- ?(focus = Focus.make ())
208208- ?(on_key=(fun _->`Unhandled))
209209- input
210210- =
211211- let attr = Lwd.var border_attr in
212212- let input =
213213- input
214214- |> Lwd.map2 (focus |> Focus.status) ~f:(fun focus ui ->
215215- ui |> Ui.keyboard_area ~focus on_key)
216216- in
217217- border_box_custom_border
218218- ?scaling
219219- ?pad
220220- ?pad_w
221221- ?pad_h
222222- ?label_top
223223- ?label_bottom
224224- (let$ focus = Focus.status focus in
225225- if Focus.has_focus focus then focus_attr else border_attr)
226226- input
227227-;;
228228-229229-(** Creates a bordered box around the given [input] widget.
230230-231231- @param scaling
232232- Controls how the input widget is sized within the border box. Can be:
233233- - [`Static] - The input widget is not resized.
234234- - [`Expand sw] - The input widget is allowed to expand to fill the available space, with a stretch width [sw].
235235- - [`Shrinkable (min_width, sw)] - The input widget is allowed to shrink to a minimum width of [min_width], and expand with a stretch width [sw].
236236- @param pad The padding around the input widget within the border box.
237237- @param pad_w The horizontal padding around the input widget.
238238- @param pad_h The vertical padding around the input widget.
239239- @param label An optional label to display within the border box.
240240- @param input The input widget to be bordered.
241241- @param border_attr Style for the border, defaults to [A.empty]. *)
242242-let border_box
243243- ?scaling
244244- ?pad
245245- ?pad_w
246246- ?pad_h
247247- ?label_top
248248- ?label_bottom
249249- ?(border_attr = A.empty)
250250- input
251251- =
252252- border_box_custom_border
253253- ?scaling
254254- ?pad
255255- ?pad_w
256256- ?pad_h
257257- ?label_top
258258- ?label_bottom
259259- (border_attr |> Lwd.pure)
260260- input
261261-;;
262262-263263-;;
+48-47
jj_tui/lib/widgets/border_box.ml
···8080 let make_label max_width label_str =
8181 I.strf " %s " (truncate_string (max_width - 2) label_str)
8282 ;;
8383-8483end
85848685open Intern
8787- (** Internal function for rendering a border box with known dimensions and padding.*)
8888- let border_box_intern
8989- ?(border_attr = A.empty)
9090- ?(label_top = I.empty)
9191- ?(label_bottom = I.empty)
9292- w
9393- h
9494- pad
9595- pad_w
9696- pad_h
9797- input
9898- =
9999- (*can't go below 1 internal width or things get weird*)
100100- let h = if pad_h < 1 then Int.max h 1 else h in
101101- let w = if pad_w < 1 then Int.max w 1 else w in
102102- (* this is a weird quirk, but we have to be careful of runaway size expansion.
103103- If we increase the width of the space by making the vbar longer than the input ui element it will be able to expand to fill that space.
104104- That will then increase the vbar and increase the height etc etc untill the max height is reached*)
105105- let vbar =
106106- I.uchar border_attr (Uchar.of_int 0x2502) 1 (h + (pad_h * 2))
107107- |> Ui.atom
108108- |> Ui.resize ~h:0
109109- in
110110- Ui.vcat
111111- [
112112- outline_top border_attr w label_top |> Ui.atom |> Ui.resize ~w:0
113113- ; Ui.hcat
114114- [
115115- vbar
116116- ; I.void pad_w 1 |> Ui.atom
117117- ; Ui.vcat
118118- [
119119- I.void 1 pad_h |> Ui.atom
120120- ; input |> Ui.resize ~pad
121121- ; I.void 1 pad_h |> Ui.atom
122122- ]
123123- ; I.void pad_w 1 |> Ui.atom
124124- ; vbar
125125- ]
126126- ; outline_bot border_attr w label_bottom |> Ui.atom |> Ui.resize ~w:0
127127- ]
128128- ;;
8686+8787+(** Internal function for rendering a border box with known dimensions and padding.*)
8888+let border_box_intern
8989+ ?(border_attr = A.empty)
9090+ ?(label_top = I.empty)
9191+ ?(label_bottom = I.empty)
9292+ w
9393+ h
9494+ pad
9595+ pad_w
9696+ pad_h
9797+ input
9898+ =
9999+ (*can't go below 1 internal width or things get weird*)
100100+ let h = if pad_h < 1 then Int.max h 1 else h in
101101+ let w = if pad_w < 1 then Int.max w 1 else w in
102102+ (* this is a weird quirk, but we have to be careful of runaway size expansion.
103103+ If we increase the width of the space by making the vbar longer than the input ui element it will be able to expand to fill that space.
104104+ That will then increase the vbar and increase the height etc etc untill the max height is reached*)
105105+ let vbar =
106106+ I.uchar border_attr (Uchar.of_int 0x2502) 1 (h + (pad_h * 2))
107107+ |> Ui.atom
108108+ |> Ui.resize ~h:0
109109+ in
110110+ Ui.vcat
111111+ [
112112+ outline_top border_attr w label_top |> Ui.atom |> Ui.resize ~w:0
113113+ ; Ui.hcat
114114+ [
115115+ vbar
116116+ ; I.void pad_w 1 |> Ui.atom
117117+ ; Ui.vcat
118118+ [
119119+ I.void 1 pad_h |> Ui.atom
120120+ ; input |> Ui.resize ~pad
121121+ ; I.void 1 pad_h |> Ui.atom
122122+ ]
123123+ ; I.void pad_w 1 |> Ui.atom
124124+ ; vbar
125125+ ]
126126+ ; outline_bot border_attr w label_bottom |> Ui.atom |> Ui.resize ~w:0
127127+ ]
128128+;;
129129130130let border_box_custom_border
131131 ?(scaling = `Static)
···192192 @param input The input widget to be bordered.
193193 @param border_attr Style for the border, defaults to [A.empty].
194194 @param focus Focus handle for the box .
195195- @param focus_attr Style for the border when focused, defaults to [A.fg A.blue]. *)
195195+ @param focus_attr Style for the border when focused, defaults to [A.fg A.blue].
196196+ @param on_key
197197+ Callback called when a key is pressed while the box is focused. Useful for performing actions when the box is selected . *)
196198let border_box_focusable
197199 ?scaling
198200 ?pad
···203205 ?(border_attr = A.empty)
204206 ?(focus_attr = A.fg A.blue)
205207 ?(focus = Focus.make ())
208208+ ?(on_key = fun _ -> `Unhandled)
206209 input
207210 =
208211 let attr = Lwd.var border_attr in
209212 let input =
210213 input
211214 |> Lwd.map2 (focus |> Focus.status) ~f:(fun focus ui ->
212212- ui |> Ui.keyboard_area ~focus (fun _ -> `Unhandled))
215215+ ui |> Ui.keyboard_area ~focus on_key)
213216 in
214217 border_box_custom_border
215218 ?scaling
···256259 (border_attr |> Lwd.pure)
257260 input
258261;;
259259-260260-;;
+14-14
jj_tui/lib/widgets/widgets.ml
···33open Lwd_infix
44open! Util
55open! Widgets_citty
66-include Box_widget
66+include Border_box
77include Shared
88include Selection_list
99module Wip = Wip
···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)
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;;