diff --git a/frontend/common/PlutoConnection.js b/frontend/common/PlutoConnection.js index 9a60f8ba41..b4c336a04d 100644 --- a/frontend/common/PlutoConnection.js +++ b/frontend/common/PlutoConnection.js @@ -409,7 +409,7 @@ export const create_pluto_connection = async ({ // Ping faster than timeout? setTimeout(ping, 28 * 1000) }) - .catch() + .catch(() => undefined) } ping() diff --git a/frontend/components/CellInput.js b/frontend/components/CellInput.js index b1d63f08b8..e3a57c6421 100644 --- a/frontend/components/CellInput.js +++ b/frontend/components/CellInput.js @@ -64,6 +64,7 @@ import { commentKeymap } from "./CellInput/comment_mixed_parsers.js" import { ScopeStateField } from "./CellInput/scopestate_statefield.js" import { mod_d_command } from "./CellInput/mod_d_command.js" import { open_bottom_right_panel } from "./BottomRightPanel.js" +import { timeout_promise } from "../common/PlutoConnection.js" export const ENABLE_CM_MIXED_PARSER = window.localStorage.getItem("ENABLE_CM_MIXED_PARSER") === "true" @@ -383,6 +384,9 @@ export const CellInput = ({ set_error(null) throw to_throw } + const notebook_id_ref = useRef(notebook_id) + notebook_id_ref.current = notebook_id + const newcm_ref = useRef(/** @type {EditorView?} */ (null)) const dom_node_ref = useRef(/** @type {HTMLElement?} */ (null)) const remote_code_ref = useRef(/** @type {string?} */ (null)) @@ -596,7 +600,7 @@ export const CellInput = ({ // TODO Use https://codemirror.net/6/docs/ref/#state.Prec when added to pluto-codemirror-setup prevent_holding_a_key_from_doing_things_across_cells, - pkgBubblePlugin({ pluto_actions, notebook_id }), + pkgBubblePlugin({ pluto_actions, notebook_id_ref }), ScopeStateField, syntaxHighlighting(pluto_syntax_colors), syntaxHighlighting(pluto_syntax_colors_html), @@ -641,8 +645,8 @@ export const CellInput = ({ }, }), pluto_paste_plugin({ - pluto_actions: pluto_actions, - cell_id: cell_id, + pluto_actions, + cell_id, }), // Update live docs when in a cell that starts with `?` EditorView.updateListener.of((update) => { @@ -671,7 +675,13 @@ export const CellInput = ({ go_to_definition_plugin, pluto_autocomplete({ request_autocomplete: async ({ text }) => { - let { message } = await pluto_actions.send("complete", { query: text }, { notebook_id: notebook_id }) + let response = await timeout_promise( + pluto_actions.send("complete", { query: text }, { notebook_id: notebook_id_ref.current }), + 5000 + ).catch(console.warn) + if (!response) return null + + let { message } = response return { start: utf8index_to_ut16index(text, message.start), stop: utf8index_to_ut16index(text, message.stop), diff --git a/frontend/components/CellInput/pkg_bubble_plugin.js b/frontend/components/CellInput/pkg_bubble_plugin.js index 57699013ce..05d66455bc 100644 --- a/frontend/components/CellInput/pkg_bubble_plugin.js +++ b/frontend/components/CellInput/pkg_bubble_plugin.js @@ -247,11 +247,11 @@ export const NotebookpackagesFacet = Facet.define({ compare: _.isEqual, }) -export const pkgBubblePlugin = ({ pluto_actions, notebook_id }) => +export const pkgBubblePlugin = ({ pluto_actions, notebook_id_ref }) => ViewPlugin.fromClass( class { update_decos(view) { - const ds = pkg_decorations(view, { pluto_actions, notebook_id, nbpkg: view.state.facet(NotebookpackagesFacet) }) + const ds = pkg_decorations(view, { pluto_actions, notebook_id: notebook_id_ref.current, nbpkg: view.state.facet(NotebookpackagesFacet) }) this.decorations = ds } diff --git a/frontend/components/CellInput/pluto_autocomplete.js b/frontend/components/CellInput/pluto_autocomplete.js index a7b3828c53..2130d6a484 100644 --- a/frontend/components/CellInput/pluto_autocomplete.js +++ b/frontend/components/CellInput/pluto_autocomplete.js @@ -161,7 +161,10 @@ function match_string_complete(ctx) { /** Use the completion results from the Julia server to create CM completion objects, but only for path completions (TODO: broken) and latex completions. */ let julia_special_completions_to_cm = (/** @type {PlutoRequestAutocomplete} */ request_autocomplete) => async (ctx) => { let to_complete = ctx.state.sliceDoc(0, ctx.pos) - let { start, stop, results } = await request_autocomplete({ text: to_complete }) + + let found = await request_autocomplete({ text: to_complete }) + if (!found) return null + let { start, stop, results } = found let should_apply_unicode_completion = !match_string_complete(ctx) @@ -216,7 +219,9 @@ const julia_code_completions_to_cm = (/** @type {PlutoRequestAutocomplete} */ re to_complete = to_complete.slice(0, is_symbol_completion.from + 1) + to_complete.slice(is_symbol_completion.from + 2) } - let { start, stop, results } = await request_autocomplete({ text: to_complete }) + let found = await request_autocomplete({ text: to_complete }) + if (!found) return null + let { start, stop, results } = found if (is_symbol_completion) { // If this is a symbol completion thing, we need to add the `:` back in by moving the end a bit furher @@ -345,7 +350,7 @@ const local_variables_completion = (ctx) => { * @type {{ start: number, stop: number, results: Array<[string, (string | null), boolean, boolean, (string | null), (string | null)]> }} * * @typedef PlutoRequestAutocomplete - * @type {(options: { text: string }) => Promise} + * @type {(options: { text: string }) => Promise} */ /** @@ -365,12 +370,13 @@ export let pluto_autocomplete = ({ request_autocomplete, on_update_doc_query }) **/ let memoize_last_request_autocomplete = async (options) => { if (_.isEqual(options, last_query)) { - return await last_result - } else { - last_query = options - last_result = request_autocomplete(options) - return await last_result + let result = await last_result + if (result != null) return result } + + last_query = options + last_result = request_autocomplete(options) + return await last_result } return [