1
0
Fork 0
mirror of synced 2024-07-06 15:00:49 +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. // Match decoration for HBS bindings
const bindStyle = new MatchDecorator({ const hbsMatchDeco = new MatchDecorator({
regexp: FIND_ANY_HBS_REGEX, regexp: FIND_ANY_HBS_REGEX,
decoration: () => { decoration: () => {
return Decoration.mark({ return Decoration.mark({
@ -95,12 +95,35 @@
}) })
}, },
}) })
const hbsMatchDecoPlugin = ViewPlugin.define(
let plugin = ViewPlugin.define(
view => ({ view => ({
decorations: bindStyle.createDeco(view), decorations: hbsMatchDeco.createDeco(view),
update(u) { 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 = () => { const buildBaseExtensions = () => {
return [ return [
...(mode.name === "handlebars" ? [plugin] : []),
drawSelection(), drawSelection(),
dropCursor(), dropCursor(),
bracketMatching(), bracketMatching(),
@ -165,7 +187,10 @@
override: [...completions], override: [...completions],
closeOnBlur: true, closeOnBlur: true,
icons: false, icons: false,
optionClass: () => "autocomplete-option", optionClass: completion =>
completion.simple
? "autocomplete-option-simple"
: "autocomplete-option",
}) })
) )
complete.push( complete.push(
@ -191,18 +216,23 @@
view.dispatch(tr) view.dispatch(tr)
return true return true
} }
return false return false
}) })
) )
} }
// JS only plugins
if (mode.name === "javascript") { if (mode.name === "javascript") {
complete.push(snippetMatchDecoPlugin)
complete.push(javascript()) complete.push(javascript())
if (!readonly) { if (!readonly) {
complete.push(highlightWhitespace()) complete.push(highlightWhitespace())
} }
} }
// HBS only plugins
else {
complete.push(hbsMatchDecoPlugin)
}
if (placeholder) { if (placeholder) {
complete.push(placeholderFn(placeholder)) complete.push(placeholderFn(placeholder))
@ -376,9 +406,12 @@
font-style: italic; font-style: italic;
} }
/* Highlight bindings */ /* Highlight bindings and snippets */
.code-editor :global(.binding-wrap) { .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 */ /* Completion popover */
@ -407,7 +440,8 @@
} }
/* Completion item container */ /* 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: var(--spacing-s) var(--spacing-m) !important;
padding-left: calc(16px + 2 * var(--spacing-m)) !important; padding-left: calc(16px + 2 * var(--spacing-m)) !important;
display: flex; display: flex;
@ -415,9 +449,13 @@
align-items: center; align-items: center;
color: var(--spectrum-alias-text-color); color: var(--spectrum-alias-text-color);
} }
.code-editor :global(.autocomplete-option-simple) {
padding-left: var(--spacing-s) !important;
}
/* Highlighted completion item */ /* 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); background: var(--spectrum-global-color-blue-400);
color: white; color: white;
} }
@ -433,6 +471,9 @@
font-family: var(--font-sans); font-family: var(--font-sans);
text-transform: capitalize; text-transform: capitalize;
} }
.code-editor :global(.autocomplete-option-simple .cm-completionLabel) {
text-transform: none;
}
/* Completion item type */ /* Completion item type */
.code-editor :global(.autocomplete-option .cm-completionDetail) { .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) => { const bindingFilter = (options, query) => {
return options.filter(completion => { return options.filter(completion => {
const section_parsed = completion.section.name.toLowerCase() 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) => { export const bindingsToCompletions = (bindings, mode) => {
const bindingByCategory = groupBy(bindings, "category") const bindingByCategory = groupBy(bindings, "category")
const categoryMeta = bindings?.reduce((acc, ele) => { const categoryMeta = bindings?.reduce((acc, ele) => {

View file

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