-module(wink). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -export([init/1, draw/1]). -export_type([style/0, border/0, color/0, decoration/0, spacing/0, config/0, box/0]). -type style() :: single | round | solid | frame | cross | spring | thick | double | single_double | double_single | classic | hidden | {custom, border()}. -type border() :: {border, binary(), binary(), binary(), binary(), binary(), binary()}. -type color() :: black | red | green | yellow | blue | magenta | cyan | white | default | reset_color. -type decoration() :: bold | dim | italic | underline | reversed | reset_decoration. -type spacing() :: {spacing, integer(), integer(), integer(), integer()}. -type config() :: {config, style(), color(), color(), spacing(), spacing(), list(decoration())}. -type box() :: {box, fun((binary()) -> binary())}. -spec apply_ansis(binary(), list(binary())) -> binary(). apply_ansis(Text, Ansis) -> _pipe = Ansis, _pipe@1 = gleam@string:concat(_pipe), gleam@string:append(_pipe@1, Text). -spec get_style(style()) -> border(). get_style(Style) -> case Style of single -> {border, <<"┐"/utf8>>, <<"┌"/utf8>>, <<"┘"/utf8>>, <<"└"/utf8>>, <<"─"/utf8>>, <<"│"/utf8>>}; frame -> {border, <<"◹"/utf8>>, <<"◸"/utf8>>, <<"◿"/utf8>>, <<"◺"/utf8>>, <<"─"/utf8>>, <<"│"/utf8>>}; cross -> {border, <<"┼"/utf8>>, <<"┼"/utf8>>, <<"┼"/utf8>>, <<"┼"/utf8>>, <<"─"/utf8>>, <<"│"/utf8>>}; spring -> {border, <<"╳"/utf8>>, <<"╳"/utf8>>, <<"╳"/utf8>>, <<"╳"/utf8>>, <<"╳"/utf8>>, <<"╳"/utf8>>}; thick -> {border, <<"█"/utf8>>, <<"█"/utf8>>, <<"█"/utf8>>, <<"█"/utf8>>, <<"█"/utf8>>, <<"█"/utf8>>}; double -> {border, <<"╗"/utf8>>, <<"╔"/utf8>>, <<"╝"/utf8>>, <<"╚"/utf8>>, <<"═"/utf8>>, <<"║"/utf8>>}; round -> {border, <<"╮"/utf8>>, <<"╭"/utf8>>, <<"╯"/utf8>>, <<"╰"/utf8>>, <<"─"/utf8>>, <<"│"/utf8>>}; solid -> {border, <<"┓"/utf8>>, <<"┏"/utf8>>, <<"┛"/utf8>>, <<"┗"/utf8>>, <<"━"/utf8>>, <<"┃"/utf8>>}; single_double -> {border, <<"╖"/utf8>>, <<"╓"/utf8>>, <<"╜"/utf8>>, <<"╙"/utf8>>, <<"─"/utf8>>, <<"║"/utf8>>}; double_single -> {border, <<"╕"/utf8>>, <<"╒"/utf8>>, <<"╛"/utf8>>, <<"╘"/utf8>>, <<"═"/utf8>>, <<"│"/utf8>>}; classic -> {border, <<"+"/utf8>>, <<"+"/utf8>>, <<"+"/utf8>>, <<"+"/utf8>>, <<"-"/utf8>>, <<"|"/utf8>>}; hidden -> {border, <<"+"/utf8>>, <<"+"/utf8>>, <<"+"/utf8>>, <<"+"/utf8>>, <<" "/utf8>>, <<" "/utf8>>}; {custom, Border} -> Border end. -spec draw_row(integer(), config()) -> binary(). draw_row(Width, Config) -> _pipe = <<" "/utf8>>, _pipe@1 = gleam@string:repeat( _pipe, erlang:element(5, erlang:element(6, Config)) ), _pipe@2 = gleam@string:append( _pipe@1, erlang:element(7, get_style(erlang:element(2, Config))) ), _pipe@3 = gleam@string:append( _pipe@2, gleam@string:repeat(<<" "/utf8>>, Width) ), _pipe@4 = gleam@string:append( _pipe@3, erlang:element(7, get_style(erlang:element(2, Config))) ), _pipe@5 = gleam@string:append( _pipe@4, gleam@string:repeat( <<" "/utf8>>, erlang:element(3, erlang:element(6, Config)) ) ), gleam@string:append(_pipe@5, <<"\n"/utf8>>). -spec draw_bottom(integer(), config()) -> binary(). draw_bottom(Width, Config) -> _pipe = draw_row(Width, Config), _pipe@1 = gleam@string:repeat( _pipe, erlang:element(4, erlang:element(5, Config)) ), _pipe@2 = gleam@string:append( _pipe@1, gleam@string:repeat( <<" "/utf8>>, erlang:element(5, erlang:element(6, Config)) ) ), _pipe@3 = gleam@string:append( _pipe@2, erlang:element(5, get_style(erlang:element(2, Config))) ), _pipe@4 = gleam@string:append( _pipe@3, gleam@string:repeat( erlang:element(6, get_style(erlang:element(2, Config))), Width ) ), _pipe@5 = gleam@string:append( _pipe@4, erlang:element(4, get_style(erlang:element(2, Config))) ), _pipe@6 = gleam@string:append( _pipe@5, gleam@string:repeat( <<" "/utf8>>, erlang:element(3, erlang:element(6, Config)) ) ), gleam@string:append( _pipe@6, gleam@string:repeat( <<"\n"/utf8>>, erlang:element(4, erlang:element(6, Config)) ) ). -spec get_color(color()) -> binary(). get_color(Color) -> <<"\x{001b}"/utf8, (case Color of black -> <<"[30m"/utf8>>; red -> <<"[31m"/utf8>>; green -> <<"[32m"/utf8>>; yellow -> <<"[33m"/utf8>>; blue -> <<"[34m"/utf8>>; magenta -> <<"[35m"/utf8>>; cyan -> <<"[36m"/utf8>>; white -> <<"[37m"/utf8>>; default -> <<"[39m"/utf8>>; reset_color -> <<"[0m"/utf8>> end)/binary>>. -spec draw_top(integer(), config()) -> binary(). draw_top(Width, Config) -> _pipe = get_color(erlang:element(3, Config)), _pipe@1 = gleam@string:append( _pipe, gleam@string:repeat( <<"\n"/utf8>>, erlang:element(2, erlang:element(6, Config)) ) ), _pipe@2 = gleam@string:append( _pipe@1, gleam@string:repeat( <<" "/utf8>>, erlang:element(5, erlang:element(6, Config)) ) ), _pipe@3 = gleam@string:append( _pipe@2, erlang:element(3, get_style(erlang:element(2, Config))) ), _pipe@4 = gleam@string:append( _pipe@3, gleam@string:repeat( erlang:element(6, get_style(erlang:element(2, Config))), Width ) ), _pipe@5 = gleam@string:append( _pipe@4, erlang:element(2, get_style(erlang:element(2, Config))) ), _pipe@6 = gleam@string:append( _pipe@5, gleam@string:repeat( <<" "/utf8>>, erlang:element(3, erlang:element(6, Config)) ) ), gleam@string:append(_pipe@6, <<"\n"/utf8>>). -spec get_decoration(decoration()) -> binary(). get_decoration(Decoration) -> <<"\x{001b}"/utf8, (case Decoration of bold -> <<"[1m"/utf8>>; dim -> <<"[1m"/utf8>>; italic -> <<"[3m"/utf8>>; underline -> <<"[4m"/utf8>>; reversed -> <<"[7m"/utf8>>; reset_decoration -> <<"[0m"/utf8>> end)/binary>>. -spec apply_decorations(list(decoration())) -> binary(). apply_decorations(Decorations) -> _pipe = Decorations, _pipe@1 = gleam@list:map(_pipe, fun get_decoration/1), gleam@string:concat(_pipe@1). -spec draw_middle(binary(), integer(), config()) -> binary(). draw_middle(Msg, Width, Config) -> _pipe = draw_row(Width, Config), _pipe@1 = gleam@string:repeat( _pipe, erlang:element(2, erlang:element(5, Config)) ), _pipe@2 = gleam@string:append( _pipe@1, gleam@string:repeat( <<" "/utf8>>, erlang:element(5, erlang:element(6, Config)) ) ), _pipe@3 = gleam@string:append( _pipe@2, erlang:element(7, get_style(erlang:element(2, Config))) ), _pipe@4 = gleam@string:append( _pipe@3, gleam@string:repeat( <<" "/utf8>>, erlang:element(5, erlang:element(5, Config)) ) ), _pipe@5 = gleam@string:append(_pipe@4, get_color(erlang:element(4, Config))), _pipe@6 = gleam@string:append( _pipe@5, apply_ansis( Msg, [get_color(erlang:element(4, Config)), apply_decorations(erlang:element(7, Config))] ) ), _pipe@7 = gleam@string:append(_pipe@6, get_decoration(reset_decoration)), _pipe@8 = gleam@string:append(_pipe@7, get_color(erlang:element(3, Config))), _pipe@9 = gleam@string:append( _pipe@8, gleam@string:repeat( <<" "/utf8>>, erlang:element(3, erlang:element(5, Config)) ) ), _pipe@10 = gleam@string:append( _pipe@9, erlang:element(7, get_style(erlang:element(2, Config))) ), _pipe@11 = gleam@string:append( _pipe@10, gleam@string:repeat( <<" "/utf8>>, erlang:element(3, erlang:element(6, Config)) ) ), gleam@string:append(_pipe@11, <<"\n"/utf8>>). -spec draw_box(binary(), config()) -> binary(). draw_box(Msg, Config) -> Length = gleam@string:length(Msg), Width = (erlang:element(5, erlang:element(5, Config)) + Length) + erlang:element( 3, erlang:element(5, Config) ), gleam@string:concat( [draw_top(Width, Config), draw_middle(Msg, Width, Config), draw_bottom(Width, Config)] ). -spec init(config()) -> box(). init(Cfg) -> {box, fun(Msg) -> draw_box(Msg, Cfg) end}. -spec draw(binary()) -> binary(). draw(Msg) -> draw_box( Msg, {config, round, default, default, {spacing, 1, 1, 1, 1}, {spacing, 1, 1, 1, 1}, []} ).