remove recipe macro; add dependency on RecipesBase

This commit is contained in:
Thomas Breloff 2016-05-06 14:55:42 -04:00
parent 1808b81d59
commit f1679f82c1
7 changed files with 129 additions and 125 deletions

View File

@ -5,3 +5,4 @@ Reexport
Compat Compat
Requires Requires
FixedSizeArrays FixedSizeArrays
RecipesBase

View File

@ -8,6 +8,7 @@ using Reexport
@reexport using Colors @reexport using Colors
using Requires using Requires
using FixedSizeArrays using FixedSizeArrays
@reexport using RecipesBase
export export
AbstractPlot, AbstractPlot,

View File

@ -75,7 +75,7 @@ function plot!(plt::Plot, args...; kw...)
userkw = preprocessArgs!(d) userkw = preprocessArgs!(d)
# for plotting recipes, swap out the args and update the parameter dictionary # for plotting recipes, swap out the args and update the parameter dictionary
args = _apply_recipe(d, userkw, args...) args = RecipesBase.apply_recipe(d, userkw, args...)
_add_markershape(d) _add_markershape(d)
dumpdict(d, "After plot! preprocessing") 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::AMat) = size(x,2)
num_series(x) = 1 num_series(x) = 1
_apply_recipe(d::KW, kw::KW) = () # _apply_recipe(d::KW, kw::KW) = ()
# if it's not a recipe, just do nothing and return the args # if it's not a recipe, just do nothing and return the args
function _apply_recipe(d::KW, kw::KW, args...; issubplot=false) function RecipesBase.apply_recipe(d::KW, kw::KW, args...; issubplot=false)
if issubplot && !isempty(args) && !haskey(d, :n) && !haskey(d, :layout) if issubplot && !isempty(args) && !haskey(d, :n) && !haskey(d, :layout)
# put in a sensible default # put in a sensible default
d[:n] = maximum(map(num_series, args)) d[:n] = maximum(map(num_series, args))
@ -28,126 +28,126 @@ function _apply_recipe(d::KW, kw::KW, args...; issubplot=false)
args args
end end
macro kw(k, v) # macro kw(k, v)
esc(:(get!(d, $k, $v))) # esc(:(get!(d, $k, $v)))
end # end
#
function _is_arrow_tuple(expr::Expr) # function _is_arrow_tuple(expr::Expr)
expr.head == :tuple && # expr.head == :tuple &&
isa(expr.args[1], Expr) && # isa(expr.args[1], Expr) &&
expr.args[1].head == :(-->) # expr.args[1].head == :(-->)
end # end
#
function _equals_symbol(arg::Symbol, sym::Symbol) # function _equals_symbol(arg::Symbol, sym::Symbol)
arg == sym # arg == sym
end # end
function _equals_symbol(arg::Expr, sym::Symbol) # function _equals_symbol(arg::Expr, sym::Symbol)
arg.head == :quote && arg.args[1] == sym # arg.head == :quote && arg.args[1] == sym
end # end
#
# TODO: when this is moved out of Plots, also move the replacement of key aliases to just after the _apply_recipe calls # # TODO: when this is moved out of Plots, also move the replacement of key aliases to just after the _apply_recipe calls
function replace_recipe_arrows!(expr::Expr) # function replace_recipe_arrows!(expr::Expr)
for (i,e) in enumerate(expr.args) # for (i,e) in enumerate(expr.args)
if isa(e,Expr) # if isa(e,Expr)
#
# process trailing flags, like: # # process trailing flags, like:
# a --> b, :quiet, :force # # a --> b, :quiet, :force
quiet, require, force = false, false, false # quiet, require, force = false, false, false
if _is_arrow_tuple(e) # if _is_arrow_tuple(e)
for flag in e.args # for flag in e.args
if _equals_symbol(flag, :quiet) # if _equals_symbol(flag, :quiet)
quiet = true # quiet = true
elseif _equals_symbol(flag, :require) # elseif _equals_symbol(flag, :require)
require = true # require = true
elseif _equals_symbol(flag, :force) # elseif _equals_symbol(flag, :force)
force = true # force = true
end # end
end # end
e = e.args[1] # e = e.args[1]
end # end
#
# we are going to recursively swap out `a --> b, flags...` commands # # we are going to recursively swap out `a --> b, flags...` commands
if e.head == :(-->) # if e.head == :(-->)
k, v = e.args # k, v = e.args
keyexpr = :(get(Plots._keyAliases, $k, $k)) # keyexpr = :(get(Plots._keyAliases, $k, $k))
#
set_expr = if force # set_expr = if force
# forced override user settings # # forced override user settings
:(d[$keyexpr] = $v) # :(d[$keyexpr] = $v)
else # else
# if the user has set this keyword, use theirs # # if the user has set this keyword, use theirs
:(get!(d, $keyexpr, $v)) # :(get!(d, $keyexpr, $v))
end # end
#
expr.args[i] = if quiet # expr.args[i] = if quiet
# quietly ignore keywords which are not supported # # quietly ignore keywords which are not supported
:($keyexpr in supportedArgs() ? $set_expr : nothing) # :($keyexpr in supportedArgs() ? $set_expr : nothing)
elseif require # elseif require
# error when not supported by the backend # # error when not supported by the backend
:($keyexpr in supportedArgs() ? $set_expr : error("In recipe: required keyword ", $k, " is not supported by backend $(backend_name())")) # :($keyexpr in supportedArgs() ? $set_expr : error("In recipe: required keyword ", $k, " is not supported by backend $(backend_name())"))
else # else
set_expr # set_expr
end # end
#
# @show quiet, force, expr.args[i] # # @show quiet, force, expr.args[i]
#
elseif e.head != :call # elseif e.head != :call
# we want to recursively replace the arrows, but not inside function calls # # we want to recursively replace the arrows, but not inside function calls
# as this might include things like Dict(1=>2) # # as this might include things like Dict(1=>2)
replace_recipe_arrows!(e) # replace_recipe_arrows!(e)
end # end
end # end
end # end
end # end
#
#
macro recipe(funcexpr::Expr) # macro recipe(funcexpr::Expr)
lhs, body = funcexpr.args # lhs, body = funcexpr.args
#
if !(funcexpr.head in (:(=), :function)) # if !(funcexpr.head in (:(=), :function))
error("Must wrap a valid function call!") # error("Must wrap a valid function call!")
end # end
if !(isa(lhs, Expr) && lhs.head == :call) # if !(isa(lhs, Expr) && lhs.head == :call)
error("Expected `lhs = ...` with lhs as a call Expr... got: $lhs") # error("Expected `lhs = ...` with lhs as a call Expr... got: $lhs")
end # end
#
# for parametric definitions, take the "curly" expression and add the func # # for parametric definitions, take the "curly" expression and add the func
front = lhs.args[1] # front = lhs.args[1]
func = :(Plots._apply_recipe) # func = :(Plots._apply_recipe)
if isa(front, Expr) && front.head == :curly # if isa(front, Expr) && front.head == :curly
front.args[1] = func # front.args[1] = func
func = front # func = front
end # end
#
# get the arg list, stripping out any keyword parameters into a # # get the arg list, stripping out any keyword parameters into a
# bunch of get!(kw, key, value) lines # # bunch of get!(kw, key, value) lines
args = lhs.args[2:end] # args = lhs.args[2:end]
kw_body = Expr(:block) # kw_body = Expr(:block)
if isa(args[1], Expr) && args[1].head == :parameters # if isa(args[1], Expr) && args[1].head == :parameters
for kwpair in args[1].args # for kwpair in args[1].args
k, v = kwpair.args # k, v = kwpair.args
push!(kw_body.args, :(get!(kw, $(QuoteNode(k)), $v))) # push!(kw_body.args, :(get!(kw, $(QuoteNode(k)), $v)))
end # end
args = args[2:end] # args = args[2:end]
end # end
#
# replace all the key => value lines with argument setting logic # # replace all the key => value lines with argument setting logic
replace_recipe_arrows!(body) # replace_recipe_arrows!(body)
#
# now build a function definition for _apply_recipe, wrapping the return value in a tuple if needed # # now build a function definition for _apply_recipe, wrapping the return value in a tuple if needed
esc(quote # esc(quote
function $func(d::KW, kw::KW, $(args...); issubplot=false) # function $func(d::KW, kw::KW, $(args...); issubplot=false)
$kw_body # $kw_body
ret = $body # ret = $body
if typeof(ret) <: Tuple # if typeof(ret) <: Tuple
ret # ret
else # else
(ret,) # (ret,)
end # end
end # end
end) # end)
end # end
#
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------

