Skip to content

Commit

Permalink
Fix Ctrl+Q for stack traces (#36344)
Browse files Browse the repository at this point in the history
* alternative fix for #36340
* refactor method hint mechanism
* make LAST_SHOWN_LINE_INFOS lowercase
* implement style suggestion from @KristofferC
* fix use of LAST_SHOWN_LINE_INFOS on latest master
  • Loading branch information
simeonschaub authored Jul 8, 2020
1 parent f383881 commit 114e581
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 34 deletions.
8 changes: 4 additions & 4 deletions base/errorshow.jl
Original file line number Diff line number Diff line change
Expand Up @@ -699,8 +699,8 @@ function print_stackframe(io, i, frame, n, digit_align_width, modulecolor)

# Used by the REPL to make it possible to open
# the location of a stackframe/method in the editor.
if haskey(io, :LAST_SHOWN_LINE_INFOS)
push!(io[:LAST_SHOWN_LINE_INFOS], (string(frame.file), frame.line))
if haskey(io, :last_shown_line_infos)
push!(io[:last_shown_line_infos], (string(frame.file), frame.line))
end

inlined = getfield(frame, :inlined)
Expand Down Expand Up @@ -749,8 +749,8 @@ end


function show_backtrace(io::IO, t::Vector)
if haskey(io, :LAST_SHOWN_LINE_INFOS)
resize!(io[:LAST_SHOWN_LINE_INFOS], 0)
if haskey(io, :last_shown_line_infos)
empty!(io[:last_shown_line_infos])
end

# t is a pre-processed backtrace (ref #12856)
Expand Down
17 changes: 11 additions & 6 deletions base/methodshow.jl
Original file line number Diff line number Diff line change
Expand Up @@ -240,17 +240,20 @@ function show_method_table(io::IO, ms::MethodList, max::Int=-1, header::Bool=tru
end
n = rest = 0
local last
LAST_SHOWN_LINE_INFOS = get(io, :LAST_SHOWN_LINE_INFOS, Tuple{String,Int}[])

resize!(LAST_SHOWN_LINE_INFOS, 0)
last_shown_line_infos = get(io, :last_shown_line_infos, nothing)
last_shown_line_infos === nothing || empty!(last_shown_line_infos)

for meth in ms
if max==-1 || n<max
n += 1
println(io)
print(io, "[$n] ")
show(io, meth)
file, line = updated_methodloc(meth)
push!(LAST_SHOWN_LINE_INFOS, (string(file), line))
if last_shown_line_infos !== nothing
push!(last_shown_line_infos, (string(file), line))
end
else
rest += 1
last = meth
Expand Down Expand Up @@ -374,16 +377,18 @@ show(io::IO, mime::MIME"text/html", mt::Core.MethodTable) = show(io, mime, Metho

# pretty-printing of AbstractVector{Method}
function show(io::IO, mime::MIME"text/plain", mt::AbstractVector{Method})
LAST_SHOWN_LINE_INFOS = get(io, :LAST_SHOWN_LINE_INFOS, Tuple{String,Int}[])
resize!(LAST_SHOWN_LINE_INFOS, 0)
last_shown_line_infos = get(io, :last_shown_line_infos, nothing)
last_shown_line_infos === nothing || empty!(last_shown_line_infos)
first = true
for (i, m) in enumerate(mt)
first || println(io)
first = false
print(io, "[$(i)] ")
show(io, m)
file, line = updated_methodloc(m)
push!(LAST_SHOWN_LINE_INFOS, (string(file), line))
if last_shown_line_infos !== nothing
push!(last_shown_line_infos, (string(file), line))
end
end
end

Expand Down
53 changes: 29 additions & 24 deletions stdlib/REPL/src/REPL.jl
Original file line number Diff line number Diff line change
Expand Up @@ -204,37 +204,26 @@ end
==(a::REPLDisplay, b::REPLDisplay) = a.repl === b.repl

function display(d::REPLDisplay, mime::MIME"text/plain", x)
io = outstream(d.repl)
get(io, :color, false) && write(io, answer_color(d.repl))
if isdefined(d.repl, :options) && isdefined(d.repl.options, :iocontext)
# this can override the :limit property set initially
io = foldl(IOContext, d.repl.options.iocontext,
init=IOContext(io, :limit => true, :module => Main))
end

infos = Tuple{String,Int}[]
io = IOContext(io, :LAST_SHOWN_LINE_INFOS => infos)

show(io, mime, x)
println(io)

if !isempty(infos)
d.repl.last_shown_line_infos = infos
println(
io,
"\nTo edit a specific method, type the corresponding number into the " *
"REPL and press Ctrl+Q",
)
with_methodtable_hint(d.repl) do io
get(io, :color, false) && write(io, answer_color(d.repl))
if isdefined(d.repl, :options) && isdefined(d.repl.options, :iocontext)
# this can override the :limit property set initially
io = foldl(IOContext, d.repl.options.iocontext,
init=IOContext(io, :limit => true, :module => Main))
end
show(io, mime, x)
println(io)
end

nothing
end
display(d::REPLDisplay, x) = display(d, MIME("text/plain"), x)

function print_response(repl::AbstractREPL, @nospecialize(response), show_value::Bool, have_color::Bool)
repl.waserror = response[2]
io = IOContext(outstream(repl), :module => Main)
print_response(io, response, show_value, have_color, specialdisplay(repl))
with_methodtable_hint(repl) do io
io = IOContext(io, :module => Main)
print_response(io, response, show_value, have_color, specialdisplay(repl))
end
nothing
end
function print_response(errio::IO, @nospecialize(response), show_value::Bool, have_color::Bool, specialdisplay=nothing)
Expand Down Expand Up @@ -495,6 +484,22 @@ function complete_line(c::LatexCompletions, s)
return unique!(map(completion_text, ret)), partial[range], should_complete
end

with_methodtable_hint(f, repl) = f(outstream(repl))
function with_methodtable_hint(f, repl::LineEditREPL)
linfos = Tuple{String,Int}[]
io = IOContext(outstream(repl), :last_shown_line_infos => linfos)
f(io)
if !isempty(linfos)
repl.last_shown_line_infos = linfos
println(
io,
"\nTo edit a specific method, type the corresponding number into the " *
"REPL and press Ctrl+Q",
)
end
nothing
end

mutable struct REPLHistoryProvider <: HistoryProvider
history::Vector{String}
history_file::Union{Nothing,IO}
Expand Down
42 changes: 42 additions & 0 deletions stdlib/REPL/test/repl.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1240,3 +1240,45 @@ frontend_task = @async begin
end
REPL.start_repl_backend(backend)
Base.wait(frontend_task)

macro throw_with_linenumbernode(err)
Expr(:block, LineNumberNode(42, Symbol("test.jl")), :(() -> throw($err)))
end

@testset "last shown line infos" begin
out_stream = IOBuffer()
term = REPL.TTYTerminal("dumb", IOBuffer(), out_stream, IOBuffer())
repl = REPL.LineEditREPL(term, false)
repl.specialdisplay = REPL.REPLDisplay(repl)

REPL.print_response(repl, (methods(+), false), true, false)
seekstart(out_stream)
@test count(
contains(
"To edit a specific method, type the corresponding number into the REPL and " *
"press Ctrl+Q"
),
eachline(out_stream),
) == 1
take!(out_stream)

err = ErrorException("Foo")
bt = try
@throw_with_linenumbernode(err)()
catch
Base.catch_stack()
end

repl.backendref = REPL.REPLBackendRef(Channel(1), Channel(1))
put!(repl.backendref.response_channel, (bt, true))

REPL.print_response(repl, (err, true), true, false)
seekstart(out_stream)
@test count(
contains(
"To edit a specific method, type the corresponding number into the REPL and " *
"press Ctrl+Q"
),
eachline(out_stream),
) == 1
end

0 comments on commit 114e581

Please sign in to comment.