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
176 μs

This notebook contains visual debugging:

👀 Reading hidden code
235 μ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
108 ms

and visual testing:

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

4.5 ms
👀 Reading hidden code
using PlutoUI
162 ms

Type definitions

👀 Reading hidden code
165 μs
abstract type TestResult end
👀 Reading hidden code
336 μs
abstract type Fail <: TestResult end
👀 Reading hidden code
323 μs
abstract type Pass <: TestResult end
👀 Reading hidden code
355 μs
Any
const Code = Any
👀 Reading hidden code
125 μ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.2 ms
struct Error <: Fail
expr::Code
error
end
👀 Reading hidden code
1.1 ms
struct Wrong <: Fail
expr::Code
result
end
👀 Reading hidden code
1.1 ms
struct CorrectCall <: Pass
expr::Code
arg_results::Vector
end
👀 Reading hidden code
1.2 ms

Test macro

👀 Reading hidden code
159 μ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.1 ms
👀 Reading hidden code
8.8 μ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
171 ms
:(x == [1, 2 + 2])
e = :(x == [1,2+2])
👀 Reading hidden code
25.9 μs
x = [1,3]
👀 Reading hidden code
13.6 μs
@test missing == 2
👀 Reading hidden code
33.9 ms
4
==
4
@test 2+2 == 2+2
👀 Reading hidden code
4.9 ms
==
@test x == [1,2+2]
👀 Reading hidden code
17.9 ms
==
@test rand(50) == [rand(50),2]
👀 Reading hidden code
98.6 ms
always_false(
,
,
123
)
@test always_false(rand(50), rand(50),123)
👀 Reading hidden code
24.1 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
17.7 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
30.9 ms
always_false([1, 2, 3]...)
false
@visual_debug always_false([1,2,3]...)
👀 Reading hidden code
32.8 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
24.4 μs
always_false (generic function with 1 method)
always_false(args...; kwargs...) = false
👀 Reading hidden code
1.1 ms
isless(
4
,
1
)
@test isless(2+2,1)
👀 Reading hidden code
7.3 ms
isless(
1
,
4
)
@test isless(1,2+2)
👀 Reading hidden code
1.5 ms
@bind n Slider(1:10)
👀 Reading hidden code
253 ms
iseven(
1
)
@test iseven(n^2)
👀 Reading hidden code
51.3 ms
@bind k Slider(0:15)
👀 Reading hidden code
630 μs
8
@test 4+4 ∈ [1:k...]
👀 Reading hidden code
29.2 ms
isempty(
)
@test isempty((1:k) .^ 2)
👀 Reading hidden code
60.8 ms
isempty(
)
@test isempty([1,sqrt(2)])
👀 Reading hidden code
33.6 ms
1
👀 Reading hidden code
54.1 ms
1
@test 1 ∈ rand(60)
👀 Reading hidden code
1.5 ms
1
@test rand(60) ∋ 1
👀 Reading hidden code
8.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
110 μs
true
(@test isodd(3)) isa Pass
👀 Reading hidden code
3.8 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
497 ms
flatmap (generic function with 1 method)
flatmap(args...) = vcat(map(args...)...)
👀 Reading hidden code
433 μ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
238 ms
embed_display (generic function with 1 method)
emb = embed_display
👀 Reading hidden code
13.1 μs
div (generic function with 1 method)
div(x; class="", style="") = @htl("<div class=$(class) style=$(style)>$(x)</div>")
👀 Reading hidden code
1.6 ms
div (generic function with 2 methods)
div(; class="", style="") = x -> @htl("<div class=$(class) style=$(style)>$(x)</div>")
👀 Reading hidden code
2.0 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
474 μ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
1.9 ms
remove_linenums (generic function with 2 methods)
remove_linenums(x) = x
👀 Reading hidden code
337 μs

DEbugging 1

