diff --git a/lib/makeup/lexers/elixir_lexer.ex b/lib/makeup/lexers/elixir_lexer.ex index 0ba80df..31c2839 100644 --- a/lib/makeup/lexers/elixir_lexer.ex +++ b/lib/makeup/lexers/elixir_lexer.ex @@ -531,8 +531,11 @@ defmodule Makeup.Lexers.ElixirLexer do [newline, first | postprocess_helper(rest)] end - defp postprocess_helper([{:string_sigil, attrs, content} | tokens]) do - # content is a list of the format ["~", sigil_char, separator, ... sigil_content ..., end_separator] + defp postprocess_helper([{:string_sigil, attrs, ["~" | _] = content} | tokens]) do + # content is a list of the format ["~", sigil_char, separator, ... sigil_content ..., end_separator]. + # A sigil containing interpolation is split into multiple :string_sigil tokens, + # of which only the first starts with "~"; the rest are plain sigil content + # and fall through to the catch-all clause. sigil = content |> Enum.at(1) diff --git a/test/makeup/lexers/elixir_lexer/elixir_lexer_sigil_lexer_test.exs b/test/makeup/lexers/elixir_lexer/elixir_lexer_sigil_lexer_test.exs index a7c0ae5..47fc16b 100644 --- a/test/makeup/lexers/elixir_lexer/elixir_lexer_sigil_lexer_test.exs +++ b/test/makeup/lexers/elixir_lexer/elixir_lexer_sigil_lexer_test.exs @@ -21,6 +21,29 @@ defmodule ElixirLexerSigilLexerTest do Application.put_env(:makeup_elixir, :sigil_lexers, %{}) end + test "does not treat continuation tokens of interpolated sigils as sigils" do + defmodule PassthroughLexer do + def lex(input, opts) do + [{:keyword, %{opts: opts}, input}] + end + end + + Makeup.Lexers.ElixirLexer.register_sigil_lexer("H", PassthroughLexer) + + # A sigil containing interpolation is split into multiple :string_sigil + # tokens. The `H` at index 1 of the continuation token `/HEAD"` must not + # be mistaken for a ~H sigil. + assert lex(~S[~w"refs/remotes/#{remote}/HEAD"]) == [ + {:string_sigil, %{}, "~w\"refs/remotes/"}, + {:string_interpol, %{group_id: "group-1"}, "\#{"}, + {:name, %{}, "remote"}, + {:string_interpol, %{group_id: "group-1"}, "}"}, + {:string_sigil, %{}, "/HEAD\""} + ] + after + Application.put_env(:makeup_elixir, :sigil_lexers, %{}) + end + test "does not lex inside iex prompts" do # does not exist, but should also not be invoked Makeup.Lexers.ElixirLexer.register_sigil_lexer("PY", DoesNotExist, foo: :bar)