Skip to content

Commit

Permalink
Switched to minipeg for color parsing
Browse files Browse the repository at this point in the history
	Hex RGB added

	Next:
	Fix dialyzer
	Fix warnings
	Get to test coverage 100%
  • Loading branch information
RobertDober committed Dec 4, 2024
1 parent 771fd5a commit dabbcca
Show file tree
Hide file tree
Showing 9 changed files with 106 additions and 21 deletions.
5 changes: 5 additions & 0 deletions lib/ex_aequo_colors.ex
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ defmodule ExAequoColors do
Color.color_reset(to_string(subject), [flag1, flag2])
end

@doc """
Convenience delegation
"""
defdelegate colorize(line, options), to: Colorizer
defdelegate colorize(line), to: Colorizer

def version, do: @version
end
Expand Down
2 changes: 1 addition & 1 deletion lib/ex_aequo_colors/cli.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ defmodule ExAequoColors.Cli do
alias ExAequoColors.Colorizer.Parser, as: Parser
import ExAequoBase.Map, only: [put_if: 3]
import ExAequoColors.Color, only: [color: 2]
import ExAequoColors.Colorizer, only: [colorize: 1, colorize: 2, colorize!: 3, mk_options_and_rgxen: 1]
import ExAequoColors.Colorizer, only: [colorize: 1, colorize: 2, colorize!: 3]

@moduledoc false

Expand Down
2 changes: 1 addition & 1 deletion lib/ex_aequo_colors/color.ex
Original file line number Diff line number Diff line change
Expand Up @@ -516,7 +516,7 @@ defmodule ExAequoColors.Color do
|> Enum.join()
end

def color_code(colorspec), do: _extract_code(:reset)
def color_code(colorspec), do: _extract_code(colorspec)

@doc ~S"""
Transform a string and color specifications into an IO Chardata with a
Expand Down
31 changes: 26 additions & 5 deletions lib/ex_aequo_colors/colorizer.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ defmodule ExAequoColors.Colorizer do

alias ExAequoColors.Color
alias ExAequoColors.Colorizer.Parser, as: Parser
import ExAequoBase.Enum, only: [map_ok: 2]
import ExAequoBase.Fn, only: [select: 1]
import ExAequoBase.Text, only: [behead: 2, parse_up_to: 3]

import ExAequoBase.Map, only: [put_if: 3]

@moduledoc ~S"""
Backend of the cli
Expand All @@ -17,6 +16,7 @@ defmodule ExAequoColors.Colorizer do
@default_options %{
trigger: "<",
closer: ">",
reset: "",
resetter: "$"
}

