diff --git a/README.md b/README.md index 740f73c..bccd14f 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,9 @@ Querying: - `st`: show the "status" (current function, source code and current expression to run) - `bt`: show a backtrace - `fr [i::Int]`: show all variables in the current or `i`th frame +- `p` + - `p`: print all variables in the current frame (same as `fr`) + - `p x [y ...]`: print the value of the variable(s) `x` (and `y` ...) Evaluation: - `w` diff --git a/src/commands.jl b/src/commands.jl index 95e524b..d4cb0bb 100644 --- a/src/commands.jl +++ b/src/commands.jl @@ -140,6 +140,31 @@ function execute_command(state::DebuggerState, v::Union{Val{:up}, Val{:down}}, c end return execute_command(state, Val(:f), string("f ", state.level + offset)) end + +function execute_command(state::DebuggerState, ::Val{:p}, cmd::AbstractString) + cmds = split(cmd, r" +") + io = output_stream(state) + frame = active_frame(state) + if length(cmds) == 1 + print_locals(io, frame) + else + vars = JuliaInterpreter.locals(frame) + for requested_var in cmds[2:end] + found = false + for var in vars + if string(var.name) == requested_var + print_var(io, var) + found = true + end + end + if !found + printstyled(io, "no variable `$requested_var` in this frame\n"; color=Base.error_color()) + end + end + end + return false +end + function execute_command(state::DebuggerState, ::Val{:w}, cmd::AbstractString) # TODO show some info messages? cmds = split(cmd, r" +") @@ -269,6 +294,9 @@ function execute_command(state::DebuggerState, ::Union{Val{:help}, Val{:?}}, cmd - `st`: show the "status" (current function, source code and current expression to run)\\ - `bt`: show a backtrace\\ - `fr [i::Int]`: show all variables in the current or `i`th frame\\ + - `p`\\ + - `p`: print all variables in the current frame (same as `fr`)\\ + - `p x [y ...]`: print the value of the variable(s) `x` (and `y` ...)\\ Evaluation:\\ diff --git a/test/misc.jl b/test/misc.jl index 6665006..ac08773 100644 --- a/test/misc.jl +++ b/test/misc.jl @@ -251,3 +251,18 @@ end ret, _, _ = Debugger.completions(provider, "x", "x") @test "x" in ret end + +@testset "p command" begin + function command_output(frame, cmd) + buf = IOBuffer() + term = REPL.Terminals.TTYTerminal("dumb", stdin, buf, stderr) + state = Debugger.DebuggerState(; frame=frame, terminal=term) + execute_command(state, Val{Symbol(first(split(cmd)))}(), cmd) + return String(take!(buf)) + end + f_p_cmd(x) = (y = x + 1; y * 2) + frame = @make_frame f_p_cmd(3) + @test occursin("x::$Int = 3", command_output(frame, "p x")) + @test occursin("x::$Int = 3", command_output(frame, "p")) + @test occursin("no variable `nope` in this frame", command_output(frame, "p nope")) +end