Skip to content

Commit

Permalink
Allow autocomplete in strings and comments with <TAB> (#2892)
Browse files Browse the repository at this point in the history
Co-authored-by: Michiel Dral <[email protected]>
  • Loading branch information
fonsp and dralletje authored Apr 11, 2024
1 parent 27c4234 commit 61478b1
Showing 1 changed file with 18 additions and 14 deletions.
32 changes: 18 additions & 14 deletions frontend/components/CellInput/pluto_autocomplete.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { open_bottom_right_panel } from "../BottomRightPanel.js"
import { ENABLE_CM_AUTOCOMPLETE_ON_TYPE } from "../CellInput.js"
import { GlobalDefinitionsFacet } from "./go_to_definition_plugin.js"

let { autocompletion, completionKeymap, completionStatus, acceptCompletion } = autocomplete
let { autocompletion, completionKeymap, completionStatus, acceptCompletion, selectedCompletion } = autocomplete

// These should be imported from @codemirror/autocomplete, but they are not exported.
const completionState = autocompletion()[1]
Expand Down Expand Up @@ -101,8 +101,11 @@ const pluto_autocomplete_keymap = [
*/
let update_docs_from_autocomplete_selection = (on_update_doc_query) => {
return EditorView.updateListener.of((update) => {
// Can't use this yet as it has not enough info to apply the change (source.from and source.to)
// let selected_completion = autocomplete.selectedCompletion(update.state)
// But we can use `selectedCompletion` to better check if the autocomplete is open
// (for some reason `autocompletion_state?.open != null` isn't enough anymore?)
// Sadly we still need `update.state.field(completionState, false)` as well because we can't
// apply the result from `selectedCompletion()` yet (has no .from and .to, for example)
if (selectedCompletion(update.state) == null) return

let autocompletion_state = update.state.field(completionState, false)
let open_autocomplete = autocompletion_state?.open
Expand All @@ -123,6 +126,10 @@ let update_docs_from_autocomplete_selection = (on_update_doc_query) => {
// Apply completion to state, which will yield us a `Transaction`.
// The nice thing about this is that we can use the resulting state from the transaction,
// without updating the actual state of the editor.
// NOTE This could bite someone who isn't familiar with this, but there isn't an easy way to fix it without a lot of console spam:
// .... THIS UPDATE WILL DO CONSOLE.LOG'S LIKE ANY UPDATE WOULD DO
// .... Which means you sometimes get double logs from codemirror extensions...
// .... Very disorienting 😵‍💫
let result_transaction = update.state.update({
changes: {
from,
Expand Down Expand Up @@ -183,9 +190,9 @@ const validFor = (text) => {
/** Use the completion results from the Julia server to create CM completion objects. */
const julia_code_completions_to_cm =
(/** @type {PlutoRequestAutocomplete} */ request_autocomplete) => async (/** @type {autocomplete.CompletionContext} */ ctx) => {
if (writing_variable_name_or_keyword(ctx)) return null
if (match_special_symbol_complete(ctx)) return null
if (ctx.tokenBefore(["Number", "Comment", "String", "TripleString"]) != null) return null
if (!ctx.explicit && writing_variable_name_or_keyword(ctx)) return null
if (!ctx.explicit && ctx.tokenBefore(["Number", "Comment", "String", "TripleString"]) != null) return null

let to_complete = /** @type {String} */ (ctx.state.sliceDoc(0, ctx.pos))

Expand All @@ -196,9 +203,6 @@ const julia_code_completions_to_cm =
to_complete = to_complete.slice(0, is_symbol_completion.from + 1) + to_complete.slice(is_symbol_completion.from + 2)
}

// no path autocompletions
if (ctx.tokenBefore(["String"]) != null) return null

const globals = ctx.state.facet(GlobalDefinitionsFacet)
const is_already_a_global = (text) => text != null && Object.keys(globals).includes(text)

Expand Down Expand Up @@ -284,9 +288,9 @@ const julia_code_completions_to_cm =
}

const complete_anyword = async (/** @type {autocomplete.CompletionContext} */ ctx) => {
if (writing_variable_name_or_keyword(ctx)) return null
if (match_special_symbol_complete(ctx)) return null
if (ctx.tokenBefore(["Number", "Comment", "String", "TripleString"]) != null) return null
if (!ctx.explicit && writing_variable_name_or_keyword(ctx)) return null
if (!ctx.explicit && ctx.tokenBefore(["Number", "Comment", "String", "TripleString"]) != null) return null

const results_from_cm = await autocomplete.completeAnyWord(ctx)
if (results_from_cm === null) return null
Expand Down Expand Up @@ -328,9 +332,9 @@ const writing_variable_name_or_keyword = (/** @type {autocomplete.CompletionCont

/** @returns {Promise<autocomplete.CompletionResult?>} */
const global_variables_completion = async (/** @type {autocomplete.CompletionContext} */ ctx) => {
if (writing_variable_name_or_keyword(ctx)) return null
if (match_special_symbol_complete(ctx)) return null
if (ctx.tokenBefore(["Number", "Comment", "String", "TripleString"]) != null) return null
if (!ctx.explicit && writing_variable_name_or_keyword(ctx)) return null
if (!ctx.explicit && ctx.tokenBefore(["Number", "Comment", "String", "TripleString"]) != null) return null

const globals = ctx.state.facet(GlobalDefinitionsFacet)

Expand Down Expand Up @@ -417,9 +421,9 @@ const special_symbols_completion = (/** @type {() => Promise<SpecialSymbols?>} *
}

return async (/** @type {autocomplete.CompletionContext} */ ctx) => {
if (writing_variable_name_or_keyword(ctx)) return null
if (!match_special_symbol_complete(ctx)) return null
if (ctx.tokenBefore(["Number", "Comment"]) != null) return null
if (!ctx.explicit && writing_variable_name_or_keyword(ctx)) return null
if (!ctx.explicit && ctx.tokenBefore(["Number", "Comment"]) != null) return null

const result = await get_special_symbols()

Expand Down

0 comments on commit 61478b1

Please sign in to comment.