Skip to content

Commit 7dfbc95

Browse files
committed
Use StyledStrings Faces for stacktrace printing
This allows for the faces used (e.g. the file path) to be user-customised, which provides an escape from themes that make bright black invisible.
1 parent 9e575cb commit 7dfbc95

File tree

2 files changed

+45
-27
lines changed

2 files changed

+45
-27
lines changed

base/errorshow.jl

+44-26
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,39 @@ function showerror(io::IO, ex, bt; backtrace=true)
100100
end
101101
end
102102

103+
function stacktrace_path(file::Union{Nothing, String}, line::Union{Nothing, Int64})
104+
realfile = if !isnothing(file) && file != "" && !startswith(String(file), "REPL")
105+
fixup_stdlib_path(String(file))
106+
end
107+
pathstr = file
108+
if !isnothing(pathstr)
109+
stacktrace_expand_basepaths() && (pathstr = something(find_source_file(file), file))
110+
stacktrace_contract_userdir() && (pathstr = contractuser(pathstr))
111+
end
112+
linestr, llen = if !isnothing(line) && line > 0
113+
string(something(pathstr, ""), ':', line), ncodeunits(string(line))
114+
else
115+
something(pathstr, ""), 0
116+
end
117+
if !isnothing(realfile)
118+
flen = ncodeunits(basename(realfile))
119+
AnnotatedString(linestr,
120+
[(1:ncodeunits(linestr), :link => Filesystem.uripath(realfile)),
121+
(1:ncodeunits(linestr)-flen-llen-1, :face => :julia_stacktrace_location),
122+
(ncodeunits(linestr)-flen-llen:ncodeunits(linestr)-llen-1, :face => :julia_stacktrace_filename),
123+
(ncodeunits(linestr)-llen:ncodeunits(linestr), :face => :julia_stacktrace_fileline)])
124+
else
125+
AnnotatedString(linestr, [(1:ncodeunits(linestr), :face => :julia_stacktrace_location)])
126+
end
127+
end
128+
129+
stacktrace_path(location::LineNumberNode) =
130+
stacktrace_path(if !isnothing(location.file) String(location.file) end, location.line)
131+
103132
function showerror(io::IO, ex::LoadError, bt; backtrace=true)
104133
!isa(ex.error, LoadError) && print(io, "LoadError: ")
105134
showerror(io, ex.error, bt, backtrace=backtrace)
106-
print(io, "\nin expression starting at $(ex.file):$(ex.line)")
135+
print(io, "\nin expression starting at ", stacktrace_path(ex.file, ex.line))
107136
end
108137
showerror(io::IO, ex::LoadError) = showerror(io, ex, [])
109138

@@ -616,7 +645,7 @@ end
616645
const update_stackframes_callback = Ref{Function}(identity)
617646

618647
const STACKTRACE_MODULECOLORS = Iterators.Stateful(Iterators.cycle([:magenta, :cyan, :green, :yellow]))
619-
const STACKTRACE_FIXEDCOLORS = IdDict(Base => :light_black, Core => :light_black)
648+
const STACKTRACE_FIXEDCOLORS = IdDict(Base => :julia_stacktrace_basemodule, Core => :julia_stacktrace_basemodule)
620649

621650
function show_full_backtrace(io::IO, trace::Vector; print_linebreaks::Bool)
622651
num_frames = length(trace)
@@ -701,9 +730,9 @@ function show_reduced_backtrace(io::IO, t::Vector)
701730
cycle_length = repeated_cycle[1][2]
702731
repetitions = repeated_cycle[1][3]
703732
popfirst!(repeated_cycle)
704-
printstyled(io,
705-
"--- the above ", cycle_length, " lines are repeated ",
706-
repetitions, " more time", repetitions>1 ? "s" : "", " ---", color = :light_black)
733+
repmsg = string("--- the above ", cycle_length, " lines are repeated ",
734+
repetitions, " more time", repetitions>1 ? "s" : "", " ---")
735+
print(io, AnnotatedString(repmsg, [(1:ncodeunits(repmsg), :face => :julia_stacktrace_repetition)]))
707736
if i < length(displayed_stackframes)
708737
println(io)
709738
stacktrace_linebreaks() && println(io)
@@ -756,41 +785,30 @@ function print_stackframe(io, i, frame::StackFrame, n::Int, ndigits_max, modulec
756785
digit_align_width = ndigits_max + 2
757786

758787
# frame number
759-
print(io, " ", lpad("[" * string(i) * "]", digit_align_width))
760-
print(io, " ")
788+
frameindex = lpad('[' * string(i) * ']', digit_align_width)
789+
print(io, ' ', AnnotatedString(frameindex, [(1:ncodeunits(frameindex), :face => :julia_stacktrace_frameindex)]), ' ')
761790

762791
StackTraces.show_spec_linfo(IOContext(io, :backtrace=>true), frame)
763792
if n > 1
764-
printstyled(io, " (repeats $n times)"; color=:light_black)
793+
repmsg = " (repeats $n times)"
794+
print(io, AnnotatedString(repmsg, [(2:ncodeunits(repmsg), :face => :julia_stacktrace_repetition)]))
765795
end
766796
println(io)
767797

768798
# @ Module path / file : line
769799
print_module_path_file(io, modul, file, line; modulecolor, digit_align_width)
770800

771801
# inlined
772-
printstyled(io, inlined ? " [inlined]" : "", color = :light_black)
802+
print(io, if inlined AnnotatedString("[inlined]", [(1:9, :face => :julia_stacktrace_inlined)]) else "" end)
773803
end
774804

775-
function print_module_path_file(io, modul, file, line; modulecolor = :light_black, digit_align_width = 0)
776-
printstyled(io, " " ^ digit_align_width * "@", color = :light_black)
777-
778-
# module
805+
function print_module_path_file(io, modul, file, line; modulecolor = :bright_black, digit_align_width = 0)
806+
print(io, ' ' ^ digit_align_width, AnnotatedString("@", [(1:1, :face => :julia_stacktrace_location)]))
779807
if modul !== nothing && modulecolor !== nothing
780-
print(io, " ")
781-
printstyled(io, modul, color = modulecolor)
808+
mstr = string(modul)
809+
print(io, " ", AnnotatedString(mstr, [(1:ncodeunits(mstr), :face => modulecolor)]))
782810
end
783-
784-
# filepath
785-
file = fixup_stdlib_path(file)
786-
stacktrace_expand_basepaths() && (file = something(find_source_file(file), file))
787-
stacktrace_contract_userdir() && (file = contractuser(file))
788-
print(io, " ")
789-
dir = dirname(file)
790-
!isempty(dir) && printstyled(io, dir, Filesystem.path_separator, color = :light_black)
791-
792-
# filename, separator, line
793-
printstyled(io, basename(file), ":", line; color = :light_black, underline = true)
811+
print(io, ' ', stacktrace_path(file, line))
794812
end
795813

796814
function show_backtrace(io::IO, t::Vector)

base/path.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -627,7 +627,7 @@ function uripath(path::String)
627627
s, r"[^A-Za-z0-9\-_.~]+" => percent_escape)
628628
string("file://", gethostname(), '/',
629629
join(map(encode_uri_component,
630-
split(path, Filesystem.path_separator, keepempty=false)),
630+
split(path, path_separator_re, keepempty=false)),
631631
'/'))
632632
end
633633

0 commit comments

Comments
 (0)