Skip to content

Commit

Permalink
Fix Snapshot.regroup/2 when special char starts the line
Browse files Browse the repository at this point in the history
  • Loading branch information
ku1ik committed Mar 20, 2024
1 parent a501af0 commit b78cf33
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 9 deletions.
28 changes: 19 additions & 9 deletions lib/asciinema/recordings/snapshot.ex
Original file line number Diff line number Diff line change
Expand Up @@ -93,20 +93,30 @@ defmodule Asciinema.Recordings.Snapshot do

defp group_line_segments([]), do: []

defp group_line_segments([first_segment | segments]) do
defp group_line_segments(cells) do
{segments, last_segment} =
Enum.reduce(segments, {[], first_segment}, fn {char, attrs, char_width},
{segments,
{prev_char, prev_attrs, prev_char_width}} ->
if attrs == prev_attrs && char_width == prev_char_width && char_width == 1 &&
!special_char(char) do
{segments, {prev_char <> char, attrs, char_width}}
Enum.reduce(cells, {[], nil}, fn {cur_char, cur_attrs, cur_char_width} = current,
{segments, prev} ->
if cur_char_width > 1 || special_char(cur_char) do
{[current, prev | segments], nil}
else
{[{prev_char, prev_attrs, prev_char_width} | segments], {char, attrs, char_width}}
case prev do
{prev_chars, prev_attrs, prev_char_width} ->
if cur_attrs == prev_attrs && cur_char_width == prev_char_width do
{segments, {prev_chars <> cur_char, prev_attrs, prev_char_width}}
else
{[prev | segments], current}
end

nil ->
{segments, current}
end
end
end)

Enum.reverse([last_segment | segments])
[last_segment | segments]
|> Enum.filter(& &1)
|> Enum.reverse()
end

@box_drawing_range Range.new(0x2500, 0x257F)
Expand Down
85 changes: 85 additions & 0 deletions test/asciinema/recordings/snapshot_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,91 @@ defmodule Asciinema.Recordings.SnapshotTest do
|> Map.get(:lines)
end

describe "regroup/2" do
test "splits into individual chars" do
lines = [[[" foo bar ", %{fg: 1}, 1]]]

lines =
lines
|> Snapshot.new(:segments)
|> Snapshot.regroup(:cells)
|> Map.get(:lines)

assert lines == [
[
{" ", %{fg: 1}, 1},
{"f", %{fg: 1}, 1},
{"o", %{fg: 1}, 1},
{"o", %{fg: 1}, 1},
{" ", %{fg: 1}, 1},
{"b", %{fg: 1}, 1},
{"a", %{fg: 1}, 1},
{"r", %{fg: 1}, 1},
{" ", %{fg: 1}, 1}
]
]
end

test "groups into multi-char segments" do
lines = [
[
[" ", %{fg: 1}, 1],
["f", %{fg: 1}, 1],
["o", %{fg: 2}, 1],
["o", %{fg: 2}, 1],
[" ", %{fg: 1}, 1],
["b", %{fg: 1}, 1],
["a", %{fg: 1}, 1],
["r", %{fg: 1}, 1],
["连", %{fg: 1}, 2]
]
]

lines =
lines
|> Snapshot.new(:cells)
|> Snapshot.regroup(:segments)
|> Map.get(:lines)

assert lines == [[
{" f", %{fg: 1}, 1},
{"oo", %{fg: 2}, 1},
{" bar", %{fg: 1}, 1},
{"连", %{fg: 1}, 2},
]]
end

test "keeps special chars in their own segments" do
lines = [
[
["▚", %{}, 1],
["f", %{}, 1],
["o", %{}, 1],
["o", %{}, 1],
["▚", %{}, 1],
["b", %{}, 1],
["a", %{}, 1],
["r", %{}, 1],
["▚", %{}, 1]
]
]

lines =
lines
|> Snapshot.new(:cells)
|> Snapshot.regroup(:segments)
|> Map.get(:lines)

assert lines == [[
{"▚", %{}, 1},
{"foo", %{}, 1},
{"▚", %{}, 1},
{"bar", %{}, 1},
{"▚", %{}, 1},
]]
end
end

describe "crop/3" do
test "blank taller terminal" do
assert crop(
Expand Down

0 comments on commit b78cf33

Please sign in to comment.