diff --git a/lib/owl/box.ex b/lib/owl/box.ex index 26e1a6b..ecd9d9b 100644 --- a/lib/owl/box.ex +++ b/lib/owl/box.ex @@ -104,7 +104,7 @@ defmodule Owl.Box do ...> |> Owl.Data.tag(:green) ...> |> Owl.Box.new(title: Owl.Data.tag("Red!", :red)) ...> |> Owl.Data.tag(:cyan) - ...> |> Owl.Data.to_ansidata() + ...> |> Owl.Data.to_chardata() ...> |> to_string() \""" \e[36m┌─\e[31mRed!\e[36m────┐\e[39m @@ -116,7 +116,7 @@ defmodule Owl.Box do ...> |> Owl.Data.tag(:green) ...> |> Owl.Box.new(title: Owl.Data.tag("Red!", :red)) ...> |> Owl.Data.tag(:cyan) - ...> |> Owl.Data.to_ansidata() + ...> |> Owl.Data.to_chardata() ...> |> to_string() \""" \e[36m┌─\e[31mRed!\e[36m────┐\e[39m @@ -131,7 +131,7 @@ defmodule Owl.Box do ...> border_style: :double, ...> border_tag: :cyan ...> ) - ...> |> Owl.Data.to_ansidata() + ...> |> Owl.Data.to_chardata() ...> |> to_string() \""" \e[36m╔\e[39m\e[36m══════════════════\e[39m\e[36m╗\e[39m @@ -148,7 +148,7 @@ defmodule Owl.Box do ...> border_style: :double, ...> border_tag: :cyan ...> ) - ...> |> Owl.Data.to_ansidata() + ...> |> Owl.Data.to_chardata() ...> |> to_string() \""" \e[36m╔\e[39m\e[36m═\e[39mGreeting!\e[36m════════\e[39m\e[36m╗\e[39m diff --git a/lib/owl/data.ex b/lib/owl/data.ex index 9d7a7b9..dba0d11 100644 --- a/lib/owl/data.ex +++ b/lib/owl/data.ex @@ -1,12 +1,12 @@ defmodule Owl.Data do @moduledoc """ - A set of functions for `t:iodata/0` with [tags](`Owl.Tag`). + A set of functions for `t:chardata/0` with [tags](`Owl.Tag`). """ alias Owl.Data.Sequence @typedoc """ - A recursive data type that is similar to `t:iodata/0`, but additionally supports `t:Owl.Tag.t/1`. + A recursive data type that is similar to `t:chardata/0`, but additionally supports `t:Owl.Tag.t/1`. Can be printed using `Owl.IO.puts/2`. """ @@ -94,7 +94,7 @@ defmodule Owl.Data do iex> ["Hello ", Owl.Data.tag("world", :red), ["!"]] |> Owl.Data.untag() ["Hello ", "world", ["!"]] """ - @spec untag(t()) :: iodata() + @spec untag(t()) :: IO.chardata() def untag(data) when is_list(data) do Enum.map(data, &untag_child/1) end @@ -227,8 +227,8 @@ defmodule Owl.Data do iex> ["first\\nsecond\\n", Owl.Data.tag("third\\nfourth", :red)] ...> |> Owl.Data.lines() ...> |> Owl.Data.unlines() - ...> |> Owl.Data.to_ansidata() - Owl.Data.to_ansidata(["first\\nsecond\\n", Owl.Data.tag("third\\nfourth", :red)]) + ...> |> Owl.Data.to_chardata() + Owl.Data.to_chardata(["first\\nsecond\\n", Owl.Data.tag("third\\nfourth", :red)]) """ @spec unlines([t()]) :: [t()] def unlines(data) do @@ -258,16 +258,15 @@ defmodule Owl.Data do end @doc ~S""" - Transforms data to `t:IO.ANSI.ansidata/0` format which can be consumed by `IO` module. + Transforms data to `t:chardata/0` format which can be consumed by `IO` module. ## Examples - iex> "hello" |> Owl.Data.tag(:red) |> Owl.Data.to_ansidata() + iex> "hello" |> Owl.Data.tag(:red) |> Owl.Data.to_chardata() [[[[[] | "\e[31m"], "hello"] | "\e[39m"] | "\e[0m"] - """ - @spec to_ansidata(t()) :: IO.ANSI.ansidata() - def to_ansidata(data) do + @spec to_chardata(t()) :: IO.chardata() + def to_chardata(data) do # combination of lines + unlines is needed in order to break background and do not spread it to the end of the line data |> lines() @@ -276,6 +275,12 @@ defmodule Owl.Data do |> IO.ANSI.format() end + @doc false + @deprecated "Use `Owl.Data.to_chardata/1` instead" + def to_ansidata(data) do + to_chardata(data) + end + defp do_to_ansidata( %Owl.Tag{sequences: sequences, data: data}, open_tags @@ -309,11 +314,11 @@ defmodule Owl.Data do defp do_to_ansidata(term, _open_tags), do: term @doc ~S""" - Transforms data from `t:IO.ANSI.ansidata/0`, replacing raw escape sequences with tags (see `tag/2`). + Transforms chardata, replacing raw escape sequences with tags (see `tag/2`). This makes it possible to use data formatted outside of Owl with other Owl modules, like `Owl.Box`. - The `ansidata` passed to this function must contain escape sequences as separate binaries, not concatenated with other data. + The `data` passed to this function must contain escape sequences as separate binaries, not concatenated with other data. For instance, the following will work: iex> Owl.Data.from_ansidata(["\e[31m", "hello"]) @@ -326,16 +331,22 @@ defmodule Owl.Data do ## Examples - iex> [:red, "hello"] |> IO.ANSI.format() |> Owl.Data.from_ansidata() + iex> [:red, "hello"] |> IO.ANSI.format() |> Owl.Data.from_chardata() Owl.Data.tag("hello", :red) """ - @spec from_ansidata(IO.ANSI.ansidata()) :: t() - def from_ansidata(ansidata) do - {data, _open_tags} = do_from_ansidata(ansidata, %{}) + @spec from_chardata(IO.chardata()) :: t() + def from_chardata(data) do + {data, _open_tags} = do_from_chardata(data, %{}) data end - defp do_from_ansidata(binary, open_tags) when is_binary(binary) do + @doc false + @deprecated "Use `Owl.Data.from_chardata/1` instead" + def from_ansidata(data) do + from_chardata(data) + end + + defp do_from_chardata(binary, open_tags) when is_binary(binary) do case Sequence.ansi_to_type(binary) do :reset -> {[], %{}} @@ -348,21 +359,21 @@ defmodule Owl.Data do end end - defp do_from_ansidata(integer, open_tags) when is_integer(integer) do + defp do_from_chardata(integer, open_tags) when is_integer(integer) do {tag_all(integer, open_tags), open_tags} end - defp do_from_ansidata([], open_tags) do + defp do_from_chardata([], open_tags) do {[], open_tags} end - defp do_from_ansidata([inner], open_tags) do - do_from_ansidata(inner, open_tags) + defp do_from_chardata([inner], open_tags) do + do_from_chardata(inner, open_tags) end - defp do_from_ansidata([head | tail], open_tags) do - {head, open_tags} = do_from_ansidata(head, open_tags) - {tail, open_tags} = do_from_ansidata(tail, open_tags) + defp do_from_chardata([head | tail], open_tags) do + {head, open_tags} = do_from_chardata(head, open_tags) + {tail, open_tags} = do_from_chardata(tail, open_tags) case {head, tail} do {[], _} -> diff --git a/lib/owl/io.ex b/lib/owl/io.ex index d9ec890..f12bde0 100644 --- a/lib/owl/io.ex +++ b/lib/owl/io.ex @@ -444,7 +444,7 @@ defmodule Owl.IO do rest -> puts(rest |> Enum.reverse() |> Owl.Data.unlines()) end - prompt = Owl.Data.to_ansidata(last_row) + prompt = Owl.Data.to_chardata(last_row) pid = spawn_link(fn -> loop_prompt(prompt) end) ref = make_ref() value = IO.gets(prompt) @@ -457,7 +457,7 @@ defmodule Owl.IO do defp gets(false = _secret, prompt) do prompt - |> Owl.Data.to_ansidata() + |> Owl.Data.to_chardata() |> IO.gets() |> normalize_gets_result() end @@ -550,7 +550,7 @@ defmodule Owl.IO do """ @spec puts(Owl.Data.t(), device :: IO.device()) :: :ok def puts(data, device \\ :stdio) do - data = Owl.Data.to_ansidata(data) + data = Owl.Data.to_chardata(data) IO.puts(device, data) end @@ -599,7 +599,7 @@ defmodule Owl.IO do |> Keyword.merge(opts) |> Keyword.update(:label, nil, fn nil -> nil - value -> Owl.Data.to_ansidata(value) + value -> Owl.Data.to_chardata(value) end) ) end diff --git a/lib/owl/progress_bar.ex b/lib/owl/progress_bar.ex index 7b0cd01..884df50 100644 --- a/lib/owl/progress_bar.ex +++ b/lib/owl/progress_bar.ex @@ -260,7 +260,7 @@ defmodule Owl.ProgressBar do ...> partial_symbols: [Owl.Data.tag("-", :green), Owl.Data.tag("=", :blue)], ...> empty_symbol: " ", ...> screen_width: 40 - ...> })|> Owl.Data.to_ansidata() |> to_string + ...> })|> Owl.Data.to_chardata() |> to_string() "Demo [\e[34m=\e[39m ] 4%\e[0m" iex> Owl.ProgressBar.render(%{ diff --git a/lib/owl/table.ex b/lib/owl/table.ex index fe9d742..ad7f0c5 100644 --- a/lib/owl/table.ex +++ b/lib/owl/table.ex @@ -56,7 +56,7 @@ defmodule Owl.Table do ...> padding_x: 1, ...> sort_columns: :desc ...> ) - ...> |> Owl.Data.to_ansidata() + ...> |> Owl.Data.to_chardata() ...> |> to_string() \""" ╭──────────┬──────────╮ diff --git a/test/owl/box_test.exs b/test/owl/box_test.exs index 205f66d..12ad9f3 100644 --- a/test/owl/box_test.exs +++ b/test/owl/box_test.exs @@ -304,8 +304,8 @@ defmodule Owl.BoxTest do assert [Owl.Data.tag("Hi there!", :red), " Hi", [Owl.Data.tag("!!!", :green)]] |> Owl.Box.new(max_width: 6, word_wrap: :normal, border_style: :none) - |> Owl.Data.to_ansidata() - |> Owl.Data.from_ansidata() + |> Owl.Data.to_chardata() + |> Owl.Data.from_chardata() |> List.flatten() == [ Owl.Data.tag("Hi", :red), " ", @@ -322,8 +322,8 @@ defmodule Owl.BoxTest do assert "A B C" |> Owl.Data.tag([:red, :green_background]) |> Owl.Box.new(word_wrap: :normal, border_style: :none, max_width: 80) - |> Owl.Data.to_ansidata() - |> Owl.Data.from_ansidata() + |> Owl.Data.to_chardata() + |> Owl.Data.from_chardata() <~> [ [ [ diff --git a/test/owl/data_test.exs b/test/owl/data_test.exs index e517dba..e0aa57f 100644 --- a/test/owl/data_test.exs +++ b/test/owl/data_test.exs @@ -273,18 +273,18 @@ defmodule Owl.DataTest do end end - test inspect(&Owl.Data.to_ansidata/1) do - assert Owl.Data.to_ansidata(["1", "2", ["3", "4"], "5"]) == [ + test inspect(&Owl.Data.to_chardata/1) do + assert Owl.Data.to_chardata(["1", "2", ["3", "4"], "5"]) == [ [[[[[], "1"], "2"], "3"], "4"], "5" ] - assert Owl.Data.to_ansidata(Owl.Data.tag("Hello", :red)) == [ + assert Owl.Data.to_chardata(Owl.Data.tag("Hello", :red)) == [ [[[[] | "\e[31m"], "Hello"] | "\e[39m"] | "\e[0m" ] assert to_string( - Owl.Data.to_ansidata([ + Owl.Data.to_chardata([ Owl.Data.tag( [ Owl.Data.tag("prefix: ", [:red_background, :yellow]), @@ -302,93 +302,93 @@ defmodule Owl.DataTest do "\e[31m\e[33m\e[41mprefix: \e[49m\e[31mHello\e[33m inner \e[31m world\e[39m\e[34m!!!\e[39m!!\e[0m" ] - assert Owl.Data.to_ansidata([Owl.Data.tag("#", :red), Owl.Data.tag("#", :red)]) == [ + assert Owl.Data.to_chardata([Owl.Data.tag("#", :red), Owl.Data.tag("#", :red)]) == [ [[[[[[[] | "\e[31m"], "#"] | "\e[39m"] | "\e[31m"], "#"] | "\e[39m"] | "\e[0m" ] - assert Owl.Data.to_ansidata(["Hello ", Owl.Data.tag("world", :blink_slow), "!"]) == [ + assert Owl.Data.to_chardata(["Hello ", Owl.Data.tag("world", :blink_slow), "!"]) == [ [[[[[[], "Hello "] | "\e[5m"], "world"] | "\e[25m"], "!"] | "\e[0m" ] - assert Owl.Data.to_ansidata(["Hello ", Owl.Data.tag("world", :blink_rapid), "!"]) == [ + assert Owl.Data.to_chardata(["Hello ", Owl.Data.tag("world", :blink_rapid), "!"]) == [ [[[[[[], "Hello "] | "\e[6m"], "world"] | "\e[25m"], "!"] | "\e[0m" ] - assert Owl.Data.to_ansidata(["Hello ", Owl.Data.tag("world", :faint), "!"]) == [ + assert Owl.Data.to_chardata(["Hello ", Owl.Data.tag("world", :faint), "!"]) == [ [[[[[[], "Hello "] | "\e[2m"], "world"] | "\e[22m"], "!"] | "\e[0m" ] - assert Owl.Data.to_ansidata(["Hello ", Owl.Data.tag("world", :bright), "!"]) == [ + assert Owl.Data.to_chardata(["Hello ", Owl.Data.tag("world", :bright), "!"]) == [ [[[[[[], "Hello "] | "\e[1m"], "world"] | "\e[22m"], "!"] | "\e[0m" ] - assert Owl.Data.to_ansidata(["Hello ", Owl.Data.tag("world", :inverse), "!"]) == [ + assert Owl.Data.to_chardata(["Hello ", Owl.Data.tag("world", :inverse), "!"]) == [ [[[[[[], "Hello "] | "\e[7m"], "world"] | "\e[27m"], "!"] | "\e[0m" ] - assert Owl.Data.to_ansidata(["Hello ", Owl.Data.tag("world", :underline), "!"]) == [ + assert Owl.Data.to_chardata(["Hello ", Owl.Data.tag("world", :underline), "!"]) == [ [[[[[[], "Hello "] | "\e[4m"], "world"] | "\e[24m"], "!"] | "\e[0m" ] - assert Owl.Data.to_ansidata(["Hello ", Owl.Data.tag("world", :italic), "!"]) == [ + assert Owl.Data.to_chardata(["Hello ", Owl.Data.tag("world", :italic), "!"]) == [ [[[[[[], "Hello "] | "\e[3m"], "world"] | "\e[23m"], "!"] | "\e[0m" ] - assert Owl.Data.to_ansidata(["Hello ", Owl.Data.tag("world", :overlined), "!"]) == [ + assert Owl.Data.to_chardata(["Hello ", Owl.Data.tag("world", :overlined), "!"]) == [ [[[[[[], "Hello "] | "\e[53m"], "world"] | "\e[55m"], "!"] | "\e[0m" ] - assert Owl.Data.to_ansidata(["Hello ", Owl.Data.tag("world", :reverse), "!"]) == [ + assert Owl.Data.to_chardata(["Hello ", Owl.Data.tag("world", :reverse), "!"]) == [ [[[[[[], "Hello "] | "\e[7m"], "world"] | "\e[27m"], "!"] | "\e[0m" ] - assert Owl.Data.to_ansidata(["Hello ", Owl.Data.tag("world", :light_red), "!"]) == [ + assert Owl.Data.to_chardata(["Hello ", Owl.Data.tag("world", :light_red), "!"]) == [ [[[[[[], "Hello "] | "\e[91m"], "world"] | "\e[39m"], "!"] | "\e[0m" ] - assert Owl.Data.to_ansidata(["Hello ", Owl.Data.tag("world", :light_red_background), "!"]) == + assert Owl.Data.to_chardata(["Hello ", Owl.Data.tag("world", :light_red_background), "!"]) == [[[[[[[], "Hello "] | "\e[101m"], "world"] | "\e[49m"], "!"] | "\e[0m"] - assert Owl.Data.to_ansidata(["Hello ", Owl.Data.tag("world", :default_color), "!"]) == [ + assert Owl.Data.to_chardata(["Hello ", Owl.Data.tag("world", :default_color), "!"]) == [ [[[[[[], "Hello "] | "\e[39m"], "world"] | "\e[39m"], "!"] | "\e[0m" ] - assert Owl.Data.to_ansidata(["Hello ", Owl.Data.tag("world", :default_background), "!"]) == [ + assert Owl.Data.to_chardata(["Hello ", Owl.Data.tag("world", :default_background), "!"]) == [ [[[[[[], "Hello "] | "\e[49m"], "world"] | "\e[49m"], "!"] | "\e[0m" ] - assert Owl.Data.to_ansidata(["Hello ", Owl.Data.tag("world", IO.ANSI.color(161)), "!"]) == [ + assert Owl.Data.to_chardata(["Hello ", Owl.Data.tag("world", IO.ANSI.color(161)), "!"]) == [ [[[[[[], "Hello "], "\e[38;5;161m"], "world"] | "\e[39m"], "!"] | "\e[0m" ] - assert Owl.Data.to_ansidata([ + assert Owl.Data.to_chardata([ "Hello ", Owl.Data.tag("world", IO.ANSI.color_background(161)), "!" ]) == [[[[[[[], "Hello "], "\e[48;5;161m"], "world"] | "\e[49m"], "!"] | "\e[0m"] - assert Owl.Data.to_ansidata([Owl.Data.tag([Owl.Data.tag("Hello ", :red), " world"], :red)]) == + assert Owl.Data.to_chardata([Owl.Data.tag([Owl.Data.tag("Hello ", :red), " world"], :red)]) == [[[[[[[] | "\e[31m"] | "\e[31m"], "Hello "], " world"] | "\e[39m"] | "\e[0m"] end - describe inspect(&Owl.Data.from_ansidata/1) do - test "converting to ansidata and back" do - assert to_from_ansidata(Owl.Data.tag("Hello", :red)) == + describe inspect(&Owl.Data.from_chardata/1) do + test "converting to chardata and back" do + assert to_from_chardata(Owl.Data.tag("Hello", :red)) == Owl.Data.tag("Hello", :red) - assert to_from_ansidata(Owl.Data.tag(["Hello", ?!], :red)) == + assert to_from_chardata(Owl.Data.tag(["Hello", ?!], :red)) == Owl.Data.tag(["Hello", "!"], :red) - assert to_from_ansidata([Owl.Data.tag("Hello", :red), ?!]) == + assert to_from_chardata([Owl.Data.tag("Hello", :red), ?!]) == [Owl.Data.tag("Hello", :red), "!"] - assert to_from_ansidata(["Hello ", Owl.Data.tag("world", :underline), "!"]) == + assert to_from_chardata(["Hello ", Owl.Data.tag("world", :underline), "!"]) == [["Hello ", Owl.Data.tag("world", :underline)], "!"] - assert to_from_ansidata(["Hello ", Owl.Data.tag("world", [:red, :underline]), "!"]) + assert to_from_chardata(["Hello ", Owl.Data.tag("world", [:red, :underline]), "!"]) <~> [["Hello ", Owl.Data.tag("world", [:red, :underline])], "!"] - assert to_from_ansidata( + assert to_from_chardata( Owl.Data.tag(["Hello, ", Owl.Data.tag("world", :underline), "!"], :red) ) <~> [ @@ -396,16 +396,16 @@ defmodule Owl.DataTest do Owl.Data.tag("!", :red) ] - assert to_from_ansidata(["Hello ", Owl.Data.tag("world", IO.ANSI.color(161)), "!"]) == + assert to_from_chardata(["Hello ", Owl.Data.tag("world", IO.ANSI.color(161)), "!"]) == [["Hello ", Owl.Data.tag("world", "\e[38;5;161m")], "!"] - assert to_from_ansidata([ + assert to_from_chardata([ "Hello ", Owl.Data.tag("world", IO.ANSI.color_background(161)), "!" ]) == [["Hello ", Owl.Data.tag("world", "\e[48;5;161m")], "!"] - assert to_from_ansidata([ + assert to_from_chardata([ Owl.Data.tag( [ Owl.Data.tag("prefix: ", [:red_background, :yellow]), @@ -436,13 +436,13 @@ defmodule Owl.DataTest do ] end - test "converts ansidata highlighted using Inspect.Algebra" do - ansidata = + test "converts chardata highlighted using Inspect.Algebra" do + chardata = [foo: 1, bar: "two"] |> Inspect.Algebra.to_doc(Inspect.Opts.new(syntax_colors: IO.ANSI.syntax_colors())) |> Inspect.Algebra.format(:infinity) - assert Owl.Data.from_ansidata(ansidata) == [ + assert Owl.Data.from_chardata(chardata) == [ "[", [ "", @@ -469,28 +469,28 @@ defmodule Owl.DataTest do ] end - test "converts ansidata fragments" do - assert [:red, "Hello"] |> IO.ANSI.format_fragment() |> Owl.Data.from_ansidata() == + test "converts chardata fragments" do + assert [:red, "Hello"] |> IO.ANSI.format_fragment() |> Owl.Data.from_chardata() == Owl.Data.tag("Hello", :red) assert [:red, "Hello ", [:yellow, "world"]] |> IO.ANSI.format_fragment() - |> Owl.Data.from_ansidata() == [ + |> Owl.Data.from_chardata() == [ Owl.Data.tag("Hello ", :red), Owl.Data.tag("world", :yellow) ] end test "converts from charlists" do - assert Owl.Data.from_ansidata(["\e[31m", ~c"Hello"]) == Owl.Data.tag(~c"Hello", :red) + assert Owl.Data.from_chardata(["\e[31m", ~c"Hello"]) == Owl.Data.tag(~c"Hello", :red) end test "does not convert data concatenated with escape sequences" do - assert Owl.Data.from_ansidata(["\e[31mHello\e[0m"]) == "\e[31mHello\e[0m" + assert Owl.Data.from_chardata(["\e[31mHello\e[0m"]) == "\e[31mHello\e[0m" end - defp to_from_ansidata(tagged) do - tagged |> Owl.Data.to_ansidata() |> Owl.Data.from_ansidata() + defp to_from_chardata(tagged) do + tagged |> Owl.Data.to_chardata() |> Owl.Data.from_chardata() end end diff --git a/test/owl/table_test.exs b/test/owl/table_test.exs index 31409cd..430fde2 100644 --- a/test/owl/table_test.exs +++ b/test/owl/table_test.exs @@ -501,9 +501,9 @@ defmodule Owl.TableTest do table = Owl.Table.new(rows, opts) expected_result = String.trim_trailing(expected_result, "\n") - assert table |> Owl.Data.to_ansidata() |> to_string() == expected_result, + assert table |> Owl.Data.to_chardata() |> to_string() == expected_result, to_string( - Owl.Data.to_ansidata([ + Owl.Data.to_chardata([ "Tables do not match\n", Owl.Data.tag("result:", :cyan), "\n",