Skip to content

Commit d201517

Browse files
committed
🚂 Autorun=autofun
1 parent bc9111e commit d201517

File tree

16 files changed

+168
-63
lines changed

16 files changed

+168
-63
lines changed

‎Project.toml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name = "Pluto"
22
uuid = "c3e4b0f8-55cb-11ea-2926-15256bba5781"
33
license = "MIT"
44
authors = ["Fons van der Plas <fonsvdplas@gmail.com>", "Mikołaj Bochenski <iceflamecode@gmail.com>"]
5-
version = "0.6.3"
5+
version = "0.6.4"
66

77
[deps]
88
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"

‎assets/bond.js‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,10 @@ document.addEventListener("celloutputchanged", (e) => {
2424
}
2525
const bondNodes = cellNode.querySelectorAll("bond")
2626

27-
bondNodes.forEach(bond => {
28-
bond.generator = observablehq.Generators.input(bond.firstChild)
29-
makeBond(bond)
27+
bondNodes.forEach(bondNode => {
28+
bondNode.generator = observablehq.Generators.input(bondNode.firstChild)
29+
window.allCellsCompletedPromise.then(_ => {
30+
makeBond(bondNode)
31+
})
3032
})
3133
}, false)

‎assets/client.js‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ class PlutoConnection {
148148
}
149149
this.psocket.onopen = () => {
150150
this.sendreceive("connect", {}).then(u => {
151+
this.plutoCONFIG = u.message.CONFIG
151152
if(this.notebookID && !u.message.notebookExists){
152153
// https://github.com/fonsp/Pluto.jl/issues/55
153154
document.location.href = "/"

‎assets/editor.js‎

Lines changed: 57 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -168,25 +168,29 @@ document.addEventListener("DOMContentLoaded", () => {
168168
return roundedtime + '\xa0' + prefices[i] + "s"
169169
}
170170

171-
function updateLocalCellOutput(cellNode, mime, output, errormessage, runtime) {
172-
cellNode.classList.remove("running")
173-
cellNode.querySelector("runarea>span").innerText = prettytime(runtime)
171+
function updateLocalCellOutput(cellNode, msg) {
172+
if(msg.running){
173+
cellNode.classList.add("running")
174+
} else {
175+
cellNode.classList.remove("running")
176+
}
177+
cellNode.querySelector("runarea>span").innerText = prettytime(msg.runtime)
174178

175179
const outputNode = cellNode.querySelector("celloutput")
176180

177181
oldHeight = outputNode.scrollHeight
178182

179-
if (errormessage) {
183+
if (msg.errormessage) {
180184
outputNode.innerHTML = "<pre><code></code></pre>"
181-
outputNode.querySelector("code").innerHTML = rewrittenError(errormessage)
185+
outputNode.querySelector("code").innerHTML = rewrittenError(msg.errormessage)
182186
cellNode.classList.add("error")
183187
} else {
184188
cellNode.classList.remove("error")
185-
if (mime == "text/html" || mime == "image/svg+xml") {
189+
if (msg.mime == "text/html" || msg.mime == "image/svg+xml") {
186190

187-
// if(outputNode.innerHTML != output){
191+
// if(outputNode.innerHTML != msg.output){
188192
// }
189-
outputNode.innerHTML = output
193+
outputNode.innerHTML = msg.output
190194

191195
// from https://stackoverflow.com/a/26716182
192196
// to execute all scripts in the output html:
@@ -215,11 +219,11 @@ document.addEventListener("DOMContentLoaded", () => {
215219
MathJax.typeset()
216220
} else {
217221
outputNode.innerHTML = "<pre><code></code></pre>"
218-
outputNode.querySelector("code").innerText = output
222+
outputNode.querySelector("code").innerText = msg.output
219223
}
220224
}
221-
document.dispatchEvent(new CustomEvent("celloutputchanged", {detail: {cell: cellNode, mime: mime}}))
222-
if(output == null && errormessage == null){
225+
document.dispatchEvent(new CustomEvent("celloutputchanged", {detail: {cell: cellNode, mime: msg.mime}}))
226+
if(msg.output == null && msg.errormessage == null){
223227
cellNode.classList.add("output-notinsync")
224228
} else {
225229
cellNode.classList.remove("output-notinsync")
@@ -299,7 +303,7 @@ document.addEventListener("DOMContentLoaded", () => {
299303
newFolded = false
300304
} else if (window.getSelection().isCollapsed) {
301305
// Do not fold if the click event was fired because the user selects text in the output.
302-
if (e.target.tagName != "A" && e.target.tagName != "INPUT") {
306+
if (e.target.tagName != "A" && e.target.tagName != "INPUT" && e.target.tagName != "SELECT") {
303307
// Do not fold if a link was clicked.
304308
newFolded = !newFolded
305309
}
@@ -376,8 +380,8 @@ document.addEventListener("DOMContentLoaded", () => {
376380

377381
/* REQUEST FUNCTIONS FOR REMOTE CHANGES */
378382

379-
window.allCellsCompleted = true
380-
window.allCellsCompletedPromise = new Promise(r => r()) // resolved
383+
window.allCellsCompleted = true // will be set to false soon
384+
window.allCellsCompletedPromise = null
381385

382386
function refreshAllCompletionPromise(){
383387
if(allCellsCompleted){
@@ -389,6 +393,7 @@ document.addEventListener("DOMContentLoaded", () => {
389393
}
390394

391395
window.refreshAllCompletionPromise = refreshAllCompletionPromise
396+
refreshAllCompletionPromise()
392397

393398
function requestChangeRemoteCell(uuid, createPromise=false) {
394399
refreshAllCompletionPromise()
@@ -398,21 +403,25 @@ document.addEventListener("DOMContentLoaded", () => {
398403
return client.send("changecell", { code: newCode }, uuid, createPromise)
399404
}
400405

401-
function requestRunAllRemoteCells() {
406+
function requestRunAllRemoteCells(setInputs=true) {
407+
if(!window.allCellsCompleted){
408+
return
409+
}
402410
refreshAllCompletionPromise()
403411
const promises = []
404412

405413
for (var uuid in window.localCells) {
406414
const cellNode = window.localCells[uuid]
407415
cellNode.classList.add("running")
408-
promises.push(
409-
client.sendreceive("setinput", {
410-
code: window.codeMirrors[uuid].getValue()
411-
}, uuid).then(u => {
412-
updateLocalCellInput(true, cellNode, u.message.code, u.message.folded)
413-
})
414-
)
415-
416+
if(setInputs){
417+
promises.push(
418+
client.sendreceive("setinput", {
419+
code: window.codeMirrors[uuid].getValue()
420+
}, uuid).then(u => {
421+
updateLocalCellInput(true, cellNode, u.message.code, u.message.folded)
422+
})
423+
)
424+
}
416425
}
417426
Promise.all(promises).then(() => {
418427
client.send("runall", {})
@@ -452,7 +461,7 @@ document.addEventListener("DOMContentLoaded", () => {
452461

453462
switch (update.type) {
454463
case "cell_output":
455-
updateLocalCellOutput(window.localCells[update.cellID], message.mime, message.output, message.errormessage, message.runtime)
464+
updateLocalCellOutput(window.localCells[update.cellID], message)
456465
break
457466
case "cell_running":
458467
// TODO: catch exception
@@ -499,6 +508,7 @@ document.addEventListener("DOMContentLoaded", () => {
499508
window.customPlutoListeners = {}
500509

501510
function onEstablishConnection() {
511+
const runAll = client.plutoCONFIG["PLUTO_RUN_NOTEBOOK_ON_LOAD"] == "true"
502512
// on socket success
503513
client.send("getallnotebooks", {})
504514

@@ -507,27 +517,35 @@ document.addEventListener("DOMContentLoaded", () => {
507517

508518
update.message.cells.forEach((cell, index) => {
509519
const cellNode = createLocalCell(index, cell.uuid, "", false)
520+
runAll && cellNode.classList.add("running")
510521
promises.push(
511522
client.sendreceive("getinput", {}, cell.uuid).then(u => {
512523
updateLocalCellInput(true, cellNode, u.message.code, u.message.folded)
513524
})
514525
)
515526
promises.push(
516527
client.sendreceive("getoutput", {}, cell.uuid).then(u => {
517-
const message = u.message
518-
updateLocalCellOutput(cellNode, message.mime, message.output, message.errormessage, message.runtime)
528+
updateLocalCellOutput(cellNode, u.message)
519529
})
520530
)
521531
})
522532

523533
Promise.all(promises).then(() => {
524-
// We do a code completion request to trigger starting the workpsace
525-
client.sendreceive("complete", {
526-
query: "nothinginparticular"
527-
}).then(() => {
534+
function happy() {
528535
document.body.classList.remove("loading")
529536
console.info("Workspace initialized")
530-
})
537+
}
538+
if (runAll
539+
&& !document.querySelector("notebook>cell.running")
540+
&& document.querySelector("notebook>cell.output-notinsync")) {
541+
requestRunAllRemoteCells(false)
542+
window.allCellsCompletedPromise.then(happy)
543+
} else {
544+
// We do a code completion request to trigger starting the workpsace
545+
client.sendreceive("complete", {
546+
query: "nothinginparticular"
547+
}).then(happy)
548+
}
531549
})
532550
}).catch(console.error)
533551

@@ -773,6 +791,14 @@ document.addEventListener("DOMContentLoaded", () => {
773791
e.preventDefault()
774792
}
775793
break
794+
case 82: // r
795+
if(e.ctrlKey){
796+
if(notebookPath != "unknown"){
797+
document.location.href = "/open?path=" + encodeURIComponent(notebookPath)
798+
e.preventDefault()
799+
}
800+
}
801+
break
776802
case 83: // s
777803
if(e.ctrlKey){
778804
filePickerCodeMirror.focus()

‎assets/light.css‎

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,7 @@ cell.running.error>trafficlight {
350350
}
351351
}
352352

353+
353354
cell.dependent>cellinput>.CodeMirror,
354355
cell.warning>cellinput>.CodeMirror,
355356
cell.error>cellinput>.CodeMirror {
@@ -366,6 +367,24 @@ cell.error>cellinput>.CodeMirror {
366367
}
367368
}
368369

370+
cell.output-notinsync>cellinput>.CodeMirror,
371+
cell.codediffers>cellinput>.CodeMirror {
372+
border: 1px solid hsla(46, 70%, 37%, 0.68);
373+
padding-left: 0px;
374+
}
375+
376+
cell.output-notinsync>runarea,
377+
cell.codediffers>runarea {
378+
opacity: 100%;
379+
/* background: hsla(46, 70%, 37%, 0.35); */
380+
}
381+
cell.output-notinsync>runarea>button,
382+
cell.codediffers>runarea>button {
383+
animation-name: 👀;
384+
animation-duration: 4s;
385+
animation-iteration-count: infinite;
386+
}
387+
369388
@keyframes 🌈 {
370389
from {
371390
background-color: hsl(0, 100%, 98%);
@@ -384,6 +403,17 @@ cell.error>cellinput>.CodeMirror {
384403
}
385404
}
386405

406+
@keyframes 👀 {
407+
0%, 80%, 100% {
408+
transform: scale(1.0);
409+
opacity: 50%;
410+
}
411+
90% {
412+
transform: scale(1.2);
413+
opacity: 100%;
414+
}
415+
}
416+
387417

388418
/* CODEMIRROR STYLE */
389419

@@ -422,7 +452,7 @@ Based on "Paraíso (Light)" by Jan T. Sott:
422452

423453
cell.output-notinsync .cm-s-default .CodeMirror-gutters,
424454
cell.codediffers .cm-s-default .CodeMirror-gutters {
425-
background: hsla(46, 90%, 94%, 1);
455+
background: hsla(46, 70%, 88%, 1);
426456
}
427457

428458
.cm-s-default .CodeMirror-guttermarker {

‎src/Pluto.jl‎

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,28 @@ const PKG_ROOT_DIR = normpath(joinpath(@__DIR__, ".."))
77
const PLUTO_VERSION = VersionNumber(Pkg.TOML.parsefile(joinpath(PKG_ROOT_DIR, "Project.toml"))["version"])
88
const PLUTO_VERSION_STR = 'v' * string(PLUTO_VERSION)
99
const JULIA_VERSION_STR = 'v' * string(VERSION)
10+
const CONFIG = Dict(
11+
"PLUTO_RUN_NOTEBOOK_ON_LOAD" => "true",
12+
)
1013

1114
@info """\n
12-
Welcome to Pluto $(PLUTO_VERSION_STR)! âš¡
15+
Welcome to Pluto $(PLUTO_VERSION_STR) 🎈
16+
Start a notebook server using:
1317
14-
Let us know what you think:
15-
https://github.com/fonsp/Pluto.jl
18+
julia> Pluto.run(1234)
19+
20+
Have a look at the FAQ:
21+
https://github.com/fonsp/Pluto.jl/wiki
1622
\n"""
1723

1824
include("./react/ExploreExpression.jl")
25+
include("./runner/PlutoRunner.jl")
1926
using .ExploreExpression
2027

2128
include("./notebookserver/Cell.jl")
2229
include("./notebookserver/Notebook.jl")
2330
include("./notebookserver/Client.jl")
2431

25-
include("./runner/PlutoRunner.jl")
2632
include("./react/WorkspaceManager.jl")
2733

2834
include("./react/Errors.jl")

‎src/notebookserver/Cell.jl‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,12 @@ mutable struct Cell
1313
repr_mime::MIME
1414
runtime::Union{Missing,UInt64}
1515
code_folded::Bool
16+
running::Bool
1617

1718
parsedcode::Any
1819
symstate::SymbolsState
1920
module_usings::Set{Expr}
2021
end
2122

22-
Cell(uuid, code) = Cell(uuid, code, nothing, nothing, MIME("text/plain"), missing, false, nothing, SymbolsState(), Set{Expr}())
23+
Cell(uuid, code) = Cell(uuid, code, nothing, nothing, MIME("text/plain"), missing, false, false, nothing, SymbolsState(), Set{Expr}())
2324
Cell(code) = Cell(uuid1(), code)

‎src/notebookserver/Client.jl‎

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
11
mutable struct Client
22
id::Symbol
33
stream::Any
4-
stream_accesstoken::Channel{Nothing}
54
connected_notebook::Union{Notebook,Nothing}
65
pendingupdates::Channel
76
end
87

98
Client(id::Symbol, stream) = let
10-
at = Channel{Nothing}(1)
11-
put!(at, nothing)
12-
Client(id, stream, at, nothing, Channel(1024))
9+
Client(id, stream, nothing, Channel(1024))
1310
end
1411

1512
struct Initiator
@@ -38,6 +35,7 @@ function clientupdate_cell_output(notebook::Notebook, cell::Cell; initiator::Uni
3835
:output => payload,
3936
:errormessage => cell.error_repr,
4037
:runtime => cell.runtime,
38+
:running => cell.running,
4139
),
4240
notebook, cell, initiator)
4341
end

‎src/notebookserver/Notebook.jl‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,13 @@ end
6767
function save_notebook(io, notebook::Notebook)
6868
write(io, "### A Pluto.jl notebook ###\n")
6969
write(io, "# " * PLUTO_VERSION_STR * "\n")
70-
70+
# Anything between the version string and the first UUID delimiter will be ignored by the notebook loader.
71+
println(io, "")
72+
println(io, "using Markdown")
73+
# Super Advanced Code Analysisâ„¢ to add the @bind macro to the saved file if it's used somewhere.
74+
if any(occursin("@bind", c.code) for c in notebook.cells)
75+
write(io, PlutoRunner.fake_bind)
76+
end
7177
# TODO: this can be optimised by caching the topological order:
7278
# maintain cache with ordered UUIDs
7379
# whenever a run_reactive is done, move the found cells **up** until they are in one group, and order them topologcally within that group. Errable cells go to the bottom.

‎src/react/ExploreExpression.jl‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ function explore!(ex::Expr, scopestate::ScopeState)::SymbolsState
377377
ex.args
378378
end
379379

380-
packagenames = map(e->e.args[1], imports)
380+
packagenames = map(e->e.args[end], imports)
381381

382382
return SymbolsState(Set{Symbol}(), Set{Symbol}(packagenames))
383383
else

0 commit comments

Comments
 (0)