To be able to edit code and run cells, you need to run the notebook yourself. Where would you like to run the notebook?

This notebook takes about 40 seconds to run.

In the cloud (experimental)

Binder is a free, open source service that runs scientific notebooks in the cloud! It will take a while, usually 2-7 minutes to get a session.

On your computer

(Recommended if you want to store your changes.)

  1. Copy the notebook URL:
  2. Run Pluto

    (Also see: How to install Julia and Pluto)

  3. Paste URL in the Open box

Frontmatter

If you are publishing this notebook on the web, you can set the parameters below to provide HTML metadata. This is useful for search engines and social media.

Author 1

(You need Pluto#main to run this notebook)

👀 Reading hidden code
185 μs

This notebook contains visual debugging:

👀 Reading hidden code
220 μs
begin (1 + 2) + (7 - 6) plot(2000 .+ 30 .* rand(2 + 2)) 4 + 5 sqrt(sqrt(sqrt(5))) md"# asdf"end begin
3
+ (7 - 6)
plot(2000 .+ 30 .* rand(2 + 2)) 4 + 5 sqrt(sqrt(sqrt(5))) md"# asdf"end
begin
3
+
1
plot(2000 .+ 30 .* rand(2 + 2)) 4 + 5 sqrt(sqrt(sqrt(5))) md"# asdf"end
begin
4
plot(2000 .+ 30 .* rand(2 + 2)) 4 + 5 sqrt(sqrt(sqrt(5))) md"# asdf"end
begin
4
plot(2000 .+ 30 .* rand(
4
))
4 + 5 sqrt(sqrt(sqrt(5))) md"# asdf"end
begin
4
plot(2000 .+ 30 .*
)
4 + 5 sqrt(sqrt(sqrt(5))) md"# asdf"end
begin
4
plot(2000 .+
)
4 + 5 sqrt(sqrt(sqrt(5))) md"# asdf"end
begin
4
plot(
)
4 + 5 sqrt(sqrt(sqrt(5))) md"# asdf"end
begin
4
4 + 5 sqrt(sqrt(sqrt(5))) md"# asdf"end
begin
4
9
sqrt(sqrt(sqrt(5))) md"# asdf"end
begin
4
9
sqrt(sqrt(
2.23606797749979
))
md"# asdf"end
begin
4
9
sqrt(
1.4953487812212205
)
md"# asdf"end
begin
4
9
1.2228445449938519
md"# asdf"end
begin
4
9
1.2228445449938519

asdf

end

asdf

👀 Reading hidden code
(1+2) + (7-6)
plot(2000 .+ 30 .* rand(2+2))
4+5
sqrt(sqrt(sqrt(5)))
md"# asdf"
end
107 ms

and visual testing:

👀 Reading hidden code
211 μs
8
👀 Reading hidden code
@test 4+4 ∈ [1:7...]
41.4 ms
👀 Reading hidden code
TableOfContents()
10.9 μs
👀 Reading hidden code
using HypertextLiteral
: @htl, @htl_str

5.4 ms
using PlutoUI
👀 Reading hidden code
194 ms

Type definitions

👀 Reading hidden code
170 μs
abstract type TestResult end
👀 Reading hidden code
424 μs
abstract type Fail <: TestResult end
👀 Reading hidden code
396 μs
abstract type Pass <: TestResult end
👀 Reading hidden code
361 μs
Any
const Code = Any
👀 Reading hidden code
108 μs
struct Correct <: Pass
expr::Code
end
👀 Reading hidden code
1.2 ms
struct WrongCall <: Fail
expr::Code
arg_results::Vector
end
👀 Reading hidden code
1.3 ms
struct Error <: Fail
expr::Code
error
end
👀 Reading hidden code
1.2 ms
struct Wrong <: Fail
expr::Code
result
end
👀 Reading hidden code
1.2 ms
struct CorrectCall <: Pass
expr::Code
arg_results::Vector
end
👀 Reading hidden code
1.2 ms

Test macro

👀 Reading hidden code
171 μs
test (generic function with 1 method)
function test(expr)
if Meta.isexpr(expr, :call)
quote
expr_raw = $(QuoteNode(expr))
try
arg_results = [$((expr.args[2:end] .|> esc)...)]
result = $(esc(:eval))(Expr(:call, $(expr.args[1] |> QuoteNode), arg_results...))
if result === true
CorrectCall(expr_raw, arg_results)
elseif result === false
WrongCall(expr_raw, arg_results)
else
Wrong(expr_raw, result)
end
catch e
rethrow(e)
# Error(expr_raw, e)
end
end
end
end
👀 Reading hidden code
1.2 ms
👀 Reading hidden code
9.0 μs
begin
    var"#578#expr_raw" = $(QuoteNode(:(x == [1, 2 + 2])))
    try
        var"#579#arg_results" = [x, [1, 2 + 2]]
        var"#580#result" = eval(Main.workspace#5.Expr(:call, :(==), var"#579#arg_results"...))
        if var"#580#result" === true
            Main.workspace#5.CorrectCall(var"#578#expr_raw", var"#579#arg_results")
        elseif var"#580#result" === false
            Main.workspace#5.WrongCall(var"#578#expr_raw", var"#579#arg_results")
        else
            Main.workspace#5.Wrong(var"#578#expr_raw", var"#580#result")
        end
    catch var"#583#e"
        Main.workspace#5.rethrow(var"#583#e")
    end
end
var"@test"; macroexpand(@__MODULE__, :(@test x == [1,2+2]); recursive=false) |> prettycolors
👀 Reading hidden code
201 ms
:(x == [1, 2 + 2])
e = :(x == [1,2+2])
👀 Reading hidden code
26.3 μs
x = [1,3]
👀 Reading hidden code
13.2 μs
@test missing == 2
👀 Reading hidden code
39.7 ms
4
==
4
@test 2+2 == 2+2
👀 Reading hidden code
5.8 ms
==
@test x == [1,2+2]
👀 Reading hidden code
72.8 ms
==
@test rand(50) == [rand(50),2]
👀 Reading hidden code
110 ms
always_false(
,
,
123
)
@test always_false(rand(50), rand(50),123)
👀 Reading hidden code
27.0 ms
!(always_false(rand(2), rand(2), 123)) !(always_false(
, rand(2), 123))
!(always_false(
,
, 123))
!
false
true
@visual_debug !always_false(rand(2), rand(2),123)
👀 Reading hidden code
16.3 ms
!(!(always_false(rand(2), rand(2), 123; r = 123)))
false
@visual_debug !!always_false(rand(2), rand(2),123; r=123)
👀 Reading hidden code
35.6 ms
always_false([1, 2, 3]...)
false
@visual_debug always_false([1,2,3]...)
👀 Reading hidden code
39.0 ms
Expr
  head: Symbol call
  args: Array{Any}((4,))
    1: Symbol f
    2: Int64 1
    3: Expr
      head: Symbol ...
      args: Array{Any}((1,))
        1: Int64 2
    4: Expr
      head: Symbol kw
      args: Array{Any}((2,))
        1: Symbol x
        2: Int64 3
Dump(:(
f(1,2...,x=3)
))
👀 Reading hidden code
26.6 μs
always_false (generic function with 1 method)
always_false(args...; kwargs...) = false
👀 Reading hidden code
1.2 ms
isless(
4
,
1
)
@test isless(2+2,1)
👀 Reading hidden code
9.2 ms
isless(
1
,
4
)
@test isless(1,2+2)
👀 Reading hidden code
1.8 ms
@bind n Slider(1:10)
👀 Reading hidden code
269 ms
iseven(
1
)
@test iseven(n^2)
👀 Reading hidden code
7.8 ms
@bind k Slider(0:15)
👀 Reading hidden code
741 μs
8
@test 4+4 ∈ [1:k...]
👀 Reading hidden code
33.6 ms
isempty(
)
@test isempty((1:k) .^ 2)
👀 Reading hidden code
84.9 ms
isempty(
)
@test isempty([1,sqrt(2)])
👀 Reading hidden code
35.7 ms
1
👀 Reading hidden code
57.3 ms
1
@test 1 ∈ rand(60)
👀 Reading hidden code
1.7 ms
1
@test rand(60) ∋ 1
👀 Reading hidden code
9.9 ms
html"""
<style>

pt-dot {
flex: 0 0 auto;
background: grey;
width: 1em;
height: 1em;
bottom: -.1em;
border-radius: 100%;
margin-right: .7em;
display: block;
position: relative;
}


.fail > pt-dot {
background: #f75d5d;

}
.pass > pt-dot {
background: #56a038;

}


.pluto-test {
font-family: "JuliaMono", monospace;
font-size: 0.75rem;
padding: 4px;

min-height: 25px;
}


.pluto-test.pass {
color: rgba(0,0,0,.5);
}

.pluto-test.fail {
background: linear-gradient(90deg, #ff2e2e14, transparent);
border-radius: 7px;
}


.pluto-test>.arg_result {
flex: 0 0 auto;
}

.pluto-test>.arg_result>div,
.pluto-test>.arg_result>div>pluto-display>div {
display: inline-flex;
}


.pluto-test>.comma {
margin-right: .5em;
}

.pluto-test.call>code {
padding: 0px;
}

.pluto-test.call.infix-operator>div {
overflow-x: auto;
}

.pluto-test {
display: flex;
align-items: baseline;
}

.pluto-test.call.infix-operator>.fname {
margin: 0px .6em;
/*color: darkred;*/
}
"""
👀 Reading hidden code
113 μs
true
(@test isodd(3)) isa Pass
👀 Reading hidden code
4.0 ms
begin
macro test(expr)
test(expr)
end
function Base.show(io::IO, m::MIME"text/html", call::Union{WrongCall,CorrectCall})
fname = call.expr.args[1]
infix = length(call.arg_results) == 2 && Meta.isbinaryoperator(fname)
classes = [
"pluto-test",
"call",
(isa(call,CorrectCall) ? "correct" : "wrong"),
(isa(call,Pass) ? "pass" : "fail"),
infix ? "infix-operator" : "prefix-operator",
]
result = @htl("""
<div class=$(classes)>
<pt-dot></pt-dot>
$(infix ? @htl("""
$(emb(call.arg_results[1]) |> div)<span class="fname">$(fname)</span>$(emb(call.arg_results[2]) |> div)
""") : @htl("""
<span class="fname">$(fname)(</span>$(
commas(
map(div(;class="arg_result"), embed_display.(call.arg_results))
)
)<span>)</span>
"""))
</div>
""")
Base.show(io, m, result)
end
# function Base.show(io::IO, m::MIME"text/html", c::Correct)
# result = @htl("""
# <div class=$([
# "pluto-test", "pass", "correct",
# ])>
# <pt-dot></pt-dot>
# <span>$((string(remove_linenums(c.expr))))</span>
# </div>
# """)
# Base.show(io, m, result)
# end
end
👀 Reading hidden code
30.3 ms
flatmap (generic function with 1 method)
flatmap(args...) = vcat(map(args...)...)
👀 Reading hidden code
537 μs
commas (generic function with 2 methods)
function commas(xs, comma=@htl("<span class='comma'>, </span>"))
flatmap(enumerate(xs)) do (i,x)
if i == length(xs)
[x]
else
[x,comma]
end
end
end
👀 Reading hidden code
236 ms
embed_display (generic function with 1 method)
emb = embed_display
👀 Reading hidden code
13.3 μs
div (generic function with 1 method)
div(x; class="", style="") = @htl("<div class=$(class) style=$(style)>$(x)</div>")
👀 Reading hidden code
480 ms
div (generic function with 2 methods)
div(; class="", style="") = x -> @htl("<div class=$(class) style=$(style)>$(x)</div>")
👀 Reading hidden code
2.1 ms

👀 Reading hidden code
59.9 μs
prettycolors (generic function with 1 method)
prettycolors(e) = Markdown.MD([Markdown.Code("julia", string(remove_linenums(e)))])
👀 Reading hidden code
502 μs
remove_linenums (generic function with 1 method)
remove_linenums(e::Expr) = if e.head === :macrocall
Expr(e.head, (remove_linenums(x) for x in e.args)...)
else
Expr(e.head, (remove_linenums(x) for x in e.args if !(x isa LineNumberNode))...)
end
👀 Reading hidden code
2.1 ms
remove_linenums (generic function with 2 methods)
remove_linenums(x) = x
👀 Reading hidden code
355 μs

DEbugging 1

md"""
# DEbugging 1
"""
👀 Reading hidden code
168 μs
onestep (generic function with 1 method)
function onestep(e::Expr; m=Module())
results = Any[]
# push!(results, e)
arg_results = Any[a for a in e.args]
for (i,a) in enumerate(e.args)
arg_results[i] = if a isa QuoteNode
a
elseif (e.head === :call || e.head === :let) && i == 1
a
elseif a isa Expr
inner_results = onestep(a; m=m)
for ir in inner_results
arg_results[i] = ir
push!(results, Expr(e.head, arg_results...))
end
inner_results[end]
else
a
end
# push!(results, Expr(e.head, arg_results...))
end
push!(results, Core.eval(m, Expr(e.head, arg_results...)))
results
end
👀 Reading hidden code
3.8 ms
expr_debug (generic function with 1 method)
function expr_debug(x)
e = remove_linenums(x)
Any[e, onestep(e)...]
end
👀 Reading hidden code
1.1 ms
UInt64
👀 Reading hidden code
2.4 ms
expr_hash (generic function with 1 method)
👀 Reading hidden code
1.3 ms
expr_hash (generic function with 2 methods)
👀 Reading hidden code
548 μs
debug_result = expr_debug(:(
let
r = if rand(Bool)
20
else
16
end
y = sqrt(4)
y == sqrt(sqrt(r))
end
));
👀 Reading hidden code
11.5 ms
@bind step Slider(1:length(debug_result))
👀 Reading hidden code
881 μs
let
    r = if rand(Bool)
            20
        else
            16
        end
    y = sqrt(4)
    y == sqrt(sqrt(r))
end
debug_result[step] |> prettycolors
👀 Reading hidden code
125 μs

Debugging 1.5

md"""
# Debugging 1.5
"""
👀 Reading hidden code
169 μs
struct Computed
x
end
👀 Reading hidden code
992 μs
computed (generic function with 1 method)
computed(x) = Computed(x)
👀 Reading hidden code
392 μs

👀 Reading hidden code
82.0 μs
expand_computed (generic function with 1 method)
expand_computed(x) = x
👀 Reading hidden code
367 μs
expand_computed (generic function with 2 methods)
expand_computed(c::Computed) = c.x
👀 Reading hidden code
401 μs
expand_computed (generic function with 3 methods)
expand_computed(e::Expr) = Expr(e.head, expand_computed.(e.args)...)
👀 Reading hidden code
494 μs
onestep_light (generic function with 1 method)
function onestep_light(e::Expr; m=Module())
results = Any[]
# will be modified
arg_results = Any[a for a in e.args]

if e.head === :call || e.head === :begin || e.head === :block
# push!(results, e)


for (i,a) in enumerate(e.args)
arg_results[i] = if a isa QuoteNode
a
elseif (Meta.isexpr(e, :call) || Meta.isexpr(e, :let)) && i == 1
a
elseif a isa Expr
inner_results = onestep_light(a; m=m)
for ir in inner_results
arg_results[i] = ir
push!(results, Expr(e.head, arg_results...))
end

inner_results[end]
else
a
end

# push!(results, Expr(e.head, arg_results...))
end
end
push!(results, Computed(Core.eval(m, expand_computed(Expr(e.head, arg_results...)))))
results
end
👀 Reading hidden code
3.9 ms
@eval_step_by_step (macro with 1 method)
macro eval_step_by_step(e)
Computed
if can_interpret(e)
quote
Any[$(QuoteNode(e)), $(onestep_light(e; m=__module__))...]
end
else
quote
[$(QuoteNode(e)), Computed($(esc(e)))]
end
end
end
👀 Reading hidden code
911 μs
quote
    Main.workspace#6.Any[$(QuoteNode(:(sqrt(sqrt(3))))), Any[:(sqrt(Computed(1.7320508075688772))), Computed(1.3160740129524924)]...]
end
remove_linenums( @macroexpand @eval_step_by_step sqrt(sqrt(3)) )
👀 Reading hidden code
2.0 ms
@eval_step_by_step sqrt(sqrt(length([1,2])))
👀 Reading hidden code
16.3 ms
@eval_step_by_step xasdf = 123
👀 Reading hidden code
50.1 ms
Error message

UndefVarError: xasdf not defined

Stack trace

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

  1. xasdf
xasdf
👀 Reading hidden code
---
onestep_light(quote
1+2
2+3
4+5
sqrt(sqrt(sqrt(5)))
end |> remove_linenums)
👀 Reading hidden code
164 ms
can_interpret (generic function with 1 method)
can_interpret(x) = true
👀 Reading hidden code
1.3 ms
can_interpret_call_arg (generic function with 1 method)
can_interpret_call_arg(e::Expr) = !(e.head === :(...) || e.head === :kw || e.head === :parameters)
👀 Reading hidden code
693 μs
can_interpret_call_arg (generic function with 2 methods)
can_interpret_call_arg(x) = true
👀 Reading hidden code
389 μs
true
Meta.isbinaryoperator(:(==))
👀 Reading hidden code
31.8 μs
can_interpret (generic function with 2 methods)
can_interpret(e::Expr) = if false
false
elseif e.head === :call && !all(can_interpret_call_arg, e.args)
false
# elseif e.head === :(=) || e.head === :macrocall
# false
else
all(can_interpret, e.args)
end
👀 Reading hidden code
685 μs

Displaying

👀 Reading hidden code
163 μs

👀 Reading hidden code
59.8 μs
find_computed! (generic function with 1 method)
find_computed!(found, c::Computed) = push!(found, c)
👀 Reading hidden code
404 μs
find_computed! (generic function with 2 methods)
find_computed!(found, expr::Expr) = find_computed!.([found], expr.args)
👀 Reading hidden code
495 μs
find_computed! (generic function with 3 methods)
find_computed!(found, x) = nothing
👀 Reading hidden code
353 μs
find_computed (generic function with 1 method)
find_computed(x) = let
r = Any[]
find_computed!(r, x)
r
end
👀 Reading hidden code
470 μs
onestep_light(quote
1+2
2+3
4+5
sqrt(sqrt(sqrt(5)))
end |> remove_linenums) .|> find_computed
👀 Reading hidden code
661 ms
slot! (generic function with 1 method)
slot!(found, c::Computed) = let
k = Symbol("__slot", join(rand('a':'z', 16)), "__")
found[k] = c
k
end
👀 Reading hidden code
662 μs
slot! (generic function with 2 methods)
slot!(found, x) = x
👀 Reading hidden code
400 μs
slot! (generic function with 3 methods)
slot!(found, e::Expr) = Expr(e.head, slot!.([found], e.args)...)
👀 Reading hidden code
644 μs
slot (generic function with 1 method)
slot(e) = let
d = Dict{Symbol,Any}()
new_e = slot!(d, e)
d, new_e
end
👀 Reading hidden code
600 μs
onestep_light(quote
(1+2) + (7-6)
2+3
4+5
sqrt(sqrt(sqrt(5)))
end |> remove_linenums) .|> slot
👀 Reading hidden code
354 ms
preish (generic function with 1 method)
preish(x) = @htl("<pre-ish>$(x)</pre-ish>")
👀 Reading hidden code
561 μs
display_slotted (generic function with 1 method)
function display_slotted(expr)
d, e = slot(expr)
s = string(e |> remove_linenums)
lines = split(s, "\n")
r = r"\_\_slot[a-z]{16}\_\_"
@htl("""<slotted-code>
$(
map(lines) do l
keys = [Symbol(m.match) for m in eachmatch(r, l)]
rest = split(l, r; keepempty=true)
result = vcat((
[preish(r), embed_display(d[k].x)]
for (r,k) in zip(rest, keys)
)...)
push!(result, preish(last(rest)))
@htl("<line-like>$(result)</line-like>")
end
)
</slotted-code>""")
end
👀 Reading hidden code
11.5 ms
html"""
<style>
slotted-code {
font-family: "JuliaMono", monospace;
font-size: .75rem;
display: flex;
flex-direction: column;
}
pre-ish {
white-space: pre;
}

slotted-code pluto-display>div {
display: inline-block;
}

line-like {
display: flex;
}
"""
👀 Reading hidden code
104 μs
# rs = @eval_step_by_step(begin
# (1+2) + (7-6)
# first(2000 .+ 30 .* rand(2+2))
# 4+5
# sqrt(sqrt(sqrt(5)))
# end) .|> display_slotted
👀 Reading hidden code
8.9 μs
using Plots
👀 Reading hidden code
3.5 s
plot (generic function with 1 method)
plot(args...; kwargs...) = Plots.plot(args...; size=(100,100), kwargs...)
👀 Reading hidden code
1.6 ms
rs = @eval_step_by_step(begin
(1+2) + (7-6)
plot(2000 .+ 30 .* rand(2+2))
4+5
sqrt(sqrt(sqrt(5)))
end) .|> display_slotted
👀 Reading hidden code
4.0 s
@bind rindex Slider(eachindex(rs))
👀 Reading hidden code
34.9 ms
begin (1 + 2) + (7 - 6) plot(2000 .+ 30 .* rand(2 + 2)) 4 + 5 sqrt(sqrt(sqrt(5)))end
rs[rindex]
👀 Reading hidden code
15.5 μs
begin (1 + 2) + (7 - 6) plot(2000 .+ 30 .* rand(2 + 2)) 4 + 5 sqrt(sqrt(sqrt(5)))end begin
3
+ (7 - 6)
plot(2000 .+ 30 .* rand(2 + 2)) 4 + 5 sqrt(sqrt(sqrt(5)))end
begin
3
+
1
plot(2000 .+ 30 .* rand(2 + 2)) 4 + 5 sqrt(sqrt(sqrt(5)))end
begin
4
plot(2000 .+ 30 .* rand(2 + 2)) 4 + 5 sqrt(sqrt(sqrt(5)))end
begin
4
plot(2000 .+ 30 .* rand(
4
))
4 + 5 sqrt(sqrt(sqrt(5)))end
begin
4
plot(2000 .+ 30 .*
)
4 + 5 sqrt(sqrt(sqrt(5)))end
begin
4
plot(2000 .+
)
4 + 5 sqrt(sqrt(sqrt(5)))end
begin
4
plot(
)
4 + 5 sqrt(sqrt(sqrt(5)))end
begin
4
4 + 5 sqrt(sqrt(sqrt(5)))end
begin
4
9
sqrt(sqrt(sqrt(5)))end
begin
4
9
sqrt(sqrt(
2.23606797749979
))
end
begin
4
9
sqrt(
1.4953487812212205
)
end
begin
4
9
1.2228445449938519
end
1.2228445449938519
frames(rs)
👀 Reading hidden code
15.7 μs
@visual_debug (macro with 1 method)
macro visual_debug(expr)
frames
display_slotted
var"@eval_step_by_step"
quote
@eval_step_by_step($(expr)) .|> display_slotted |> frames
end
end
👀 Reading hidden code
621 μs
begin (1 + 2) + (7 - 6) plot(2000 .+ 30 .* rand(2 + 2)) 4 + 5 sqrt(sqrt(sqrt(5)))end begin
3
+ (7 - 6)
plot(2000 .+ 30 .* rand(2 + 2)) 4 + 5 sqrt(sqrt(sqrt(5)))end
begin
3
+
1
plot(2000 .+ 30 .* rand(2 + 2)) 4 + 5 sqrt(sqrt(sqrt(5)))end
begin
4
plot(2000 .+ 30 .* rand(2 + 2)) 4 + 5 sqrt(sqrt(sqrt(5)))end
begin
4
plot(2000 .+ 30 .* rand(
4
))
4 + 5 sqrt(sqrt(sqrt(5)))end
begin
4
plot(2000 .+ 30 .*
)
4 + 5 sqrt(sqrt(sqrt(5)))end
begin
4
plot(2000 .+
)
4 + 5 sqrt(sqrt(sqrt(5)))end
begin
4
plot(
)
4 + 5 sqrt(sqrt(sqrt(5)))end
begin
4
4 + 5 sqrt(sqrt(sqrt(5)))end
begin
4
9
sqrt(sqrt(sqrt(5)))end
begin
4
9
sqrt(sqrt(
2.23606797749979
))
end
begin
4
9
sqrt(
1.4953487812212205
)
end
begin
4
9
1.2228445449938519
end
1.2228445449938519
@visual_debug begin
(1+2) + (7-6)
plot(2000 .+ 30 .* rand(2+2))
4+5
sqrt(sqrt(sqrt(5)))
end
👀 Reading hidden code
23.7 ms
frames (generic function with 1 method)
function frames(fs)
@htl("""
<div>
<p-frames>
$(fs)
</p-frames>
<img src="https://cdn.jsdelivr.net/gh/ionic-team/ionicons@5.0.0/src/svg/time-outline.svg" style="width: 1em; transform: scale(-1,1); opacity: .5; margin-left: 2em;">
<input class="timescrub" type=range min=1 max=$(length(fs)) value=$(max(1,length(fs)-1))>
<script>
const div = currentScript.parentElement
const input = div.querySelector("input.timescrub")
const frames = div.querySelector("p-frames")
const setviz = () => {
Array.from(frames.children).forEach((f,i) => {
f.style.display = i + 1 === input.valueAsNumber ? "inherit" : "none"
})
}
setviz()
input.addEventListener("input", setviz)
</script>



</div>
""")
end
👀 Reading hidden code
744 μs
👀 Reading hidden code
73.4 μs
👀 Reading hidden code
78.0 μs
👀 Reading hidden code
74.1 μs
👀 Reading hidden code
74.5 μs
👀 Reading hidden code
72.7 μs
👀 Reading hidden code
72.8 μs