handle user keywords properly for recipes

This commit is contained in:
Thomas Breloff 2016-05-06 10:50:54 -04:00
parent d3439f0d7e
commit cf03779c5b
4 changed files with 34 additions and 43 deletions

View File

@ -621,7 +621,17 @@ function preprocessArgs!(d::KW)
delete!(d, :link)
end
return
# pull out invalid keywords into their own KW dict... these are likely user-defined through recipes
kw = KW()
for k in keys(d)
try
default(k)
catch
# not a valid key... pop and add to user list
kw[k] = pop!(d, k)
end
end
kw
end
# -----------------------------------------------------------------------------

View File

@ -53,7 +53,7 @@ function plot(args...; kw...)
plt = _create_plot(pkg, plotargs) # create a new, blank plot
delete!(d, :background_color)
plot!(plt, args...; d...) # add to it
plot!(plt, args...; kw...) # add to it
end
@ -72,10 +72,10 @@ end
# this adds to a specific plot... most plot commands will flow through here
function plot!(plt::Plot, args...; kw...)
d = KW(kw)
preprocessArgs!(d)
userkw = preprocessArgs!(d)
# for plotting recipes, swap out the args and update the parameter dictionary
args = _apply_recipe(d, args...; kw...)
args = _apply_recipe(d, userkw, args...)
_add_markershape(d)
dumpdict(d, "After plot! preprocessing")

View File

@ -17,10 +17,10 @@ plot!(plt::Plot, recipe::PlotRecipe, args...; kw...) = plot!(getRecipeXY(recipe)
num_series(x::AMat) = size(x,2)
num_series(x) = 1
_apply_recipe(d::KW; kw...) = ()
_apply_recipe(d::KW, kw::KW) = ()
# if it's not a recipe, just do nothing and return the args
function _apply_recipe(d::KW, args...; issubplot=false, kw...)
function _apply_recipe(d::KW, kw::KW, args...; issubplot=false)
if issubplot && !haskey(d, :n) && !haskey(d, :layout)
# put in a sensible default
d[:n] = maximum(map(num_series, args))
@ -105,7 +105,6 @@ macro recipe(funcexpr::Expr)
if !(isa(lhs, Expr) && lhs.head == :call)
error("Expected `lhs = ...` with lhs as a call Expr... got: $lhs")
end
args = lhs.args[2:end]
# for parametric definitions, take the "curly" expression and add the func
front = lhs.args[1]
@ -115,12 +114,25 @@ macro recipe(funcexpr::Expr)
func = front
end
# get the arg list, stripping out any keyword parameters into a
# bunch of get!(kw, key, value) lines
args = lhs.args[2:end]
kw_body = Expr(:block)
if isa(args[1], Expr) && args[1].head == :parameters
for kwpair in args[1].args
k, v = kwpair.args
push!(kw_body.args, :(get!(kw, $(QuoteNode(k)), $v)))
end
args = args[2:end]
end
# replace all the key => value lines with argument setting logic
replace_recipe_arrows!(body)
# now build a function definition for _apply_recipe, wrapping the return value in a tuple if needed
esc(quote
function $func(d::KW, $(args...); issubplot=false, kw...)
function $func(d::KW, kw::KW, $(args...); issubplot=false)
$kw_body
ret = $body
if typeof(ret) <: Tuple
ret
@ -131,37 +143,6 @@ macro recipe(funcexpr::Expr)
end)
end
# macro plotrecipe(args, expr)
# if !isa(args, Expr)
# error("The first argument to `@plotrecipe` should be a valid argument list for dispatch.")
# end
#
# # wrap the args in a tuple
# if args.head != :tuple
# args = Expr(:tuple, args)
# end
#
# # # handle positional args
# # fixed_args = []
# # positional_exprs = []
# # for arg in args
# # if
#
# # replace all the key => value lines with argument setting logic
# replace_recipe_arrows!(expr)
#
# # now build a function definition for _apply_recipe, wrapping the return value in a tuple if needed
# esc(quote
# function Plots._apply_recipe(d::KW, $(args.args...); issubplot=false, kw...)
# ret = $expr
# if typeof(ret) <: Tuple
# ret
# else
# (ret,)
# end
# end
# end)
# end
# ---------------------------------------------------------------------------

View File

@ -43,7 +43,7 @@ function subplot(args...; kw...)
preprocessArgs!(d)
# for plotting recipes, swap out the args and update the parameter dictionary
args = _apply_recipe(d, args...; kw..., issubplot=true)
args = _apply_recipe(d, KW(kw), args...; issubplot=true)
_add_markershape(d)
# figure out the layout
@ -70,7 +70,7 @@ function subplot(args...; kw...)
# create the object and do the plotting
subplt = Subplot(nothing, plts, pkg, length(layout), 0, layout, d, false, false, false, (r,c) -> (nothing,nothing))
subplot!(subplt, args...; d...)
subplot!(subplt, args...; kw...)
subplt
end
@ -117,10 +117,10 @@ end
function _preprocess_subplot(subplt::Subplot, d::KW, args = ())
validateSubplotSupported()
preprocessArgs!(d)
userkw = preprocessArgs!(d)
# for plotting recipes, swap out the args and update the parameter dictionary
args = _apply_recipe(d, args...; d..., issubplot=true)
args = _apply_recipe(d, userkw, args...; issubplot=true)
_add_markershape(d)
dumpdict(d, "After subplot! preprocessing")