md"""
# DEbugging 1
"""
👀 Reading hidden code
169 μ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.6 ms
expr_debug (generic function with 1 method)
function expr_debug(x)
e = remove_linenums(x)
Any[e, onestep(e)...]
end
👀 Reading hidden code
1000 μs
UInt64
👀 Reading hidden code
2.3 ms
expr_hash (generic function with 1 method)
👀 Reading hidden code
1.1 ms
expr_hash (generic function with 2 methods)
👀 Reading hidden code
357 μ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
10.2 ms
@bind step Slider(1:length(debug_result))
👀 Reading hidden code
646 μ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
101 μs

Debugging 1.5

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

👀 Reading hidden code
67.0 μs
expand_computed (generic function with 1 method)
expand_computed(x) = x
👀 Reading hidden code
356 μs
expand_computed (generic function with 2 methods)
expand_computed(c::Computed) = c.x
👀 Reading hidden code
375 μs
expand_computed (generic function with 3 methods)
expand_computed(e::Expr) = Expr(e.head, expand_computed.(e.args)...)
👀 Reading hidden code
468 μ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.8 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
843 μ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
1.6 ms
@eval_step_by_step sqrt(sqrt(length([1,2])))
👀 Reading hidden code
14.6 ms
@eval_step_by_step xasdf = 123
👀 Reading hidden code
146 μs
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
145 ms
can_interpret (generic function with 1 method)
can_interpret(x) = true
👀 Reading hidden code
821 μs
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
633 μs
can_interpret_call_arg (generic function with 2 methods)
can_interpret_call_arg(x) = true
👀 Reading hidden code
331 μs
true
Meta.isbinaryoperator(:(==))
👀 Reading hidden code
26.1 μ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
633 μs

Displaying

👀 Reading hidden code
164 μs

👀 Reading hidden code
58.7 μs
find_computed! (generic function with 1 method)
find_computed!(found, c::Computed) = push!(found, c)
👀 Reading hidden code
365 μs
find_computed! (generic function with 2 methods)
find_computed!(found, expr::Expr) = find_computed!.([found], expr.args)
👀 Reading hidden code
467 μs
find_computed! (generic function with 3 methods)
find_computed!(found, x) = nothing
👀 Reading hidden code
359 μs
find_computed (generic function with 1 method)
find_computed(x) = let
r = Any[]
find_computed!(r, x)
r
end
👀 Reading hidden code
449 μs
onestep_light(quote
1+2
2+3
4+5
sqrt(sqrt(sqrt(5)))
end |> remove_linenums) .|> find_computed
👀 Reading hidden code
600 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
604 μs
slot! (generic function with 2 methods)
slot!(found, x) = x
👀 Reading hidden code
347 μs
slot! (generic function with 3 methods)
slot!(found, e::Expr) = Expr(e.head, slot!.([found], e.args)...)
👀 Reading hidden code
520 μ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
515 μs
onestep_light(quote
(1+2) + (7-6)
2+3
4+5
sqrt(sqrt(sqrt(5)))
end |> remove_linenums) .|> slot
👀 Reading hidden code
314 ms
preish (generic function with 1 method)
preish(x) = @htl("<pre-ish>$(x)</pre-ish>")
👀 Reading hidden code
474 μ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
10.9 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
103 μ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.8 μs
using Plots
👀 Reading hidden code
3.3 s
plot (generic function with 1 method)
plot(args...; kwargs...) = Plots.plot(args...; size=(100,100), kwargs...)
👀 Reading hidden code
1.4 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
3.6 s
@bind rindex Slider(eachindex(rs))
👀 Reading hidden code
30.0 ms
begin (1 + 2) + (7 - 6) plot(2000 .+ 30 .* rand(2 + 2)) 4 + 5 sqrt(sqrt(sqrt(5)))end
rs[rindex]
👀 Reading hidden code
11.7 μ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
32.2 μ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
595 μ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
2.2 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
702 μs
👀 Reading hidden code
60.2 μs
👀 Reading hidden code
58.8 μs
👀 Reading hidden code
58.3 μs
👀 Reading hidden code
58.2 μs
👀 Reading hidden code
58.5 μs
👀 Reading hidden code
59.0 μs