Skip to content

Commit b84f56a

Browse files
authored
Merge pull request #53 from timholy/teh/add2dev
Update Rebugger to Revise.pkgdatas
2 parents c1b84fa + 84fe340 commit b84f56a

13 files changed

+198
-107
lines changed

.travis.yml

+12-10
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,24 @@ os:
55
- linux
66
- osx
77
julia:
8-
- 0.7
98
- 1.0
109
- nightly
1110
notifications:
1211
email: false
1312
git:
1413
depth: 99999999
1514

16-
# TODO: remove this once HeaderREPLs is registered
17-
before_script:
18-
- julia -e 'using Pkg;
19-
Pkg.clone("https://github.com/timholy/HeaderREPLs.jl")'
20-
21-
after_script: # TODO: change to after_success once https://github.com/JuliaLang/julia/issues/28306 is fixed
15+
after_success:
2216
# push coverage results to Codecov
2317
- julia -e 'using Pkg, Rebugger; cd(joinpath(dirname(pathof(Rebugger)), "..")); Pkg.add("Coverage"); using Coverage; Codecov.submit(Codecov.process_folder())'
24-
# Update the documentation
25-
- julia -e 'using Pkg; ps=Pkg.PackageSpec(name="Documenter", version="0.19"); Pkg.add(ps); Pkg.pin(ps)'
26-
- julia -e 'using Rebugger; ENV["DOCUMENTER_DEBUG"] = "true"; include(joinpath(dirname(pathof(Rebugger)), "..", "docs", "make.jl"))'
18+
19+
jobs:
20+
include:
21+
- stage: "Documentation"
22+
julia: 1.0
23+
os: linux
24+
script:
25+
- julia --project=docs/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd()));
26+
Pkg.instantiate()'
27+
- julia --project=docs/ docs/make.jl
28+
after_success: skip

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
[![codecov.io](http://codecov.io/github/timholy/Rebugger.jl/coverage.svg?branch=master)](http://codecov.io/github/timholy/Rebugger.jl?branch=master)
66

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

1111
The name "Rebugger" has 3 meanings:
@@ -19,7 +19,7 @@ The name "Rebugger" has 3 meanings:
1919
**See the documentation**:
2020

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

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

REQUIRE

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
julia 0.7
2-
Revise 0.7.15
1+
julia 1.0
2+
Revise 1.0
33
HeaderREPLs 0.2

appveyor.yml

-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
environment:
22
matrix:
3-
- julia_version: 0.7
43
- julia_version: 1
54
- julia_version: nightly
65

docs/Project.toml

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[deps]
2+
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
3+
4+
[compat]
5+
Documenter = "~0.21"

docs/make.jl

+1-8
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ using Documenter, Rebugger
33
makedocs(
44
modules = [Rebugger],
55
clean = false,
6-
format = :html,
6+
format = Documenter.HTML(prettyurls = get(ENV, "CI", nothing) == "true"),
77
sitename = "Rebugger.jl",
88
authors = "Tim Holy",
99
linkcheck = !("skiplinks" in ARGS),
@@ -15,15 +15,8 @@ makedocs(
1515
"internals.md",
1616
"reference.md",
1717
],
18-
# # Use clean URLs, unless built as a "local" build
19-
# html_prettyurls = !("local" in ARGS),
20-
# html_canonical = "https://juliadocs.github.io/Rebugger.jl/stable/",
2118
)
2219

2320
deploydocs(
2421
repo = "github.com/timholy/Rebugger.jl.git",
25-
target = "build",
26-
julia = "1.0",
27-
deps = nothing,
28-
make = nothing,
2922
)

docs/src/images/stepin4.png

66.4 KB
Loading

docs/src/index.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Introduction to Rebugger
22

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

77
The name "Rebugger" has 3 meanings:

docs/src/usage.md

+70-31
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,21 @@ Select the expression you want to step into by positioning "point" (your cursor)
1919
at the desired location in the command line:
2020

2121
```@raw html
22-
<img src="images/stepin1.png" width="200px"/>
22+
<img src="images/stepin1.png" width="160px"/>
2323
```
2424

2525
It's essential that point is at the very first character of the expression, in this case on
2626
the `s` in `show`.
27+
28+
!!! note
29+
Don't confuse the REPL's cursor with your mouse pointer.
30+
Your mouse is essentially irrelevant on the REPL; use arrow keys or the other
31+
[navigation features of Julia's REPL](https://docs.julialang.org/en/latest/stdlib/REPL/).
32+
2733
Now if you hit Meta-e, you should see something like this:
2834

2935
```@raw html
30-
<img src="images/stepin2.png" width="822px"/>
36+
<img src="images/stepin2.png" width="660px"/>
3137
```
3238

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

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

4955
```@raw html
50-
<img src="images/stepin3.png" width="859px"/>
56+
<img src="images/stepin3.png" width="690px"/>
5157
```
5258

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

64+
You can edit these expressions to insert code to display variables or test
65+
changes to the code.
66+
As an experiment, try stepping into the `show_vector` call from the example above
67+
and adding `@show limited` to display a local variable's value:
68+
69+
```@raw html
70+
<img src="images/stepin4.png" width="800px"/>
71+
```
72+
73+
!!! note
74+
When editing expressions, you can insert a blank line with Meta-Enter (i.e., Esc-Enter, Alt-Enter, or Option-Enter).
75+
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.
76+
5877
Having illustrated the importance of "point" and the various colors used for messages from Rebugger,
5978
to ensure readability the remaining examples will be rendered as text.
6079

80+
6181
## Capturing stacktraces
6282

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

83103
To capture the stacktrace, type the last line again or hit the up arrow, but instead of
84-
pressing enter type Meta-s.
104+
pressing Enter, type Meta-s.
85105
After a short delay, you should see something like this:
106+
86107
```julia
87108
julia> colorant"hsl(80%, 20%, 15%)"
88109
┌ Warning: Tuple{getfield(Colors, Symbol("#@colorant_str")),LineNumberNode,Module,Any} was not found, perhaps it was generated by code
89-
└ @ Revise ~/.julia/dev/Revise/src/Revise.jl:614
110+
└ @ Revise ~/.julia/dev/Revise/src/Revise.jl:659
90111
Captured elements of stacktrace:
91-
[1] parse_hsl_hue(num::AbstractString) in Colors at /home/tim/.julia/dev/Colors/src/parse.jl:25
92-
[2] _parse_colorant(desc::AbstractString) in Colors at /home/tim/.julia/dev/Colors/src/parse.jl:51
93-
[3] parse(::Type{C}, desc::AbstractString) where C<:Colorant in Colors at /home/tim/.julia/dev/Colors/src/parse.jl:140
94-
parse_hsl_hue(num::AbstractString) in Colors at /home/tim/.julia/dev/Colors/src/parse.jl:25
112+
[1] parse_hsl_hue(num::AbstractString) in Colors at /home/tim/.julia/packages/Colors/4hvzi/src/parse.jl:25
113+
[2] _parse_colorant(desc::AbstractString) in Colors at /home/tim/.julia/packages/Colors/4hvzi/src/parse.jl:51
114+
[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
115+
[4] parse(::Type{C}, desc::AbstractString) where C<:Colorant in Colors at /home/tim/.julia/packages/Colors/4hvzi/src/parse.jl:140
116+
parse_hsl_hue(num::AbstractString) in Colors at /home/tim/.julia/packages/Colors/4hvzi/src/parse.jl:25
95117
num = 80%
96-
rebug> @eval Colors let (num,) = Main.Rebugger.getstored("c592f0a4-a226-11e8-1002-fd2731558606")
118+
rebug> @eval Colors let (num,) = Main.Rebugger.getstored("57dbc76a-0def-11e9-1dbf-ef97d29d2e25")
97119
begin
98120
if num[end] == '%'
99121
error("hue cannot end in %")
@@ -105,23 +127,48 @@ rebug> @eval Colors let (num,) = Main.Rebugger.getstored("c592f0a4-a226-11e8-100
105127
```
106128

107129
(Again, if this doesn't happen check [Keyboard shortcuts](@ref) and [Customize keybindings](@ref).)
130+
You are in the method corresponding to `[1]` in the stacktrace.
108131
Now you can navigate with your up and down arrows to browse the captured stacktrace.
109-
You can pick any of these expressions to execute (hit Enter) or edit before execution.
110-
For example you could add `@show` commands to examine intermediate variables or test
111-
out different ways to fix a bug.
132+
For example, if you hit the up arrow twice, you will be in the method corresponding to `[3]`:
133+
134+
```julia
135+
julia> colorant"hsl(80%, 20%, 15%)"
136+
┌ Warning: Tuple{getfield(Colors, Symbol("#@colorant_str")),LineNumberNode,Module,Any} was not found, perhaps it was generated by code
137+
└ @ Revise ~/.julia/dev/Revise/src/Revise.jl:659
138+
Captured elements of stacktrace:
139+
[1] parse_hsl_hue(num::AbstractString) in Colors at /home/tim/.julia/packages/Colors/4hvzi/src/parse.jl:25
140+
[2] _parse_colorant(desc::AbstractString) in Colors at /home/tim/.julia/packages/Colors/4hvzi/src/parse.jl:51
141+
[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
142+
[4] parse(::Type{C}, desc::AbstractString) where C<:Colorant in Colors at /home/tim/.julia/packages/Colors/4hvzi/src/parse.jl:140
143+
_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
144+
C = Colorant
145+
SUP = Any
146+
desc = hsl(80%, 20%, 15%)
147+
rebug> @eval Colors let (C, SUP, desc) = Main.Rebugger.getstored("57d9ebc0-0def-11e9-2ab0-e5d1e4c6e82d")
148+
begin
149+
_parse_colorant(desc)
150+
end
151+
end
152+
```
153+
154+
You can hit the down arrow and go back to earlier entries in the trace.
155+
Alternatively, you can pick any of these expressions to execute (hit Enter) or edit before execution.
112156
You can use the REPL history to test the results of many different changes to the same "method";
113157
the "method" will be run with the same inputs each time.
114158

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

117167
### "Missing" methods from stacktraces
118168

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

126173
When many methods use keyword arguments, the apparent difference between the
127174
"real" stacktrace and the "captured" stacktrace can be quite dramatic:
@@ -154,29 +201,21 @@ Stacktrace:
154201
julia> Pkg.add("NoPkg") # hit Meta-s here
155202
Captured elements of stacktrace:
156203
[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
157-
[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
158-
[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
159-
[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
160-
[5] add(args...) in Pkg.API at /home/tim/src/julia-1.0/usr/share/julia/stdlib/v1.0/Pkg/src/API.jl:69
204+
[2] add(args...) in Pkg.API at /home/tim/src/julia-1.0/usr/share/julia/stdlib/v1.0/Pkg/src/API.jl:69
161205
pkgerror(msg::String...) in Pkg.Types at /home/tim/src/julia-1.0/usr/share/julia/stdlib/v1.0/Pkg/src/Types.jl:120
162206
msg = ("The following package names could not be resolved:\n * NoPkg (not found in project, manifest or registry)\nPlease specify by known `name=uuid`.",)
163-
rebug> @eval Pkg.Types let (msg,) = Main.Rebugger.getstored("b5c899c2-a228-11e8-0877-d102334a9f65")
207+
rebug> @eval Pkg.Types let (msg,) = Main.Rebugger.getstored("161c53ba-0dfe-11e9-0f8f-59f468aec692")
164208
begin
165209
throw(PkgError(join(msg)))
166210
end
167211
end
168212
```
169213

170-
Note that only five methods got captured but the stacktrace is much longer.
214+
Note that only two methods got captured but the stacktrace is much longer.
171215
Most of these methods, however, start with `#`, an indication that they are
172-
generated methods rather than ones that appear in the source code.
173-
The interactive stacktrace visits only those methods that appear in the original source code.
174-
175-
!!! note
176-
`Pkg` is one of Julia's standard libraries, and to step into or trace Julia's stdlibs
177-
you must build Julia from source.
178-
179-
216+
generated (keyword-handling) methods rather than ones that appear directly in the source code.
217+
For now, Rebugger omits these entries.
218+
However, you can enter (i.e., Meta-e) such methods from one that is higher in the stack trace.
180219

181220
### Modified "signatures"
182221

src/Rebugger.jl

+18-12
Original file line numberDiff line numberDiff line change
@@ -23,21 +23,27 @@ function repl_init(repl)
2323
repl.interface = REPL.setup_interface(repl; extra_repl_keymap = get_rebugger_modeswitch_dict())
2424
end
2525

26-
function __init__()
26+
function rebugrepl_init()
2727
# Set up the Rebugger REPL mode with all of its key bindings
2828
repl_inited = isdefined(Base, :active_repl)
29-
@async begin
30-
while !isdefined(Base, :active_repl)
31-
sleep(0.05)
32-
end
33-
sleep(0.1) # for extra safety
34-
# Set up the custom "rebug" REPL
35-
main_repl = Base.active_repl
36-
repl = HeaderREPL(main_repl, RebugHeader())
37-
interface = REPL.setup_interface(repl; extra_repl_keymap=[get_rebugger_modeswitch_dict(), rebugger_keys])
38-
rebug_prompt_ref[] = interface.modes[end]
39-
add_keybindings(; override=repl_inited, deprecated_keybindings..., keybindings...)
29+
while !isdefined(Base, :active_repl)
30+
sleep(0.05)
4031
end
32+
sleep(0.1) # for extra safety
33+
# Set up the custom "rebug" REPL
34+
main_repl = Base.active_repl
35+
repl = HeaderREPL(main_repl, RebugHeader())
36+
interface = REPL.setup_interface(repl; extra_repl_keymap=[get_rebugger_modeswitch_dict(), rebugger_keys])
37+
rebug_prompt_ref[] = interface.modes[end]
38+
add_keybindings(; override=repl_inited, deprecated_keybindings..., keybindings...)
39+
end
40+
41+
42+
function __init__()
43+
schedule(Task(rebugrepl_init))
4144
end
4245

46+
include("precompile.jl")
47+
_precompile_()
48+
4349
end # module

0 commit comments

Comments
 (0)