View File

@ -43,7 +43,7 @@ function subplot(args...; kw...)
preprocessArgs!(d) preprocessArgs!(d)
# for plotting recipes, swap out the args and update the parameter dictionary # for plotting recipes, swap out the args and update the parameter dictionary
args = _apply_recipe(d, KW(kw), args...; issubplot=true) args = RecipesBase.apply_recipe(d, KW(kw), args...; issubplot=true)
_add_markershape(d) _add_markershape(d)
# figure out the layout # figure out the layout
@ -120,7 +120,7 @@ function _preprocess_subplot(subplt::Subplot, d::KW, args = ())
userkw = preprocessArgs!(d) userkw = preprocessArgs!(d)
# for plotting recipes, swap out the args and update the parameter dictionary # for plotting recipes, swap out the args and update the parameter dictionary
args = _apply_recipe(d, userkw, args...; issubplot=true) args = RecipesBase.apply_recipe(d, userkw, args...; issubplot=true)
_add_markershape(d) _add_markershape(d)
dumpdict(d, "After subplot! preprocessing") dumpdict(d, "After subplot! preprocessing")

View File

@ -3,6 +3,7 @@ julia 0.4
Colors Colors
Reexport Reexport
Requires Requires
RecipesBase
FactCheck FactCheck
Cairo Cairo
Gadfly Gadfly

View File

@ -7,6 +7,7 @@ Pkg.build("ImageMagick")
Pkg.clone("GR") Pkg.clone("GR")
Pkg.build("GR") Pkg.build("GR")
Pkg.clone("https://github.com/JuliaPlots/RecipesBase.jl.git")
Pkg.clone("https://github.com/tbreloff/ExamplePlots.jl.git"); Pkg.clone("https://github.com/tbreloff/ExamplePlots.jl.git");
# Pkg.clone("https://github.com/JunoLab/Blink.jl.git") # Pkg.clone("https://github.com/JunoLab/Blink.jl.git")