diff --git a/docs/make.jl b/docs/make.jl index 85e0141..8825f02 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -1,4 +1,5 @@ using Documenter, Gnuplot +empty!(Gnuplot.options.mime) makedocs(sitename="Gnuplot.jl", authors = "Giorgio Calderone", diff --git a/src/Gnuplot.jl b/src/Gnuplot.jl index 1f93d3b..b9894fd 100644 --- a/src/Gnuplot.jl +++ b/src/Gnuplot.jl @@ -184,7 +184,6 @@ mutable struct GPSession <: Session plots::Vector{SinglePlot} # commands and plot commands (one entry for each plot of the multiplot) curmid::Int # current multiplot ID pin::Base.Pipe; - pout::Base.Pipe; perr::Base.Pipe; proc::Base.Process; channel::Channel{String}; @@ -443,60 +442,71 @@ end # --------------------------------------------------------------------- -pagerTokens() = ["Press return for more:"] -function GPSession(sid::Symbol) - function readTask(sid, stream, channel) - function gpreadline(stream) - line = "" - while true - c = read(stream, Char) - (c == '\r') && continue - (c == '\n') && break - if c == Char(0x1b) # sixel - buf = Vector{UInt8}() - push!(buf, UInt8(c)) - while true - c = read(stream, Char) - push!(buf, UInt8(c)) - (c == Char(0x1b)) && break - end - c = read(stream, Char) - push!(buf, UInt8(c)) - write(stdout, buf) - continue - end - line *= c - for token in pagerTokens() # handle pager interaction - if (length(line) == length(token)) && (line == token) - return line - end +function readTask(gp::GPSession) + pagerTokens() = ["Press return for more:"] + + repeatID = 0 + function gpreadline() + line = "" + while true + c = read(gp.perr, Char) + (c == '\r') && continue + (c == '\n') && break + line *= c + for token in pagerTokens() # handle pager interaction + if (length(line) == length(token)) && (line == token) + # GNUPLOT_CAPTURE_END maybe lost when pager is + # running: send it again. + repeatID += 1 + write(gp.pin, "\nprint 'GNUPLOT_CAPTURE_END $repeatID'\n") + line = "" end end - return line end + if line == "GNUPLOT_CAPTURE_BEGIN" + repeatID += 1 + write(gp.pin, "\nprint 'GNUPLOT_CAPTURE_END $repeatID'\n") + end + return line + end + try saveOutput = false - while isopen(stream) - line = gpreadline(stream) + while isopen(gp.perr) + line = gpreadline() if line == "GNUPLOT_CAPTURE_BEGIN" saveOutput = true - elseif line == "GNUPLOT_CAPTURE_END" - put!(channel, line) + elseif line == "GNUPLOT_CAPTURE_END $repeatID" saveOutput = false + put!(gp.channel, "GNUPLOT_CAPTURE_END") + elseif !isnothing(findfirst("GNUPLOT_CAPTURE_END", line)) + continue # old GNUPLOT_CAPTURE_END, ignore it else if line != "" if options.verbose || !saveOutput - printstyled(color=:cyan, "GNUPLOT ($sid) -> $line\n") + printstyled(color=:cyan, "GNUPLOT ($(gp.sid)) -> $line\n") end end - (saveOutput) && (put!(channel, line)) + (saveOutput) && (put!(gp.channel, line)) end end - delete!(sessions, sid) - return nothing + catch err + if isopen(gp.perr) + @error "Error occurred in readTask for session $(gp.sid)" + @show(err) + else + put!(gp.channel, "GNUPLOT_CAPTURE_END") + end end + if options.verbose + printstyled(color=:red, "GNUPLOT ($(gp.sid)) Process terminated\n") + end + delete!(sessions, gp.sid) +end + +function GPSession(sid::Symbol) session = DrySession(sid) if !options.dry try @@ -510,26 +520,22 @@ function GPSession(sid::Symbol) end pin = Base.Pipe() - pout = Base.Pipe() perr = Base.Pipe() - proc = run(pipeline(`$(options.cmd)`, stdin=pin, stdout=pout, stderr=perr), wait=false) + proc = run(pipeline(`$(options.cmd)`, stdin=pin, stdout=stdout, stderr=perr), wait=false) chan = Channel{String}(32) # Close unused sides of the pipes - Base.close(pout.in) Base.close(perr.in) Base.close(pin.out) - Base.start_reading(pout.out) Base.start_reading(perr.out) - # Start reading tasks - @async readTask(sid, pout, chan) - @async readTask(sid, perr, chan) - out = GPSession(getfield.(Ref(session), fieldnames(DrySession))..., - pin, pout, perr, proc, chan) + pin, perr, proc, chan) sessions[sid] = out + # Start reading tasks + @async readTask(out) + return out end @@ -614,33 +620,11 @@ function writeread(gp::GPSession, str::AbstractString) options.verbose = verbose write(gp, str) - options.verbose = false - write(gp, "print 'GNUPLOT_CAPTURE_END'") - options.verbose = verbose - out = Vector{String}() while true l = take!(gp.channel) - if l in pagerTokens() - # Consume all data from the pager - while true - write(gp, "") - sleep(0.5) - if isready(gp.channel) - while isready(gp.channel) - push!(out, take!(gp.channel)) - end - else - options.verbose = false - write(gp, "print 'GNUPLOT_CAPTURE_END'") - options.verbose = verbose - break - end - end - else - l == "GNUPLOT_CAPTURE_END" && break - push!(out, l) - end + l == "GNUPLOT_CAPTURE_END" && break + push!(out, l) end return out end @@ -867,7 +851,6 @@ end function quit(gp::GPSession) close(gp.pin) - close(gp.pout) close(gp.perr) wait( gp.proc) exitCode = gp.proc.exitcode @@ -934,7 +917,7 @@ function execall(gp::GPSession; term::AbstractString="", output::AbstractString= gpexec(gp, s) end end - (length(gp.plots) > 1) && gpexec(gp, "unset multiplot") + gpexec(gp, "unset multiplot") (output != "") && gpexec(gp, "set output") if term != "" gpexec(gp, "set term $former_term $former_opts") diff --git a/test/runtests.jl b/test/runtests.jl index 0ef5733..3ed3239 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,16 +1,15 @@ using Test, Gnuplot try - @info "Gnuplot version: " * string(Gnuplot.gpversion()) + @info "Gnuplot.jl version: " * string(Gnuplot.version()) + @info "gnuplot version: " * string(Gnuplot.gpversion()) catch Gnuplot.options.dry = true end -Gnuplot.options.term = "unknown" x = [1, 2, 3] y = [4, 5, 6] - s = Gnuplot.arrays2datablock(x) @test all(s .== [" 1" , " 2" , @@ -90,10 +89,32 @@ s = Gnuplot.arrays2datablock(1:3, 1:3, ["One", "Two", "Three"]) #----------------------------------------------------------------- +dummy = palette_names() pal = palette(:deepsea) @test pal == "set palette defined (0.0 '#2B004D', 0.25 '#4E0F99', 0.5 '#3C54D4', 0.75 '#48A9F8', 1.0 '#C5ECFF')\nset palette maxcol 5\n" -ls = linetypes(:Set1_5) -@test ls == "unset for [i=1:256] linetype i\nset linetype 1 lc rgb '#E41A1C' lw 1 dt solid pt 1 ps 1\nset linetype 2 lc rgb '#377EB8' lw 1 dt solid pt 2 ps 1\nset linetype 3 lc rgb '#4DAF4A' lw 1 dt solid pt 3 ps 1\nset linetype 4 lc rgb '#984EA3' lw 1 dt solid pt 4 ps 1\nset linetype 5 lc rgb '#FF7F00' lw 1 dt solid pt 5 ps 1\nset linetype cycle 5\n" +ls = linetypes(:Set1_5, lw=1.5, ps=2) +@test ls == "unset for [i=1:256] linetype i\nset linetype 1 lc rgb '#E41A1C' lw 1.5 dt solid pt 1 ps 2\nset linetype 2 lc rgb '#377EB8' lw 1.5 dt solid pt 2 ps 2\nset linetype 3 lc rgb '#4DAF4A' lw 1.5 dt solid pt 3 ps 2\nset linetype 4 lc rgb '#984EA3' lw 1.5 dt solid pt 4 ps 2\nset linetype 5 lc rgb '#FF7F00' lw 1.5 dt solid pt 5 ps 2\nset linetype cycle 5\n" + +dummy = terminals() +if "sixelgd" in terminals() + Gnuplot.options.term = "sixelgd enhanced" +elseif "sixel" in terminals() + Gnuplot.options.term = "sixel enhanced" +elseif "dumb" in terminals() + Gnuplot.options.term = "dumb enhanced ansi" +else + Gnuplot.options.term = "unknown" +end +Gnuplot.quitall() +@gp 1:9 +@info "using terminal: " terminal() + +test_terminal() +test_terminal("dumb") +try + test_terminal("sixelgd") +catch +end #----------------------------------------------------------------- # Test wth empty dataset @@ -247,8 +268,19 @@ Gnuplot.quitall() "splot x9, v, (u<0.5) ? -1 : sinc(x9,v) notitle") + +x = randn(5000); +y = randn(5000); +h = hist(x, y, nbins1=20, nbins2=20); +clines = contourlines(h, "levels discrete 15, 30, 45"); +@gp clines +@gp "set size ratio -1" +for i in 1:length(clines) + @gp :- clines[i].data "w l t '$(clines[i].z)' lw $i dt $i" +end + + Gnuplot.options.verbose = true -# Gnuplot.options.term = "sixel" not vailable in Travis CI @gp randn(10^6) randn(10^6) @gp :- 0. 0. Gnuplot.quit(:default) @@ -256,6 +288,4 @@ Gnuplot.quit(:default) Gnuplot.options.dry = true @gp hist(randn(1000)) -t = terminals() - Gnuplot.quitall()