I am playing with EEx and I am trying to create a custom engine. I am trying to override the handle_assign/1
function from the EEx.Engine. The problem is I don’t understand what are the valid atoms. Here is my code
def handle_assign({:"??", meta, [{name, _, atom}]}) when is_atom(name) and is_atom(atom) do
line = meta[:line] || 0
quote line: line, do: Clouseau.TemplateEngine.assign_valid?(var!(assigns), unquote(name))
end
def assign_valid?(assigns, key) do
case Map.get(assigns, key) do
val when val in ["", nil, false] -> false
_ -> true
end
end
I want to use it like <%= if ??module, do: ":" %>
.
This crashes on compilation with
iex(17)> recompile
Compiling 3 files (.ex)
{:<>, [line: 12],
[{{:., [line: 12], [{:__aliases__, [line: 12], [:IO, :ANSI]}, :blue]},
[line: 12], []},
{:<>, [line: 12], [{:@, [line: 12], [{:file, [line: 12], nil}]}, "\n"]}]}
{:<>, [line: 14],
[{{:., [line: 14], [{:__aliases__, [line: 14], [:IO, :ANSI]}, :green]},
[line: 14], []}, {:@, [line: 14], [{:module, [line: 14], nil}]}]}
== Compilation error in file lib/render.ex ==
** (SyntaxError) lib/render.ex:14: syntax error before: module
lib/eex/compiler.ex:37: EEx.Compiler.generate_buffer/4
lib/render.ex:12: (module)
(stdlib) erl_eval.erl:670: :erl_eval.do_apply/6
** (exit) shutdown: 1
(elixir) lib/kernel/parallel_compiler.ex:325: Kernel.ParallelCompiler.terminate/1
(elixir) lib/kernel/parallel_compiler.ex:65: Kernel.ParallelCompiler.spawn_compilers/3
(mix) lib/mix/compilers/elixir.ex:159: Mix.Compilers.Elixir.compile_manifest/8
(mix) lib/mix/compilers/elixir.ex:86: Mix.Compilers.Elixir.compile/6
(mix) lib/mix/tasks/compile.elixir.ex:68: Mix.Tasks.Compile.Elixir.run/1
(mix) lib/mix/task.ex:301: Mix.Task.run_task/3
(elixir) lib/enum.ex:1270: Enum."-map/2-lists^map/1-0-"/2
(elixir) lib/enum.ex:1270: Enum."-map/2-lists^map/1-0-"/2
iex(17)>
When I replace the :"??"
with :??
, :?
, :"?"
and doing the appropriate changes in the template, still crashes. And generally it crashes with everything I tried except -
and @
.
If I use :-
in the code above it works OK.
def handle_assign({:-, meta, [{name, _, atom}]}) when is_atom(name) and is_atom(atom) do
line = meta[:line] || 0
quote line: line, do: Clouseau.TemplateEngine.assign_valid?(var!(assigns), unquote(name))
end
Why is that and how can I work around it?
P.S.: what does the line quote line: line, do:
do in the code above? I have been reading about macros but I haven’t seen that syntax with arbitrary keys in the options before.