Ignore RFC 1468 switch to ASCII code sequence (#225)

This ignores "\e(B" which sometimes shows up even when the other RFC
1468 Japanese character set switch codes aren't used. This also updates
defmodifier so that it can be used with non-CSI escape codes (the
ones that start with '[').
This commit is contained in:
Frank Hunleth 2021-04-20 09:05:30 -04:00 committed by GitHub
parent 5100d2723a
commit b1ceedc220
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 16 additions and 6 deletions

View file

@ -3,7 +3,7 @@ defmodule Livebook.ANSI.Modifier do
defmacro defmodifier(modifier, code, terminator \\ "m") do
quote bind_quoted: [modifier: modifier, code: code, terminator: terminator] do
defp ansi_prefix_to_modifier(unquote("#{code}#{terminator}") <> rest) do
defp ansi_prefix_to_modifier(unquote("[#{code}#{terminator}") <> rest) do
{:ok, unquote(modifier), rest}
end
end
@ -43,7 +43,7 @@ defmodule LivebookWeb.ANSI do
def ansi_string_to_html(string, opts \\ []) do
renderer = Keyword.get(opts, :renderer, &default_renderer/2)
[head | ansi_prefixed_strings] = String.split(string, "\e[")
[head | ansi_prefixed_strings] = String.split(string, "\e")
{:safe, head_html} = Phoenix.HTML.html_escape(head)
head_html = renderer.("", head_html)
@ -58,7 +58,7 @@ defmodule LivebookWeb.ANSI do
{modifiers, rest}
{:error, _rest} ->
{modifiers, "\e[" <> string}
{modifiers, "\e" <> string}
end
{:safe, content} = Phoenix.HTML.html_escape(rest)
@ -73,7 +73,7 @@ defmodule LivebookWeb.ANSI do
end
# Below goes a number of `ansi_prefix_to_modifier` function definitions,
# that take a string like "32msomething" (starting with ANSI code without the leading "\e[")
# that take a string like "[32msomething" (starting with ANSI code without the leading "\e")
# and parse the prefix into the corresponding modifier.
# The function returns either {:ok, modifier, rest} or {:error, rest}
@ -105,18 +105,24 @@ defmodule LivebookWeb.ANSI do
defmodifier({:text_decoration, :overline}, 53)
defmodifier({:text_decoration, :reset}, 55)
defp ansi_prefix_to_modifier("38;5;" <> string) do
defp ansi_prefix_to_modifier("[38;5;" <> string) do
with {:ok, color, rest} <- bit8_prefix_to_color(string) do
{:ok, {:foreground_color, color}, rest}
end
end
defp ansi_prefix_to_modifier("48;5;" <> string) do
defp ansi_prefix_to_modifier("[48;5;" <> string) do
with {:ok, color, rest} <- bit8_prefix_to_color(string) do
{:ok, {:background_color, color}, rest}
end
end
# "\e(B" is RFC1468's switch to ASCII character set and can be ignored. This
# can appear even when JIS character sets aren't in use.
defp ansi_prefix_to_modifier("(B" <> rest) do
{:ok, :ignored, rest}
end
defp bit8_prefix_to_color(string) do
case Integer.parse(string) do
{n, "m" <> rest} when n in 0..255 ->

View file

@ -94,5 +94,9 @@ defmodule LivebookWeb.ANSITest do
ANSI.ansi_string_to_html("cat", renderer: div_renderer)
|> Phoenix.HTML.safe_to_string()
end
test "ignores RFC 1468 switch to ASCII" do
assert ~s{cat} == ANSI.ansi_string_to_html("\e(Bcat") |> Phoenix.HTML.safe_to_string()
end
end
end