Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Rebugger to Revise.pkgdatas #53

Merged
merged 7 commits into from
Jan 2, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 12 additions & 10 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,24 @@ os:
- linux
- osx
julia:
- 0.7
- 1.0
- nightly
notifications:
email: false
git:
depth: 99999999

# TODO: remove this once HeaderREPLs is registered
before_script:
- julia -e 'using Pkg;
Pkg.clone("https://github.com/timholy/HeaderREPLs.jl")'

after_script: # TODO: change to after_success once https://github.com/JuliaLang/julia/issues/28306 is fixed
after_success:
# push coverage results to Codecov
- julia -e 'using Pkg, Rebugger; cd(joinpath(dirname(pathof(Rebugger)), "..")); Pkg.add("Coverage"); using Coverage; Codecov.submit(Codecov.process_folder())'
# Update the documentation
- julia -e 'using Pkg; ps=Pkg.PackageSpec(name="Documenter", version="0.19"); Pkg.add(ps); Pkg.pin(ps)'
- julia -e 'using Rebugger; ENV["DOCUMENTER_DEBUG"] = "true"; include(joinpath(dirname(pathof(Rebugger)), "..", "docs", "make.jl"))'

jobs:
include:
- stage: "Documentation"
julia: 1.0
os: linux
script:
- julia --project=docs/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd()));
Pkg.instantiate()'
- julia --project=docs/ docs/make.jl
after_success: skip
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
[![codecov.io](http://codecov.io/github/timholy/Rebugger.jl/coverage.svg?branch=master)](http://codecov.io/github/timholy/Rebugger.jl?branch=master)

Rebugger is an expression-level debugger for Julia.
It has no ability to interact with or manipulate call stacks (see [ASTInterpreter2](https://github.com/Keno/ASTInterpreter2.jl)),
It has no ability to interact with or manipulate call stacks (see [Gallium](https://github.com/Keno/Gallium.jl)),
but it can trace execution via the manipulation of Julia expressions.

The name "Rebugger" has 3 meanings:
Expand All @@ -19,7 +19,7 @@ The name "Rebugger" has 3 meanings:
**See the documentation**:

[![](https://img.shields.io/badge/docs-stable-blue.svg)](https://timholy.github.io/Rebugger.jl/stable)
[![](https://img.shields.io/badge/docs-latest-blue.svg)](https://timholy.github.io/Rebugger.jl/latest)
[![](https://img.shields.io/badge/docs-latest-blue.svg)](https://timholy.github.io/Rebugger.jl/dev)

Note that Rebugger may benefit from custom configuration, as described in the documentation.

Expand Down
4 changes: 2 additions & 2 deletions REQUIRE
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
julia 0.7
Revise 0.7.15
julia 1.0
Revise 1.0
HeaderREPLs 0.2
1 change: 0 additions & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
environment:
matrix:
- julia_version: 0.7
- julia_version: 1
- julia_version: nightly

Expand Down
5 changes: 5 additions & 0 deletions docs/Project.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[deps]
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"

[compat]
Documenter = "~0.21"
9 changes: 1 addition & 8 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ using Documenter, Rebugger
makedocs(
modules = [Rebugger],
clean = false,
format = :html,
format = Documenter.HTML(prettyurls = get(ENV, "CI", nothing) == "true"),
sitename = "Rebugger.jl",
authors = "Tim Holy",
linkcheck = !("skiplinks" in ARGS),
Expand All @@ -15,15 +15,8 @@ makedocs(
"internals.md",
"reference.md",
],
# # Use clean URLs, unless built as a "local" build
# html_prettyurls = !("local" in ARGS),
# html_canonical = "https://juliadocs.github.io/Rebugger.jl/stable/",
)

deploydocs(
repo = "github.com/timholy/Rebugger.jl.git",
target = "build",
julia = "1.0",
deps = nothing,
make = nothing,
)
Binary file added docs/src/images/stepin4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion docs/src/index.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Introduction to Rebugger

Rebugger is an expression-level debugger for Julia.
It has no ability to interact with or manipulate call stacks (see [ASTInterpreter2](https://github.com/Keno/ASTInterpreter2.jl)),
It has no ability to interact with or manipulate call stacks (see [Gallium](https://github.com/Keno/Gallium.jl)),
but it can trace execution via the manipulation of Julia expressions.

The name "Rebugger" has 3 meanings:
Expand Down
101 changes: 70 additions & 31 deletions docs/src/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,21 @@ Select the expression you want to step into by positioning "point" (your cursor)
at the desired location in the command line:

```@raw html
<img src="images/stepin1.png" width="200px"/>
<img src="images/stepin1.png" width="160px"/>
```

It's essential that point is at the very first character of the expression, in this case on
the `s` in `show`.

!!! note
Don't confuse the REPL's cursor with your mouse pointer.
Your mouse is essentially irrelevant on the REPL; use arrow keys or the other
[navigation features of Julia's REPL](https://docs.julialang.org/en/latest/stdlib/REPL/).

Now if you hit Meta-e, you should see something like this:

```@raw html
<img src="images/stepin2.png" width="822px"/>
<img src="images/stepin2.png" width="660px"/>
```

(If not, check [Keyboard shortcuts](@ref) and [Customize keybindings](@ref).)
Expand All @@ -42,22 +48,36 @@ Indented blue line(s) show the value(s) of any input arguments or type parameter
If you're following along, move your cursor to the next `show` call as illustrated above.
Hit Meta-e again. You should see a new `show` method, this time with two input arguments.

Now let's demonstrate another important display item: position your cursor at the
Now let's demonstrate another important display item: position point at the
beginning of the `_show_empty` call and hit Meta-e.
The display should now look like this:

```@raw html
<img src="images/stepin3.png" width="859px"/>
<img src="images/stepin3.png" width="690px"/>
```

This time, note the yellow/orange line: this is a warning message, and you should pay attention to these.
(You might also see red lines, which are generally more serious "errors.")
In this case execution never reached `_show_empty`, because it enters `show_vector` instead;
if you moved your cursor there, you could trace execution more completely.

You can edit these expressions to insert code to display variables or test
changes to the code.
As an experiment, try stepping into the `show_vector` call from the example above
and adding `@show limited` to display a local variable's value:

```@raw html
<img src="images/stepin4.png" width="800px"/>
```

!!! note
When editing expressions, you can insert a blank line with Meta-Enter (i.e., Esc-Enter, Alt-Enter, or Option-Enter).
See the many [advanced features of Julia's REPL](https://docs.julialang.org/en/latest/stdlib/REPL/#Key-bindings-1) that allow you to efficiently edit these `let`-blocks.

Having illustrated the importance of "point" and the various colors used for messages from Rebugger,
to ensure readability the remaining examples will be rendered as text.


## Capturing stacktraces

For a quick demo, we'll use the `Colors` package (`add` it if you don't have it)
Expand All @@ -81,19 +101,21 @@ in expression starting at REPL[3]:1
```

To capture the stacktrace, type the last line again or hit the up arrow, but instead of
pressing enter type Meta-s.
pressing Enter, type Meta-s.
After a short delay, you should see something like this:

```julia
julia> colorant"hsl(80%, 20%, 15%)"
┌ Warning: Tuple{getfield(Colors, Symbol("#@colorant_str")),LineNumberNode,Module,Any} was not found, perhaps it was generated by code
└ @ Revise ~/.julia/dev/Revise/src/Revise.jl:614
└ @ Revise ~/.julia/dev/Revise/src/Revise.jl:659
Captured elements of stacktrace:
[1] parse_hsl_hue(num::AbstractString) in Colors at /home/tim/.julia/dev/Colors/src/parse.jl:25
[2] _parse_colorant(desc::AbstractString) in Colors at /home/tim/.julia/dev/Colors/src/parse.jl:51
[3] parse(::Type{C}, desc::AbstractString) where C<:Colorant in Colors at /home/tim/.julia/dev/Colors/src/parse.jl:140
parse_hsl_hue(num::AbstractString) in Colors at /home/tim/.julia/dev/Colors/src/parse.jl:25
[1] parse_hsl_hue(num::AbstractString) in Colors at /home/tim/.julia/packages/Colors/4hvzi/src/parse.jl:25
[2] _parse_colorant(desc::AbstractString) in Colors at /home/tim/.julia/packages/Colors/4hvzi/src/parse.jl:51
[3] _parse_colorant(::Type{C}, ::Type{SUP}, desc::AbstractString) where {C<:Colorant, SUP} in Colors at /home/tim/.julia/packages/Colors/4hvzi/src/parse.jl:112
[4] parse(::Type{C}, desc::AbstractString) where C<:Colorant in Colors at /home/tim/.julia/packages/Colors/4hvzi/src/parse.jl:140
parse_hsl_hue(num::AbstractString) in Colors at /home/tim/.julia/packages/Colors/4hvzi/src/parse.jl:25
num = 80%
rebug> @eval Colors let (num,) = Main.Rebugger.getstored("c592f0a4-a226-11e8-1002-fd2731558606")
rebug> @eval Colors let (num,) = Main.Rebugger.getstored("57dbc76a-0def-11e9-1dbf-ef97d29d2e25")
begin
if num[end] == '%'
error("hue cannot end in %")
Expand All @@ -105,23 +127,48 @@ rebug> @eval Colors let (num,) = Main.Rebugger.getstored("c592f0a4-a226-11e8-100
```

(Again, if this doesn't happen check [Keyboard shortcuts](@ref) and [Customize keybindings](@ref).)
You are in the method corresponding to `[1]` in the stacktrace.
Now you can navigate with your up and down arrows to browse the captured stacktrace.
You can pick any of these expressions to execute (hit Enter) or edit before execution.
For example you could add `@show` commands to examine intermediate variables or test
out different ways to fix a bug.
For example, if you hit the up arrow twice, you will be in the method corresponding to `[3]`:

```julia
julia> colorant"hsl(80%, 20%, 15%)"
┌ Warning: Tuple{getfield(Colors, Symbol("#@colorant_str")),LineNumberNode,Module,Any} was not found, perhaps it was generated by code
└ @ Revise ~/.julia/dev/Revise/src/Revise.jl:659
Captured elements of stacktrace:
[1] parse_hsl_hue(num::AbstractString) in Colors at /home/tim/.julia/packages/Colors/4hvzi/src/parse.jl:25
[2] _parse_colorant(desc::AbstractString) in Colors at /home/tim/.julia/packages/Colors/4hvzi/src/parse.jl:51
[3] _parse_colorant(::Type{C}, ::Type{SUP}, desc::AbstractString) where {C<:Colorant, SUP} in Colors at /home/tim/.julia/packages/Colors/4hvzi/src/parse.jl:112
[4] parse(::Type{C}, desc::AbstractString) where C<:Colorant in Colors at /home/tim/.julia/packages/Colors/4hvzi/src/parse.jl:140
_parse_colorant(::Type{C}, ::Type{SUP}, desc::AbstractString) where {C<:Colorant, SUP} in Colors at /home/tim/.julia/packages/Colors/4hvzi/src/parse.jl:112
C = Colorant
SUP = Any
desc = hsl(80%, 20%, 15%)
rebug> @eval Colors let (C, SUP, desc) = Main.Rebugger.getstored("57d9ebc0-0def-11e9-2ab0-e5d1e4c6e82d")
begin
_parse_colorant(desc)
end
end
```

You can hit the down arrow and go back to earlier entries in the trace.
Alternatively, you can pick any of these expressions to execute (hit Enter) or edit before execution.
You can use the REPL history to test the results of many different changes to the same "method";
the "method" will be run with the same inputs each time.

!!! note
When point is at the end of the input, the up and down arrows step through the history.
But if you move point into the method body (e.g., by using left-arrow),
the up and down arrows move within the method body.
If you've entered edit mode, you can go back to history mode using PgUp and PgDn.

## Important notes

### "Missing" methods from stacktraces

In the example above, you may have noticed the warning about the `@colorant_str` macro
being omitted from the "captured" (interactive) expressions comprising the stacktrace.
Macros are not traced.
Also notice that the inlined method does not appear in the captured stacktrace.
However, you can enter an inlined method using "step in," starting from the method
above it in the stacktrace.

When many methods use keyword arguments, the apparent difference between the
"real" stacktrace and the "captured" stacktrace can be quite dramatic:
Expand Down Expand Up @@ -154,29 +201,21 @@ Stacktrace:
julia> Pkg.add("NoPkg") # hit Meta-s here
Captured elements of stacktrace:
[1] pkgerror(msg::String...) in Pkg.Types at /home/tim/src/julia-1.0/usr/share/julia/stdlib/v1.0/Pkg/src/Types.jl:120
[2] ensure_resolved(env::Pkg.Types.EnvCache, pkgs::AbstractArray{Pkg.Types.PackageSpec,1}) in Pkg.Types at /home/tim/src/julia-1.0/usr/share/julia/stdlib/v1.0/Pkg/src/Types.jl:860
[3] add_or_develop(ctx::Pkg.Types.Context, pkgs::Array{Pkg.Types.PackageSpec,1}) in Pkg.API at /home/tim/src/julia-1.0/usr/share/julia/stdlib/v1.0/Pkg/src/API.jl:32
[4] add_or_develop(pkgs::Array{String,1}) in Pkg.API at /home/tim/src/julia-1.0/usr/share/julia/stdlib/v1.0/Pkg/src/API.jl:28
[5] add(args...) in Pkg.API at /home/tim/src/julia-1.0/usr/share/julia/stdlib/v1.0/Pkg/src/API.jl:69
[2] add(args...) in Pkg.API at /home/tim/src/julia-1.0/usr/share/julia/stdlib/v1.0/Pkg/src/API.jl:69
pkgerror(msg::String...) in Pkg.Types at /home/tim/src/julia-1.0/usr/share/julia/stdlib/v1.0/Pkg/src/Types.jl:120
msg = ("The following package names could not be resolved:\n * NoPkg (not found in project, manifest or registry)\nPlease specify by known `name=uuid`.",)
rebug> @eval Pkg.Types let (msg,) = Main.Rebugger.getstored("b5c899c2-a228-11e8-0877-d102334a9f65")
rebug> @eval Pkg.Types let (msg,) = Main.Rebugger.getstored("161c53ba-0dfe-11e9-0f8f-59f468aec692")
begin
throw(PkgError(join(msg)))
end
end
```

Note that only five methods got captured but the stacktrace is much longer.
Note that only two methods got captured but the stacktrace is much longer.
Most of these methods, however, start with `#`, an indication that they are
generated methods rather than ones that appear in the source code.
The interactive stacktrace visits only those methods that appear in the original source code.

!!! note
`Pkg` is one of Julia's standard libraries, and to step into or trace Julia's stdlibs
you must build Julia from source.


generated (keyword-handling) methods rather than ones that appear directly in the source code.
For now, Rebugger omits these entries.
However, you can enter (i.e., Meta-e) such methods from one that is higher in the stack trace.

### Modified "signatures"

Expand Down
30 changes: 18 additions & 12 deletions src/Rebugger.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,27 @@ function repl_init(repl)
repl.interface = REPL.setup_interface(repl; extra_repl_keymap = get_rebugger_modeswitch_dict())
end

function __init__()
function rebugrepl_init()
# Set up the Rebugger REPL mode with all of its key bindings
repl_inited = isdefined(Base, :active_repl)
@async begin
while !isdefined(Base, :active_repl)
sleep(0.05)
end
sleep(0.1) # for extra safety
# Set up the custom "rebug" REPL
main_repl = Base.active_repl
repl = HeaderREPL(main_repl, RebugHeader())
interface = REPL.setup_interface(repl; extra_repl_keymap=[get_rebugger_modeswitch_dict(), rebugger_keys])
rebug_prompt_ref[] = interface.modes[end]
add_keybindings(; override=repl_inited, deprecated_keybindings..., keybindings...)
while !isdefined(Base, :active_repl)
sleep(0.05)
end
sleep(0.1) # for extra safety
# Set up the custom "rebug" REPL
main_repl = Base.active_repl
repl = HeaderREPL(main_repl, RebugHeader())
interface = REPL.setup_interface(repl; extra_repl_keymap=[get_rebugger_modeswitch_dict(), rebugger_keys])
rebug_prompt_ref[] = interface.modes[end]
add_keybindings(; override=repl_inited, deprecated_keybindings..., keybindings...)
end


function __init__()
schedule(Task(rebugrepl_init))
end

include("precompile.jl")
_precompile_()

end # module
Loading