-module(tobble@internal@render). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -define(FILEPATH, "src/tobble/internal/render.gleam"). -export([apply_horizontal_rules/2, apply_title_position/2, apply_hide_title/1, apply_column_width/2, to_yielder/3, apply_table_width/2, default_render_context/1, apply_line_type/2]). -export_type([context/0, horizontal_rule_position/0, scaled_column_widths/0, line_type/0, title_position/0, horizontal_rules/0, visibility/0, title_options/0, table_line/0]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. ?MODULEDOC(false). -opaque context() :: {context, list(integer()), visibility(), horizontal_rules(), title_options(), fun((table_line()) -> binary())}. -type horizontal_rule_position() :: top_rule_position | center_rule_position | bottom_rule_position. -type scaled_column_widths() :: {scaled_column_widths, list(integer()), integer()}. -type line_type() :: box_drawing_chars_line_type | box_drawing_chars_with_rounded_corners_line_type | a_s_c_i_i_line_type | blank_line_type. -type title_position() :: top_title_position | bottom_title_position. -type horizontal_rules() :: header_only_horizontal_rules | every_row_has_horizontal_rules | no_horizontal_rules. -type visibility() :: visible | hidden. -type title_options() :: {title_options, title_position(), visibility()}. -type table_line() :: horizontal_line | vertical_line | four_way_junction | start_junction | end_junction | top_junction | bottom_junction | top_start_corner_junction | top_end_corner_junction | bottom_start_corner_junction | bottom_end_corner_junction. -file("src/tobble/internal/render.gleam", 133). ?DOC(false). -spec apply_horizontal_rules(context(), horizontal_rules()) -> context(). apply_horizontal_rules(Context, Rules) -> _record = Context, {context, erlang:element(2, _record), erlang:element(3, _record), Rules, erlang:element(5, _record), erlang:element(6, _record)}. -file("src/tobble/internal/render.gleam", 140). ?DOC(false). -spec apply_title_position(context(), title_position()) -> context(). apply_title_position(Context, Position) -> _record = Context, {context, erlang:element(2, _record), erlang:element(3, _record), erlang:element(4, _record), {title_options, Position, visible}, erlang:element(6, _record)}. -file("src/tobble/internal/render.gleam", 151). ?DOC(false). -spec apply_hide_title(context()) -> context(). apply_hide_title(Context) -> _record = Context, {context, erlang:element(2, _record), erlang:element(3, _record), erlang:element(4, _record), begin _record@1 = erlang:element(5, Context), {title_options, erlang:element(2, _record@1), hidden} end, erlang:element(6, _record)}. -file("src/tobble/internal/render.gleam", 195). ?DOC(false). -spec apply_column_width(context(), integer()) -> context(). apply_column_width(Context, Desired_width) -> _record = Context, {context, gleam@list:map( erlang:element(2, Context), fun(_) -> gleam@int:max(1, Desired_width) end ), erlang:element(3, _record), erlang:element(4, _record), erlang:element(5, _record), erlang:element(6, _record)}. -file("src/tobble/internal/render.gleam", 252). ?DOC(false). -spec render_horizontal_rule(context(), horizontal_rule_position()) -> binary(). render_horizontal_rule(Context, Position) -> Start_junction = case Position of top_rule_position -> (erlang:element(6, Context))(top_start_corner_junction); center_rule_position -> (erlang:element(6, Context))(start_junction); bottom_rule_position -> (erlang:element(6, Context))(bottom_start_corner_junction) end, Middle_junction = case Position of top_rule_position -> (erlang:element(6, Context))(top_junction); center_rule_position -> (erlang:element(6, Context))(four_way_junction); bottom_rule_position -> (erlang:element(6, Context))(bottom_junction) end, End_junction = case Position of top_rule_position -> (erlang:element(6, Context))(top_end_corner_junction); center_rule_position -> (erlang:element(6, Context))(end_junction); bottom_rule_position -> (erlang:element(6, Context))(bottom_end_corner_junction) end, Horizontal = (erlang:element(6, Context))(horizontal_line), Rule = begin _pipe = erlang:element(2, Context), _pipe@3 = gleam@list:map(_pipe, fun(Width) -> _pipe@1 = Horizontal, _pipe@2 = gleam@string:repeat(_pipe@1, Width + 2), gleam_stdlib:identity(_pipe@2) end), _pipe@4 = gleam@string_tree:join(_pipe@3, Middle_junction), _pipe@5 = gleam@string_tree:prepend(_pipe@4, Start_junction), _pipe@6 = gleam@string_tree:append(_pipe@5, End_junction), unicode:characters_to_binary(_pipe@6) end, Rule. -file("src/tobble/internal/render.gleam", 214). ?DOC(false). -spec top_border_yielder(context()) -> gleam@yielder:yielder(binary()). top_border_yielder(Context) -> case erlang:element(3, Context) of hidden -> gleam@yielder:empty(); visible -> gleam@yielder:once( fun() -> render_horizontal_rule(Context, top_rule_position) end ) end. -file("src/tobble/internal/render.gleam", 222). ?DOC(false). -spec bottom_border_yielder(context()) -> gleam@yielder:yielder(binary()). bottom_border_yielder(Context) -> case erlang:element(3, Context) of hidden -> gleam@yielder:empty(); visible -> gleam@yielder:once( fun() -> render_horizontal_rule(Context, bottom_rule_position) end ) end. -file("src/tobble/internal/render.gleam", 425). ?DOC(false). -spec limit_text_width(binary(), integer()) -> binary(). limit_text_width(Text, Width) -> string_width:limit(Text, {size, string:length(Text), Width}, <<""/utf8>>). -file("src/tobble/internal/render.gleam", 435). ?DOC(false). -spec pad_end(binary(), integer()) -> binary(). pad_end(Text, Width) -> string_width:align(Text, Width, left, <<" "/utf8>>). -file("src/tobble/internal/render.gleam", 419). ?DOC(false). -spec column_text_to_width(binary(), integer()) -> binary(). column_text_to_width(Text, Width) -> _pipe = Text, _pipe@1 = limit_text_width(_pipe, Width), pad_end(_pipe@1, Width). -file("src/tobble/internal/render.gleam", 402). ?DOC(false). -spec render_visual_row(context(), list(binary())) -> binary(). render_visual_row(Context, Column_text) -> Start_separator = <<((erlang:element(6, Context))(vertical_line))/binary, " "/utf8>>, Center_separator = <<<<" "/utf8, ((erlang:element(6, Context))(vertical_line))/binary>>/binary, " "/utf8>>, End_separator = <<" "/utf8, ((erlang:element(6, Context))(vertical_line))/binary>>, _pipe = Column_text, _pipe@3 = gleam@list:map2( _pipe, erlang:element(2, Context), fun(Column, Width) -> _pipe@1 = Column, _pipe@2 = column_text_to_width(_pipe@1, Width), gleam_stdlib:identity(_pipe@2) end ), _pipe@4 = gleam@string_tree:join(_pipe@3, Center_separator), _pipe@5 = gleam@string_tree:prepend(_pipe@4, Start_separator), _pipe@6 = gleam@string_tree:append(_pipe@5, End_separator), unicode:characters_to_binary(_pipe@6). -file("src/tobble/internal/render.gleam", 439). ?DOC(false). -spec pad_list_end(list(MGF), integer(), MGF) -> list(MGF). pad_list_end(List, To_length, Filler) -> Length = erlang:length(List), case Length >= To_length of true -> List; false -> gleam@list:flatten( [List, gleam@list:repeat(Filler, To_length - Length)] ) end. -file("src/tobble/internal/render.gleam", 451). ?DOC(false). -spec max_length(list(MGI), fun((MGI) -> integer())) -> {ok, integer()} | {error, nil}. max_length(Lists, Get_length) -> case Lists of [] -> {error, nil}; Lists@1 -> _pipe = Lists@1, _pipe@1 = gleam@list:fold( _pipe, 0, fun(Acc, Lengthable) -> Length = Get_length(Lengthable), case Length > Acc of true -> Length; false -> Acc end end ), {ok, _pipe@1} end. -file("src/tobble/internal/render.gleam", 204). ?DOC(false). -spec column_lengths(tobble@internal@rows:rows(binary())) -> list(integer()). column_lengths(Rows) -> tobble@internal@rows:columnwise_fold( Rows, 0, fun(Max, Column) -> _pipe = Column, _pipe@1 = gleam@string:split(_pipe, <<"\n"/utf8>>), _pipe@2 = max_length(_pipe@1, fun string_width:line/1), _pipe@3 = gleam@result:unwrap(_pipe@2, 0), gleam@int:max(_pipe@3, Max) end ). -file("src/tobble/internal/render.gleam", 373). ?DOC(false). -spec row_yielder(context(), list(binary())) -> gleam@yielder:yielder(binary()). row_yielder(Context, Column_text) -> Column_lines = gleam@list:map2( Column_text, erlang:element(2, Context), fun(Text, Width) -> _pipe = Text, _pipe@1 = limit_text_width(_pipe, Width), gleam@string:split(_pipe@1, <<"\n"/utf8>>) end ), Height = begin _pipe@2 = Column_lines, _pipe@3 = max_length(_pipe@2, fun erlang:length/1), gleam@result:unwrap(_pipe@3, 1) end, Visual_rows = begin _pipe@4 = Column_lines, _pipe@5 = gleam@list:map( _pipe@4, fun(Column) -> pad_list_end(Column, Height, <<""/utf8>>) end ), gleam@list:transpose(_pipe@5) end, gleam@yielder:unfold( Visual_rows, fun(Remaining_rows) -> case Remaining_rows of [] -> done; [Visual_row | Rest_rows] -> {next, render_visual_row(Context, Visual_row), Rest_rows} end end ). -file("src/tobble/internal/render.gleam", 344). ?DOC(false). -spec row_with_horizontal_rule_yielder(context(), list(binary())) -> gleam@yielder:yielder(binary()). row_with_horizontal_rule_yielder(Context, Column_text) -> gleam@yielder:append( row_yielder(Context, Column_text), gleam@yielder:once( fun() -> render_horizontal_rule(Context, center_rule_position) end ) ). -file("src/tobble/internal/render.gleam", 359). ?DOC(false). -spec grouped_rows_yielder(context(), tobble@internal@rows:rows(binary())) -> gleam@yielder:yielder(gleam@yielder:yielder(binary())). grouped_rows_yielder(Context, Rows) -> gleam@yielder:unfold( Rows, fun(Remaining_rows) -> case tobble@internal@rows:pop_row(Remaining_rows) of {error, nil} -> done; {ok, {Row, Rest_rows}} -> {next, row_yielder(Context, Row), Rest_rows} end end ). -file("src/tobble/internal/render.gleam", 333). ?DOC(false). -spec rows_with_horizontal_rules_everywhere_yielder( context(), tobble@internal@rows:rows(binary()) ) -> gleam@yielder:yielder(binary()). rows_with_horizontal_rules_everywhere_yielder(Context, Rows) -> _pipe = grouped_rows_yielder(Context, Rows), _pipe@1 = gleam@yielder:intersperse( _pipe, gleam@yielder:once( fun() -> render_horizontal_rule(Context, center_rule_position) end ) ), gleam@yielder:flatten(_pipe@1). -file("src/tobble/internal/render.gleam", 354). ?DOC(false). -spec visual_rows_yielder(context(), tobble@internal@rows:rows(binary())) -> gleam@yielder:yielder(binary()). visual_rows_yielder(Context, Rows) -> gleam@yielder:flatten(grouped_rows_yielder(Context, Rows)). -file("src/tobble/internal/render.gleam", 317). ?DOC(false). -spec rows_with_header_yielder(context(), tobble@internal@rows:rows(binary())) -> gleam@yielder:yielder(binary()). rows_with_header_yielder(Context, Rows) -> case tobble@internal@rows:pop_row(Rows) of {error, nil} -> gleam@yielder:empty(); {ok, {Head_row, Rest_rows}} -> gleam@yielder:append( row_with_horizontal_rule_yielder(Context, Head_row), visual_rows_yielder(Context, Rest_rows) ) end. -file("src/tobble/internal/render.gleam", 305). ?DOC(false). -spec table_content_yielder(context(), tobble@internal@rows:rows(binary())) -> gleam@yielder:yielder(binary()). table_content_yielder(Context, Rows) -> case erlang:element(4, Context) of header_only_horizontal_rules -> rows_with_header_yielder(Context, Rows); every_row_has_horizontal_rules -> rows_with_horizontal_rules_everywhere_yielder(Context, Rows); no_horizontal_rules -> visual_rows_yielder(Context, Rows) end. -file("src/tobble/internal/render.gleam", 480). ?DOC(false). -spec minimum_decoration_width(integer()) -> integer(). minimum_decoration_width(Num_columns) -> ((Num_columns * 2) + (Num_columns - 1)) + 2. -file("src/tobble/internal/render.gleam", 291). ?DOC(false). -spec render_title(context(), binary()) -> binary(). render_title(Context, Title) -> Num_columns = erlang:length(erlang:element(2, Context)), Width = minimum_decoration_width(Num_columns) + gleam@int:sum( erlang:element(2, Context) ), _pipe = Title, _pipe@1 = string_width:limit( _pipe, {size, string:length(Title), Width}, <<""/utf8>> ), string_width:align(_pipe@1, Width, center, <<" "/utf8>>). -file("src/tobble/internal/render.gleam", 230). ?DOC(false). -spec title_yielder(context(), gleam@option:option(binary()), title_position()) -> gleam@yielder:yielder(binary()). title_yielder(Context, Maybe_title, Position) -> _pipe = Maybe_title, _pipe@3 = gleam@option:map( _pipe, fun(Title) -> case erlang:element(5, Context) of {title_options, Chosen_position, visible} when Chosen_position =:= Position -> _pipe@1 = render_title(Context, Title), _pipe@2 = gleam@string:split(_pipe@1, <<"\n"/utf8>>), gleam@yielder:from_list(_pipe@2); {title_options, _, _} -> gleam@yielder:empty() end end ), gleam@option:unwrap(_pipe@3, gleam@yielder:empty()). -file("src/tobble/internal/render.gleam", 76). ?DOC(false). -spec to_yielder( context(), tobble@internal@rows:rows(binary()), gleam@option:option(binary()) ) -> gleam@yielder:yielder(binary()). to_yielder(Context, Rows, Title) -> _pipe = title_yielder(Context, Title, top_title_position), _pipe@1 = gleam@yielder:append(_pipe, top_border_yielder(Context)), _pipe@2 = gleam@yielder:append( _pipe@1, table_content_yielder(Context, Rows) ), _pipe@3 = gleam@yielder:append(_pipe@2, bottom_border_yielder(Context)), gleam@yielder:append( _pipe@3, title_yielder(Context, Title, bottom_title_position) ). -file("src/tobble/internal/render.gleam", 470). ?DOC(false). -spec column_content_width_for_table_width(integer(), integer()) -> integer(). column_content_width_for_table_width(Num_columns, Desired_width) -> Desired_width@1 = Desired_width - minimum_decoration_width(Num_columns), gleam@int:max(Desired_width@1, Num_columns). -file("src/tobble/internal/render.gleam", 497). ?DOC(false). -spec scale_empty_columns(list(integer()), integer()) -> scaled_column_widths(). scale_empty_columns(Widths, Allowed_extra_width) -> {Extra_width, New_widths} = gleam@list:map_fold( Widths, Allowed_extra_width, fun(Acc, Width) -> case Acc of 0 -> {Acc, Width}; Acc@1 when Width =:= 0 -> {Acc@1 - 1, Width + 1}; Acc@2 -> {Acc@2, Width} end end ), {scaled_column_widths, New_widths, Extra_width}. -file("src/tobble/internal/render.gleam", 527). ?DOC(false). -spec do_redistribute_extra_width(list(integer()), integer()) -> scaled_column_widths(). do_redistribute_extra_width(Widths, Allowed_extra_width) -> {Extra_width@2, New_widths} = gleam@list:map_fold( Widths, Allowed_extra_width, fun(Extra_width, Width) -> case Extra_width of 0 -> {Extra_width, Width}; Extra_width@1 -> {Extra_width@1 - 1, Width + 1} end end ), {scaled_column_widths, New_widths, Extra_width@2}. -file("src/tobble/internal/render.gleam", 513). ?DOC(false). -spec redistribute_extra_width(list(integer()), integer()) -> scaled_column_widths(). redistribute_extra_width(Widths, Allowed_extra_width) -> case Allowed_extra_width of 0 -> {scaled_column_widths, Widths, 0}; Allowed_extra_width@1 -> Redistributed = do_redistribute_extra_width( Widths, Allowed_extra_width@1 ), redistribute_extra_width( erlang:element(2, Redistributed), erlang:element(3, Redistributed) ) end. -file("src/tobble/internal/render.gleam", 159). ?DOC(false). -spec apply_table_width(context(), integer()) -> context(). apply_table_width(Context, Desired_width) -> Desired_width@1 = column_content_width_for_table_width( erlang:length(erlang:element(2, Context)), Desired_width ), Total_original_width = gleam@int:sum(erlang:element(2, Context)), Scaled_widths = gleam@list:map( erlang:element(2, Context), fun(Column_width) -> case Total_original_width of 0 -> 0; Gleam@denominator -> Column_width * Desired_width@1 div Gleam@denominator end end ), Total_scaled_width = gleam@int:sum(Scaled_widths), case gleam@int:compare(Total_scaled_width, Total_original_width) of gt -> _record = Context, {context, Scaled_widths, erlang:element(3, _record), erlang:element(4, _record), erlang:element(5, _record), erlang:element(6, _record)}; eq -> _record = Context, {context, Scaled_widths, erlang:element(3, _record), erlang:element(4, _record), erlang:element(5, _record), erlang:element(6, _record)}; lt -> Extra_width = Desired_width@1 - Total_scaled_width, {scaled_column_widths, Scaled_widths@1, Extra_width@1} = scale_empty_columns( Scaled_widths, Extra_width ), {scaled_column_widths, Scaled_widths@2, _} = redistribute_extra_width( Scaled_widths@1, Extra_width@1 ), _record@1 = Context, {context, Scaled_widths@2, erlang:element(3, _record@1), erlang:element(4, _record@1), erlang:element(5, _record@1), erlang:element(6, _record@1)} end. -file("src/tobble/internal/render.gleam", 546). ?DOC(false). -spec lookup_ascii_table_line(table_line()) -> binary(). lookup_ascii_table_line(Element) -> case Element of horizontal_line -> <<"-"/utf8>>; vertical_line -> <<"|"/utf8>>; four_way_junction -> <<"+"/utf8>>; start_junction -> <<"+"/utf8>>; end_junction -> <<"+"/utf8>>; top_junction -> <<"+"/utf8>>; bottom_junction -> <<"+"/utf8>>; top_start_corner_junction -> <<"+"/utf8>>; top_end_corner_junction -> <<"+"/utf8>>; bottom_start_corner_junction -> <<"+"/utf8>>; bottom_end_corner_junction -> <<"+"/utf8>> end. -file("src/tobble/internal/render.gleam", 89). ?DOC(false). -spec default_render_context(tobble@internal@rows:rows(binary())) -> context(). default_render_context(Rows) -> {context, column_lengths(Rows), visible, header_only_horizontal_rules, {title_options, top_title_position, visible}, fun lookup_ascii_table_line/1}. -file("src/tobble/internal/render.gleam", 562). ?DOC(false). -spec lookup_box_drawing_table_line(table_line()) -> binary(). lookup_box_drawing_table_line(Element) -> case Element of horizontal_line -> <<"─"/utf8>>; vertical_line -> <<"│"/utf8>>; four_way_junction -> <<"┼"/utf8>>; start_junction -> <<"├"/utf8>>; end_junction -> <<"┤"/utf8>>; top_junction -> <<"┬"/utf8>>; bottom_junction -> <<"┴"/utf8>>; top_start_corner_junction -> <<"┌"/utf8>>; top_end_corner_junction -> <<"┐"/utf8>>; bottom_start_corner_junction -> <<"└"/utf8>>; bottom_end_corner_junction -> <<"┘"/utf8>> end. -file("src/tobble/internal/render.gleam", 578). ?DOC(false). -spec lookup_box_drawing_rounded_corner_table_line(table_line()) -> binary(). lookup_box_drawing_rounded_corner_table_line(Element) -> case Element of horizontal_line -> <<"─"/utf8>>; vertical_line -> <<"│"/utf8>>; four_way_junction -> <<"┼"/utf8>>; start_junction -> <<"├"/utf8>>; end_junction -> <<"┤"/utf8>>; top_junction -> <<"┬"/utf8>>; bottom_junction -> <<"┴"/utf8>>; top_start_corner_junction -> <<"╭"/utf8>>; top_end_corner_junction -> <<"╮"/utf8>>; bottom_start_corner_junction -> <<"╰"/utf8>>; bottom_end_corner_junction -> <<"╯"/utf8>> end. -file("src/tobble/internal/render.gleam", 594). ?DOC(false). -spec lookup_blank_table_line(table_line()) -> binary(). lookup_blank_table_line(Element) -> case Element of horizontal_line -> <<" "/utf8>>; vertical_line -> <<" "/utf8>>; four_way_junction -> <<" "/utf8>>; start_junction -> <<" "/utf8>>; end_junction -> <<" "/utf8>>; top_junction -> <<" "/utf8>>; bottom_junction -> <<" "/utf8>>; top_start_corner_junction -> <<" "/utf8>>; top_end_corner_junction -> <<" "/utf8>>; bottom_start_corner_junction -> <<" "/utf8>>; bottom_end_corner_junction -> <<" "/utf8>> end. -file("src/tobble/internal/render.gleam", 100). ?DOC(false). -spec apply_line_type(context(), line_type()) -> context(). apply_line_type(Context, Line_type) -> case Line_type of a_s_c_i_i_line_type -> _record = Context, {context, erlang:element(2, _record), visible, erlang:element(4, _record), erlang:element(5, _record), fun lookup_ascii_table_line/1}; box_drawing_chars_line_type -> _record@1 = Context, {context, erlang:element(2, _record@1), visible, erlang:element(4, _record@1), erlang:element(5, _record@1), fun lookup_box_drawing_table_line/1}; box_drawing_chars_with_rounded_corners_line_type -> _record@2 = Context, {context, erlang:element(2, _record@2), visible, erlang:element(4, _record@2), erlang:element(5, _record@2), fun lookup_box_drawing_rounded_corner_table_line/1}; blank_line_type -> _record@3 = Context, {context, erlang:element(2, _record@3), hidden, erlang:element(4, _record@3), erlang:element(5, _record@3), fun lookup_blank_table_line/1} end.