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 }) => {
-
- ${diagnostics.map(
- ({ message, from, to, line }) =>
- html`- // 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} />
-
`)
- }
-
+
+ ${diagnostics.map(
+ ({ message, from, to, line }) =>
+ html`-
+ // 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} />
+
`
+ )}
+
- `;
+ `
}
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`-
+ (frame) =>
+ html`
-
<${Funccall} frame=${frame} />
@
<${StackFrameFilename} frame=${frame} cell_id=${cell_id} />
- ${frame.inlined ? html`[inlined]` : null}
`
- )}
+ )}
`}
`
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 }) => {
+
${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`
+
+ Here is what happened:
+
- ${stacktrace.map(
- (frame) =>
- html`-
+ ${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`
-
+ ${from_this_notebook ? html`<${LinePreview} frame=${frame} />` : null}
+
<${Funccall} frame=${frame} />
@
<${StackFrameFilename} frame=${frame} cell_id=${cell_id} />
- `
- )}
+
+ `
+ })}
`}
`
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`
- 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`-
- ${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}
`
})}
+ ${limited
+ ? html`-
+ {
+ set_show_more(true)
+ e.preventDefault()
+ }}
+ >Show more...
+
`
+ : 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 }) => {
-
+
${diagnostics.map(
({ message, from, to, line }) =>
html`-
// 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`
-
- 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`-
<${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;