Skip to content

Commit

Permalink
Upgrade codemirror with new parser (#2980)
Browse files Browse the repository at this point in the history
Co-authored-by: Sergio A. Vargas <[email protected]>
  • Loading branch information
fonsp and savq authored Jan 17, 2025
1 parent c1baaac commit b64cdc7
Show file tree
Hide file tree
Showing 18 changed files with 3,610 additions and 5,088 deletions.
12 changes: 6 additions & 6 deletions frontend/components/CellInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ import {
} from "../imports/CodemirrorPlutoSetup.js"

import { markdown, html as htmlLang, javascript, sqlLang, python, julia_mixed } from "./CellInput/mixedParsers.js"
import { julia_andrey } from "../imports/CodemirrorPlutoSetup.js"
import { julia } from "../imports/CodemirrorPlutoSetup.js"
import { pluto_autocomplete } from "./CellInput/pluto_autocomplete.js"
import { NotebookpackagesFacet, pkgBubblePlugin } from "./CellInput/pkg_bubble_plugin.js"
import { awesome_line_wrapping, get_start_tabs } from "./CellInput/awesome_line_wrapping.js"
Expand Down Expand Up @@ -119,7 +119,7 @@ const common_style_tags = [

export const pluto_syntax_colors_julia = HighlightStyle.define(common_style_tags, {
all: { color: `var(--cm-color-editor-text)` },
scope: julia_andrey().language,
scope: julia().language,
})

export const pluto_syntax_colors_javascript = HighlightStyle.define(common_style_tags, {
Expand Down Expand Up @@ -365,12 +365,12 @@ export const CellInput = ({
return true
}

const anySelect = cm.state.selection.ranges.some(r => !r.empty)
const anySelect = cm.state.selection.ranges.some((r) => !r.empty)
if (anySelect) {
return indentMore(cm)
} else {
cm.dispatch(
cm.state.changeByRange(selection => ({
cm.dispatch(
cm.state.changeByRange((selection) => ({
range: EditorSelection.cursor(selection.from + 1),
changes: { from: selection.from, to: selection.to, insert: "\t" },
}))
Expand Down Expand Up @@ -661,7 +661,7 @@ export const CellInput = ({
]
: [
//
julia_andrey(),
julia(),
]),
go_to_definition_plugin,
pluto_autocomplete({
Expand Down
21 changes: 11 additions & 10 deletions frontend/components/CellInput/LiveDocsFromCursor.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { EditorState, syntaxTree } from "../../imports/CodemirrorPlutoSetup.js"
import { ScopeStateField } from "./scopestate_statefield.js"

let get_root_variable_from_expression = (cursor) => {
if (cursor.name === "SubscriptExpression") {
if (cursor.name === "IndexExpression") {
cursor.firstChild()
return get_root_variable_from_expression(cursor)
}
Expand All @@ -20,12 +20,13 @@ let get_root_variable_from_expression = (cursor) => {
let VALID_DOCS_TYPES = [
"Identifier",
"FieldExpression",
"SubscriptExpression",
"IndexExpression",
"MacroFieldExpression",
"MacroIdentifier",
"Operator",
"Definition",
"ParameterizedIdentifier",
"TypeHead",
"Signature",
"ParametrizedExpression",
]
let keywords_that_have_docs_and_are_cool = [
"import",
Expand All @@ -49,12 +50,12 @@ let is_docs_searchable = (/** @type {import("../../imports/CodemirrorPlutoSetup.
} else if (VALID_DOCS_TYPES.includes(cursor.name)) {
if (cursor.firstChild()) {
do {
// Numbers themselves can't be docs searched, but using numbers inside SubscriptExpression can be.
if (cursor.name === "Number") {
// Numbers themselves can't be docs searched, but using numbers inside IndexExpression can be.
if (cursor.name === "IntegerLiteral" || cursor.name === "FloatLiteral") {
continue
}
// This is for the VERY specific case like `Vector{Int}(1,2,3,4) which I want to yield `Vector{Int}`
if (cursor.name === "TypeArgumentList") {
if (cursor.name === "BraceExpression") {
continue
}
if (cursor.name === "FieldName" || cursor.name === "MacroName" || cursor.name === "MacroFieldName") {
Expand Down Expand Up @@ -129,7 +130,7 @@ export let get_selected_doc_from_state = (/** @type {EditorState} */ state, verb
// - Struct name is useless: you are looking at the definition
// - Properties are just named, not in the workspace or anything
// Only thing we do want, are types and the right hand side of `=`'s.
if (parents.includes("AssignmentExpression") && parents.indexOf("AssignmentExpression") < index_of_struct_in_parents) {
if (parents.includes("binding") && parents.indexOf("binding") < index_of_struct_in_parents) {
// We're inside a `... = ...` inside the struct
} else if (parents.includes("TypedExpression") && parents.indexOf("TypedExpression") < index_of_struct_in_parents) {
// We're inside a `x::X` inside the struct
Expand Down Expand Up @@ -229,7 +230,7 @@ export let get_selected_doc_from_state = (/** @type {EditorState} */ state, verb
}

// `a = 1` would yield `=`, `a += 1` would yield `+=`
if (cursor.name === "AssignmentExpression") {
if (cursor.name === "binding") {
let end_of_first = cursor.node.firstChild.to
let beginning_of_last = cursor.node.lastChild.from
return state.doc.sliceString(end_of_first, beginning_of_last).trim()
Expand Down Expand Up @@ -320,7 +321,7 @@ export let get_selected_doc_from_state = (/** @type {EditorState} */ state, verb
return undefined
}
// If we are expanding to an AssigmentExpression, we DONT want to show `=`
if (parent.name === "AssignmentExpression") {
if (parent.name === "binding") {
return undefined
}
} finally {
Expand Down
31 changes: 23 additions & 8 deletions frontend/components/CellInput/block_matcher_plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ function match_try_node(node) {
finally_node && { from: finally_node.from, to: finally_node.to },
{ from: possibly_end.from, to: possibly_end.to },
].filter((x) => x != null)

}

function match_block(node) {
Expand Down Expand Up @@ -207,11 +206,7 @@ function match_block(node) {
return decorations
}

if (node.name === "try"
|| node.name === "catch"
|| node.name === "finally"
|| node.name === "else") {

if (node.name === "try" || node.name === "catch" || node.name === "finally" || node.name === "else") {
if (node.name === "catch") node = node.parent
if (node.name === "finally") node = node.parent
if (node.name === "else") node = node.parent
Expand Down Expand Up @@ -299,8 +294,9 @@ export function matchBrackets(state, pos, dir, config = {}) {
node = tree.resolveInner(pos, dir)

let result = match_block(node)
return result || matchPlainBrackets(state, pos, dir, tree, node.type, maxScanDistance, brackets)
return result || matchPlainBrackets(state, pos, dir, tree, bracket_node_name_normalizer(node.name), maxScanDistance, brackets)
}

function matchPlainBrackets(state, pos, dir, tree, tokenType, maxScanDistance, brackets) {
let startCh = dir < 0 ? state.sliceDoc(pos - 1, pos) : state.sliceDoc(pos, pos + 1)
let bracket = brackets.indexOf(startCh)
Expand All @@ -314,7 +310,7 @@ function matchPlainBrackets(state, pos, dir, tree, tokenType, maxScanDistance, b
let basePos = pos + distance * dir
for (let pos = dir > 0 ? 0 : text.length - 1, end = dir > 0 ? text.length : -1; pos != end; pos += dir) {
let found = brackets.indexOf(text[pos])
if (found < 0 || tree.resolve(basePos + pos, 1).type != tokenType) continue
if (found < 0 || bracket_node_name_normalizer(tree.resolve(basePos + pos, 1).name) != tokenType) continue
if ((found % 2 == 0) == dir > 0) {
depth++
} else if (depth == 1) {
Expand All @@ -332,3 +328,22 @@ function matchPlainBrackets(state, pos, dir, tree, tokenType, maxScanDistance, b
}
return iter.done ? [startToken] : null
}

/**
* Little modification to the original matchPlainBrackets function: in our Julia language, the node that opens a bracket is called "(". In e.g. markdown it's called LinkMark or something (the same name for opening and closing). We don't have this so we make them equal.
*/
const bracket_node_name_normalizer = (/** @type {String} */ node_name) => {
switch (node_name) {
case "(":
case ")":
return "()"
case "[":
case "]":
return "[]"
case "{":
case "}":
return "{}"
default:
return node_name
}
}
4 changes: 2 additions & 2 deletions frontend/components/CellInput/debug_syntax_plugin.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { EditorView, syntaxTree, syntaxTreeAvailable } from "../../imports/CodemirrorPlutoSetup.js"
import { EditorView, syntaxTree, syntaxTreeAvailable, Text } from "../../imports/CodemirrorPlutoSetup.js"
import { iterate_with_cursor } from "./lezer_template.js"

/**
* @param {any} doc
* @param {Text} doc
* @param {ReturnType<typeof syntaxTree>} tree
*/
let find_error_nodes = (doc, tree) => {
Expand Down
Loading

0 comments on commit b64cdc7

Please sign in to comment.