From 5dd47b1226de0859338a2036d04770388dd5691a Mon Sep 17 00:00:00 2001 From: Fons van der Plas Date: Tue, 17 Sep 2024 13:12:12 +0200 Subject: [PATCH 01/27] frontend tweaks --- frontend/components/Notebook.js | 6 +++++- frontend/components/TreeView.js | 3 --- frontend/treeview.css | 1 + 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/frontend/components/Notebook.js b/frontend/components/Notebook.js index 90ff0f7b57..d21d7a83d7 100644 --- a/frontend/components/Notebook.js +++ b/frontend/components/Notebook.js @@ -163,7 +163,11 @@ export const Notebook = ({ let global_definition_locations = useMemo( () => Object.fromEntries( - Object.values(notebook?.cell_dependencies ?? {}).flatMap((x) => Object.keys(x.downstream_cells_map).map((variable) => [variable, x.cell_id])) + Object.values(notebook?.cell_dependencies ?? {}).flatMap((x) => + Object.keys(x.downstream_cells_map) + .filter((variable) => !variable.includes(".")) + .map((variable) => [variable, x.cell_id]) + ) ), [notebook?.cell_dependencies] ) diff --git a/frontend/components/TreeView.js b/frontend/components/TreeView.js index b3a07b3f79..99c73b0e3a 100644 --- a/frontend/components/TreeView.js +++ b/frontend/components/TreeView.js @@ -85,9 +85,6 @@ const useKeyboardClickable = (element_ref) => { const prefix = ({ prefix, prefix_short }) => { const element_ref = useRef(/** @type {HTMLElement?} */ (null)) - useEffect(() => { - console.log(element_ref.current) - }, []) useKeyboardClickable(element_ref) return html`${prefix}${prefix_short} Date: Tue, 17 Sep 2024 15:50:23 +0200 Subject: [PATCH 02/27] Bump micromatch from 4.0.4 to 4.0.8 in /frontend-bundler (#3014) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- frontend-bundler/package-lock.json | 32 +++++++++++++++--------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/frontend-bundler/package-lock.json b/frontend-bundler/package-lock.json index e54c2bb1b4..ed403cad78 100644 --- a/frontend-bundler/package-lock.json +++ b/frontend-bundler/package-lock.json @@ -4587,12 +4587,12 @@ } }, "node_modules/micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dependencies": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" + "braces": "^3.0.3", + "picomatch": "^2.3.1" }, "engines": { "node": ">=8.6" @@ -5284,9 +5284,9 @@ "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" }, "node_modules/picomatch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "engines": { "node": ">=8.6" }, @@ -10324,12 +10324,12 @@ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" }, "micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "requires": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" + "braces": "^3.0.3", + "picomatch": "^2.3.1" } }, "miller-rabin": { @@ -10839,9 +10839,9 @@ "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" }, "picomatch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==" + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" }, "pn": { "version": "1.1.0", From 36c4b0598e143acd1cade5a78f4a2469321af11a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 17 Sep 2024 16:02:33 +0200 Subject: [PATCH 03/27] Bump elliptic from 6.5.4 to 6.5.7 in /frontend-bundler (#3024) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- frontend-bundler/package-lock.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/frontend-bundler/package-lock.json b/frontend-bundler/package-lock.json index ed403cad78..a267b7e425 100644 --- a/frontend-bundler/package-lock.json +++ b/frontend-bundler/package-lock.json @@ -3110,9 +3110,9 @@ "integrity": "sha512-kZYCHqwJ1ctGrYDlOcWQH+/AftAm/KD4lEnLDNwS0kKwx1x6dU4zv+GuDjsPPOGn/2TjnKBaZjDyjXaoix0q/A==" }, "node_modules/elliptic": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", - "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "version": "6.5.7", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.7.tgz", + "integrity": "sha512-ESVCtTwiA+XhY3wyh24QqRGBoP3rEdDUl3EDUUo9tft074fi19IrdpH7hLCMMP3CIj7jb3W96rn8lt/BqIlt5Q==", "dependencies": { "bn.js": "^4.11.9", "brorand": "^1.1.0", @@ -9244,9 +9244,9 @@ "integrity": "sha512-kZYCHqwJ1ctGrYDlOcWQH+/AftAm/KD4lEnLDNwS0kKwx1x6dU4zv+GuDjsPPOGn/2TjnKBaZjDyjXaoix0q/A==" }, "elliptic": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", - "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "version": "6.5.7", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.7.tgz", + "integrity": "sha512-ESVCtTwiA+XhY3wyh24QqRGBoP3rEdDUl3EDUUo9tft074fi19IrdpH7hLCMMP3CIj7jb3W96rn8lt/BqIlt5Q==", "requires": { "bn.js": "^4.11.9", "brorand": "^1.1.0", From 78fbc95f633c6495dbe27a96e2828f2c8eb6e1d1 Mon Sep 17 00:00:00 2001 From: Fons van der Plas Date: Tue, 17 Sep 2024 16:05:52 +0200 Subject: [PATCH 04/27] Update Bundle.yml --- .github/workflows/Bundle.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/Bundle.yml b/.github/workflows/Bundle.yml index d7a218e8f7..fe21495182 100644 --- a/.github/workflows/Bundle.yml +++ b/.github/workflows/Bundle.yml @@ -19,6 +19,7 @@ concurrency: jobs: trigger: runs-on: ubuntu-latest + timeout-minutes: 20 steps: - uses: actions/checkout@v4 # We use that PAT token instead of GITHUB_TOKEN because we are triggering another github action on the 'release' event. From 53e1981fbc7ad09d91acd8ee37a1bd6228aa5904 Mon Sep 17 00:00:00 2001 From: Daniel Wennberg Date: Sun, 22 Sep 2024 15:27:56 -0400 Subject: [PATCH 05/27] Fix fallback for errors in logging (#3013) --- src/runner/PlutoRunner/src/PlutoRunner.jl | 4 +++ .../src/evaluation/deleting globals.jl | 4 +-- src/runner/PlutoRunner/src/io/logging.jl | 8 ++--- test/Logging.jl | 32 +++++++++++++++++++ 4 files changed, 42 insertions(+), 6 deletions(-) diff --git a/src/runner/PlutoRunner/src/PlutoRunner.jl b/src/runner/PlutoRunner/src/PlutoRunner.jl index 37d6184a07..46f33c6075 100644 --- a/src/runner/PlutoRunner/src/PlutoRunner.jl +++ b/src/runner/PlutoRunner/src/PlutoRunner.jl @@ -76,4 +76,8 @@ include("./io/logging.jl") include("./io/stdout.jl") include("./precompile.jl") +function __init__() + original_stderr[] = stderr +end + end diff --git a/src/runner/PlutoRunner/src/evaluation/deleting globals.jl b/src/runner/PlutoRunner/src/evaluation/deleting globals.jl index 0e8ce45536..6bebf0a4eb 100644 --- a/src/runner/PlutoRunner/src/evaluation/deleting globals.jl +++ b/src/runner/PlutoRunner/src/evaluation/deleting globals.jl @@ -87,7 +87,7 @@ function move_vars( catch ex if !(ex isa UndefVarError) @warn "Failed to move variable $(symbol) to new workspace:" - showerror(original_stderr, ex, stacktrace(catch_backtrace())) + showerror(original_stderr[], ex, stacktrace(catch_backtrace())) end end end @@ -198,7 +198,7 @@ function try_delete_toplevel_methods(workspace::Module, (cell_id, name_parts)::T (val isa Function) && delete_toplevel_methods(val, cell_id) catch ex @warn "Failed to delete methods for $(name_parts)" - showerror(original_stderr, ex, stacktrace(catch_backtrace())) + showerror(original_stderr[], ex, stacktrace(catch_backtrace())) false end catch diff --git a/src/runner/PlutoRunner/src/io/logging.jl b/src/runner/PlutoRunner/src/io/logging.jl index e1d3d05072..6231bd5c81 100644 --- a/src/runner/PlutoRunner/src/io/logging.jl +++ b/src/runner/PlutoRunner/src/io/logging.jl @@ -1,7 +1,6 @@ import Logging -const original_stdout = stdout -const original_stderr = stderr +const original_stderr = Ref{IO}() const old_logger = Ref{Union{Logging.AbstractLogger,Nothing}}(nothing) @@ -113,8 +112,9 @@ function Logging.handle_message(pl::PlutoCellLogger, level, msg, _module, group, yield() catch e - println(original_stderr, "Failed to relay log from PlutoRunner") - showerror(original_stderr, e, stacktrace(catch_backtrace())) + Logging.with_logger(Logging.ConsoleLogger(original_stderr[])) do + @error "Failed to relay log from PlutoRunner" exception=(e, catch_backtrace()) + end nothing end diff --git a/test/Logging.jl b/test/Logging.jl index c34d3f2654..ed5dc87774 100644 --- a/test/Logging.jl +++ b/test/Logging.jl @@ -66,6 +66,14 @@ using Pluto.WorkspaceManager: poll "show(stdout, collect(1:500))", # 24 "show(stdout, \"text/plain\", collect(1:500))", # 25 "display(collect(1:500))", # 26 + + "struct StructThatErrorsOnPrinting end", # 27 + """ + Base.print(::IO, ::StructThatErrorsOnPrinting) = error("Can't print this") + """, # 28 + """ + @info "" _id=StructThatErrorsOnPrinting() + """, # 29 ])) @testset "Stdout" begin @@ -201,4 +209,28 @@ using Pluto.WorkspaceManager: poll end cleanup(🍭, notebook) + + @testset "Logging error fallback" begin + # This testset needs to use a local worker to capture the worker stderr (which is + # different from the notebook stderr) + 🍍 = ServerSession() + 🍍.options.evaluation.workspace_use_distributed = false + + io = IOBuffer() + old_stderr = PlutoRunner.original_stderr[] + PlutoRunner.original_stderr[] = io + + update_run!(🍍, notebook, notebook.cells[27:29]) + + msg = String(take!(io)) + close(io) + PlutoRunner.original_stderr[] = old_stderr + + @test notebook.cells[27] |> noerror + @test notebook.cells[28] |> noerror + @test notebook.cells[29] |> noerror + @test occursin("Failed to relay log from PlutoRunner", msg) + + cleanup(🍍, notebook) + end end From a1138121415cea5338157b60f41ce860b40bde1d Mon Sep 17 00:00:00 2001 From: Fons van der Plas Date: Tue, 1 Oct 2024 15:13:07 +0200 Subject: [PATCH 06/27] Remove JuliaMono Latin subsets, fix #3029 --- frontend/editor.css | 2 ++ frontend/fonts/juliamono.css | 16 ---------------- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/frontend/editor.css b/frontend/editor.css index 46a8c2c347..fb756026d4 100644 --- a/frontend/editor.css +++ b/frontend/editor.css @@ -3464,6 +3464,8 @@ pluto-cell.code_differs .cm-editor .cm-gutters { position: absolute; right: 3px; pointer-events: none; + font-family: Arial; + transform: scale(1.8); } .cm-editor .cm-lineNumbers .cm-gutterElement:hover { color: var(--cm-color-line-numbers); diff --git a/frontend/fonts/juliamono.css b/frontend/fonts/juliamono.css index cd3d10d465..85af525edd 100644 --- a/frontend/fonts/juliamono.css +++ b/frontend/fonts/juliamono.css @@ -1,19 +1,3 @@ -@font-face { - font-family: JuliaMono; - src: url("https://cdn.jsdelivr.net/gh/cormullion/juliamono@0.047/webfonts/JuliaMono-RegularLatin.woff2") format("woff2"); - font-display: swap; - font-weight: 400; - unicode-range: U+00-7F; /* Basic Latin characters */ -} - -@font-face { - font-family: JuliaMono; - src: url("https://cdn.jsdelivr.net/gh/cormullion/juliamono@0.047/webfonts/JuliaMono-BoldLatin.woff2") format("woff2"); - font-display: swap; - font-weight: 700; - unicode-range: U+00-7F; /* Basic Latin characters */ -} - @font-face { font-family: JuliaMono; src: url("https://cdn.jsdelivr.net/gh/cormullion/juliamono@0.047/webfonts/JuliaMono-Regular.woff2") format("woff2"); From d4cd52be45ff717ed4db5a195d85a6f1b6271826 Mon Sep 17 00:00:00 2001 From: Fons van der Plas Date: Wed, 2 Oct 2024 09:57:44 +0200 Subject: [PATCH 07/27] Revert "Remove JuliaMono Latin subsets, fix #3029" This reverts commit a1138121415cea5338157b60f41ce860b40bde1d. --- frontend/editor.css | 2 -- frontend/fonts/juliamono.css | 16 ++++++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/frontend/editor.css b/frontend/editor.css index fb756026d4..46a8c2c347 100644 --- a/frontend/editor.css +++ b/frontend/editor.css @@ -3464,8 +3464,6 @@ pluto-cell.code_differs .cm-editor .cm-gutters { position: absolute; right: 3px; pointer-events: none; - font-family: Arial; - transform: scale(1.8); } .cm-editor .cm-lineNumbers .cm-gutterElement:hover { color: var(--cm-color-line-numbers); diff --git a/frontend/fonts/juliamono.css b/frontend/fonts/juliamono.css index 85af525edd..cd3d10d465 100644 --- a/frontend/fonts/juliamono.css +++ b/frontend/fonts/juliamono.css @@ -1,3 +1,19 @@ +@font-face { + font-family: JuliaMono; + src: url("https://cdn.jsdelivr.net/gh/cormullion/juliamono@0.047/webfonts/JuliaMono-RegularLatin.woff2") format("woff2"); + font-display: swap; + font-weight: 400; + unicode-range: U+00-7F; /* Basic Latin characters */ +} + +@font-face { + font-family: JuliaMono; + src: url("https://cdn.jsdelivr.net/gh/cormullion/juliamono@0.047/webfonts/JuliaMono-BoldLatin.woff2") format("woff2"); + font-display: swap; + font-weight: 700; + unicode-range: U+00-7F; /* Basic Latin characters */ +} + @font-face { font-family: JuliaMono; src: url("https://cdn.jsdelivr.net/gh/cormullion/juliamono@0.047/webfonts/JuliaMono-Regular.woff2") format("woff2"); From c27f4bd030f98628129e6055b0ecd5b7df91f023 Mon Sep 17 00:00:00 2001 From: Fons van der Plas Date: Wed, 2 Oct 2024 10:45:05 +0200 Subject: [PATCH 08/27] cm: Fix highlight causing tab shifts --- frontend/components/CellInput.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/components/CellInput.js b/frontend/components/CellInput.js index d3a88150b2..3da72fa4a6 100644 --- a/frontend/components/CellInput.js +++ b/frontend/components/CellInput.js @@ -594,7 +594,7 @@ export const CellInput = ({ rectangularSelection({ eventFilter: (e) => e.altKey && e.shiftKey && e.button == 0, }), - highlightSelectionMatches({ minSelectionLength: 2 }), + highlightSelectionMatches({ minSelectionLength: 2, wholeWords: true }), bracketMatching(), docs_updater, tab_help_plugin, From 1a7856314447343b5e4517a30f05c42d4fd978dd Mon Sep 17 00:00:00 2001 From: Fons van der Plas Date: Wed, 2 Oct 2024 11:24:50 +0200 Subject: [PATCH 09/27] css: fix nested admonitions --- frontend/editor.css | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/frontend/editor.css b/frontend/editor.css index 46a8c2c347..85567be5ef 100644 --- a/frontend/editor.css +++ b/frontend/editor.css @@ -341,31 +341,31 @@ pluto-output div.admonition.hint { background: var(--jl-info-color); border: 5px solid var(--jl-info-accent-color); } -pluto-output div.admonition.note .admonition-title, -pluto-output div.admonition.info .admonition-title, -pluto-output div.admonition.hint .admonition-title { +pluto-output div.admonition.note > .admonition-title, +pluto-output div.admonition.info > .admonition-title, +pluto-output div.admonition.hint > .admonition-title { background: var(--jl-info-accent-color); } pluto-output div.admonition.warning { background: var(--jl-warn-color); border: 5px solid var(--jl-warn-accent-color); } -pluto-output div.admonition.warning .admonition-title { +pluto-output div.admonition.warning > .admonition-title { background: var(--jl-warn-accent-color); } pluto-output div.admonition.danger { background: var(--jl-danger-color); border: 5px solid var(--jl-danger-accent-color); } -pluto-output div.admonition.danger .admonition-title { +pluto-output div.admonition.danger > .admonition-title { background: var(--jl-danger-accent-color); } -pluto-output div.admonition.hint .admonition-title ~ * { +pluto-output div.admonition.hint > .admonition-title ~ * { filter: blur(0.25em); } -pluto-output div.admonition.hint:hover .admonition-title ~ *, -pluto-output div.admonition.hint:focus-within .admonition-title ~ * { +pluto-output div.admonition.hint:hover > .admonition-title ~ *, +pluto-output div.admonition.hint:focus-within > .admonition-title ~ * { filter: blur(0em); } From 9b90311a4310b368b5179c8de2c6691babe02a47 Mon Sep 17 00:00:00 2001 From: Fons van der Plas Date: Wed, 2 Oct 2024 15:52:28 +0200 Subject: [PATCH 10/27] fix latex markdown --- frontend/components/Popup.js | 2 +- src/packages/Packages.jl | 1 + src/runner/PlutoRunner/src/PlutoRunner.jl | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/frontend/components/Popup.js b/frontend/components/Popup.js index b5a14314e9..6b56502f60 100644 --- a/frontend/components/Popup.js +++ b/frontend/components/Popup.js @@ -97,7 +97,7 @@ export const Popup = ({ notebook, disable_input }) => { requestAnimationFrame(() => { element_focused_before_popup.current = document.activeElement const el = element_ref.current?.querySelector("a") ?? element_ref.current - console.log("restoring focus to", el) + // console.debug("restoring focus to", el) el?.focus?.() }) } else { diff --git a/src/packages/Packages.jl b/src/packages/Packages.jl index 4fb1192eda..13bf3517e7 100644 --- a/src/packages/Packages.jl +++ b/src/packages/Packages.jl @@ -592,6 +592,7 @@ function update_nbpkg_core( end + PkgCompat.refresh_registry_cache() 🐧 = !PkgCompat.is_original(notebook.nbpkg_ctx) should_instantiate_again = !notebook.nbpkg_ctx_instantiated || 🐧 diff --git a/src/runner/PlutoRunner/src/PlutoRunner.jl b/src/runner/PlutoRunner/src/PlutoRunner.jl index 46f33c6075..4e449833a2 100644 --- a/src/runner/PlutoRunner/src/PlutoRunner.jl +++ b/src/runner/PlutoRunner/src/PlutoRunner.jl @@ -55,6 +55,7 @@ include("./evaluation/run_expression.jl") include("./evaluation/deleting globals.jl") +include("./display/LaTeX.jl") include("./display/format_output.jl") include("./display/IOContext.jl") include("./display/syntax error.jl") From 7c39672a550e1b766a17dfdcc080a6334ec663ba Mon Sep 17 00:00:00 2001 From: Fons van der Plas Date: Thu, 3 Oct 2024 12:41:01 +0200 Subject: [PATCH 11/27] Stack frame tweaks (#3039) --- 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 From 99cf0e4a469d0d74d01db5f4baab307ea6439b2c Mon Sep 17 00:00:00 2001 From: Fons van der Plas Date: Thu, 3 Oct 2024 12:59:29 +0200 Subject: [PATCH 12/27] Stack trace tweaks part 2 --- frontend/components/ErrorMessage.js | 96 ++++++++++++++++--- frontend/treeview.css | 25 +++-- .../PlutoRunner/src/display/Exception.jl | 2 + 3 files changed, 102 insertions(+), 21 deletions(-) diff --git a/frontend/components/ErrorMessage.js b/frontend/components/ErrorMessage.js index 21f120e197..03db50bd1b 100644 --- a/frontend/components/ErrorMessage.js +++ b/frontend/components/ErrorMessage.js @@ -4,6 +4,7 @@ import { html, useContext, useEffect, useLayoutEffect, useRef, useState } from " import { highlight } from "./CellOutput.js" import { PkgTerminalView } from "./PkgTerminalView.js" import _ from "../imports/lodash.js" +import { open_bottom_right_panel } from "./BottomRightPanel.js" const extract_cell_id = (/** @type {string} */ file) => { const sep_index = file.indexOf("#==#") @@ -24,12 +25,40 @@ const focus_line = (cell_id, line) => }) ) +const DocLink = ({ frame }) => { + let pluto_actions = useContext(PlutoActionsContext) + + if (frame.parent_module == null) return null + if (ignore_funccall(frame)) return null + + const nb = pluto_actions.get_notebook() + + const pkg_name = frame.source_package + const builtin = ["Main", "Core", "Base"].includes(pkg_name) + const installed = nb?.nbpkg?.installed_versions?.[frame.source_package] != null + + if (!builtin && nb?.nbpkg != null && !installed) return null + + return html`   { + e.preventDefault() + open_bottom_right_panel("docs") + pluto_actions.set_doc_query(`${frame.parent_module}.${frame.call.split("(")[0]}`) + }} + >docs` +} + 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` { @@ -37,17 +66,18 @@ const StackFrameFilename = ({ frame, cell_id }) => { e.preventDefault() }} > - ${frame_cell_id == cell_id ? "This\xa0cell" : "Other\xa0cell"}: line ${frame.line} + ${frame_cell_id == cell_id ? "This\xa0cell" : "Other\xa0cell"}: line ${frame.line} ` - return html`${a}` } else { 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 file_line = html`${frame.file}:${frame.line}` + + const text = sp != null ? html`${origin} → ${file_line}` : file_line const href = frame?.url?.startsWith?.("https") ? frame.url : null - return html`${text}:${frame.line}` + return html`${text}` } } @@ -66,9 +96,12 @@ const Funccall = ({ frame }) => { ? html`${frame.call.substr(0, bracket_index)}<${ClickToExpandIfLong} text=${frame.call.substr(bracket_index)} />` : html`${frame.call}` - return html`${inner}${at}` + return html`${inner}` } +const LIMIT_LONG = 200, + LIMIT_PREVIEW = 100 + const ClickToExpandIfLong = ({ text }) => { let [expanded, set_expanded] = useState(false) @@ -76,16 +109,16 @@ const ClickToExpandIfLong = ({ text }) => { set_expanded(false) }, [text]) - const collaped_text = html`${text.slice(0, 250)} { e.preventDefault() set_expanded(true) }} - >...more......Show more...${text.slice(-1)}` - return html` ${expanded ? text : text.length < 300 ? text : collaped_text} ` + return html`${expanded ? text : text.length < LIMIT_LONG ? text : collaped_text}` } const LinePreview = ({ frame, num_context_lines = 2 }) => { @@ -161,7 +194,7 @@ 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 } }))} @@ -169,7 +202,11 @@ export const ParseError = ({ cell_id, diagnostics }) => { window.dispatchEvent(new CustomEvent("cell_highlight_range", { detail: { cell_id, from: null, to: null } }))} >
    - ${message}${at}<${StackFrameFilename} frame=${{ file: "#==#" + cell_id, line }} cell_id=${cell_id} /> + ${message} +
    + ${at} + <${StackFrameFilename} frame=${{ file: "#==#" + cell_id, line }} cell_id=${cell_id} /> +
  • ` )} @@ -179,6 +216,29 @@ export const ParseError = ({ cell_id, diagnostics }) => { ` } +const frame_is_important_heuristic = (frame, frame_index, limited_stacktrace, frame_cell_id) => { + if (frame_cell_id != null) return true + + const [funcname, params] = frame.call.split("(", 2) + + if (["_collect", "collect_similar", "iterate", "error", "macro expansion"].includes(funcname)) { + return false + } + + if (params == null) { + // no type signature... must be some function call that got optimized away or something special + // probably not directly relevant + return false + } + + if ((funcname.match(/#/g) ?? "").length >= 2) { + // anonymous function: #plot#142 + return false + } + + return true +} + export const ErrorMessage = ({ msg, stacktrace, cell_id }) => { let pluto_actions = useContext(PlutoActionsContext) const default_rewriter = { @@ -371,20 +431,26 @@ export const ErrorMessage = ({ msg, stacktrace, cell_id }) => {
      - ${limited_stacktrace.map((frame) => { + ${limited_stacktrace.map((frame, frame_index) => { 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. + const important = frame_is_important_heuristic(frame, frame_index, limited_stacktrace, frame_cell_id) + + return html`
    2. <${Funccall} frame=${frame} /> - <${StackFrameFilename} frame=${frame} cell_id=${cell_id} /> +
      + ${at} + <${StackFrameFilename} frame=${frame} cell_id=${cell_id} /> + <${DocLink} frame=${frame} /> +
      ${from_this_notebook ? html`<${LinePreview} frame=${frame} num_context_lines=${from_this_cell ? 1 : 2} />` : null}
    3. ` })} ${limited - ? html`
    4. + ? html`
    5. { diff --git a/frontend/treeview.css b/frontend/treeview.css index 3de86abcc2..dba349629f 100644 --- a/frontend/treeview.css +++ b/frontend/treeview.css @@ -285,11 +285,18 @@ jlerror > section > ol { /* transform-origin: top; */ /* perspective-origin: top; */ } +jlerror > section > ol > li { + margin-block-end: 1em; +} + +jlerror > section > ol > li:not(.important):not(:hover) { + opacity: 0.5; +} jlerror > section > ol > li.from_this_notebook { --bg: var(--jl-info-acccolor); background: var(--bg); outline: 3px solid var(--bg); - padding: 0.4em 0.2em; + padding: 0.4em 0em; border-radius: 0.6em; } jlerror > section .classical-frame > mark { @@ -302,7 +309,13 @@ jlerror > section .classical-frame > mark { jlerror > section .classical-frame > mark > strong { color: var(--black); } -jlerror > section .classical-frame > em > a { +jlerror > section .frame-source { + display: flex; + flex-direction: row; + align-items: baseline; + /* justify-content: flex-end; */ +} +jlerror > section .frame-source > a { background: var(--jlerror-a-bg-color); border-radius: 4px; padding: 1px 7px; @@ -310,16 +323,16 @@ jlerror > section .classical-frame > em > a { 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]) { +jlerror > section .frame-source > a:not([href]) { filter: grayscale(1); } -jlerror > section .classical-frame > em > a[href].remote-url { +jlerror > section .frame-source > a[href].remote-url { filter: hue-rotate(160deg); } -jlerror > section li.from_this_notebook:not(.from_this_cell) .classical-frame > em > a[href] { +jlerror > section li.from_this_notebook:not(.from_this_cell) .frame-source > a[href] { filter: hue-rotate(50deg); } -jlerror > section .classical-frame > span { +jlerror > section .frame-source > span { opacity: 0.4; padding: 0px 0.2em; } diff --git a/src/runner/PlutoRunner/src/display/Exception.jl b/src/runner/PlutoRunner/src/display/Exception.jl index d292e170be..6ee21618ab 100644 --- a/src/runner/PlutoRunner/src/display/Exception.jl +++ b/src/runner/PlutoRunner/src/display/Exception.jl @@ -62,6 +62,7 @@ function format_output(val::CapturedException; context=default_iocontext) pretty = map(stack_relevant) do s method = method_from_frame(s) sp = source_package(method) + pm = method isa Method ? parentmodule(method) : nothing Dict( :call => pretty_stackcall(s, s.linfo), @@ -73,6 +74,7 @@ function format_output(val::CapturedException; context=default_iocontext) :linfo_type => string(typeof(s.linfo)), :url => frame_url(method), :source_package => sp === nothing ? nothing : string(sp), + :parent_module => pm === nothing ? nothing : string(pm), ) end else From 261923e147aa77ed4300f27eb5130a1746e30e50 Mon Sep 17 00:00:00 2001 From: Fons van der Plas Date: Thu, 3 Oct 2024 13:02:12 +0200 Subject: [PATCH 13/27] Stack trace tweaks part 3 --- frontend/components/ErrorMessage.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/frontend/components/ErrorMessage.js b/frontend/components/ErrorMessage.js index 03db50bd1b..efc704dbab 100644 --- a/frontend/components/ErrorMessage.js +++ b/frontend/components/ErrorMessage.js @@ -28,15 +28,17 @@ const focus_line = (cell_id, line) => const DocLink = ({ frame }) => { let pluto_actions = useContext(PlutoActionsContext) + if (extract_cell_id(frame.file)) return null if (frame.parent_module == null) return null if (ignore_funccall(frame)) return null - const nb = pluto_actions.get_notebook() + const funcname = frame.call.split("(")[0] + if (funcname === "") return null + const nb = pluto_actions.get_notebook() const pkg_name = frame.source_package const builtin = ["Main", "Core", "Base"].includes(pkg_name) const installed = nb?.nbpkg?.installed_versions?.[frame.source_package] != null - if (!builtin && nb?.nbpkg != null && !installed) return null return html`   { onClick=${(e) => { e.preventDefault() open_bottom_right_panel("docs") - pluto_actions.set_doc_query(`${frame.parent_module}.${frame.call.split("(")[0]}`) + pluto_actions.set_doc_query(`${frame.parent_module}.${funcname}`) }} >docs Date: Thu, 3 Oct 2024 13:47:54 +0200 Subject: [PATCH 14/27] Update Exception.jl --- src/runner/PlutoRunner/src/display/Exception.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runner/PlutoRunner/src/display/Exception.jl b/src/runner/PlutoRunner/src/display/Exception.jl index 6ee21618ab..bc494b656f 100644 --- a/src/runner/PlutoRunner/src/display/Exception.jl +++ b/src/runner/PlutoRunner/src/display/Exception.jl @@ -62,7 +62,7 @@ function format_output(val::CapturedException; context=default_iocontext) pretty = map(stack_relevant) do s method = method_from_frame(s) sp = source_package(method) - pm = method isa Method ? parentmodule(method) : nothing + pm = VERSION >= v"1.9" && method isa Method ? parentmodule(method) : nothing Dict( :call => pretty_stackcall(s, s.linfo), From 9e3ea8f85bb5d8151e8f42617f25d11202848d78 Mon Sep 17 00:00:00 2001 From: Fons van der Plas Date: Thu, 3 Oct 2024 20:57:38 +0200 Subject: [PATCH 15/27] Motivational words for errors (#3040) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Théo Galy-Fajou --- frontend/components/ErrorMessage.js | 58 +++++++++++++++++++++++++---- frontend/hide-ui.css | 1 + frontend/treeview.css | 29 ++++++++++++++- 3 files changed, 79 insertions(+), 9 deletions(-) diff --git a/frontend/components/ErrorMessage.js b/frontend/components/ErrorMessage.js index efc704dbab..d40bc0bc11 100644 --- a/frontend/components/ErrorMessage.js +++ b/frontend/components/ErrorMessage.js @@ -1,6 +1,6 @@ import { cl } from "../common/ClassTable.js" import { PlutoActionsContext } from "../common/PlutoContext.js" -import { html, useContext, useEffect, useLayoutEffect, useRef, useState } from "../imports/Preact.js" +import { html, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState } from "../imports/Preact.js" import { highlight } from "./CellOutput.js" import { PkgTerminalView } from "./PkgTerminalView.js" import _ from "../imports/lodash.js" @@ -205,10 +205,7 @@ export const ParseError = ({ cell_id, diagnostics }) => { >
      ${message} -
      - ${at} - <${StackFrameFilename} frame=${{ file: "#==#" + cell_id, line }} cell_id=${cell_id} /> -
      +
      ${at}<${StackFrameFilename} frame=${{ file: "#==#" + cell_id, line }} cell_id=${cell_id} />
    6. ` )} @@ -423,6 +420,11 @@ export const ErrorMessage = ({ msg, stacktrace, cell_id }) => { ) return html` +
      + Error message + +
      +
      ${matched_rewriter.display(msg)}
      ${stacktrace.length == 0 || !(matched_rewriter.show_stacktrace?.() ?? true) ? null @@ -443,8 +445,7 @@ export const ErrorMessage = ({ msg, stacktrace, cell_id }) => {
      <${Funccall} frame=${frame} />
      - ${at} - <${StackFrameFilename} frame=${frame} cell_id=${cell_id} /> + ${at}<${StackFrameFilename} frame=${frame} cell_id=${cell_id} /> <${DocLink} frame=${frame} />
      @@ -465,9 +466,52 @@ export const ErrorMessage = ({ msg, stacktrace, cell_id }) => { : null}
    `} + <${Motivation} stacktrace=${stacktrace} /> ` } +const motivational_words = [ + // + "Don't panic!", + "Keep calm, you got this!", + "You got this!", + "Silly computer!", + "Silly computer!", + "beep boop CRASH 🤖", + "computer bad, you GREAT!", + "Probably not your fault!", + "Try asking on Julia Discourse!", + "uhmmmmmm??!", + "Maybe time for a break? ☕️", + "Everything is going to be okay!", + "Computers are hard!", + "C'est la vie !", + "¯\\_(ツ)_/¯", + "Oh no! 🙀", + "this suckz 💣", + "Be patient :)", + // Errors horen erbij + // Ook de pros krijgen errors + ...Array(30).fill(null), +] + +const Motivation = ({ stacktrace }) => { + const msg = useMemo(() => { + return motivational_words[Math.floor(Math.random() * motivational_words.length)] + }, [stacktrace]) + + return msg == null + ? null + : html`
    { + window.open("https://discourse.julialang.org/", "_blank")?.focus() + }} + > + ${msg} +
    ` +} + const get_erred_upstreams = ( /** @type {import("./Editor.js").NotebookData?} */ notebook, /** @type {string} */ cell_id, diff --git a/frontend/hide-ui.css b/frontend/hide-ui.css index f73eab0fa4..36085469fe 100644 --- a/frontend/hide-ui.css +++ b/frontend/hide-ui.css @@ -28,6 +28,7 @@ pluto-runarea, .MJX_ToolTip, .MJX_HoverRegion, .MJX_LiveRegion, + .dont-panic, nav#undo_delete { display: none !important; } diff --git a/frontend/treeview.css b/frontend/treeview.css index dba349629f..3d63fe4322 100644 --- a/frontend/treeview.css +++ b/frontend/treeview.css @@ -267,10 +267,14 @@ jlerror > header > p { jlerror > header > p:first-child { font-weight: bold; } -jlerror .stacktrace-header { +jlerror .stacktrace-header, +jlerror .error-header { font-family: var(--system-ui-font-stack); } -jlerror .stacktrace-header > secret-h1 { +jlerror .error-header { + margin-block-end: 1em; +} +jlerror secret-h1 { font-size: 1.9rem; font-weight: 700; } @@ -336,6 +340,9 @@ jlerror > section .frame-source > span { opacity: 0.4; padding: 0px 0.2em; } +jlerror > section .doclink { + user-select: none; +} jlerror li::marker { background: red; @@ -401,6 +408,24 @@ jlerror li .frame-line-preview pre > code:last-of-type:not(.frame-line) { margin-bottom: var(--crop); } +jlerror .dont-panic { + position: absolute; + top: 0; + right: 0; + padding: 0.5em; + background: var(--pluto-logs-debug-color); + color: var(--black); + border-radius: 0.2em; + font-family: var(--system-ui-font-stack); + font-size: 1.2rem; + font-weight: 700; + transform: rotate(6deg); +} + +body.disable_ui jlerror .dont-panic { + display: none; +} + table.pluto-table { table-layout: fixed; } From f968c47da1fae5b2607500c54ebe7b30d13865a0 Mon Sep 17 00:00:00 2001 From: Fons van der Plas Date: Thu, 3 Oct 2024 21:19:37 +0200 Subject: [PATCH 16/27] Update TryThisPR.yml --- .github/workflows/TryThisPR.yml | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/.github/workflows/TryThisPR.yml b/.github/workflows/TryThisPR.yml index ef6a2dedd7..62cfecf04e 100644 --- a/.github/workflows/TryThisPR.yml +++ b/.github/workflows/TryThisPR.yml @@ -9,15 +9,10 @@ jobs: runs-on: ubuntu-latest continue-on-error: true steps: - - uses: actions/github-script@v5 + - uses: nefrob/pr-description@v1.1.2 with: - github-token: ${{secrets.GITHUB_TOKEN}} - script: | - github.rest.issues.createComment({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - body: ` + content: | + ## Try this Pull Request! Open Julia and type: \`\`\`jl @@ -26,5 +21,5 @@ jobs: julia> Pkg.add(url="${context.payload.pull_request.head.repo.html_url}", rev="${context.payload.pull_request.head.ref}") julia> using ${context.payload.repository.name.replace(/\.jl$/,"")} \`\`\` - ` - }) + regex: "jkhsdkjhasdfkjhawkejfbawkehfkajshdfkjahsdf" + token: ${{ secrets.GITHUB_TOKEN }} From 819b452b98995429aa6cba2cf401ee3df99437c5 Mon Sep 17 00:00:00 2001 From: Fons van der Plas Date: Thu, 3 Oct 2024 21:27:23 +0200 Subject: [PATCH 17/27] Update TryThisPR.yml --- .github/workflows/TryThisPR.yml | 40 ++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/.github/workflows/TryThisPR.yml b/.github/workflows/TryThisPR.yml index 62cfecf04e..bea09f6d1f 100644 --- a/.github/workflows/TryThisPR.yml +++ b/.github/workflows/TryThisPR.yml @@ -9,17 +9,37 @@ jobs: runs-on: ubuntu-latest continue-on-error: true steps: + + - uses: denoland/setup-deno@v1 + with: + deno-version: "1.16.1" + - uses: actions/github-script@v5 + with: + github-token: ${{secrets.GITHUB_TOKEN}} + script: | + require("fs").writeFileSync("context.json", JSON.stringify(context)) + + - name: Generate comment + id: generate-comment + run: | + deno eval ' + const context = JSON.parse(await Deno.readTextFile("context.json")); + const body = ` + ## Try this Pull Request! + Open Julia and type: + \`\`\`jl + julia> import Pkg + julia> Pkg.activate(temp=true) + julia> Pkg.add(url="${context.payload.pull_request.head.repo.html_url}", rev="${context.payload.pull_request.head.ref}") + julia> using ${context.payload.repository.name.replace(/\.jl$/,"")} + \`\`\` + ` + await Deno.writeTextFile("comment.txt", body); + ' + - uses: nefrob/pr-description@v1.1.2 with: - content: | - - ## Try this Pull Request! - Open Julia and type: - \`\`\`jl - julia> import Pkg - julia> Pkg.activate(temp=true) - julia> Pkg.add(url="${context.payload.pull_request.head.repo.html_url}", rev="${context.payload.pull_request.head.ref}") - julia> using ${context.payload.repository.name.replace(/\.jl$/,"")} - \`\`\` + content: "comment.txt" + contentIsFilePath: "true" regex: "jkhsdkjhasdfkjhawkejfbawkehfkajshdfkjahsdf" token: ${{ secrets.GITHUB_TOKEN }} From ef2348fd1e4dd74d9b119769e52d73000184131f Mon Sep 17 00:00:00 2001 From: Fons van der Plas Date: Thu, 3 Oct 2024 21:31:51 +0200 Subject: [PATCH 18/27] Error message title (#3041) --- frontend/components/ErrorMessage.js | 19 ++++++++++++++++++- frontend/treeview.css | 4 ++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/frontend/components/ErrorMessage.js b/frontend/components/ErrorMessage.js index d40bc0bc11..510df24850 100644 --- a/frontend/components/ErrorMessage.js +++ b/frontend/components/ErrorMessage.js @@ -224,6 +224,11 @@ const frame_is_important_heuristic = (frame, frame_index, limited_stacktrace, fr return false } + if (funcname.includes("throw")) return false + + // too sciency + if (frame.inlined) return false + if (params == null) { // no type signature... must be some function call that got optimized away or something special // probably not directly relevant @@ -419,9 +424,11 @@ export const ErrorMessage = ({ msg, stacktrace, cell_id }) => { (frame) => !(ignore_location(frame) && ignore_funccall(frame)) ) + const first_package = get_first_package(limited_stacktrace) + return html`
    - Error message + Error message${first_package == null ? null : ` from ${first_package}`}
    @@ -470,6 +477,16 @@ export const ErrorMessage = ({ msg, stacktrace, cell_id }) => {
    ` } +const get_first_package = (limited_stacktrace) => { + for (let [i, frame] of limited_stacktrace.entries()) { + const frame_cell_id = extract_cell_id(frame.file) + if (frame_cell_id) return undefined + + const important = frame_is_important_heuristic(frame, i, limited_stacktrace, frame_cell_id) + if (!important) continue + + if (frame.source_package) return frame.source_package + } const motivational_words = [ // "Don't panic!", diff --git a/frontend/treeview.css b/frontend/treeview.css index 3d63fe4322..e4fa55fa8f 100644 --- a/frontend/treeview.css +++ b/frontend/treeview.css @@ -296,6 +296,10 @@ jlerror > section > ol > li { jlerror > section > ol > li:not(.important):not(:hover) { opacity: 0.5; } + +jlerror > section > ol > li:not(.important)::marker { + font-weight: 100; +} jlerror > section > ol > li.from_this_notebook { --bg: var(--jl-info-acccolor); background: var(--bg); From 12ab1e347eb16f3c4dcca66518c3b0892ed132c7 Mon Sep 17 00:00:00 2001 From: Fons van der Plas Date: Fri, 4 Oct 2024 09:43:55 +0200 Subject: [PATCH 19/27] Remove `Main.var"workspace#5"` from stack traces (#3044) --- src/runner/PlutoRunner/src/display/Exception.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runner/PlutoRunner/src/display/Exception.jl b/src/runner/PlutoRunner/src/display/Exception.jl index bc494b656f..835c500cee 100644 --- a/src/runner/PlutoRunner/src/display/Exception.jl +++ b/src/runner/PlutoRunner/src/display/Exception.jl @@ -65,7 +65,7 @@ function format_output(val::CapturedException; context=default_iocontext) pm = VERSION >= v"1.9" && method isa Method ? parentmodule(method) : nothing Dict( - :call => pretty_stackcall(s, s.linfo), + :call => replace(pretty_stackcall(s, s.linfo), r"Main\.var\"workspace#\d+\"\." => ""), :inlined => s.inlined, :from_c => s.from_c, :file => basename(String(s.file)), From 6bb6b98b74e7d50dbc1996ac0c025e1eaa8322c6 Mon Sep 17 00:00:00 2001 From: Fons van der Plas Date: Fri, 4 Oct 2024 10:00:19 +0200 Subject: [PATCH 20/27] oops --- frontend/components/ErrorMessage.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frontend/components/ErrorMessage.js b/frontend/components/ErrorMessage.js index 510df24850..c980ef1193 100644 --- a/frontend/components/ErrorMessage.js +++ b/frontend/components/ErrorMessage.js @@ -487,6 +487,8 @@ const get_first_package = (limited_stacktrace) => { if (frame.source_package) return frame.source_package } +} + const motivational_words = [ // "Don't panic!", From a7243598d6aca7c86fa18b36295b357dce8137b0 Mon Sep 17 00:00:00 2001 From: Fons van der Plas Date: Fri, 4 Oct 2024 15:10:33 +0200 Subject: [PATCH 21/27] Binder: skip "Safe preview" mode --- frontend/common/Binder.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/frontend/common/Binder.js b/frontend/common/Binder.js index 21c9842dd9..334d754067 100644 --- a/frontend/common/Binder.js +++ b/frontend/common/Binder.js @@ -156,7 +156,10 @@ export const start_binder = async ({ setStatePromise, connect, launch_params }) } let open_remotely = async (p1, p2) => { - const open_url = with_query_params(new URL("open", binder_session_url), { [p1]: p2 }) + const open_url = with_query_params(new URL("open", binder_session_url), { + [p1]: p2, + execution_allowed: "true", + }) console.log(`open ${p1}:`, open_url) return fetch(with_token(open_url), { From 4190ad06a46d190d90306dedbf6bc0ee99561fd0 Mon Sep 17 00:00:00 2001 From: Fons van der Plas Date: Fri, 4 Oct 2024 17:22:58 +0200 Subject: [PATCH 22/27] Stack trace: bracket-matched hiding and expanding and more (#3045) --- frontend/components/ErrorMessage.js | 88 +++++++++++++------ frontend/treeview.css | 8 ++ .../PlutoRunner/src/display/Exception.jl | 16 +++- 3 files changed, 85 insertions(+), 27 deletions(-) diff --git a/frontend/components/ErrorMessage.js b/frontend/components/ErrorMessage.js index c980ef1193..369b79e6ee 100644 --- a/frontend/components/ErrorMessage.js +++ b/frontend/components/ErrorMessage.js @@ -32,7 +32,7 @@ const DocLink = ({ frame }) => { if (frame.parent_module == null) return null if (ignore_funccall(frame)) return null - const funcname = frame.call.split("(")[0] + const funcname = frame.func if (funcname === "") return null const nb = pluto_actions.get_notebook() @@ -88,39 +88,62 @@ const at = html` from ` const ignore_funccall = (frame) => frame.call === "top-level scope" const ignore_location = (frame) => frame.file === "none" +const funcname_args = (call) => { + const anon_match = call.indexOf(")(") + if (anon_match != -1) { + return [call.substring(0, anon_match + 1), call.substring(anon_match + 1)] + } else { + const bracket_index = call.indexOf("(") + if (bracket_index != -1) { + return [call.substring(0, bracket_index), call.substring(bracket_index)] + } else { + return [call, ""] + } + } +} + const Funccall = ({ frame }) => { - if (ignore_funccall(frame)) return null + let [expanded_state, set_expanded] = useState(false) + useEffect(() => { + set_expanded(false) + }, [frame]) - const bracket_index = frame.call.indexOf("(") + const silly_to_hide = (frame.call_short.match(/…/g) ?? "").length <= 1 && frame.call.length < frame.call_short.length + 7 - let inner = - bracket_index != -1 - ? html`${frame.call.substr(0, bracket_index)}<${ClickToExpandIfLong} text=${frame.call.substr(bracket_index)} />` - : html`${frame.call}` + const expanded = expanded_state || (frame.call === frame.call_short && frame.func === funcname_args(frame.call)[0]) || silly_to_hide - return html`${inner}` -} + if (ignore_funccall(frame)) return null -const LIMIT_LONG = 200, - LIMIT_PREVIEW = 100 + const call = expanded ? frame.call : frame.call_short -const ClickToExpandIfLong = ({ text }) => { - let [expanded, set_expanded] = useState(false) + const call_funcname_args = funcname_args(call) + const funcname = expanded ? call_funcname_args[0] : frame.func - useEffect(() => { - set_expanded(false) - }, [text]) + // if function name is #12 or #15#16 then it is an anonymous function - const collaped_text = html`${text.slice(0, LIMIT_PREVIEW)} { - e.preventDefault() - set_expanded(true) - }} - >...Show more...${text.slice(-1)}` + const funcname_display = funcname.match(/^#\d+(#\d+)?$/) + ? html`anonymous function` + : funcname + console.log(funcname, funcname.match(/^#\d+(#\d+)?$/), funcname_display) + + let inner = html`${funcname_display}<${HighlightCallArgumentNames} code=${call_funcname_args[1]} />` + + const id = useMemo(() => Math.random().toString(36).substring(7), [frame]) - return html`${expanded ? text : text.length < LIMIT_LONG ? text : collaped_text}` + return html`${inner} ${!expanded + ? html` { + e.preventDefault() + set_expanded(true) + }} + >...show types...` + : null}` } const LinePreview = ({ frame, num_context_lines = 2 }) => { @@ -172,6 +195,19 @@ const JuliaHighlightedLine = ({ code, frameLine, i }) => { >` } +const HighlightCallArgumentNames = ({ code }) => { + const code_ref = useRef(/** @type {HTMLPreElement?} */ (null)) + useLayoutEffect(() => { + if (code_ref.current) { + const html = code.replaceAll(/([^():{},; ]*)::/g, "$1::") + + code_ref.current.innerHTML = html + } + }, [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 }) => { @@ -218,7 +254,7 @@ export const ParseError = ({ cell_id, diagnostics }) => { const frame_is_important_heuristic = (frame, frame_index, limited_stacktrace, frame_cell_id) => { if (frame_cell_id != null) return true - const [funcname, params] = frame.call.split("(", 2) + const [funcname, params] = funcname_args(frame.call) if (["_collect", "collect_similar", "iterate", "error", "macro expansion"].includes(funcname)) { return false diff --git a/frontend/treeview.css b/frontend/treeview.css index e4fa55fa8f..31fbfc2ee6 100644 --- a/frontend/treeview.css +++ b/frontend/treeview.css @@ -317,6 +317,14 @@ jlerror > section .classical-frame > mark { jlerror > section .classical-frame > mark > strong { color: var(--black); } +jlerror > section .classical-frame s-span { + /* color: var(--cm-color-type); */ +} +jlerror > section .classical-frame s-span .argument_name { + color: var(--jlerror-mark-color); + color: var(--cm-color-var); + color: var(--cm-color-type); +} jlerror > section .frame-source { display: flex; flex-direction: row; diff --git a/src/runner/PlutoRunner/src/display/Exception.jl b/src/runner/PlutoRunner/src/display/Exception.jl index 835c500cee..66e7e1b76c 100644 --- a/src/runner/PlutoRunner/src/display/Exception.jl +++ b/src/runner/PlutoRunner/src/display/Exception.jl @@ -60,12 +60,16 @@ function format_output(val::CapturedException; context=default_iocontext) stack_relevant = stack[1:something(limit, end)] pretty = map(stack_relevant) do s + func = s.func === nothing ? nothing : s.func isa Symbol ? String(s.func) : repr(s.func) method = method_from_frame(s) sp = source_package(method) pm = VERSION >= v"1.9" && method isa Method ? parentmodule(method) : nothing + call = replace(pretty_stackcall(s, s.linfo), r"Main\.var\"workspace#\d+\"\." => "") Dict( - :call => replace(pretty_stackcall(s, s.linfo), r"Main\.var\"workspace#\d+\"\." => ""), + :call => call, + :call_short => type_depth_limit(call, 0), + :func => func, :inlined => s.inlined, :from_c => s.from_c, :file => basename(String(s.file)), @@ -124,6 +128,16 @@ function pretty_stackcall(frame::Base.StackFrame, linfo::Module) end +function type_depth_limit(call::String, n::Int) + !occursin("{" , call) && return call + @static if isdefined(Base, :type_depth_limit) && hasmethod(Base.type_depth_limit, Tuple{String, Int}) + Base.type_depth_limit(call, n) + else + call + end +end + + "Because even showerror can error... 👀" function try_showerror(io::IO, e, args...) try From 08615ff407b1de4a5f8ea015e920434f4e3fd1cd Mon Sep 17 00:00:00 2001 From: Fons van der Plas Date: Fri, 4 Oct 2024 17:24:54 +0200 Subject: [PATCH 23/27] Error messages: allow color from Julia (#3046) --- frontend/components/ErrorMessage.js | 14 +++++++++++++- src/runner/PlutoRunner/src/display/Exception.jl | 2 +- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/frontend/components/ErrorMessage.js b/frontend/components/ErrorMessage.js index 369b79e6ee..c7e053bf8a 100644 --- a/frontend/components/ErrorMessage.js +++ b/frontend/components/ErrorMessage.js @@ -5,6 +5,7 @@ import { highlight } from "./CellOutput.js" import { PkgTerminalView } from "./PkgTerminalView.js" import _ from "../imports/lodash.js" import { open_bottom_right_panel } from "./BottomRightPanel.js" +import AnsiUp from "../imports/AnsiUp.js" const extract_cell_id = (/** @type {string} */ file) => { const sep_index = file.indexOf("#==#") @@ -279,11 +280,22 @@ const frame_is_important_heuristic = (frame, frame_index, limited_stacktrace, fr return true } +const AnsiUpLine = (/** @type {{value: string}} */ { value }) => { + const node_ref = useRef(/** @type {HTMLElement?} */ (null)) + + useEffect(() => { + if (!node_ref.current) return + node_ref.current.innerHTML = new AnsiUp().ansi_to_html(value) + }, [node_ref.current, value]) + + return value === "" ? html`


    ` : html`

    ` +} + export const ErrorMessage = ({ msg, stacktrace, cell_id }) => { let pluto_actions = useContext(PlutoActionsContext) const default_rewriter = { pattern: /.?/, - display: (/** @type{string} */ x) => _.dropRightWhile(x.split("\n"), (s) => s === "").map((line) => html`

    ${line === "" ? html`
    ` : line}

    `), + display: (/** @type{string} */ x) => _.dropRightWhile(x.split("\n"), (s) => s === "").map((line) => html`<${AnsiUpLine} value=${line} />`), } const rewriters = [ { diff --git a/src/runner/PlutoRunner/src/display/Exception.jl b/src/runner/PlutoRunner/src/display/Exception.jl index 66e7e1b76c..91691c301c 100644 --- a/src/runner/PlutoRunner/src/display/Exception.jl +++ b/src/runner/PlutoRunner/src/display/Exception.jl @@ -141,7 +141,7 @@ end "Because even showerror can error... 👀" function try_showerror(io::IO, e, args...) try - showerror(io, e, args...) + showerror(IOContext(io, :color => true), e, args...) catch show_ex print(io, "\nFailed to show error:\n\n") try_showerror(io, show_ex, stacktrace(catch_backtrace())) From d7e925d0981df76d02df26817dbc131cbae0b55c Mon Sep 17 00:00:00 2001 From: Paul Berg Date: Tue, 8 Oct 2024 18:46:03 +0200 Subject: [PATCH 24/27] apply unicode completion to all matching cursors (#3047) --- frontend/components/CellInput/pluto_autocomplete.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/frontend/components/CellInput/pluto_autocomplete.js b/frontend/components/CellInput/pluto_autocomplete.js index edca7a4aee..588412b7df 100644 --- a/frontend/components/CellInput/pluto_autocomplete.js +++ b/frontend/components/CellInput/pluto_autocomplete.js @@ -404,7 +404,10 @@ const apply_completion = (view, completion, from, to) => { } } - view.dispatch({ changes: { from, to, insert }, annotations: autocomplete.pickedCompletion.of(completion) }) + view.dispatch({ + ...autocomplete.insertCompletionText(view.state, insert, from, to), + annotations: autocomplete.pickedCompletion.of(completion), + }) } const special_symbols_completion = (/** @type {() => Promise} */ request_special_symbols) => { From 26b88d44d5a5130123989852296851ab770bdb18 Mon Sep 17 00:00:00 2001 From: Paul Berg Date: Thu, 10 Oct 2024 10:39:29 +0200 Subject: [PATCH 25/27] Test 1.11 (#3048) --- .github/workflows/Test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/Test.yml b/.github/workflows/Test.yml index d9174fd144..f8278dcd7c 100644 --- a/.github/workflows/Test.yml +++ b/.github/workflows/Test.yml @@ -34,7 +34,7 @@ jobs: fail-fast: false matrix: # We test quite a lot of versions because we do some OS and version specific things unfortunately - julia-version: ["1.6", "1.10", "~1.11.0-0"] #, "nightly"] # "~1.12.0-0"] + julia-version: ["1.6", "1.10", "1.11"] #, "nightly"] # "~1.12.0-0"] os: [ubuntu-latest, macOS-latest, windows-latest] steps: From 6197c793b0f1d260a0d2f41176c1753915652fe2 Mon Sep 17 00:00:00 2001 From: Fons van der Plas Date: Thu, 10 Oct 2024 10:54:59 +0200 Subject: [PATCH 26/27] Warn about using Julia version before 1.10 (#3049) --- src/webserver/WebServer.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/webserver/WebServer.jl b/src/webserver/WebServer.jl index dbbfded50d..6c96f621c2 100644 --- a/src/webserver/WebServer.jl +++ b/src/webserver/WebServer.jl @@ -145,7 +145,7 @@ function run!(session::ServerSession) @info "Loading..." end - if VERSION < v"1.6.2" + if VERSION < v"1.10.0" @warn("\nPluto is running on an old version of Julia ($(VERSION)) that is no longer supported. Visit https://julialang.org/downloads/ for more information about upgrading Julia.") end From af7f5e96dd2dd50b3a512f0ff91fe516cfb15ac3 Mon Sep 17 00:00:00 2001 From: Fons van der Plas Date: Thu, 10 Oct 2024 10:55:18 +0200 Subject: [PATCH 27/27] Update Project.toml --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index f084e9998d..4bf9df1b72 100644 --- a/Project.toml +++ b/Project.toml @@ -2,7 +2,7 @@ name = "Pluto" uuid = "c3e4b0f8-55cb-11ea-2926-15256bba5781" license = "MIT" authors = ["Fons van der Plas "] -version = "0.19.46" +version = "0.19.47" [deps] Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"