Add code mirror completions for snippets
This commit is contained in:
parent
cef0911950
commit
79ae159329
|
@ -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) {
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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) => {
|
||||
|
|
Loading…
Reference in New Issue