Add initial support for horizontal filling

This commit is contained in:
Dmitrii Kovanikov 2024-04-07 12:54:08 +01:00
parent e7b216cdfb
commit 2d6a0083bf
5 changed files with 74 additions and 20 deletions

View File

@ -8,8 +8,10 @@ type chunk = {
let fmt_chunk { styles; string } = ANSITerminal.sprintf styles "%s" string
let padding_chunk width =
let padding = String.make width ' ' in
{ styles = []; string = padding }
if width <= 0 then { styles = []; string = "" }
else
let padding = String.make width ' ' in
{ styles = []; string = padding }
type t = {
chunks : chunk list;

View File

@ -15,3 +15,5 @@ let rec take n = function
| _ when n <= 0 -> []
| [] -> []
| x :: xs -> x :: take (n - 1) xs
let max_on f list = List.fold_left (fun acc x -> max acc (f x)) 0 list

View File

@ -32,25 +32,76 @@ let zip_lines (l : Line.t list) (r : Line.t list) =
else
let padding_chunk = Line.padding_chunk (max_len_l - left_len) in
let new_line =
Line.append hd_l (Line.append (Line.of_chunks [ padding_chunk ]) hd_r)
Line.append hd_l
(Line.append (Line.of_chunks [ padding_chunk ]) hd_r)
in
new_line :: zip tl_l tl_r
in
zip l r
type prerender_pass_info = {
has_fill : bool;
size_taken : int;
}
type prerender =
| Rendered of Line.t list
| Fill
let rec render_to_lines ~width = function
| Str (styles, string) -> [ Line.of_chunks [ { styles; string } ] ]
| Horizontal_fill -> [ Line.of_chunks [ Line.padding_chunk width ] ]
| Vertical rows -> List.concat_map (render_to_lines ~width) rows
| Horizontal cols -> (
match cols with
| [] -> []
(* TODO: This is potentially really slow; optimise *)
| hd :: tl ->
List.fold_left
(fun acc col -> zip_lines acc (render_to_lines ~width col))
(render_to_lines ~width hd) tl)
| Horizontal cols -> horizontal_to_lines ~width cols
and horizontal_to_lines ~width cols =
(* Step [prerender]. Check if there's Horizontal_fill, render everything else
and calculate rendered size. *)
let pass_info, prerendered =
List.fold_left
(fun (pass_info, prerendered) col ->
let new_pass_info, new_prerendered =
match col with
| Horizontal_fill ->
({ has_fill = true; size_taken = pass_info.size_taken }, Fill)
| other ->
(* WARNING: This will pass the total width to the left-most Horizontal_fill *)
let rendered = render_to_lines ~width other in
let max_line_width = List_extra.max_on Line.length rendered in
( {
has_fill = pass_info.has_fill;
size_taken = pass_info.size_taken + max_line_width;
},
Rendered rendered )
in
(* TODO: This is suboptimal *)
(new_pass_info, prerendered @ [ new_prerendered ]))
({ has_fill = false; size_taken = 0 }, [])
cols
in
(* Step [fill_size]. Calculate the size of remaining fill *)
let fill_width = width - pass_info.size_taken in
(* Step [fill]. Fill the first Horizontal_fill *)
let _, rendered =
List.fold_left
(fun (remaining_width, rendered) prerendered ->
match prerendered with
| Rendered lines -> (remaining_width, rendered @ [ lines ])
| Fill ->
( 0,
rendered
@ [ [ Line.(of_chunks [ padding_chunk remaining_width ]) ] ] ))
(fill_width, []) prerendered
in
(* Step [combine]. Combine the final columns of lines. *)
match rendered with
| [] -> []
(* TODO: This is potentially really slow; optimise *)
| hd :: tl -> List.fold_left zip_lines hd tl
let render ~width doc =
doc |> render_to_lines ~width |> List.map Line.fmt |> String_extra.unlines

View File

@ -8,9 +8,7 @@ let init ~repo ~root_dir_path : Model.initial_data =
| Fs.Dir (_, files) -> files
in
let height = Option.value (Terminal_size.get_rows ()) ~default:120 in
let width =
Option.value (Terminal_size.get_columns ()) ~default:140
in
let width = Option.value (Terminal_size.get_columns ()) ~default:140 in
{ repo; root_dir_path; files; width; height }
let app = Minttea.app ~init:Init.init ~update:Update.update ~view:View.view ()

View File

@ -3,9 +3,7 @@ let style_selected = ANSITerminal.[ Bold; green ]
let style_directory = ANSITerminal.[ Bold; magenta ]
let debug_section (model : Model.t) =
let debug_info =
Printf.sprintf "%dw x %dh" model.width model.height
in
let debug_info = Printf.sprintf "%dw x %dh" model.width model.height in
Pretty.str debug_info
let tabs_section cur_tab =
@ -28,9 +26,12 @@ let code_section (code_tab : Model.code_tab) =
Pretty.vertical [ current_path_doc; fs_doc ]
let tab_content_section (model : Model.t) =
match model.current_tab with
| Code -> code_section model.code_tab
| Issues | PullRequests -> Pretty.str ""
let tab_doc =
match model.current_tab with
| Code -> code_section model.code_tab
| Issues | PullRequests -> Pretty.str ""
in
Pretty.(horizontal [ tab_doc; horizontal_fill; str "This is test" ])
let to_doc (model : Model.t) =
let open Pretty in