From f08ab265647f085b4f9126fd728431beb7f43092 Mon Sep 17 00:00:00 2001 From: Marcin Kulik Date: Thu, 17 Oct 2024 11:17:58 +0200 Subject: [PATCH] Use more compact RGB color notation for snapshots --- lib/asciinema/recordings/snapshot.ex | 16 +++++++++++++--- native/vt_nif/src/lib.rs | 4 ++-- test/asciinema/recordings/snapshot_test.exs | 17 ++++++++++++++--- test/asciinema/vt_test.exs | 7 ++++--- 4 files changed, 33 insertions(+), 11 deletions(-) diff --git a/lib/asciinema/recordings/snapshot.ex b/lib/asciinema/recordings/snapshot.ex index 6b1ca6ea6..ec0edc6ad 100644 --- a/lib/asciinema/recordings/snapshot.ex +++ b/lib/asciinema/recordings/snapshot.ex @@ -180,11 +180,13 @@ defmodule Asciinema.Recordings.Snapshot do case {k, v} do {"fg", c} when is_number(c) and c < 8 -> "3#{c}" {"fg", c} when is_number(c) -> "38;5;#{c}" - {"fg", "rgb(" <> _} -> "38;2;#{parse_rgb(v)}" + {"fg", "#" <> _} -> "38;2;#{parse_hex_color(v)}" + {"fg", "rgb(" <> _} -> "38;2;#{parse_rgb_color(v)}" {"fg", [r, g, b]} -> "38;2;#{r};#{g};#{b}" {"bg", c} when is_number(c) and c < 8 -> "4#{c}" {"bg", c} when is_number(c) -> "48;5;#{c}" - {"bg", "rgb(" <> _} -> "48;2;#{parse_rgb(v)}" + {"bg", "#" <> _} -> "48;2;#{parse_hex_color(v)}" + {"bg", "rgb(" <> _} -> "48;2;#{parse_rgb_color(v)}" {"bg", [r, g, b]} -> "48;2;#{r};#{g};#{b}" {"bold", true} -> "1" {"faint", true} -> "2" @@ -200,7 +202,15 @@ defmodule Asciinema.Recordings.Snapshot do defp sgr_params([]), do: [] - defp parse_rgb("rgb(" <> c) do + defp parse_hex_color(<<"#", r::binary-size(2), g::binary-size(2), b::binary-size(2)>>) do + r = String.to_integer(r, 16) + g = String.to_integer(g, 16) + b = String.to_integer(b, 16) + + "#{r};#{g};#{b}" + end + + defp parse_rgb_color("rgb(" <> c) do c |> String.slice(0, String.length(c) - 1) |> String.split(",") diff --git a/native/vt_nif/src/lib.rs b/native/vt_nif/src/lib.rs index f80e3f86e..1e7242c39 100644 --- a/native/vt_nif/src/lib.rs +++ b/native/vt_nif/src/lib.rs @@ -129,7 +129,7 @@ fn chunk_to_term(cells: Vec, env: Env) -> Term { } Some(avt::Color::RGB(c)) => { - let c = format!("rgb({},{},{})", c.r, c.g, c.b); + let c = format!("#{:02x}{:02x}{:02x}", c.r, c.g, c.b); pairs.push(("fg".to_owned(), c.encode(env))); } @@ -142,7 +142,7 @@ fn chunk_to_term(cells: Vec, env: Env) -> Term { } Some(avt::Color::RGB(c)) => { - let c = format!("rgb({},{},{})", c.r, c.g, c.b); + let c = format!("#{:02x}{:02x}{:02x}", c.r, c.g, c.b); pairs.push(("bg".to_owned(), c.encode(env))); } diff --git a/test/asciinema/recordings/snapshot_test.exs b/test/asciinema/recordings/snapshot_test.exs index 0e2e17d62..4555d9f25 100644 --- a/test/asciinema/recordings/snapshot_test.exs +++ b/test/asciinema/recordings/snapshot_test.exs @@ -180,7 +180,7 @@ defmodule Asciinema.Recordings.SnapshotTest do @lines [ [[" foo bar baz", %{"bg" => 2}, 1], ["!", %{"fg" => 1}, 1]], - [["qux", %{"bg" => 2}, 1], ["连", %{}, 2], ["接", %{}, 2]] + [["qux", %{"bg" => "#102030"}, 1], ["连", %{}, 2], ["接", %{}, 2]] ] describe "fg_coords/1" do @@ -202,7 +202,7 @@ defmodule Asciinema.Recordings.SnapshotTest do %{ y: 1, segments: [ - %{text: "qux", attrs: %{"bg" => 2}, x: 0, width: 3}, + %{text: "qux", attrs: %{"bg" => "#102030"}, x: 0, width: 3}, %{text: "连", attrs: %{}, x: 3, width: 2}, %{text: "接", attrs: %{}, x: 5, width: 2} ] @@ -228,10 +228,21 @@ defmodule Asciinema.Recordings.SnapshotTest do %{ y: 1, segments: [ - %{attrs: %{"bg" => 2}, x: 0, width: 3} + %{attrs: %{"bg" => "#102030"}, x: 0, width: 3} ] } ] end end + + describe "seq/1" do + test "dumps snapshot as an ANSI sequence" do + seq = + @lines + |> Snapshot.new() + |> Snapshot.seq() + + assert seq == "\e[42m foo bar baz\e[0m\e[31m!\e[0m\r\n\e[48;2;16;32;48mqux\e[0m连接\e[?25l" + end + end end diff --git a/test/asciinema/vt_test.exs b/test/asciinema/vt_test.exs index 1352eb6b5..518171d55 100644 --- a/test/asciinema/vt_test.exs +++ b/test/asciinema/vt_test.exs @@ -10,7 +10,8 @@ defmodule Asciinema.VtTest do Vt.with_vt(8, 3, fn vt -> Vt.feed(vt, "foobar\r\n") Vt.feed(vt, "baz") - Vt.feed(vt, "全") + Vt.feed(vt, "全\r\n") + Vt.feed(vt, "\x1b[1;38:2:16:32:48mqux") Vt.dump_screen(vt) end) @@ -18,8 +19,8 @@ defmodule Asciinema.VtTest do {[ [{"foobar ", %{}, 1}], [{"baz", %{}, 1}, {"全", %{}, 2}, {" ", %{}, 1}], - [{" ", %{}, 1}] - ], {4, 1}}} = result + [{"qux", %{"bold" => true, "fg" => "#102030"}, 1}, {" ", %{}, 1}] + ], {3, 2}}} = result end test "feeding it a lot of data" do