1
0
Fork 0
mirror of synced 2024-07-04 05:50:57 +12:00

Add code mirror completions for snippets

This commit is contained in:
Andrew Kingston 2024-03-11 21:10:53 +00:00
parent cef0911950
commit 79ae159329
3 changed files with 94 additions and 13 deletions

View file

@ -83,8 +83,8 @@
})
}
// For handlebars only.
const bindStyle = new MatchDecorator({
// Match decoration for HBS bindings
const hbsMatchDeco = new MatchDecorator({
regexp: FIND_ANY_HBS_REGEX,
decoration: () => {
return Decoration.mark({
@ -95,12 +95,35 @@
})
},
})
let plugin = ViewPlugin.define(
const hbsMatchDecoPlugin = ViewPlugin.define(
view => ({
decorations: bindStyle.createDeco(view),
decorations: hbsMatchDeco.createDeco(view),
update(u) {
this.decorations = bindStyle.updateDeco(u, this.decorations)
this.decorations = hbsMatchDeco.updateDeco(u, this.decorations)
},
}),
{
decorations: v => v.decorations,
}
)
// Match decoration for snippets
const snippetMatchDeco = new MatchDecorator({
regexp: /snippets.[^\s(]+/g,
decoration: () => {
return Decoration.mark({
tag: "span",
attributes: {
class: "snippet-wrap",
},
})
},
})
const snippetMatchDecoPlugin = ViewPlugin.define(
view => ({
decorations: snippetMatchDeco.createDeco(view),
update(u) {
this.decorations = snippetMatchDeco.updateDeco(u, this.decorations)
},
}),
{
@ -142,7 +165,6 @@
const buildBaseExtensions = () => {
return [
...(mode.name === "handlebars" ? [plugin] : []),
drawSelection(),
dropCursor(),
bracketMatching(),
@ -165,7 +187,10 @@
override: [...completions],
closeOnBlur: true,
icons: false,
optionClass: () => "autocomplete-option",
optionClass: completion =>
completion.simple
? "autocomplete-option-simple"
: "autocomplete-option",
})
)
complete.push(
@ -191,18 +216,23 @@
view.dispatch(tr)
return true
}
return false
})
)
}
// JS only plugins
if (mode.name === "javascript") {
complete.push(snippetMatchDecoPlugin)
complete.push(javascript())
if (!readonly) {
complete.push(highlightWhitespace())
}
}
// HBS only plugins
else {
complete.push(hbsMatchDecoPlugin)
}
if (placeholder) {
complete.push(placeholderFn(placeholder))
@ -376,9 +406,12 @@
font-style: italic;
}
/* Highlight bindings */
/* Highlight bindings and snippets */
.code-editor :global(.binding-wrap) {
color: var(--spectrum-global-color-blue-700);
color: var(--spectrum-global-color-blue-700) !important;
}
.code-editor :global(.snippet-wrap *) {
color: #61afef !important;
}
/* Completion popover */
@ -407,7 +440,8 @@
}
/* Completion item container */
.code-editor :global(.autocomplete-option) {
.code-editor :global(.autocomplete-option),
.code-editor :global(.autocomplete-option-simple) {
padding: var(--spacing-s) var(--spacing-m) !important;
padding-left: calc(16px + 2 * var(--spacing-m)) !important;
display: flex;
@ -415,9 +449,13 @@
align-items: center;
color: var(--spectrum-alias-text-color);
}
.code-editor :global(.autocomplete-option-simple) {
padding-left: var(--spacing-s) !important;
}
/* Highlighted completion item */
.code-editor :global(.autocomplete-option[aria-selected]) {
.code-editor :global(.autocomplete-option[aria-selected]),
.code-editor :global(.autocomplete-option-simple[aria-selected]) {
background: var(--spectrum-global-color-blue-400);
color: white;
}
@ -433,6 +471,9 @@
font-family: var(--font-sans);
text-transform: capitalize;
}
.code-editor :global(.autocomplete-option-simple .cm-completionLabel) {
text-transform: none;
}
/* Completion item type */
.code-editor :global(.autocomplete-option .cm-completionDetail) {

View file

@ -102,6 +102,29 @@ export const getHelperCompletions = mode => {
}, [])
}
export const snippetAutoComplete = snippets => {
return function myCompletions(context) {
if (!snippets?.length) {
return null
}
const word = context.matchBefore(/\w*/)
if (word.from == word.to && !context.explicit) {
return null
}
return {
from: word.from,
options: snippets.map(snippet => ({
label: `snippets.${snippet.name}`,
type: "text",
simple: true,
apply: (view, completion, from, to) => {
insertSnippet(view, from, to, completion.label)
},
})),
}
}
}
const bindingFilter = (options, query) => {
return options.filter(completion => {
const section_parsed = completion.section.name.toLowerCase()
@ -247,6 +270,21 @@ export const insertBinding = (view, from, to, text, mode) => {
})
}
export const insertSnippet = (view, from, to, text, mode) => {
const parsedInsert = `${text}()`
let cursorPos = from + parsedInsert.length - 1
view.dispatch({
changes: {
from,
to,
insert: parsedInsert,
},
selection: {
anchor: cursorPos,
},
})
}
export const bindingsToCompletions = (bindings, mode) => {
const bindingByCategory = groupBy(bindings, "category")
const categoryMeta = bindings?.reduce((acc, ele) => {

View file

@ -19,6 +19,7 @@
getHelperCompletions,
jsAutocomplete,
hbAutocomplete,
snippetAutoComplete,
EditorModes,
bindingsToCompletions,
} from "../CodeEditor"
@ -98,6 +99,7 @@
...bindingCompletions,
...getHelperCompletions(EditorModes.JS),
]),
snippetAutoComplete(snippets),
]
const getModeOptions = (allowHBS, allowJS) => {