-module(trellis). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -export([style/2, table/1, param/1, with/2, to_string/1]). -export_type([table/1, cell_content/0]). -type table(FBD) :: {table, list(trellis@column:column(FBD)), list(FBD), trellis@style:style()}. -type cell_content() :: {cell_content, list(binary()), integer(), integer()}. -file("/home/ethanthoma/projects/trellis/src/trellis.gleam", 40). -spec style(table(FBH), trellis@style:style()) -> table(FBH). style(Table, Style) -> _record = Table, {table, erlang:element(2, _record), erlang:element(3, _record), Style}. -file("/home/ethanthoma/projects/trellis/src/trellis.gleam", 35). -spec table(list(FBE)) -> table(FBE). table(Rows) -> {table, [], Rows, line}. -file("/home/ethanthoma/projects/trellis/src/trellis.gleam", 51). -spec param(fun((FBK) -> FBL)) -> fun((FBK) -> FBL). param(F) -> F. -file("/home/ethanthoma/projects/trellis/src/trellis.gleam", 56). -spec with(table(FBM), trellis@column:column(FBM)) -> table(FBM). with(Table, Column) -> {table, Columns, _, _} = Table, _record = Table, {table, [Column | Columns], erlang:element(3, _record), erlang:element(4, _record)}. -file("/home/ethanthoma/projects/trellis/src/trellis.gleam", 225). -spec make_separator( trellis@style:style(), list(integer()), boolean(), boolean() ) -> binary(). make_separator(Style, Widths, Is_header, Is_top) -> {style_guide, _, Horizontal, Top_left, Top_middle, Top_right, Middle_left, Middle_right, Bottom_left, Bottom_middle, Bottom_right, Cross} = trellis@style:style(Style), {Start, Middle, End} = case {Is_top, Is_header} of {true, _} -> {Top_left, Top_middle, Top_right}; {false, true} -> {Middle_right, Cross, Middle_left}; {false, false} -> {Bottom_left, Bottom_middle, Bottom_right} end, Line = begin _pipe = Widths, gleam@list:fold( _pipe, Start, fun(Acc, Col) -> <<<>/binary, Middle/binary>> end ) end, <<(gleam@string:slice(Line, 0, string:length(Line) - 1))/binary, End/binary>>. -file("/home/ethanthoma/projects/trellis/src/trellis.gleam", 261). -spec pad_left(binary(), integer()) -> binary(). pad_left(Text, Width) -> Padding = Width - string:length(Text), <<(gleam@string:repeat(<<" "/utf8>>, Padding))/binary, Text/binary>>. -file("/home/ethanthoma/projects/trellis/src/trellis.gleam", 267). -spec pad_right(binary(), integer()) -> binary(). pad_right(Text, Width) -> Padding = Width - string:length(Text), <>, Padding))/binary>>. -file("/home/ethanthoma/projects/trellis/src/trellis.gleam", 273). -spec pad_center(binary(), integer()) -> binary(). pad_center(Text, Width) -> Padding = Width - string:length(Text), Left = Padding div 2, Right = Padding - Left, <<<<(gleam@string:repeat(<<" "/utf8>>, Left))/binary, Text/binary>>/binary, (gleam@string:repeat(<<" "/utf8>>, Right))/binary>>. -file("/home/ethanthoma/projects/trellis/src/trellis.gleam", 129). -spec make_multi_line_row( trellis@style:style(), list(trellis@column:align()), list(integer()), list(cell_content()) ) -> list(binary()). make_multi_line_row(Style, Aligns, Widths, Cell_contents) -> Vertical = erlang:element(2, trellis@style:style(Style)), Max_height = gleam@list:fold( Cell_contents, 0, fun(Acc, Cell) -> gleam@int:max(Acc, erlang:element(4, Cell)) end ), _pipe = gleam@list:range(0, Max_height - 1), gleam@list:map( _pipe, fun(Line_num) -> Parts = gleam@list:map2( gleam@list:zip(Aligns, Widths), Cell_contents, fun(Tup, Cell@1) -> {erlang:element(1, Tup), erlang:element(2, Tup), Cell@1} end ), Line_parts = gleam@list:map( Parts, fun(Part) -> {Align, Width, Cell@2} = Part, Content = gleam@list:index_fold( erlang:element(2, Cell@2), <<""/utf8>>, fun(Acc@1, Line, I) -> case Line_num =:= I of true -> Line; _ -> Acc@1 end end ), Padded = case Align of left -> pad_right(Content, Width); right -> pad_left(Content, Width); center -> pad_center(Content, Width) end, <<<<" "/utf8, Padded/binary>>/binary, " "/utf8>> end ), <<<>/binary, Vertical/binary>> end ). -file("/home/ethanthoma/projects/trellis/src/trellis.gleam", 294). -spec do_wrap(list(binary()), integer(), binary(), list(binary())) -> list(binary()). do_wrap(Words, Max_width, Current, Lines) -> case Words of [] -> case Current of <<""/utf8>> -> lists:reverse(Lines); _ -> lists:reverse([gleam@string:trim(Current) | Lines]) end; [Word | Rest] -> With_space = case Current of <<""/utf8>> -> Word; _ -> <<<>/binary, Word/binary>> end, case string:length(With_space) =< Max_width of true -> do_wrap(Rest, Max_width, With_space, Lines); false -> case Current of <<""/utf8>> -> do_wrap(Rest, Max_width, Word, Lines); _ -> do_wrap( [Word | Rest], Max_width, <<""/utf8>>, [gleam@string:trim(Current) | Lines] ) end end end. -file("/home/ethanthoma/projects/trellis/src/trellis.gleam", 328). -spec calculate_min_width(binary()) -> integer(). calculate_min_width(Text) -> _pipe = gleam@string:split(Text, <<" "/utf8>>), gleam@list:fold( _pipe, 0, fun(Acc, Word) -> gleam@int:max(Acc, string:length(Word)) end ). -file("/home/ethanthoma/projects/trellis/src/trellis.gleam", 280). -spec wrap_text(binary(), integer()) -> list(binary()). wrap_text(Text, Max_width) -> Min_width = calculate_min_width(Text), Effective_width = gleam@int:max(Max_width, Min_width), case string:length(Text) =< Effective_width of true -> [Text]; false -> Words = gleam@string:split(Text, <<" "/utf8>>), do_wrap(Words, Effective_width, <<""/utf8>>, []) end. -file("/home/ethanthoma/projects/trellis/src/trellis.gleam", 64). -spec cell_content(binary(), gleam@option:option(integer())) -> cell_content(). cell_content(Text, Width) -> Newline_splits = gleam@string:split(Text, <<"\n"/utf8>>), Lines = case Width of {some, Width@1} -> gleam@list:flat_map( Newline_splits, fun(Line) -> wrap_text(Line, Width@1) end ); none -> Newline_splits end, Content_width = gleam@list:fold( Lines, 0, fun(Acc, Line@1) -> gleam@int:max(Acc, string:length(Line@1)) end ), Final_width = case Width of {some, Max} -> gleam@int:min(Content_width, Max); none -> Content_width end, {cell_content, Lines, Final_width, erlang:length(Lines)}. -file("/home/ethanthoma/projects/trellis/src/trellis.gleam", 89). -spec calculate_widths( list(binary()), list(binary()), list(gleam@option:option(integer())) ) -> list(integer()). calculate_widths(Headers, Values, Widths) -> Header_cells = gleam@list:map2(Headers, Widths, fun cell_content/2), Columns = gleam@list:sized_chunk(Values, erlang:length(Headers)), Transposed_columns = gleam@list:transpose(Columns), Min_column_widths = gleam@list:map( Transposed_columns, fun(Col_values) -> gleam@list:fold( Col_values, 0, fun(Acc, Val) -> gleam@int:max(Acc, calculate_min_width(Val)) end ) end ), Value_cells = gleam@list:map2( Transposed_columns, Widths, fun(Col_values@1, Width) -> gleam@list:map( Col_values@1, fun(Value) -> cell_content(Value, Width) end ) end ), gleam@list:map2( gleam@list:zip(Header_cells, Widths), gleam@list:zip(Value_cells, Min_column_widths), fun(_use0, _use1) -> {Header, Max_width} = _use0, {Column_cells, Min_width} = _use1, Natural_width = gleam@list:fold( Column_cells, erlang:element(3, Header), fun(Acc@1, Cell) -> gleam@int:max(Acc@1, erlang:element(3, Cell)) end ), Width@1 = gleam@int:max(Natural_width, Min_width), case Max_width of {some, Max_width@1} -> gleam@int:max( Min_width, gleam@int:min(Width@1, Max_width@1) ); none -> Width@1 end end ). -file("/home/ethanthoma/projects/trellis/src/trellis.gleam", 175). -spec to_string(table(any())) -> binary(). to_string(Table) -> {table, Columns, Rows, Style} = Table, Columns@1 = lists:reverse(Columns), Headers = gleam@list:map( Columns@1, fun(Column) -> erlang:element(2, Column) end ), Aligns = gleam@list:map( Columns@1, fun(Column@1) -> erlang:element(3, Column@1) end ), Max_widths = gleam@list:map( Columns@1, fun(Column@2) -> erlang:element(4, Column@2) end ), Values = gleam@list:flat_map( Rows, fun(Row) -> gleam@list:map( Columns@1, fun(Col) -> (erlang:element(5, Col))(Row) end ) end ), Widths = calculate_widths(Headers, Values, Max_widths), Separator_top = make_separator(Style, Widths, true, true), Separator_header = make_separator(Style, Widths, true, false), Separator_bottom = make_separator(Style, Widths, false, false), Header_cells = gleam@list:map2(Headers, Max_widths, fun cell_content/2), Header_rows = make_multi_line_row( Style, gleam@list:map( gleam@list:range(1, erlang:length(Columns@1)), fun(_) -> center end ), Widths, Header_cells ), Body_rows = gleam@list:flat_map( Rows, fun(Row@1) -> Cell_contents = gleam@list:map2( Columns@1, Max_widths, fun(Col@1, W) -> cell_content((erlang:element(5, Col@1))(Row@1), W) end ), make_multi_line_row(Style, Aligns, Widths, Cell_contents) end ), _pipe = [Separator_top], _pipe@1 = lists:append(_pipe, Header_rows), _pipe@2 = lists:append(_pipe@1, [Separator_header]), _pipe@3 = lists:append(_pipe@2, Body_rows), _pipe@4 = lists:append(_pipe@3, [Separator_bottom]), gleam@string:join(_pipe@4, <<"\n"/utf8>>).