Someone had a question on Slack today that I had some fun with, so I figured I'd copy my answer here for posterity. Suppose I have some pluto file like
### A Pluto.jl notebook ###
# v0.16.1
using Markdown
using InteractiveUtils
# ╔═╡ f39d12e8-26eb-11ec-0e1d-5b291ffb6ca5
x = rand(10)
# ╔═╡ bafb4a21-d800-4db5-8d00-3e85a817a635
y = (x .^ 2) .- x'
# ╔═╡ ddccda44-7343-4ec4-98d7-bbd9c398806a
1 .+ x
# ╔═╡ Cell order:
# ╠═f39d12e8-26eb-11ec-0e1d-5b291ffb6ca5
# ╠═bafb4a21-d800-4db5-8d00-3e85a817a635
# ╠═ddccda44-7343-4ec4-98d7-bbd9c398806a
The question is, how can I run this as a script but retain the 'cell strcture' so that one can ask what the output of a given cell was. The idea I came up with was to basically take this file as a string, and then split
the string using # ╔═╡
as a delimiter (and throw away the following UUID). That gives me the cell structure, then I just need to assign each cell to a dictionary, put it all in a :block
and then eval
it.
function collect_cells(s)
cells = split(s, "# ╔═╡")
final_expr = Expr(:block, :(Out = Dict{Int, Any}()))
for (i, cell) ∈ enumerate(cells)
cell = cell |> IOBuffer |> eachline |> collect |> x -> join(x[2:end], "\n")
ex = :(Out[$i] = $(Meta.parse("begin\n"*cell*"\nend")))
push!(final_expr.args, ex)
end
final_expr
end
function plutoinclude(f::String#=::filename=#)
ex = collect_cells(read(f, String))
eval(ex)
end
e.g. in this case,
s = """
### A Pluto.jl notebook ###
# v0.16.1
using Markdown
using InteractiveUtils
# ╔═╡ f39d12e8-26eb-11ec-0e1d-5b291ffb6ca5
x = rand(10)
# ╔═╡ bafb4a21-d800-4db5-8d00-3e85a817a635
y = (x .^ 2) .- x'
# ╔═╡ ddccda44-7343-4ec4-98d7-bbd9c398806a
1 .+ x
# ╔═╡ Cell order:
# ╠═f39d12e8-26eb-11ec-0e1d-5b291ffb6ca5
# ╠═bafb4a21-d800-4db5-8d00-3e85a817a635
# ╠═ddccda44-7343-4ec4-98d7-bbd9c398806a
""";
collect_cells(s)
#+RESULTS:
quote
Out = Dict{Int, Any}()
Out[1] = begin
#= none:4 =#
using Markdown
#= none:5 =#
using InteractiveUtils
end
Out[2] = begin
#= none:2 =#
x = rand(10)
end
Out[3] = begin
#= none:2 =#
y = x .^ 2 .- x'
end
Out[4] = begin
#= none:2 =#
1 .+ x
end
Out[5] = begin
#= none:5 =#
end
end
Last updated: Nov 06 2024 at 04:40 UTC