I’m having trouble with code templates, quoting, and variables.
I’m using the NativeSVG package. Some of its SVG element definitions don’t allow content even though they should. In particular, I’d like to add a title
child to rect
so that my rect
s can have tooltips.
I made a local branch of NativeSVG to work in. It’s easy enough to change the flag associated with :rect
in the definition of PRIMITIVES
to enable child content.
The code in NativeSVG that defines a function for each SVG element that can have children is
for primitive in keys(filter(d -> last(d), PRIMITIVES))
eval(quote
function $primitive(f::Function, io::IOBuffer = BUFFER; kwargs...)
print(io, "<", $primitive)
for (arg, val) in kwargs
print(io, " ", replacenotallowed(arg), "=\"", val, "\"")
end
println(io, ">")
f()
println(io, "</", $primitive, ">")
end
end)
end
I’m also trying to abstract out the code that writes the SVG into a single function that can be called by those element definitions and is available to users if they require some element not considered by NativeSVG:
function element(f::Function, tagname::Symbol, io::IOBuffer = BUFFER; kwargs...)
print(io, "<", tagname)
for (arg, val) in kwargs
print(io, " ", replacenotallowed(arg), "=\"", val, "\"")
end
println(io, ">")
f()
println(io, "</", tagname, ">")
end
for primitive in keys(filter(d -> last(d), PRIMITIVES))
eval(quote
function $primitive(f::Function, io::IOBuffer = BUFFER; kwargs...)
element(f, $primitive, io; kwargs...)
end
end)
end
When I run my NativeSVG’s unit tests though, I get the error
Testing Running tests...
ERROR: LoadError: MethodError: no method matching element(::NativeSVG.var"#6#7"{var"#1#3"}, ::typeof(svg), ::IOBuffer; xmlns="http://www.w3.org/2000/svg", width="300", height="200")
Closest candidates are:
element(::Function, ::Symbol, ::IOBuffer; kwargs...) at c:\Users\Mark Nahabedian\.julia\dev\NativeSVG.jl\src\svg.jl:82
element(::Function, ::Symbol) at c:\Users\Mark Nahabedian\.julia\dev\NativeSVG.jl\src\svg.jl:82 got unsupported keyword arguments "xmlns", "width", "height"
Stacktrace:
[1] svg(f::Function, io::IOBuffer; kwargs::Base.Iterators.Pairs{Symbol, String, Tuple{Symbol, Symbol, Symbol}, NamedTuple{(:xmlns, :width, :height), Tuple{String, String, String}}})
@ NativeSVG ~\.julia\dev\NativeSVG.jl\src\svg.jl:105
The top stack trame svg
is a function defined by this code.
I don’t understand why svg
is calling element
without ‘f’ and with a var
. Presumably the 2nd argument ::typeof(svg)
is the :svg
that was substituted for $primitive
. Why did it not recognize that as Symbol
?
Can someone explain what I’m doing wrong?
Thanks.