diff --git a/lib/elixir/lib/code/identifier.ex b/lib/elixir/lib/code/identifier.ex index b6222fed8c..a01f56d247 100644 --- a/lib/elixir/lib/code/identifier.ex +++ b/lib/elixir/lib/code/identifier.ex @@ -71,11 +71,11 @@ defmodule Code.Identifier do Escapes the given identifier. """ @spec escape(binary(), char() | nil, :infinity | non_neg_integer, (char() -> iolist() | false)) :: - {escaped :: iolist(), remaining :: binary()} + {escaped :: binary(), remaining :: binary()} def escape(binary, char, limit \\ :infinity, fun \\ &escape_map/1) - when ((char in 0..0x10FFFF or is_nil(char)) and limit == :infinity) or + when (is_binary(binary) and ((char in 0..0x10FFFF or is_nil(char)) and limit == :infinity)) or (is_integer(limit) and limit >= 0) do - escape(binary, char, limit, [], fun) + escape(binary, char, limit, <<>>, fun) end defp escape(<<_, _::binary>> = binary, _char, 0, acc, _fun) do @@ -83,29 +83,33 @@ defmodule Code.Identifier do end defp escape(<>, char, count, acc, fun) do - escape(t, char, decrement(count), [acc | [?\\, char]], fun) + escape(t, char, decrement(count), <>, fun) end defp escape(<>, char, count, acc, fun) do - escape(t, char, decrement(count), [acc | [?\\, ?#, ?{]], fun) + escape(t, char, decrement(count), <>, fun) end defp escape(<>, char, count, acc, fun) do - escaped = if value = fun.(h), do: value, else: escape_char(h) - escape(t, char, decrement(count), [acc | escaped], fun) + if value = fun.(h) do + value = IO.iodata_to_binary(value) + escape(t, char, decrement(count), <>, fun) + else + escape(t, char, decrement(count), escape_char(h, acc), fun) + end end defp escape(<>, char, count, acc, fun) do - escape(t, char, decrement(count), [acc | [?\\, ?x, to_hex(a), to_hex(b)]], fun) + escape(t, char, decrement(count), <>, fun) end defp escape(<<>>, _char, _count, acc, _fun) do {acc, <<>>} end - defp escape_char(0), do: [?\\, ?0] + defp escape_char(0, acc), do: <> - defp escape_char(char) + defp escape_char(char, acc) # Some characters that are confusing (zero-width / alternative spaces) are displayed # using their unicode representation: # https://en.wikipedia.org/wiki/Universal_Character_Set_characters#Special-purpose_characters @@ -131,42 +135,44 @@ defmodule Code.Identifier do when char in 0x2000..0x200A when char == 0x205F do <> = <> - [?\\, ?u, to_hex(a), to_hex(b), to_hex(c), to_hex(d)] + <> end - defp escape_char(char) + defp escape_char(char, acc) when char in 0x20..0x7E when char in 0xA0..0xD7FF when char in 0xE000..0xFFFD when char in 0x10000..0x10FFFF do - <> + <> end - defp escape_char(char) when char < 0x100 do + defp escape_char(char, acc) when char < 0x100 do <> = <> - [?\\, ?x, to_hex(a), to_hex(b)] + <> end - defp escape_char(char) when char < 0x10000 do + defp escape_char(char, acc) when char < 0x10000 do <> = <> - [?\\, ?x, ?{, to_hex(a), to_hex(b), to_hex(c), to_hex(d), ?}] + <> end - defp escape_char(char) when char < 0x1000000 do + defp escape_char(char, acc) when char < 0x1000000 do <> = <> - [?\\, ?x, ?{, to_hex(a), to_hex(b), to_hex(c), to_hex(d), to_hex(e), to_hex(f), ?}] + + <> end - defp escape_map(?\a), do: [?\\, ?a] - defp escape_map(?\b), do: [?\\, ?b] - defp escape_map(?\d), do: [?\\, ?d] - defp escape_map(?\e), do: [?\\, ?e] - defp escape_map(?\f), do: [?\\, ?f] - defp escape_map(?\n), do: [?\\, ?n] - defp escape_map(?\r), do: [?\\, ?r] - defp escape_map(?\t), do: [?\\, ?t] - defp escape_map(?\v), do: [?\\, ?v] - defp escape_map(?\\), do: [?\\, ?\\] + defp escape_map(?\a), do: "\\a" + defp escape_map(?\b), do: "\\b" + defp escape_map(?\d), do: "\\d" + defp escape_map(?\e), do: "\\e" + defp escape_map(?\f), do: "\\f" + defp escape_map(?\n), do: "\\n" + defp escape_map(?\r), do: "\\r" + defp escape_map(?\t), do: "\\t" + defp escape_map(?\v), do: "\\v" + defp escape_map(?\\), do: "\\\\" defp escape_map(_), do: false @compile {:inline, to_hex: 1, decrement: 1} diff --git a/lib/elixir/lib/string.ex b/lib/elixir/lib/string.ex index ba83abfdad..e8b3a61c8c 100644 --- a/lib/elixir/lib/string.ex +++ b/lib/elixir/lib/string.ex @@ -326,7 +326,7 @@ defmodule String do recur_printable?(string, character_limit) end - defp recur_printable?(_string, 0), do: true + defp recur_printable?(<<_::binary>>, 0), do: true defp recur_printable?(<<>>, _character_limit), do: true for char <- 0x20..0x7E do