Current section
Files
Jump to
Current section
Files
src/tobble@internal@render.erl
-module(tobble@internal@render).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-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 |
ascii_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(OAU), integer(), OAU) -> list(OAU).
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(OAX), fun((OAX) -> 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
ascii_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.