From 3505403499dbeb1e599e99a645e0b2a9751d21c8 Mon Sep 17 00:00:00 2001 From: Giorgio Calderone Date: Sat, 11 Apr 2020 23:40:19 +0200 Subject: [PATCH] Added repl_init; Added gpreadline to cope with pager output and repl --- Project.toml | 6 ++- src/Gnuplot.jl | 110 +++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 93 insertions(+), 23 deletions(-) diff --git a/Project.toml b/Project.toml index 757c504..829aae8 100644 --- a/Project.toml +++ b/Project.toml @@ -7,16 +7,18 @@ ColorSchemes = "35d6a980-a343-548e-a6ea-1d62b119f2f4" ColorTypes = "3da002f7-5984-5a60-b8a6-cbb66c0b333f" Colors = "5ae59095-9a9b-59fe-a467-6f913c188581" DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8" +REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" +ReplMaker = "b873ce64-0db9-51f5-a568-4457d8e49576" StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91" StructC14N = "d2514e9c-36c4-5b8e-97e2-51e7675c221c" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [compat] -julia = "^1.2" ColorSchemes = "^3.5" ColorTypes = "^0.10" Colors = "^0.12" DataStructures = "^0.17" +ReplMaker="^0.2" StatsBase = "^0.33" StructC14N = "^0.3" - +julia = "^1.2" diff --git a/src/Gnuplot.jl b/src/Gnuplot.jl index 6c24498..19eee78 100644 --- a/src/Gnuplot.jl +++ b/src/Gnuplot.jl @@ -1,6 +1,7 @@ module Gnuplot using StatsBase, ColorSchemes, ColorTypes, Colors, StructC14N, DataStructures +using REPL, ReplMaker import Base.reset import Base.write @@ -284,26 +285,47 @@ end # --------------------------------------------------------------------- +pagerTokens() = ["Press return for more:"] + function GPSession(sid::Symbol) function readTask(sid, stream, channel) - saveOutput = false - - while isopen(stream) - line = readline(stream) - if (length(line) >= 1) && (line[1] == Char(0x1b)) # Escape (xterm -ti vt340) - buf = Vector{UInt8}() - append!(buf, convert(Vector{UInt8}, [line...])) - push!(buf, 0x0a) - c = 0x00 - while c != 0x1b - c = read(stream, 1)[1] - push!(buf, c) + function gpreadline(stream) + line = "" + while true + c = read(stream, Char) + (c == '\r') && continue + (c == '\n') && break + if c == Char(0x1b) + 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() + if (length(line) == length(token)) && (line == token) + return line + end end - c = read(stream, 1)[1] - push!(buf, c) - write(stdout, buf) - continue end + if (line != "GNUPLOT_CAPTURE_BEGIN") && + (line != "GNUPLOT_CAPTURE_END") && + (Base.active_repl.mistate.current_mode.prompt == "gnuplot> ") + println(stdout, line) + end + return line + end + + saveOutput = false + while isopen(stream) + line = gpreadline(stream) if line == "GNUPLOT_CAPTURE_BEGIN" saveOutput = true elseif line == "GNUPLOT_CAPTURE_END" @@ -454,8 +476,26 @@ function writeread(gp::GPSession, str::AbstractString) out = Vector{String}() while true l = take!(gp.channel) - l == "GNUPLOT_CAPTURE_END" && break - push!(out, l) + 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 end return out end @@ -744,10 +784,10 @@ function gpexec(gp::GPSession, command::String) verbose = options.verbose options.verbose = false - errno = writeread(gp, "print GPVAL_ERRNO")[1] + errno = writeread(gp, "print GPVAL_ERRNO") options.verbose = verbose - - if errno != "0" + @assert length(errno) == 1 + if errno[1] != "0" @error "\n" * join(answer, "\n") errmsg = writeread(gp, "print GPVAL_ERRMSG") write(gp.pin, "reset error\n") @@ -1684,4 +1724,32 @@ function contourlines(args...; cntrparam="level auto 10") return out end + +""" + Gnuplot.init_repl(start_key='>') + +Install a hook to replace the common Julia REPL with a gnuplot one. The key to start the REPL is the one provided in `start_key` (default: `>`). + +Note: the gnuplot REPL operates only on the default session. +""" +function repl_init(start_key='>') + function repl_exec(s) + writeread(getsession(), s) + nothing + end + + function repl_isvalid(s) + input = strip(String(take!(copy(REPL.LineEdit.buffer(s))))) + (length(input) == 0) || (input[end] != '\\') + end + + initrepl(repl_exec, + prompt_text="gnuplot> ", + prompt_color = :blue, + start_key=start_key, + mode_name="Gnuplot", + completion_provider=nothing, # TODO: fix autocompletion + valid_input_checker=repl_isvalid, sticky_mode=false) +end + end #module