Hey all. I’m having some trouble using the run
command with a variable number of args to the thing I’m trying to run
. For context, I’m playing around with some ways to very directly interact with Gnuplot scripts. I’m aware that there are several existing interfaces and I’m not trying to do anything serious here, but now I want to know how to do this correctly. Here’s my little snippet:
using DelimitedFiles
# Default kwargs. Probably eventually needs to be a dict of dicts, with the
# outer index being the "scriptname" arg, like :lineplot used in ARGORDER below.
const DEF = Dict(:terminal=>"pngcairo", :xsize=>500, :ysize=>500,
:font=>"Verdana", :fontsize=>10, :outputname=>"output.png",
:tmpfile=>nothing)
# Could use this to automatically splat out the args in the right order without
# having to touch the plot function internals.
const ARGORDER = Dict(:lineplot=>(:terminal, :xsize, :ysize, :font, :fontsize, :outputname))
# Common list of errors.
const ERRORS = Dict(:argerror=>ArgumentError("Here's a helpful error message."))
function plot(x, y; scriptname=:lineplot, kwargs...)
args = merge(DEF, kwargs) # TODO: check that no kwarg is silently ignored.
scriptfile = string(scriptname, ".gp")
tmpfile = isnothing(args[:tmpfile]) ? mktemp()[1] : args[:tmpfile]
writedlm(tmpfile, hcat(x,y), ' ')
if haskey(ARGORDER, scriptname)
# not sure if string conversion is necessary, but just trying to cover all my bases.
gp_args = map(x->string(args[x]), ARGORDER[scriptname])
else
haskey(args, :argorder) || throw(ERRORS[:argerror])
gp_args = map(x->string(args[x]), args[:argorder])
end
# (i): What is the correct way to supply these args? The help seems to suggest
# that this is a fine way to do it, but clearly I'm misreading ?run.
# run(`gnuplot -c $scriptfile $tmpfile`, gp_args...)
#
# (ii): Alternatively, I have tried this, but this leaves an extra set of
# backticks, so I somehow am not splatting these args correctly.
# run(`gnuplot -c $scriptfile $tmpfile $(map(x->string(x, " "), gp_args)...)`)
run(`xdg-open $(args[:outputname])`)
end
And the corresponding lineplot.gp
file is
set terminal ARG2 size ARG3,ARG4 enhanced font 'ARG5,ARG6'
set autoscale xfix
set autoscale yfix
set output ARG7
plot ARG1 using 1:2 with linespoints pointtype 6 notitle
unset output
The big comment chunk of the first snippet show two things that I’ve tried to do to splat the args provided by ARGORDER[:lineplot]
into the run
command, but I am clearly both misinterpreting what args...
means in the help provided by ?run
(attempt i) AND not understanding how to properly splat in a string interpolation-type thing for (attempt ii).
here’s an example call that should (at least on linux) work once these args get parsed properly:
plot(1:10, map(abs2, 1:10))
If anybody has pointers, I would really appreciate it. Thanks!