Skip to content

Commit 9432b7a

Browse files
authored
add syntax highlighting (#66)
* add syntax highlighting
1 parent bc9d739 commit 9432b7a

File tree

7 files changed

+117
-8
lines changed

7 files changed

+117
-8
lines changed

Manifest.toml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,33 @@ git-tree-sha1 = "983f5f7a57c604322917ab8bc5b86ba914d3c345"
99
uuid = "da1fd8a2-8d9e-5ec2-8556-3022fb5608a2"
1010
version = "0.3.2"
1111

12+
[[Crayons]]
13+
git-tree-sha1 = "416737eea5c50ee5a08c588ea73d77d5eebc94e7"
14+
repo-rev = "master"
15+
repo-url = "https://github.com/KristofferC/Crayons.jl.git"
16+
uuid = "a8cc5b0e-0ffa-5ad4-8c14-923d3ee1735f"
17+
version = "3.0.0"
18+
19+
[[Dates]]
20+
deps = ["Printf"]
21+
uuid = "ade2ca70-3891-5945-98fb-dc099432e06a"
22+
1223
[[Distributed]]
1324
deps = ["Random", "Serialization", "Sockets"]
1425
uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b"
1526

27+
[[DocStringExtensions]]
28+
deps = ["LibGit2", "Markdown", "Pkg", "Test"]
29+
git-tree-sha1 = "4d30e889c9f106a51ffa4791a88ffd4765bf20c3"
30+
uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
31+
version = "0.7.0"
32+
33+
[[Highlights]]
34+
deps = ["DocStringExtensions", "InteractiveUtils", "REPL", "Test"]
35+
git-tree-sha1 = "286ff83d696dd92748e603a3219618d9e407e872"
36+
uuid = "eafb193a-b7ab-5a9e-9068-77385905fa72"
37+
version = "0.3.1"
38+
1639
[[InteractiveUtils]]
1740
deps = ["Markdown"]
1841
uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
@@ -25,13 +48,24 @@ repo-url = "https://github.com/JuliaDebug/JuliaInterpreter.jl"
2548
uuid = "aa1ae85d-cabe-5617-a682-6adf51b2e16a"
2649
version = "0.1.1"
2750

51+
[[LibGit2]]
52+
uuid = "76f85450-5226-5b5a-8eaa-529ad045b433"
53+
2854
[[Logging]]
2955
uuid = "56ddb016-857b-54e1-b83d-db4d58db5568"
3056

3157
[[Markdown]]
3258
deps = ["Base64"]
3359
uuid = "d6f4376e-aef5-505a-96c1-9c027394607a"
3460

61+
[[Pkg]]
62+
deps = ["Dates", "LibGit2", "Markdown", "Printf", "REPL", "Random", "SHA", "UUIDs"]
63+
uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
64+
65+
[[Printf]]
66+
deps = ["Unicode"]
67+
uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7"
68+
3569
[[REPL]]
3670
deps = ["InteractiveUtils", "Markdown", "Sockets"]
3771
uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"
@@ -56,3 +90,6 @@ uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
5690
[[UUIDs]]
5791
deps = ["Random", "SHA"]
5892
uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
93+
94+
[[Unicode]]
95+
uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5"

Project.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ version = "0.1.0"
55

66
[deps]
77
CodeTracking = "da1fd8a2-8d9e-5ec2-8556-3022fb5608a2"
8+
Crayons = "a8cc5b0e-0ffa-5ad4-8c14-923d3ee1735f"
9+
Highlights = "eafb193a-b7ab-5a9e-9068-77385905fa72"
810
JuliaInterpreter = "aa1ae85d-cabe-5617-a682-6adf51b2e16a"
911
Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a"
1012
REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"

README.md

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ Advanced commands:
5050
- `si`: same as `se` but step into a call if a call is the next expression
5151
- `sg`: step into a generated function
5252

53-
## Breakpoints
53+
### Breakpoints
5454

5555
There are currently no designated commands in the debug mode for adding and removing breakpoints, instead they are manipulated using the API from the package JuliaInterpreter (which need to be installed). The different ways of manipulating breakpoints are documented [here](https://juliadebug.github.io/JuliaInterpreter.jl/latest/dev_reference/#Breakpoints-1).
5656

@@ -78,7 +78,7 @@ About to run: (abs_float)(2.0)
7878
| T::DataType = Float64
7979
```
8080
81-
### Breakpoint on error
81+
#### Breakpoint on error
8282
8383
It is possible to halt execution when an error is thrown. This is done by calling the exported function `break_on_error(true)`.
8484
@@ -114,6 +114,15 @@ About to run: (throw)(StringIndexError("αβ", 2))
114114
[4] f() at REPL[17]:1
115115
```
116116
117+
### Syntax highlighting
118+
119+
The source code preview is syntax highlighted and this highlighting has some options.
120+
The theme can be set by calling `Debugger.set_theme(theme)` where `theme` is a [Highlights.jl theme](https://juliadocs.github.io/Highlights.jl/stable/demo/themes.html).
121+
It can be completely turned off or alternatively, different quality settings for the colors might be chosen by calling `Debugger.set_highlight(opt)` where `opt` is a `Debugger.HighlightOption` enum.
122+
The choices are `HIGHLIGHT_OFF` `HIGHLIGHT_SYSTEM_COLORS`, `HIGHLIGHT_256_COLORS`, `HIGHLIGHT_24_BIT`. System colors works in pretty much all terminals, 256 in most terminals (with the exception of Windows)
123+
and 24 bit in some terminals.
124+
125+
117126
[travis-img]: https://travis-ci.org/JuliaDebug/Debugger.jl.svg?branch=master
118127
[travis-url]: https://travis-ci.org/JuliaDebug/Debugger.jl
119128

src/Debugger.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
module Debugger
22

3+
using Highlights
4+
using Crayons
5+
36
using Markdown
47
using Base.Meta: isexpr
58
using REPL

src/printing.jl

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ function print_var(io::IO, var::JuliaInterpreter.Variable)
1616
catch
1717
val = Suppressed("printing error")
1818
end
19-
println(io, var.name, "::", T, " = ", val)
19+
println(io, highlight_code(string(var.name, "::", T, " = ", val); context=io))
2020
end
2121

2222
print_locdesc(io::IO, frame::Frame) = println(io, locdesc(frame))
@@ -69,7 +69,7 @@ function print_next_expr(io::IO, frame::Frame)
6969
end
7070
end
7171
end
72-
print(io, expr)
72+
print(io, highlight_code(string(expr); context=io))
7373
println(io)
7474
end
7575

@@ -85,8 +85,7 @@ function print_status(io::IO, frame::Frame)
8585
else
8686
read(loc.filepath, String)
8787
end
88-
print_sourcecode(outbuf, data,
89-
loc.line, loc.defline)
88+
print_sourcecode(outbuf, data, loc.line, loc.defline)
9089
else
9190
print_codeinfo(outbuf, frame)
9291
end
@@ -134,7 +133,7 @@ function compute_source_offsets(code::String, offset::Integer, startline::Intege
134133
if offsetline - NUM_SOURCE_LINES_UP_DOWN[] > length(file.offsets) || startline > length(file.offsets)
135134
return -1, -1
136135
end
137-
startoffset = max(file.offsets[max(offsetline - NUM_SOURCE_LINES_UP_DOWN[], 1)], file.offsets[startline])
136+
startoffset = max(file.offsets[max(offsetline - NUM_SOURCE_LINES_UP_DOWN[], 1)], startline == 0 ? 0 : file.offsets[startline])
138137
stopoffset = lastindex(code)-1
139138
if offsetline + NUM_SOURCE_LINES_UP_DOWN[] < lastindex(file.offsets)
140139
stopoffset = min(stopoffset, file.offsets[offsetline + NUM_SOURCE_LINES_UP_DOWN[]] - 1)
@@ -145,7 +144,53 @@ function compute_source_offsets(code::String, offset::Integer, startline::Intege
145144
startoffset, stopoffset
146145
end
147146

148-
function print_sourcecode(io::IO, code::String, line::Integer, defline::Integer; file::SourceFile = SourceFile(code))
147+
@enum HighlightOption begin
148+
HIGHLIGHT_OFF
149+
HIGHLIGHT_SYSTEM_COLORS
150+
HIGHLIGHT_256_COLORS
151+
HIGHLIGHT_24_BIT
152+
end
153+
154+
const _syntax_highlighting = Ref(Sys.iswindows() ? HIGHLIGHT_SYSTEM_COLORS : HIGHLIGHT_256_COLORS)
155+
const _current_theme = Ref{Type{<:Highlights.AbstractTheme}}(Highlights.Themes.MonokaiTheme)
156+
157+
set_theme(theme::Type{<:Highlights.AbstractTheme}) = _current_theme[] = theme
158+
set_highlight(opt::HighlightOption) = _syntax_highlighting[] = opt
159+
160+
function Format.render(io::IO, ::MIME"text/ansi-debugger", tokens::Format.TokenIterator)
161+
for (str, id, style) in tokens
162+
fg = style.fg.active ? map(Int, (style.fg.r, style.fg.g, style.fg.b)) : :nothing
163+
bg = style.bg.active ? map(Int, (style.bg.r, style.bg.g, style.bg.b)) : :nothing
164+
crayon = Crayon(
165+
foreground = fg,
166+
background = bg,
167+
bold = style.bold ? true : :nothing,
168+
italics = style.italic ? true : :nothing,
169+
underline = style.underline ? true : :nothing,
170+
)
171+
if _syntax_highlighting[] == HIGHLIGHT_256_COLORS
172+
crayon = Crayons.to_256_colors(crayon)
173+
elseif _syntax_highlighting[] == HIGHLIGHT_SYSTEM_COLORS
174+
crayon = Crayons.to_system_colors(crayon)
175+
end
176+
print(io, crayon, str, inv(crayon))
177+
end
178+
end
179+
180+
function highlight_code(code; context=nothing)
181+
if _syntax_highlighting[] != HIGHLIGHT_OFF
182+
return sprint(highlight, MIME("text/ansi-debugger"), code, Lexers.JuliaLexer, _current_theme[]; context=context)
183+
else
184+
return code
185+
end
186+
end
187+
188+
189+
const RESET = Crayon(reset = true)
190+
191+
function print_sourcecode(io::IO, code::String, line::Integer, defline::Integer)
192+
code = highlight_code(code; context=io)
193+
file = SourceFile(code)
149194
startoffset, stopoffset = compute_source_offsets(code, file.offsets[line], defline, line+NUM_SOURCE_LINES_UP_DOWN[]; file=file)
150195

151196
if startoffset == -1
@@ -173,5 +218,6 @@ function print_sourcecode(io::IO, code::String, line::Integer, defline::Integer;
173218
println(io, textline)
174219
lineno += 1
175220
end
221+
_syntax_highlighting[] == HIGHLIGHT_OFF || print(io, RESET)
176222
println(io)
177223
end

test/misc.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,16 @@ loc = Debugger.locinfo(state.frame)
5959
@test isfile(loc.filepath)
6060
@test occursin("logging.jl", loc.filepath)
6161

62+
try
63+
Debugger.set_highlight(Debugger.HIGHLIGHT_SYSTEM_COLORS)
64+
frame = Debugger.@make_frame f()
65+
st = chomp(sprint(Debugger.print_status, frame; context = :color => true))
66+
x_1_plus_1_colored = "\e[39m\e[97mx\e[39m\e[97m \e[39m\e[91m=\e[39m\e[97m \e[39m1\e[97m \e[39m\e[91m+\e[39m\e[97m \e[39m1\e[97m"
67+
@test occursin(x_1_plus_1_colored, st)
68+
finally
69+
Debugger.set_highlight(Debugger.HIGHLIGHT_OFF)
70+
end
71+
6272
frame = @make_frame Test.eval(1)
6373
desc = Debugger.locdesc(frame)
6474
@test occursin(Sys.STDLIB, desc)

test/runtests.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ if !isdefined(Main, :isnothing)
99
isnothing(x) = x === nothing
1010
end
1111

12+
Debugger.set_highlight(Debugger.HIGHLIGHT_OFF)
13+
1214
#@testset "Main tests" begin
1315
include("utils.jl")
1416
include("misc.jl")

0 commit comments

Comments
 (0)