From 6173f896ce9224eae14625136976c47a6d4463f7 Mon Sep 17 00:00:00 2001 From: Fons van der Plas Date: Thu, 15 Feb 2024 15:23:53 +0100 Subject: [PATCH 1/8] Stacktraces: shorter for macro expansion and `@Kwargs` in Julia 1.10 --- frontend/components/CellInput.js | 1 - frontend/components/ErrorMessage.js | 47 ++++++++++++----------- frontend/treeview.css | 3 ++ src/runner/PlutoRunner/src/PlutoRunner.jl | 37 +++++++++++++----- 4 files changed, 54 insertions(+), 34 deletions(-) diff --git a/frontend/components/CellInput.js b/frontend/components/CellInput.js index 1b9b108222..f1230f93ff 100644 --- a/frontend/components/CellInput.js +++ b/frontend/components/CellInput.js @@ -936,7 +936,6 @@ const InputContextMenu = ({ on_delete, cell_id, run_cell, skip_as_script, runnin const prevously_focused_element_ref = useRef(/** @type {Element?} */ (null)) const setOpen = (val) => { - console.error("setOpen", val) if (val) { prevously_focused_element_ref.current = document.activeElement } diff --git a/frontend/components/ErrorMessage.js b/frontend/components/ErrorMessage.js index 60e83a1515..b1ee0d3bc0 100644 --- a/frontend/components/ErrorMessage.js +++ b/frontend/components/ErrorMessage.js @@ -9,6 +9,7 @@ const StackFrameFilename = ({ frame, cell_id }) => { if (sep_index != -1) { const frame_cell_id = frame.file.substr(sep_index + 4, 36) const a = html` { window.dispatchEvent( @@ -58,24 +59,24 @@ export const ParseError = ({ cell_id, diagnostics }) => {

Syntax error

-
    - ${diagnostics.map( - ({ message, from, to, line }) => - html`
  1. // NOTE: this could be moved move to `StackFrameFilename` - window.dispatchEvent(new CustomEvent("cell_highlight_range", { detail: { cell_id, from, to }})) - } - onmouseleave=${() => - window.dispatchEvent(new CustomEvent("cell_highlight_range", { detail: { cell_id, from: null, to: null }})) - } - > - ${message}@ - <${StackFrameFilename} frame=${{file: "#==#" + cell_id, line}} cell_id=${cell_id} /> -
  2. `) - } -
+
    + ${diagnostics.map( + ({ message, from, to, line }) => + html`
  1. + // NOTE: this could be moved move to `StackFrameFilename` + window.dispatchEvent(new CustomEvent("cell_highlight_range", { detail: { cell_id, from, to } }))} + onmouseleave=${() => + window.dispatchEvent(new CustomEvent("cell_highlight_range", { detail: { cell_id, from: null, to: null } }))} + > + ${message}@ + <${StackFrameFilename} frame=${{ file: "#==#" + cell_id, line }} cell_id=${cell_id} /> +
  2. ` + )} +
- `; + ` } export const ErrorMessage = ({ msg, stacktrace, cell_id }) => { @@ -102,9 +103,9 @@ export const ErrorMessage = ({ msg, stacktrace, cell_id }) => {
{ - e.preventDefault() - pluto_actions.split_remote_cell(cell_id, boundaries, true) - }} + e.preventDefault() + pluto_actions.split_remote_cell(cell_id, boundaries, true) + }} >Split this cell into ${boundaries.length} cells, or

` @@ -221,6 +222,7 @@ export const ErrorMessage = ({ msg, stacktrace, cell_id }) => { const matched_rewriter = rewriters.find(({ pattern }) => pattern.test(msg)) ?? default_rewriter + console.log(stacktrace) return html`
${matched_rewriter.display(msg)}
${stacktrace.length == 0 || !(matched_rewriter.show_stacktrace?.() ?? true) @@ -228,14 +230,13 @@ export const ErrorMessage = ({ msg, stacktrace, cell_id }) => { : html`
    ${stacktrace.map( - (frame) => - html`
  1. + (frame) => + html`
  2. <${Funccall} frame=${frame} /> @ <${StackFrameFilename} frame=${frame} cell_id=${cell_id} /> - ${frame.inlined ? html`[inlined]` : null}
  3. ` - )} + )}
`}
` diff --git a/frontend/treeview.css b/frontend/treeview.css index cd8c586b12..338f58784e 100644 --- a/frontend/treeview.css +++ b/frontend/treeview.css @@ -271,6 +271,9 @@ jlerror > section > ol > li > span { opacity: 0.8; padding: 0px 1em; } +jlerror .frame-inlined { + opacity: 0.4; +} table.pluto-table { table-layout: fixed; diff --git a/src/runner/PlutoRunner/src/PlutoRunner.jl b/src/runner/PlutoRunner/src/PlutoRunner.jl index 2028b58039..624a16bcb0 100644 --- a/src/runner/PlutoRunner/src/PlutoRunner.jl +++ b/src/runner/PlutoRunner/src/PlutoRunner.jl @@ -1218,6 +1218,16 @@ end const has_julia_syntax = isdefined(Base, :JuliaSyntax) && fieldcount(Base.Meta.ParseError) == 2 +function frame_is_from_plutorunner(frame::Base.StackTraces.StackFrame) + if frame.linfo isa Core.MethodInstance + frame.linfo.def.module === PlutoRunner + else + endswith(String(frame.file), "PlutoRunner.jl") + end +end + +frame_is_from_usercode(frame::Base.StackTraces.StackFrame) = occursin("#==#", String(frame.file)) + function format_output(val::CapturedException; context=default_iocontext) if has_julia_syntax && val.ex isa Base.Meta.ParseError && val.ex.detail isa Base.JuliaSyntax.ParseError dict = convert_parse_error_to_dict(val.ex.detail) @@ -1230,21 +1240,23 @@ function format_output(val::CapturedException; context=default_iocontext) # function_wrap_index = findfirst(f -> occursin("function_wrapped_cell", String(f.func)), stack) - function_wrap_index = findlast(f -> occursin("#==#", String(f.file)), stack) - - if function_wrap_index === nothing - for _ in 1:2 - until = findfirst(b -> b.func == :eval, reverse(stack)) - stack = until === nothing ? stack : stack[1:end - until] - end + function_wrap_index = findlast(frame_is_from_usercode, stack) + internal_index = findfirst(frame_is_from_plutorunner, stack) + + limit = if function_wrap_index !== nothing + function_wrap_index + elseif internal_index !== nothing + internal_index - 1 else - stack = stack[1:function_wrap_index] + nothing end + stack_relevant = stack[1:something(limit, end)] - pretty = map(stack) do s + pretty = map(stack_relevant) do s Dict( :call => pretty_stackcall(s, s.linfo), :inlined => s.inlined, + :from_c => s.from_c, :file => basename(String(s.file)), :path => String(s.file), :line => s.line, @@ -1290,7 +1302,12 @@ end function pretty_stackcall(frame::Base.StackFrame, linfo::Core.MethodInstance) if linfo.def isa Method - sprint(Base.show_tuple_as_call, linfo.def.name, linfo.specTypes) + @static if isdefined(Base.StackTraces, :show_spec_linfo) && hasmethod(Base.StackTraces.show_spec_linfo, Tuple{IO, Base.StackFrame}) + sprint(Base.StackTraces.show_spec_linfo, frame; context=:backtrace => true) + + else + split(string(frame), " at ") |> first + end else sprint(Base.show, linfo) end From 09282f5b718449868bcb538fc940a8b8c05b64b6 Mon Sep 17 00:00:00 2001 From: Fons van der Plas Date: Thu, 15 Feb 2024 15:26:02 +0100 Subject: [PATCH 2/8] rm --- frontend/components/ErrorMessage.js | 1 - frontend/treeview.css | 3 --- 2 files changed, 4 deletions(-) diff --git a/frontend/components/ErrorMessage.js b/frontend/components/ErrorMessage.js index b1ee0d3bc0..f5f43ea58a 100644 --- a/frontend/components/ErrorMessage.js +++ b/frontend/components/ErrorMessage.js @@ -222,7 +222,6 @@ export const ErrorMessage = ({ msg, stacktrace, cell_id }) => { const matched_rewriter = rewriters.find(({ pattern }) => pattern.test(msg)) ?? default_rewriter - console.log(stacktrace) return html`
${matched_rewriter.display(msg)}
${stacktrace.length == 0 || !(matched_rewriter.show_stacktrace?.() ?? true) diff --git a/frontend/treeview.css b/frontend/treeview.css index 338f58784e..cd8c586b12 100644 --- a/frontend/treeview.css +++ b/frontend/treeview.css @@ -271,9 +271,6 @@ jlerror > section > ol > li > span { opacity: 0.8; padding: 0px 1em; } -jlerror .frame-inlined { - opacity: 0.4; -} table.pluto-table { table-layout: fixed; From 3c2630726fbcb1873c331a91dc7233c73a3cf214 Mon Sep 17 00:00:00 2001 From: Fons van der Plas Date: Thu, 15 Feb 2024 17:00:22 +0100 Subject: [PATCH 3/8] Stack traces with code preview --- frontend/components/ErrorMessage.js | 112 +++++++++++++++++++++++----- frontend/editor.css | 4 +- frontend/light_color.css | 2 + frontend/treeview.css | 60 ++++++++++++++- 4 files changed, 154 insertions(+), 24 deletions(-) diff --git a/frontend/components/ErrorMessage.js b/frontend/components/ErrorMessage.js index f5f43ea58a..00812966f0 100644 --- a/frontend/components/ErrorMessage.js +++ b/frontend/components/ErrorMessage.js @@ -1,25 +1,38 @@ +import { cl } from "../common/ClassTable.js" import { PlutoActionsContext } from "../common/PlutoContext.js" import { EditorState, EditorView, julia_andrey, lineNumbers, syntaxHighlighting } from "../imports/CodemirrorPlutoSetup.js" import { html, useContext, useEffect, useLayoutEffect, useRef, useState } from "../imports/Preact.js" import { pluto_syntax_colors } from "./CellInput.js" +import { highlight } from "./CellOutput.js" import { Editor } from "./Editor.js" -const StackFrameFilename = ({ frame, cell_id }) => { - const sep_index = frame.file.indexOf("#==#") +const extract_cell_id = (/** @type {string} */ file) => { + const sep_index = file.indexOf("#==#") if (sep_index != -1) { - const frame_cell_id = frame.file.substr(sep_index + 4, 36) + return file.substr(sep_index + 4, 36) + } else { + return null + } +} + +const focus_line = (cell_id, line) => + window.dispatchEvent( + new CustomEvent("cell_focus", { + detail: { + cell_id: cell_id, + line: line, + }, + }) + ) + +const StackFrameFilename = ({ frame, cell_id }) => { + const frame_cell_id = extract_cell_id(frame.file) + if (frame_cell_id != null) { const a = html` { - window.dispatchEvent( - new CustomEvent("cell_focus", { - detail: { - cell_id: frame_cell_id, - line: frame.line - 1, // 1-based to 0-based index - }, - }) - ) + focus_line(frame_cell_id, frame.line - 1) e.preventDefault() }} > @@ -40,6 +53,56 @@ const Funccall = ({ frame }) => { } } +const LinePreview = ({ frame }) => { + let pluto_actions = useContext(PlutoActionsContext) + let cell_id = extract_cell_id(frame.file) + if (cell_id) { + let code = /** @type{import("./Editor.js").NotebookData?} */ (pluto_actions.get_notebook())?.cell_inputs[cell_id]?.code + + console.log(code) + if (code) { + const lines = code.split("\n") + console.log(frame.line) + + return html` { + focus_line(cell_id, frame.line - 1) + e.preventDefault() + }} + href=${`#${cell_id}`} + class="frame-line-preview" + >
+
+${lines.map((line, i) =>
+                            frame.line - 3 <= i && i <= frame.line + 1
+                                ? html`<${JuliaHighlightedLine} code=${line} frameLine=${i === frame.line - 1 && lines.length > 1} />`
+                                : null
+                        )}
+
` + } + } +} + +const JuliaHighlightedLine = ({ code, frameLine }) => { + const code_ref = useRef(/** @type {HTMLPreElement?} */ (null)) + useLayoutEffect(() => { + if (code_ref.current) { + code_ref.current.innerText = code + highlight(code_ref.current, "julia") + } + }, [code_ref.current, code]) + + return html`` +} + const insert_commas_and_and = (/** @type {any[]} */ xs) => xs.flatMap((x, i) => (i === xs.length - 1 ? [x] : i === xs.length - 2 ? [x, " and "] : [x, ", "])) export const ParseError = ({ cell_id, diagnostics }) => { @@ -59,6 +122,7 @@ export const ParseError = ({ cell_id, diagnostics }) => {

Syntax error

+
Syntax errors
    ${diagnostics.map( ({ message, from, to, line }) => @@ -69,8 +133,10 @@ export const ParseError = ({ cell_id, diagnostics }) => { onmouseleave=${() => window.dispatchEvent(new CustomEvent("cell_highlight_range", { detail: { cell_id, from: null, to: null } }))} > - ${message}@ - <${StackFrameFilename} frame=${{ file: "#==#" + cell_id, line }} cell_id=${cell_id} /> +
    + ${message}@ + <${StackFrameFilename} frame=${{ file: "#==#" + cell_id, line }} cell_id=${cell_id} /> +
    ` )}
@@ -227,15 +293,23 @@ export const ErrorMessage = ({ msg, stacktrace, cell_id }) => { ${stacktrace.length == 0 || !(matched_rewriter.show_stacktrace?.() ?? true) ? null : html`
+
Stack trace
+

Here is what happened:

+
    - ${stacktrace.map( - (frame) => - html`
  1. + ${stacktrace.map((frame) => { + const frame_cell_id = extract_cell_id(frame.file) + const from_this_notebook = frame_cell_id != null + const from_this_cell = cell_id === frame_cell_id + return html`
  2. + ${from_this_notebook ? html`<${LinePreview} frame=${frame} />` : null} +
    <${Funccall} frame=${frame} /> @ <${StackFrameFilename} frame=${frame} cell_id=${cell_id} /> -
  3. ` - )} + + ` + })}
`} ` diff --git a/frontend/editor.css b/frontend/editor.css index 4a2407741f..2e3f95d8ca 100644 --- a/frontend/editor.css +++ b/frontend/editor.css @@ -1328,7 +1328,7 @@ pluto-input .cm-editor .cm-line { pluto-input .cm-editor span.cm-highlighted-range, pluto-input .cm-editor .cm-line.cm-highlighted-line { - background-color: #bdbdbd68; + background-color: var(--cm-highlighted); border-radius: 3px; } @@ -3280,7 +3280,7 @@ Based on "Paraíso (Light)" by Jan T. Sott: .cm-editor .cm-tooltip.cm-tooltip-autocomplete li.c_from_notebook .cm-completionLabel { font-weight: bold; text-decoration: underline; - text-decoration-color: #ced2ef; + text-decoration-color: var(--cm-clickable-underline); text-decoration-thickness: 3px; text-decoration-skip-ink: none; } diff --git a/frontend/light_color.css b/frontend/light_color.css index c2c59224d5..4f96c6d541 100644 --- a/frontend/light_color.css +++ b/frontend/light_color.css @@ -186,6 +186,7 @@ --cm-line-numbers-color: #8d86875e; --cm-selection-background: hsl(214deg 100% 73% / 48%); --cm-selection-background-blurred: hsl(214deg 0% 73% / 48%); + --cm-highlighted: #cbceb668; /* code highlighting */ --cm-editor-text-color: #41323f; @@ -209,6 +210,7 @@ --cm-matchingBracket-color: black; --cm-matchingBracket-bg-color: #1b4bbb21; --cm-placeholder-text-color: rgba(0, 0, 0, 0.2); + --cm-clickable-underline: #ced2ef; /*autocomplete menu*/ --autocomplete-menu-bg-color: white; diff --git a/frontend/treeview.css b/frontend/treeview.css index cd8c586b12..686c6a68e8 100644 --- a/frontend/treeview.css +++ b/frontend/treeview.css @@ -253,25 +253,79 @@ jlerror > header > p { jlerror > header > p:first-child { font-weight: bold; } -jlerror > section > ol > li > mark { +jlerror .stacktrace-header { + font-family: var(--system-ui-font-stack); + font-size: 1.9rem; + font-weight: 700; +} +jlerror > section { + padding: 1em; + background-color: var(--code-section-bg-color); + border: 3px solid var(--pkg-terminal-border-color); + border-radius: 0.6em; + margin: 1em 0; +} +jlerror > section > ol { + line-height: 1.6; +} +jlerror > section > ol > li.from_this_notebook { + --bg: #e1efff; + background: var(--bg); + outline: 3px solid var(--bg); + padding: 0.4em 0.2em; + border-radius: 0.6em; +} +jlerror > section .classical-frame > mark { background: var(--jlerror-mark-bg-color); border-radius: 6px; color: var(--jlerror-mark-color); font-family: var(--julia-mono-font-stack); font-variant-ligatures: none; } -jlerror > section > ol > li > em > a { +jlerror > section .classical-frame > em > a { background: var(--jlerror-a-bg-color); border-radius: 4px; padding: 1px 7px; text-decoration: none; border-left: 3px solid var(--jlerror-a-border-left-color); } -jlerror > section > ol > li > span { +jlerror > section .classical-frame > span { opacity: 0.8; padding: 0px 1em; } +jlerror li::marker { + background: red; + border: 3px solid red; + /* font-size: 0.7rem; */ + font-weight: 900; + color: var(--pluto-logs-key-color); +} + +jlerror li.from_this_notebook .classical-frame { + opacity: 0.4; +} + +jlerror li a.frame-line-preview { + display: block; + text-decoration: none; + border: 3px solid var(--cm-clickable-underline); + --br: 0.6em; + border-radius: var(--br); +} +jlerror li .frame-line-preview pre:not(.asdfdsaf) { + background-color: var(--code-background); + padding: 0 1em; + border-radius: var(--br); +} + +jlerror li .frame-line-preview pre > code.frame-line { + background: var(--cm-highlighted); +} +jlerror li .frame-line-preview pre > code:not(.frame-line) { + opacity: 0.7; +} + table.pluto-table { table-layout: fixed; } From 761f204849716e6b1df715f3704ecbe15ab66e3e Mon Sep 17 00:00:00 2001 From: Fons van der Plas Date: Fri, 16 Feb 2024 10:39:30 +0100 Subject: [PATCH 4/8] yayy --- frontend/components/ErrorMessage.js | 36 +++++++++++++++++++---- frontend/editor.css | 10 ++++++- frontend/treeview.css | 12 ++++++-- src/runner/PlutoRunner/src/PlutoRunner.jl | 11 +++++++ 4 files changed, 59 insertions(+), 10 deletions(-) diff --git a/frontend/components/ErrorMessage.js b/frontend/components/ErrorMessage.js index 00812966f0..3034223ebd 100644 --- a/frontend/components/ErrorMessage.js +++ b/frontend/components/ErrorMessage.js @@ -36,11 +36,13 @@ const StackFrameFilename = ({ frame, cell_id }) => { e.preventDefault() }} > - ${frame_cell_id == cell_id ? "Local" : "Other"}: ${frame.line} + ${frame_cell_id == cell_id ? "This cell" : "Other cell"}: line ${frame.line} ` return html`${a}` } else { - return html`${frame.file}:${frame.line}` + return html`${frame.file}:${frame.line}` } } @@ -59,7 +61,6 @@ const LinePreview = ({ frame }) => { if (cell_id) { let code = /** @type{import("./Editor.js").NotebookData?} */ (pluto_actions.get_notebook())?.cell_inputs[cell_id]?.code - console.log(code) if (code) { const lines = code.split("\n") console.log(frame.line) @@ -288,28 +289,51 @@ export const ErrorMessage = ({ msg, stacktrace, cell_id }) => { const matched_rewriter = rewriters.find(({ pattern }) => pattern.test(msg)) ?? default_rewriter + const [show_more, set_show_more] = useState(false) + useEffect(() => { + set_show_more(false) + }, [msg, stacktrace, cell_id]) + + const first_stack_from_here = stacktrace.findIndex((frame) => extract_cell_id(frame.file) != null) + + const limited = !show_more && first_stack_from_here != -1 && first_stack_from_here < stacktrace.length - 1 + + const limited_stacktrace = limited ? stacktrace.slice(0, first_stack_from_here + 1) : stacktrace + return html`
${matched_rewriter.display(msg)}
${stacktrace.length == 0 || !(matched_rewriter.show_stacktrace?.() ?? true) ? null : html`
Stack trace
-

Here is what happened:

+

Here is what happened, the most recent locations are first:

    - ${stacktrace.map((frame) => { + ${limited_stacktrace.map((frame) => { const frame_cell_id = extract_cell_id(frame.file) const from_this_notebook = frame_cell_id != null const from_this_cell = cell_id === frame_cell_id return html`
  1. - ${from_this_notebook ? html`<${LinePreview} frame=${frame} />` : null}
    <${Funccall} frame=${frame} /> @ <${StackFrameFilename} frame=${frame} cell_id=${cell_id} />
    + ${from_this_notebook ? html`<${LinePreview} frame=${frame} />` : null}
  2. ` })} + ${limited + ? html`
  3. + { + set_show_more(true) + e.preventDefault() + }} + >Show more... +
  4. ` + : null}
`}
` diff --git a/frontend/editor.css b/frontend/editor.css index 2e3f95d8ca..e2861bad63 100644 --- a/frontend/editor.css +++ b/frontend/editor.css @@ -3399,7 +3399,15 @@ pluto-cell.code_differs .cm-editor .cm-gutters { } pluto-input:focus-within .cm-editor .cm-lineNumbers .cm-gutterElement::after { color: transparent; -} */ +} + */ + +pluto-cell.errored .cm-editor .cm-lineNumbers .cm-gutterElement { + color: var(--cm-line-numbers-color); +} +pluto-cell.errored .cm-editor .cm-lineNumbers .cm-gutterElement::after { + color: transparent; +} /* Case 2: Print */ @media print { .cm-editor .cm-lineNumbers .cm-gutterElement { diff --git a/frontend/treeview.css b/frontend/treeview.css index 686c6a68e8..cbf2ca3322 100644 --- a/frontend/treeview.css +++ b/frontend/treeview.css @@ -267,9 +267,12 @@ jlerror > section { } jlerror > section > ol { line-height: 1.6; + /* transform: perspective(29rem) rotateX(-12.7deg); */ + /* transform-origin: top; */ + /* perspective-origin: top; */ } jlerror > section > ol > li.from_this_notebook { - --bg: #e1efff; + --bg: var(--jl-info-acccolor); background: var(--bg); outline: 3px solid var(--bg); padding: 0.4em 0.2em; @@ -282,13 +285,16 @@ jlerror > section .classical-frame > mark { font-family: var(--julia-mono-font-stack); font-variant-ligatures: none; } -jlerror > section .classical-frame > em > a { +jlerror > section .classical-frame > em > a[href] { background: var(--jlerror-a-bg-color); border-radius: 4px; padding: 1px 7px; text-decoration: none; border-left: 3px solid var(--jlerror-a-border-left-color); } +jlerror > section .classical-frame > em > a[href].remote-url { + filter: hue-rotate(160deg); +} jlerror > section .classical-frame > span { opacity: 0.8; padding: 0px 1em; @@ -303,7 +309,7 @@ jlerror li::marker { } jlerror li.from_this_notebook .classical-frame { - opacity: 0.4; + /* opacity: 0.4; */ } jlerror li a.frame-line-preview { diff --git a/src/runner/PlutoRunner/src/PlutoRunner.jl b/src/runner/PlutoRunner/src/PlutoRunner.jl index 624a16bcb0..6dbb590f25 100644 --- a/src/runner/PlutoRunner/src/PlutoRunner.jl +++ b/src/runner/PlutoRunner/src/PlutoRunner.jl @@ -1228,6 +1228,16 @@ end frame_is_from_usercode(frame::Base.StackTraces.StackFrame) = occursin("#==#", String(frame.file)) +function frame_url(frame::Base.StackTraces.StackFrame) + if frame.linfo isa Core.MethodInstance + Base.url(frame.linfo.def) + elseif frame.linfo isa Method + Base.url(frame.linfo) + else + nothing + end +end + function format_output(val::CapturedException; context=default_iocontext) if has_julia_syntax && val.ex isa Base.Meta.ParseError && val.ex.detail isa Base.JuliaSyntax.ParseError dict = convert_parse_error_to_dict(val.ex.detail) @@ -1260,6 +1270,7 @@ function format_output(val::CapturedException; context=default_iocontext) :file => basename(String(s.file)), :path => String(s.file), :line => s.line, + :url => frame_url(s), ) end else From 951cd5a826bf65043957020310e687be14d52d8d Mon Sep 17 00:00:00 2001 From: Fons van der Plas Date: Fri, 16 Feb 2024 11:50:40 +0100 Subject: [PATCH 5/8] linenuberbs --- frontend/components/ErrorMessage.js | 15 ++++++++++----- frontend/treeview.css | 4 ++++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/frontend/components/ErrorMessage.js b/frontend/components/ErrorMessage.js index 3034223ebd..71c562f4f2 100644 --- a/frontend/components/ErrorMessage.js +++ b/frontend/components/ErrorMessage.js @@ -55,7 +55,7 @@ const Funccall = ({ frame }) => { } } -const LinePreview = ({ frame }) => { +const LinePreview = ({ frame, num_context_lines = 2 }) => { let pluto_actions = useContext(PlutoActionsContext) let cell_id = extract_cell_id(frame.file) if (cell_id) { @@ -75,8 +75,12 @@ const LinePreview = ({ frame }) => { >
 ${lines.map((line, i) =>
-                            frame.line - 3 <= i && i <= frame.line + 1
-                                ? html`<${JuliaHighlightedLine} code=${line} frameLine=${i === frame.line - 1 && lines.length > 1} />`
+                            frame.line - 1 - num_context_lines <= i && i <= frame.line - 1 + num_context_lines
+                                ? html`<${JuliaHighlightedLine}
+                                      code=${line}
+                                      i=${i}
+                                      frameLine=${i === frame.line - 1 && num_context_lines > 0 && lines.length > 1}
+                                  />`
                                 : null
                         )}
@@ -86,7 +90,7 @@ ${lines.map((line, i) => } } -const JuliaHighlightedLine = ({ code, frameLine }) => { +const JuliaHighlightedLine = ({ code, frameLine, i }) => { const code_ref = useRef(/** @type {HTMLPreElement?} */ (null)) useLayoutEffect(() => { if (code_ref.current) { @@ -97,6 +101,7 @@ const JuliaHighlightedLine = ({ code, frameLine }) => { return html` { @ <${StackFrameFilename} frame=${frame} cell_id=${cell_id} />
- ${from_this_notebook ? html`<${LinePreview} frame=${frame} />` : null} + ${from_this_notebook ? html`<${LinePreview} frame=${frame} num_context_lines=${from_this_cell ? 1 : 2} />` : null} ` })} ${limited diff --git a/frontend/treeview.css b/frontend/treeview.css index cbf2ca3322..513fcc3117 100644 --- a/frontend/treeview.css +++ b/frontend/treeview.css @@ -331,6 +331,10 @@ jlerror li .frame-line-preview pre > code.frame-line { jlerror li .frame-line-preview pre > code:not(.frame-line) { opacity: 0.7; } +jlerror li .frame-line-preview pre > code::before { + content: var(--before-content); + color: var(--cm-line-numbers-color); +} table.pluto-table { table-layout: fixed; From fb1ce7dba09e4c690811f95613914ef641f750c3 Mon Sep 17 00:00:00 2001 From: Fons van der Plas Date: Mon, 19 Feb 2024 13:36:21 +0100 Subject: [PATCH 6/8] yayyyy --- frontend/components/ErrorMessage.js | 50 +++++++++++++-------- frontend/components/Notebook.js | 2 +- frontend/treeview.css | 54 +++++++++++++++++++---- src/runner/PlutoRunner/src/PlutoRunner.jl | 1 + 4 files changed, 79 insertions(+), 28 deletions(-) diff --git a/frontend/components/ErrorMessage.js b/frontend/components/ErrorMessage.js index 71c562f4f2..28c50b18b2 100644 --- a/frontend/components/ErrorMessage.js +++ b/frontend/components/ErrorMessage.js @@ -26,6 +26,8 @@ const focus_line = (cell_id, line) => ) const StackFrameFilename = ({ frame, cell_id }) => { + if (ignore_location(frame)) return null + const frame_cell_id = extract_cell_id(frame.file) if (frame_cell_id != null) { const a = html` { e.preventDefault() }} > - ${frame_cell_id == cell_id ? "This cell" : "Other cell"}: line ${frame.line} + ${frame_cell_id == cell_id ? "This cell" : "Other cell"}: line ${frame.line} ` return html`${a}` } else { @@ -46,13 +48,20 @@ const StackFrameFilename = ({ frame, cell_id }) => { } } +const ignore_funccall = (frame) => frame.call === "top-level scope" +const ignore_location = (frame) => frame.file === "none" + const Funccall = ({ frame }) => { + if (ignore_funccall(frame)) return null + const bracket_index = frame.call.indexOf("(") - if (bracket_index != -1) { - return html`${frame.call.substr(0, bracket_index)}${frame.call.substr(bracket_index)}` - } else { - return html`${frame.call}` - } + + let inner = + bracket_index != -1 + ? html`${frame.call.substr(0, bracket_index)}${frame.call.substr(bracket_index)}` + : html`${frame.call}` + + return html`${inner}@` } const LinePreview = ({ frame, num_context_lines = 2 }) => { @@ -63,8 +72,6 @@ const LinePreview = ({ frame, num_context_lines = 2 }) => { if (code) { const lines = code.split("\n") - console.log(frame.line) - return html` { focus_line(cell_id, frame.line - 1) @@ -76,11 +83,7 @@ const LinePreview = ({ frame, num_context_lines = 2 }) => {
 ${lines.map((line, i) =>
                             frame.line - 1 - num_context_lines <= i && i <= frame.line - 1 + num_context_lines
-                                ? html`<${JuliaHighlightedLine}
-                                      code=${line}
-                                      i=${i}
-                                      frameLine=${i === frame.line - 1 && num_context_lines > 0 && lines.length > 1}
-                                  />`
+                                ? html`<${JuliaHighlightedLine} code=${line} i=${i} frameLine=${i === frame.line - 1} />`
                                 : null
                         )}
@@ -128,11 +131,12 @@ export const ParseError = ({ cell_id, diagnostics }) => {

Syntax error

-
Syntax errors
+
Syntax errors
    ${diagnostics.map( ({ message, from, to, line }) => html`
  1. // NOTE: this could be moved move to `StackFrameFilename` window.dispatchEvent(new CustomEvent("cell_highlight_range", { detail: { cell_id, from, to } }))} @@ -192,6 +196,7 @@ export const ErrorMessage = ({ msg, stacktrace, cell_id }) => {

    ${begin_hint}

    ` } }, + show_stacktrace: () => false, }, { pattern: /LoadError: cannot assign a value to variable workspace#\d+\..+ from module workspace#\d+/, @@ -255,6 +260,10 @@ export const ErrorMessage = ({ msg, stacktrace, cell_id }) => { display: default_rewriter.display, show_stacktrace: () => false, }, + { + pattern: /^\s*$/, + display: () => default_rewriter.display("Error"), + }, { pattern: /^UndefVarError: (.*) not defined\.?$/, display: (/** @type{string} */ x) => { @@ -263,7 +272,7 @@ export const ErrorMessage = ({ msg, stacktrace, cell_id }) => { // Verify that the UndefVarError is indeed about a variable from an upstream cell. const match = x.match(/UndefVarError: (.*) not defined/) - let sym = match?.[1] ?? "" + let sym = (match?.[1] ?? "").replaceAll("`", "") const undefvar_is_from_upstream = Object.values(notebook?.cell_dependencies ?? {}).some((map) => Object.keys(map.downstream_cells_map).includes(sym) ) @@ -303,15 +312,19 @@ export const ErrorMessage = ({ msg, stacktrace, cell_id }) => { const limited = !show_more && first_stack_from_here != -1 && first_stack_from_here < stacktrace.length - 1 - const limited_stacktrace = limited ? stacktrace.slice(0, first_stack_from_here + 1) : stacktrace + const limited_stacktrace = (limited ? stacktrace.slice(0, first_stack_from_here + 1) : stacktrace).filter( + (frame) => !(ignore_location(frame) && ignore_funccall(frame)) + ) return html`
    ${matched_rewriter.display(msg)}
    ${stacktrace.length == 0 || !(matched_rewriter.show_stacktrace?.() ?? true) ? null : html`
    -
    Stack trace
    -

    Here is what happened, the most recent locations are first:

    +
    + Stack trace +

    Here is what happened, the most recent locations are first:

    +
      ${limited_stacktrace.map((frame) => { @@ -321,7 +334,6 @@ export const ErrorMessage = ({ msg, stacktrace, cell_id }) => { return html`
    1. <${Funccall} frame=${frame} /> - @ <${StackFrameFilename} frame=${frame} cell_id=${cell_id} />
      ${from_this_notebook ? html`<${LinePreview} frame=${frame} num_context_lines=${from_this_cell ? 1 : 2} />` : null} diff --git a/frontend/components/Notebook.js b/frontend/components/Notebook.js index 00bd3c80fc..c7938be760 100644 --- a/frontend/components/Notebook.js +++ b/frontend/components/Notebook.js @@ -213,7 +213,7 @@ export const Notebook = ({ />` )} ${cell_outputs_delayed && notebook.cell_order.length >= render_cell_outputs_minimum - ? html`
      Loading...
      ` + ? html`
      Loading more cells...
      ` : null} ` diff --git a/frontend/treeview.css b/frontend/treeview.css index 513fcc3117..dcecee2392 100644 --- a/frontend/treeview.css +++ b/frontend/treeview.css @@ -243,9 +243,19 @@ jlerror { font-size: 0.75rem; font-family: "Roboto Mono", monospace; } +jlerror { + display: block; + padding: 1em; + background-color: var(--code-section-bg-color); + border: 3px solid var(--pkg-terminal-border-color); + border-radius: 0.6em; + margin: 1em 0; +} jlerror > header { color: var(--jlerror-header-color); + border-left: 3px solid var(--jlerror-header-color); + padding: 0.7rem; } jlerror > header > p { margin-block-end: 0.2em; @@ -255,15 +265,15 @@ jlerror > header > p:first-child { } jlerror .stacktrace-header { font-family: var(--system-ui-font-stack); +} +jlerror .stacktrace-header > secret-h1 { font-size: 1.9rem; font-weight: 700; } jlerror > section { - padding: 1em; - background-color: var(--code-section-bg-color); - border: 3px solid var(--pkg-terminal-border-color); - border-radius: 0.6em; - margin: 1em 0; + border-block-start: 3px dashed var(--pkg-terminal-border-color); + margin-block-start: 1rem; + padding-block-start: 1rem; } jlerror > section > ol { line-height: 1.6; @@ -291,12 +301,16 @@ jlerror > section .classical-frame > em > a[href] { padding: 1px 7px; text-decoration: none; border-left: 3px solid var(--jlerror-a-border-left-color); + /* font-family: var(--system-ui-font-stack); */ } jlerror > section .classical-frame > em > a[href].remote-url { filter: hue-rotate(160deg); } +jlerror > section li.from_this_notebook:not(.from_this_cell) .classical-frame > em > a[href] { + filter: hue-rotate(50deg); +} jlerror > section .classical-frame > span { - opacity: 0.8; + opacity: 0.4; padding: 0px 1em; } @@ -318,14 +332,27 @@ jlerror li a.frame-line-preview { border: 3px solid var(--cm-clickable-underline); --br: 0.6em; border-radius: var(--br); + --crop: -0.5em; } jlerror li .frame-line-preview pre:not(.asdfdsaf) { background-color: var(--code-background); - padding: 0 1em; + padding: 0; border-radius: var(--br); + overflow: hidden; + position: relative; +} + +jlerror li:not(.from_this_cell) .frame-line-preview pre::after { + content: "cell preview"; + display: block; + position: absolute; + bottom: 0; + right: 1ch; + font-weight: 900; + opacity: 0.6; } -jlerror li .frame-line-preview pre > code.frame-line { +jlerror li .frame-line-preview pre > code:not(:only-child).frame-line { background: var(--cm-highlighted); } jlerror li .frame-line-preview pre > code:not(.frame-line) { @@ -334,6 +361,17 @@ jlerror li .frame-line-preview pre > code:not(.frame-line) { jlerror li .frame-line-preview pre > code::before { content: var(--before-content); color: var(--cm-line-numbers-color); + margin-right: 0.7em; + width: 2ch; + display: inline-block; + text-align: right; +} + +jlerror li .frame-line-preview pre > code:first-of-type:not(.frame-line) { + margin-top: var(--crop); +} +jlerror li .frame-line-preview pre > code:last-of-type:not(.frame-line) { + margin-bottom: var(--crop); } table.pluto-table { diff --git a/src/runner/PlutoRunner/src/PlutoRunner.jl b/src/runner/PlutoRunner/src/PlutoRunner.jl index 6dbb590f25..10b69dcfee 100644 --- a/src/runner/PlutoRunner/src/PlutoRunner.jl +++ b/src/runner/PlutoRunner/src/PlutoRunner.jl @@ -1271,6 +1271,7 @@ function format_output(val::CapturedException; context=default_iocontext) :path => String(s.file), :line => s.line, :url => frame_url(s), + :linfo_type => string(typeof(s.linfo)), ) end else From 6ffcc0c2ff56ac95acca76b22a34397e74c6acbd Mon Sep 17 00:00:00 2001 From: Fons van der Plas Date: Mon, 19 Feb 2024 13:41:28 +0100 Subject: [PATCH 7/8] dark mode fixezs --- frontend/dark_color.css | 2 ++ frontend/editor.css | 7 ------- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/frontend/dark_color.css b/frontend/dark_color.css index 03893ad473..980f188f7f 100644 --- a/frontend/dark_color.css +++ b/frontend/dark_color.css @@ -183,6 +183,7 @@ --cm-line-numbers-color: #8d86875e; --cm-selection-background: hsl(215deg 64% 59% / 48%); --cm-selection-background-blurred: hsl(215deg 0% 59% / 48%); + --cm-highlighted: #cbceb629; /* code highlighting */ --cm-editor-text-color: #ffe9fc; @@ -206,6 +207,7 @@ --cm-matchingBracket-color: white; --cm-matchingBracket-bg-color: #c58c237a; --cm-placeholder-text-color: rgb(255 255 255 / 20%); + --cm-clickable-underline: #5d5f70; /*autocomplete menu*/ --autocomplete-menu-bg-color: var(--input-context-menu-bg-color); diff --git a/frontend/editor.css b/frontend/editor.css index e2861bad63..ec513ea583 100644 --- a/frontend/editor.css +++ b/frontend/editor.css @@ -3285,13 +3285,6 @@ Based on "Paraíso (Light)" by Jan T. Sott: text-decoration-skip-ink: none; } -@media (prefers-color-scheme: dark) { - [data-pluto-variable], - [data-pluto-variable]:hover { - text-decoration-color: #5d5f70; - } -} - body.disable_ui [data-pluto-variable], body.disable_ui [data-cell-variable] { cursor: pointer; From 006a6e8ecd0b2527c20b11a4b1276ed159449b43 Mon Sep 17 00:00:00 2001 From: Fons van der Plas Date: Mon, 19 Feb 2024 13:44:55 +0100 Subject: [PATCH 8/8] Update dark_color.css --- frontend/dark_color.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/dark_color.css b/frontend/dark_color.css index 980f188f7f..229b17544e 100644 --- a/frontend/dark_color.css +++ b/frontend/dark_color.css @@ -138,7 +138,7 @@ /* jlerror */ --jlerror-header-color: #d9baba; --jlerror-mark-bg-color: rgb(0 0 0 / 18%); - --jlerror-a-bg-color: rgba(82, 58, 58, 0.5); + --jlerror-a-bg-color: rgba(82, 58, 58, 1); --jlerror-a-border-left-color: #704141; --jlerror-mark-color: #b1a9a9;