Expand Down Expand Up @@ -68,6 +68,19 @@ defmodule ExAequoColors.Colorizer do
iex(8)> colorize("!red!!!<$", trigger: "!", closer: "!")
"\e[31m!<\e[0m"
# rgb
In three decimal numbers....
iex(9)> colorize("<12,255,0>rgb")
"\e[38;2;12;255;0mrgb"
or in hex
iex(9)> colorize("<#0cff00>rgb")
"\e[38;2;12;255;0mrgb"
"""

@spec colorize(binary()) :: color_t()
Expand All @@ -81,14 +94,22 @@ defmodule ExAequoColors.Colorizer do
end

def colorize(lines, options) do
options1 = make_options(options)
lines
|> Enum.map(&Minipeg.Parser.parse_string(Parser.chunks_parser(options), &1))
|> Enum.join(options.reset <> "\n")
|> Enum.map(&Minipeg.Parser.parse_string!(Parser.chunks_parser(options1), &1))
# |> IO.inspect
|> Enum.join(options1.reset <> "\n")
end

def colorize!(line, parser, options) do
Minipeg.Parser.parse_string(parser) <> options.reset
end

def make_options(options) do
options
|> Enum.into(@default_options)
|> put_if(Keyword.get(options, :auto), reset: Color.color_code(:reset))
end
end

# SPDX-License-Identifier: AGPL-3.0-or-later
63 changes: 54 additions & 9 deletions lib/ex_aequo_colors/colorizer/parser.ex
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ defmodule ExAequoColors.Colorizer.Parser do

defp color_code(ast) do
ast
|> Enum.join
|> IO.chardata_to_string
|> String.to_atom
|> Color.color_code
end

Expand All @@ -47,7 +48,8 @@ defmodule ExAequoColors.Colorizer.Parser do
defp color_part_parser do
select([
color_name_parser(),
rgb_parser()
rgb_dec_parser(),
rgb_hex_parser()
])
end

Expand All @@ -56,12 +58,28 @@ defmodule ExAequoColors.Colorizer.Parser do
|> satisfy(&Enum.member?(0..255, &1))
end

defp hex_bytes_parser do
hex_digit_parser = char_parser("0123456789abcdefABCDEF")
sequence([
hex_digit_parser,
hex_digit_parser,
hex_digit_parser,
maybe(
sequence([
hex_digit_parser,
hex_digit_parser,
hex_digit_parser,
]))])
end

defp doubled_special_char_parser(options) do
trigger = options.trigger |> String.at(0)
closer = options.closer |> String.at(0)
resetter = options.resetter |> String.at(0)
select([
literal_parser(trigger <> trigger),
literal_parser(closer <> closer),
literal_parser(resetter <> resetter), # |> debug(),
])
|> map(&String.at(&1, 0))
end
Expand All @@ -78,11 +96,30 @@ defmodule ExAequoColors.Colorizer.Parser do
|> map(fn _ -> Color.color_code(:reset) end)
end

defp rgb_color(rgb_ast)
defp rgb_color([r, _, g, _, b]) do
Color.color_code({r, g, b})
end
defp rgb_color(["#", [a, b, c, [d, e, f]]]) do
hex_to_dec(a, b, c, d, e, f)
|> Color.color_code
end
defp rgb_color(["#", [a, b, c, nil]]) do
hex_to_dec(a, "0", b, "0", c, "0")
|> Color.color_code
end

defp rgb_parser do
defp hex_to_dec(a, b, c, d, e, f) do
with {r, ""} <- a <> b |> Integer.parse(16) do
with {g, ""} <- c <> d |> Integer.parse(16) do
with {b, ""} <- e <> f |> Integer.parse(16) do
{r, g, b}
end
end
end
end

defp rgb_dec_parser do
sequence([
dec_byte_parser(),
char_parser(","),
Expand All @@ -93,6 +130,14 @@ defmodule ExAequoColors.Colorizer.Parser do
|> map(&rgb_color/1)
end

defp rgb_hex_parser do
sequence([
char_parser("#"),
hex_bytes_parser(),
])
|> map(&rgb_color/1)
end

defp second_color_part_parser do
sequence([
char_parser(","),
Expand All @@ -103,12 +148,12 @@ defmodule ExAequoColors.Colorizer.Parser do

defp text_parser(options) do
many_as_string(
[
options.trigger,
options.resetter,
]
|> Enum.map(&String.at(&1, 0))
|> not_char_parser(), nil, 1)
[
options.trigger,
options.resetter,
]
|> Enum.map(&String.at(&1, 0))
|> not_char_parser(), nil, 1)
end
end
# SPDX-License-Identifier: AGPL-3.0-or-later
6 changes: 3 additions & 3 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ defmodule ExAequoColors.MixProject do
# Run "mix help deps" to learn about dependencies.
defp deps do
[
{:dialyxir, "~> 1.4.3", only: [:dev], runtime: false},
{:dialyxir, "~> 1.4.5", only: [:dev], runtime: false},
# {:ex_aequo_fn, "~> 0.1.0"},
{:ex_aequo_base, "~> 0.1.5"},
{:excoveralls, "~> 0.18.2", only: [:test]},
{:excoveralls, "~> 0.18.3", only: [:test]},
{:extractly, "~> 0.5.4", only: [:dev]},
{:minipeg, "~> 0.6.5"}
{:minipeg, "~> 0.7.0"}
]
end

Expand Down
4 changes: 2 additions & 2 deletions mix.lock
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
%{
"dialyxir": {:hex, :dialyxir, "1.4.4", "fb3ce8741edeaea59c9ae84d5cec75da00fa89fe401c72d6e047d11a61f65f70", [:mix], [{:erlex, ">= 0.2.7", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "cd6111e8017ccd563e65621a4d9a4a1c5cd333df30cebc7face8029cacb4eff6"},
"dialyxir": {:hex, :dialyxir, "1.4.5", "ca1571ac18e0f88d4ab245f0b60fa31ff1b12cbae2b11bd25d207f865e8ae78a", [:mix], [{:erlex, ">= 0.2.7", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "b0fb08bb8107c750db5c0b324fa2df5ceaa0f9307690ee3c1f6ba5b9eb5d35c3"},
"erlex": {:hex, :erlex, "0.2.7", "810e8725f96ab74d17aac676e748627a07bc87eb950d2b83acd29dc047a30595", [:mix], [], "hexpm", "3ed95f79d1a844c3f6bf0cea61e0d5612a42ce56da9c03f01df538685365efb0"},
"ex_aequo_base": {:hex, :ex_aequo_base, "0.1.5", "f528cb921cb97ba008457eff9bfdf657495c68b2d9d8e89a5dfd64cbd6eb34de", [:mix], [{:ex_aequo_fn, "~> 0.1.2", [hex: :ex_aequo_fn, repo: "hexpm", optional: false]}], "hexpm", "55377f8bcf6332567b451d39aa57619bcd1ed4ba3dddc880a68136d6702ef68e"},
"ex_aequo_fn": {:hex, :ex_aequo_fn, "0.1.2", "d3c6ae73bafb1f2e1661e2b2dc4b548e577ebd7cc24d22afb0efbe1b8dca16ba", [:mix], [], "hexpm", "6e8cecd6e37dc3cd896dc631c5eb2e766e0ff6b914d110cdeedace9bc7ac1d8f"},
"excoveralls": {:hex, :excoveralls, "0.18.3", "bca47a24d69a3179951f51f1db6d3ed63bca9017f476fe520eb78602d45f7756", [:mix], [{:castore, "~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "746f404fcd09d5029f1b211739afb8fb8575d775b21f6a3908e7ce3e640724c6"},
"extractly": {:hex, :extractly, "0.5.4", "22ff3a624d814227ba842a2b59a38b1298df5531dbd4772dcbe9b97e05627145", [:mix], [], "hexpm", "612e16920317b2fb963b2da013019a614ba12b928d535a053a1efb21ddaa6268"},
"jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"},
"minipeg": {:hex, :minipeg, "0.6.5", "dafbaeb2e7970ff5e2d1604dec46abcc92aaf0918088c511849f4e79751916d2", [:mix], [], "hexpm", "8ac5a89eacdcb699c8f2d7dc0acd40a9930dc65212cce55d0741cca911e478cc"},
"minipeg": {:hex, :minipeg, "0.7.0", "232d6762560357433e8e4556d9e9d38459ccef80ed13e64e8784ccb8b08a7e0c", [:mix], [], "hexpm", "d9509eab735a410463141d2b9a9713374b4f0d5c97d44cadb64f0a8f23924aaf"},
}
1 change: 1 addition & 0 deletions test/color/basic_ansi_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ defmodule Test.Color.BasicAnsiTest do
assert col("red", :red) == "\e[31mred"
end
end

# defmodule Test.ExAequo.ColorTest do
# use ExUnit.Case

Expand Down
13 changes: 13 additions & 0 deletions test/ex_aequo_colors/colorizer_test.exs
Original file line number Diff line number Diff line change
@@ -1,7 +1,20 @@
defmodule Test.ExAequoColors.ColorizerTest do
use ExUnit.Case

import ExAequoColors.Colorizer
doctest ExAequoColors.Colorizer, import: true

describe "rgb" do
test "in dec" do
assert colorize("<23,240,31>rgb dec") == "\e[38;2;23;240;31mrgb dec"
end
test "in hex, 6 bytes" do
assert colorize("<#17f01f>rgb hex 6") == "\e[38;2;23;240;31mrgb hex 6"
end
test "in hex, 3 bytes" do
assert colorize("<#fd8>rgb hex 3") == "\e[38;2;240;208;128mrgb hex 3"
end
end

end
# SPDX-License-Identifier: AGPL-3.0-or-later

0 comments on commit dabbcca

Please sign in to comment.