From f9e044a3c5fd71ed38b2f45fb884f78b6aeecd3d Mon Sep 17 00:00:00 2001 From: Fons van der Plas Date: Wed, 2 Oct 2024 16:58:59 +0200 Subject: [PATCH] Stack frame tweaks --- frontend/components/ErrorMessage.js | 36 +++++++++++--- frontend/themes/dark.css | 48 +++++++++---------- frontend/treeview.css | 8 +++- .../PlutoRunner/src/display/Exception.jl | 23 +++++++-- 4 files changed, 80 insertions(+), 35 deletions(-) diff --git a/frontend/components/ErrorMessage.js b/frontend/components/ErrorMessage.js index 9ca2cbbb33..21f120e197 100644 --- a/frontend/components/ErrorMessage.js +++ b/frontend/components/ErrorMessage.js @@ -37,17 +37,21 @@ const StackFrameFilename = ({ frame, cell_id }) => { e.preventDefault() }} > - ${frame_cell_id == cell_id ? "This cell" : "Other cell"}: line ${frame.line} + ${frame_cell_id == cell_id ? "This\xa0cell" : "Other\xa0cell"}: line ${frame.line} ` return html`${a}` } else { - return html`${frame.file}:${frame.line}` + const sp = frame.source_package + const origin = ["Main", "Core", "Base"].includes(sp) ? "julia" : sp + + const text = sp != null ? html`${origin} → ${frame.file}` : frame.file + + const href = frame?.url?.startsWith?.("https") ? frame.url : null + return html`${text}:${frame.line}` } } -const at = html`` +const at = html` from ` const ignore_funccall = (frame) => frame.call === "top-level scope" const ignore_location = (frame) => frame.file === "none" @@ -59,12 +63,31 @@ const Funccall = ({ frame }) => { let inner = bracket_index != -1 - ? html`${frame.call.substr(0, bracket_index)}${frame.call.substr(bracket_index)}` + ? html`${frame.call.substr(0, bracket_index)}<${ClickToExpandIfLong} text=${frame.call.substr(bracket_index)} />` : html`${frame.call}` return html`${inner}${at}` } +const ClickToExpandIfLong = ({ text }) => { + let [expanded, set_expanded] = useState(false) + + useEffect(() => { + set_expanded(false) + }, [text]) + + const collaped_text = html`${text.slice(0, 250)} { + e.preventDefault() + set_expanded(true) + }} + >...more...${text.slice(-1)}` + + return html` ${expanded ? text : text.length < 300 ? text : collaped_text} ` +} + const LinePreview = ({ frame, num_context_lines = 2 }) => { let pluto_actions = useContext(PlutoActionsContext) let cell_id = extract_cell_id(frame.file) @@ -99,6 +122,7 @@ const JuliaHighlightedLine = ({ code, frameLine, i }) => { useLayoutEffect(() => { if (code_ref.current) { code_ref.current.innerText = code + delete code_ref.current.dataset.highlighted highlight(code_ref.current, "julia") } }, [code_ref.current, code]) diff --git a/frontend/themes/dark.css b/frontend/themes/dark.css index 92ec058ecd..d72c9ea39c 100644 --- a/frontend/themes/dark.css +++ b/frontend/themes/dark.css @@ -142,8 +142,8 @@ /* jlerror */ --jlerror-header-color: #d9baba; --jlerror-mark-bg-color: rgb(0 0 0 / 18%); - --jlerror-a-bg-color: rgba(82, 58, 58, 1); - --jlerror-a-border-left-color: #704141; + --jlerror-a-bg-color: hsl(65.82deg 17.14% 27.45%); + --jlerror-a-border-left-color: hsl(66 27% 35% / 1); --jlerror-mark-color: #b1a9a9; /* helpbox */ @@ -191,36 +191,36 @@ /* code highlighting */ --cm-color-editor-text: #ffe9fc; - --cm-color-comment: #e96ba8; - --cm-color-atom: hsl(8deg 72% 62%); - --cm-color-number: hsl(271deg 45% 64%); - --cm-color-property: #f99b15; - --cm-color-keyword: #ff7a6f; - --cm-color-string: hsl(20deg 69% 59%); - --cm-color-var: #afb7d3; - --cm-color-var2: #06b6ef; - --cm-color-macro: #82b38b; - --cm-color-builtin: #5e7ad3; - --cm-color-function: #f99b15; - --cm-color-type: hsl(51deg 32% 44%); - --cm-color-bracket: #a2a273; - --cm-color-tag: #ef6155; - --cm-color-link: #815ba4; - --cm-color-error-bg: #ef6155; - --cm-color-error: #f7f7f7; + --cm-color-comment: #e96ba8; + --cm-color-atom: hsl(8deg 72% 62%); + --cm-color-number: hsl(271deg 45% 64%); + --cm-color-property: #f99b15; + --cm-color-keyword: #ff7a6f; + --cm-color-string: hsl(20deg 69% 59%); + --cm-color-var: #afb7d3; + --cm-color-var2: #06b6ef; + --cm-color-macro: #82b38b; + --cm-color-builtin: #5e7ad3; + --cm-color-function: #f99b15; + --cm-color-type: hsl(51deg 32% 44%); + --cm-color-bracket: #a2a273; + --cm-color-tag: #ef6155; + --cm-color-link: #815ba4; + --cm-color-error-bg: #ef6155; + --cm-color-error: #f7f7f7; --cm-color-matchingBracket: white; --cm-color-matchingBracket-bg: #c58c237a; --cm-color-placeholder-text: rgb(255 255 255 / 20%); --cm-color-clickable-underline: #5d5f70; /* Mixed parsers */ - --cm-color-html: #00ab85; + --cm-color-html: #00ab85; --cm-color-html-accent: #00e7b4; - --cm-color-css: #ebd073; - --cm-color-css-accent: #fffed2; + --cm-color-css: #ebd073; + --cm-color-css-accent: #fffed2; --cm-css-why-doesnt-codemirror-highlight-all-the-text-aaa: #ffffea; - --cm-color-md: #a2c9d5; - --cm-color-md-accent: #00a9d1; + --cm-color-md: #a2c9d5; + --cm-color-md-accent: #00a9d1; /*autocomplete menu*/ --autocomplete-menu-bg-color: var(--input-context-menu-bg-color); diff --git a/frontend/treeview.css b/frontend/treeview.css index 7dca28b2d1..3de86abcc2 100644 --- a/frontend/treeview.css +++ b/frontend/treeview.css @@ -299,7 +299,10 @@ jlerror > section .classical-frame > mark { font-family: var(--julia-mono-font-stack); font-variant-ligatures: none; } -jlerror > section .classical-frame > em > a[href] { +jlerror > section .classical-frame > mark > strong { + color: var(--black); +} +jlerror > section .classical-frame > em > a { background: var(--jlerror-a-bg-color); border-radius: 4px; padding: 1px 7px; @@ -307,6 +310,9 @@ jlerror > section .classical-frame > em > a[href] { border-left: 3px solid var(--jlerror-a-border-left-color); /* font-family: var(--system-ui-font-stack); */ } +jlerror > section .classical-frame > em > a:not([href]) { + filter: grayscale(1); +} jlerror > section .classical-frame > em > a[href].remote-url { filter: hue-rotate(160deg); } diff --git a/src/runner/PlutoRunner/src/display/Exception.jl b/src/runner/PlutoRunner/src/display/Exception.jl index fab71bda17..d292e170be 100644 --- a/src/runner/PlutoRunner/src/display/Exception.jl +++ b/src/runner/PlutoRunner/src/display/Exception.jl @@ -14,16 +14,27 @@ end frame_is_from_usercode(frame::Base.StackTraces.StackFrame) = occursin("#==#", String(frame.file)) -function frame_url(frame::Base.StackTraces.StackFrame) +function method_from_frame(frame::Base.StackTraces.StackFrame) if frame.linfo isa Core.MethodInstance - Base.url(frame.linfo.def) + frame.linfo.def elseif frame.linfo isa Method - Base.url(frame.linfo) + frame.linfo else nothing end end +frame_url(m::Method) = Base.url(m) +frame_url(::Any) = nothing + +function source_package(m::Union{Method,Module}) + @static if VERSION >= v"1.9" + next = parentmodule(m) + next === m ? m : source_package(next) + end +end +source_package(::Any) = nothing + function format_output(val::CapturedException; context=default_iocontext) if has_julia_syntax && val.ex isa PrettySyntaxError dict = convert_parse_error_to_dict(val.ex.ex.detail) @@ -49,6 +60,9 @@ function format_output(val::CapturedException; context=default_iocontext) stack_relevant = stack[1:something(limit, end)] pretty = map(stack_relevant) do s + method = method_from_frame(s) + sp = source_package(method) + Dict( :call => pretty_stackcall(s, s.linfo), :inlined => s.inlined, @@ -56,8 +70,9 @@ function format_output(val::CapturedException; context=default_iocontext) :file => basename(String(s.file)), :path => String(s.file), :line => s.line, - :url => frame_url(s), :linfo_type => string(typeof(s.linfo)), + :url => frame_url(method), + :source_package => sp === nothing ? nothing : string(sp), ) end else