-module(string_width@internal@ansi). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/string_width/internal/ansi.gleam"). -export([match/1, strip/1]). -export_type([state/0]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. ?MODULEDOC(false). -type state() :: text | {escape, integer()} | {c_s_i, integer()} | {o_s_c, integer()} | {o_s_c_esc, integer()}. -file("src/string_width/internal/ansi.gleam", 28). ?DOC(false). -spec match(binary()) -> list({integer(), integer()}). match(Str) -> {_, _, Matches@1} = begin string_width_ffi:fold_bytes( Str, {0, text, []}, fun(_use0, Byte) -> {Pos, State, Matches} = _use0, case State of text -> case Byte of 16#1b -> {Pos + 1, {escape, Pos}, Matches}; _ -> {Pos + 1, State, Matches} end; {escape, Start} -> case Byte of 16#5b -> {Pos + 1, {c_s_i, Start}, Matches}; 16#5d -> {Pos + 1, {o_s_c, Start}, Matches}; _ when (Byte >= 16#30) andalso (Byte =< 16#3f) -> {Pos + 1, text, [{Start, (Pos - Start) + 1} | Matches]}; 16#50 -> {Pos + 1, {o_s_c, Start}, Matches}; 16#58 -> {Pos + 1, {o_s_c, Start}, Matches}; 16#5e -> {Pos + 1, {o_s_c, Start}, Matches}; 16#5f -> {Pos + 1, {o_s_c, Start}, Matches}; _ when (Byte >= 16#40) andalso (Byte =< 16#5f) -> {Pos + 1, text, [{Start, (Pos - Start) + 1} | Matches]}; _ when (Byte >= 16#60) andalso (Byte =< 16#7e) -> {Pos + 1, text, [{Start, (Pos - Start) + 1} | Matches]}; _ -> {Pos + 1, text, Matches} end; {c_s_i, Start@1} -> case Byte of _ when (Byte >= 16#20) andalso (Byte =< 16#3f) -> {Pos + 1, State, Matches}; _ when (Byte >= 16#40) andalso (Byte =< 16#7e) -> {Pos + 1, text, [{Start@1, (Pos - Start@1) + 1} | Matches]}; _ -> {Pos + 1, text, Matches} end; {o_s_c, Start@2} -> case Byte of 16#07 -> {Pos + 1, text, [{Start@2, (Pos - Start@2) + 1} | Matches]}; 16#1b -> {Pos + 1, {o_s_c_esc, Start@2}, Matches}; _ -> {Pos + 1, State, Matches} end; {o_s_c_esc, Start@3} -> case Byte of 16#5c -> {Pos + 1, text, [{Start@3, (Pos - Start@3) + 1} | Matches]}; 16#07 -> {Pos + 1, text, [{Start@3, (Pos - Start@3) + 1} | Matches]}; _ -> {Pos + 1, {o_s_c, Start@3}, Matches} end end end ) end, lists:reverse(Matches@1). -file("src/string_width/internal/ansi.gleam", 16). ?DOC(false). -spec do_strip(binary(), integer(), list({integer(), integer()}), binary()) -> binary(). do_strip(Str, Offset, Matches, Acc) -> case Matches of [] -> <>; [{From, Len} | Matches@1] -> {Before, At_ansi} = erlang:split_binary(Str, From - Offset), {_, Str@1} = erlang:split_binary(At_ansi, Len), do_strip( Str@1, From + Len, Matches@1, <> ) end. -file("src/string_width/internal/ansi.gleam", 12). ?DOC(false). -spec strip(binary()) -> binary(). strip(Str) -> do_strip(Str, 0, match(Str), <<""/utf8>>).