diff --git a/frontend/components/CellInput.js b/frontend/components/CellInput.js index 9d9a4d784f..0c7e1aa28c 100644 --- a/frontend/components/CellInput.js +++ b/frontend/components/CellInput.js @@ -4,7 +4,7 @@ import { utf8index_to_ut16index } from "../common/UnicodeTools.js" const clear_selection = (cm) => { const c = cm.getCursor() - cm.setSelection(c, c, { sroll: false }) + cm.setSelection(c, c, { scroll: false }) } export const CellInput = ({ @@ -124,7 +124,6 @@ export const CellInput = ({ useEffect(() => { if (cm_forced_focus == null) { - // clear selection clear_selection(cm_ref.current) } else { cm_ref.current.focus() diff --git a/sample/test1.jl b/sample/test1.jl index 3e5f89f093..a66507e6a8 100644 --- a/sample/test1.jl +++ b/sample/test1.jl @@ -1,7 +1,10 @@ ### A Pluto.jl notebook ### -# v0.10.0 +# v0.10.1 using Markdown +using InteractiveUtils + +# This Pluto notebook uses @bind for interactivity. When running this notebook outside of Pluto, the following 'mock version' of @bind gives bound variables a default value (instead of an error). macro bind(def, element) quote local el = $(esc(element)) @@ -49,6 +52,14 @@ md"## Autocomplete" # ╔═╡ e141f910-b162-11ea-039b-3ba1414cbd07 +# ╔═╡ c7a1f21e-c137-11ea-1d11-8fb5508ac80c +md"## Selections" + +# ╔═╡ f7297d72-c137-11ea-3a9b-a10be62c3976 +ask("manual", md"Put your cursor in this cell, scroll down 2 screens, and click somewhere else + +Page should not jump back to this cell") + # ╔═╡ 39724bae-b160-11ea-0af5-737755a57e48 md"# Network" @@ -264,6 +275,11 @@ Drag to end of the screen, **should autoscroll**") # ╔═╡ 1b569b72-b167-11ea-1462-63674f7e13db ask("manual", md"Test autocomplete") +# ╔═╡ cd3f70fc-c137-11ea-2871-936287684d2c +ask("manual", md"Select a chunk of code, then put your cursor in another cell + +Selection of the original cell should collapse") + # ╔═╡ 4902abb2-b160-11ea-1120-f501bf151fc2 ask("manual", md"Refresh quickly & slowly a couple of times") @@ -386,6 +402,9 @@ ask("visual", md"These three paragraphs must have equal spacing between them") # ╟─d890a190-b162-11ea-31dd-8d603787e5c5 # ╟─1b569b72-b167-11ea-1462-63674f7e13db # ╠═e141f910-b162-11ea-039b-3ba1414cbd07 +# ╟─c7a1f21e-c137-11ea-1d11-8fb5508ac80c +# ╠═cd3f70fc-c137-11ea-2871-936287684d2c +# ╠═f7297d72-c137-11ea-3a9b-a10be62c3976 # ╟─39724bae-b160-11ea-0af5-737755a57e48 # ╟─4902abb2-b160-11ea-1120-f501bf151fc2 # ╟─58721630-b160-11ea-30b4-e9667b4df6da diff --git a/src/webserver/Dynamic.jl b/src/webserver/Dynamic.jl index 54f72ce7bd..96073853fb 100644 --- a/src/webserver/Dynamic.jl +++ b/src/webserver/Dynamic.jl @@ -41,14 +41,14 @@ function change_remote_cellinput!(notebook, cell, newcode; initiator::Union{Init putnotebookupdates!(notebook, clientupdate_cell_input(notebook, cell, initiator=initiator)) end -responses[:connect] = (body, notebook = nothing; initiator::Union{Initiator,Missing}=missing)->begin +responses[:connect] = (body, notebook = nothing; initiator::Union{Initiator,Missing}=missing) -> begin putclientupdates!(initiator, UpdateMessage(:👋, Dict( :notebookExists => (notebook != nothing), - :ENV => filter(p->startswith(p.first, "PLUTO"), ENV), + :ENV => filter(p -> startswith(p.first, "PLUTO"), ENV), ), nothing, nothing, initiator)) end -responses[:getversion] = (body, notebook = nothing; initiator::Union{Initiator,Missing}=missing)->begin +responses[:getversion] = (body, notebook = nothing; initiator::Union{Initiator,Missing}=missing) -> begin putclientupdates!(initiator, UpdateMessage(:versioninfo, Dict( :pluto => PLUTO_VERSION_STR, :julia => JULIA_VERSION_STR, @@ -57,18 +57,19 @@ end # TODO: actions on the notebook are not thread safe -responses[:addcell] = (body, notebook::Notebook; initiator::Union{Initiator,Missing}=missing)->begin +responses[:addcell] = (body, notebook::Notebook; initiator::Union{Initiator,Missing}=missing) -> begin new_index = body["index"] + 1 # 0-based index (js) to 1-based index (julia) new_cell = Cell("") new_cell.output_repr = "" # we 'run' the code and get this output insert!(notebook.cells, new_index, new_cell) - + putnotebookupdates!(notebook, clientupdate_cell_added(notebook, new_cell, new_index, initiator=initiator)) + save_notebook(notebook) end -responses[:deletecell] = (body, notebook::Notebook, cell::Cell; initiator::Union{Initiator,Missing}=missing)->begin +responses[:deletecell] = (body, notebook::Notebook, cell::Cell; initiator::Union{Initiator,Missing}=missing) -> begin to_delete = cell # replace the cell's code with "" and do a reactive run @@ -80,13 +81,13 @@ responses[:deletecell] = (body, notebook::Notebook, cell::Cell; initiator::Union @async begin wait(runtask) - filter!(c->c.cell_id ≠ to_delete.cell_id, notebook.cells) + filter!(c -> c.cell_id ≠ to_delete.cell_id, notebook.cells) putnotebookupdates!(notebook, clientupdate_cell_deleted(notebook, to_delete, initiator=initiator)) save_notebook(notebook) # this might be "too late", but it will save the latest version of `notebook` anyways end end -responses[:movecell] = (body, notebook::Notebook, cell::Cell; initiator::Union{Initiator,Missing}=missing)->begin +responses[:movecell] = (body, notebook::Notebook, cell::Cell; initiator::Union{Initiator,Missing}=missing) -> begin to_move = cell # Indexing works as if a new cell is added. @@ -104,18 +105,19 @@ responses[:movecell] = (body, notebook::Notebook, cell::Cell; initiator::Union{I insert!(notebook.cells, new_index, to_move) deleteat!(notebook.cells, old_index) end - + putnotebookupdates!(notebook, clientupdate_cell_moved(notebook, to_move, new_index, initiator=initiator)) + save_notebook(notebook) end -responses[:changecell] = (body, notebook::Notebook, cell::Cell; initiator::Union{Initiator,Missing}=missing)->begin +responses[:changecell] = (body, notebook::Notebook, cell::Cell; initiator::Union{Initiator,Missing}=missing) -> begin newcode = body["code"] change_remote_cellinput!(notebook, cell, newcode, initiator=initiator) run_reactive_async!(notebook, cell) end -responses[:foldcell] = (body, notebook::Notebook, cell::Cell; initiator::Union{Initiator,Missing}=missing)->begin +responses[:foldcell] = (body, notebook::Notebook, cell::Cell; initiator::Union{Initiator,Missing}=missing) -> begin newfolded = body["folded"] cell.code_folded = newfolded save_notebook(notebook) @@ -123,29 +125,29 @@ responses[:foldcell] = (body, notebook::Notebook, cell::Cell; initiator::Union{I putnotebookupdates!(notebook, clientupdate_cell_folded(notebook, cell, newfolded, initiator=initiator)) end -responses[:run] = (body, notebook::Notebook, cell::Cell; initiator::Union{Initiator,Missing}=missing)->begin +responses[:run] = (body, notebook::Notebook, cell::Cell; initiator::Union{Initiator,Missing}=missing) -> begin run_reactive_async!(notebook, cell) end -responses[:runmultiple] = (body, notebook::Notebook; initiator::Union{Initiator,Missing}=missing)->begin +responses[:runmultiple] = (body, notebook::Notebook; initiator::Union{Initiator,Missing}=missing) -> begin indices = cellindex_fromID.([notebook], UUID.(body["cells"])) cells = [notebook.cells[i] for i in indices if i !== nothing] run_reactive_async!(notebook, cells) end -responses[:getinput] = (body, notebook::Notebook, cell::Cell; initiator::Union{Initiator,Missing}=missing)->begin +responses[:getinput] = (body, notebook::Notebook, cell::Cell; initiator::Union{Initiator,Missing}=missing) -> begin putclientupdates!(initiator, clientupdate_cell_input(notebook, cell, initiator=initiator)) end -responses[:setinput] = (body, notebook::Notebook, cell::Cell; initiator::Union{Initiator,Missing}=missing)->begin +responses[:setinput] = (body, notebook::Notebook, cell::Cell; initiator::Union{Initiator,Missing}=missing) -> begin change_remote_cellinput!(notebook, cell, body["code"], initiator=initiator) end -responses[:getoutput] = (body, notebook::Notebook, cell::Cell; initiator::Union{Initiator,Missing}=missing)->begin +responses[:getoutput] = (body, notebook::Notebook, cell::Cell; initiator::Union{Initiator,Missing}=missing) -> begin putclientupdates!(initiator, clientupdate_cell_output(notebook, cell, initiator=initiator)) end -responses[:getallcells] = (body, notebook::Notebook; initiator::Union{Initiator,Missing}=missing)->begin +responses[:getallcells] = (body, notebook::Notebook; initiator::Union{Initiator,Missing}=missing) -> begin # TODO: the client's update channel might get full update = UpdateMessage(:cell_list, Dict(:cells => [Dict( @@ -155,11 +157,11 @@ responses[:getallcells] = (body, notebook::Notebook; initiator::Union{Initiator, putclientupdates!(initiator, update) end -responses[:getallnotebooks] = (body, notebook = nothing; initiator::Union{Initiator,Missing}=missing)->begin +responses[:getallnotebooks] = (body, notebook = nothing; initiator::Union{Initiator,Missing}=missing) -> begin putplutoupdates!(clientupdate_notebook_list(notebooks, initiator=initiator)) end -responses[:movenotebookfile] = (body, notebook::Notebook; initiator::Union{Initiator,Missing}=missing)->begin +responses[:movenotebookfile] = (body, notebook::Notebook; initiator::Union{Initiator,Missing}=missing) -> begin newpath = tamepath(body["path"]) result = try if isfile(newpath) @@ -178,12 +180,12 @@ responses[:movenotebookfile] = (body, notebook::Notebook; initiator::Union{Initi putclientupdates!(initiator, update) end -responses[:interruptall] = (body, notebook::Notebook; initiator::Union{Initiator,Missing}=missing)->begin +responses[:interruptall] = (body, notebook::Notebook; initiator::Union{Initiator,Missing}=missing) -> begin success = WorkspaceManager.interrupt_workspace(notebook) # TODO: notify user whether interrupt was successful (i.e. whether they are using a `ProcessWorkspace`) end -responses[:shutdownworkspace] = (body, notebook::Notebook; initiator::Union{Initiator,Missing}=missing)->begin +responses[:shutdownworkspace] = (body, notebook::Notebook; initiator::Union{Initiator,Missing}=missing) -> begin listeners = putnotebookupdates!(notebook) # TODO: shutdown message if body["remove_from_list"] delete!(notebooks, notebook.notebook_id) @@ -196,7 +198,7 @@ responses[:shutdownworkspace] = (body, notebook::Notebook; initiator::Union{Init end -responses[:bond_set] = (body, notebook::Notebook; initiator::Union{Initiator,Missing}=missing)->begin +responses[:bond_set] = (body, notebook::Notebook; initiator::Union{Initiator,Missing}=missing) -> begin bound_sym = Symbol(body["sym"]) new_val = body["val"]