Replies: 2 comments 4 replies
-
I don't see a way to implement this using textmate snippet syntax, but instead of it you could use a custom completer that would inspect editor content and return completions you want. |
Beta Was this translation helpful? Give feedback.
-
I didn't realize when I first started this implementation that snippets and autocompletion are basically mutually exclusive. You either insert a snippet or do the logic that @nightwing suggested to perform autocompletion. With that cleared up I set out to rewrite our completion utilizing both techniques. Again this is dependent on our own backend APIs which return the getCompletions = function (editor, session, pos, prefix, callback) {
var line = session.getLine(pos.row)
var lineBefore = line.slice(0, pos.column)
var parsedLine = lineBefore.trimStart().split(/ (?![^<]*>)/)
var suggestions = this.autocompleteData
// If we have more than 1 we've selected a keyword
if (parsedLine.length > 1) {
suggestions = suggestions.find((x) => x.caption === parsedLine[0])
}
var result = {}
var more = true
// If we found suggestions and the suggestions have params
// then we do logic to substitue suggestions using the actual
// target, packet, item data
if (suggestions && suggestions['params']) {
// Check if this is the last autocomplete parameter
if (suggestions['params'].length == parsedLine.length - 1) {
more = false
}
// parsedLine.length - 2 because the last element is blank
// e.g. ['LABELVALUE', 'INST', '']
var current = suggestions['params'][parsedLine.length - 2]
// Check for Target name, Packet name, and Item name and use
// the tpiData to substitute actual values for suggestions
if (current['Target name']) {
suggestions = this.tpiData
} else if (current['Packet name']) {
suggestions = this.tpiData[parsedLine[1]]
} else if (current['Item name']) {
suggestions = this.tpiData[parsedLine[1]][parsedLine[2]]
} else {
// Not a special case so just use the param as is
suggestions = current
}
result = Object.keys(suggestions || {}).map((x) => {
var completions = {
value: x + (more ? ' ' : ''),
// We want the autoComplete to continue right up
// to the last parameter
command: more && 'startAutocomplete',
}
// Only add the meta (description) if we have a string
// This prevents adding (Object) descriptions
if (typeof suggestions[x] === 'string') {
completions['meta'] = suggestions[x]
}
return completions
})
} else {
// The snippet case where we just inject the snippet
result = suggestions
}
callback(null, result)
} Here's some sample data that will work with the above: // Test data useful for testing ScreenCompleter
var tpiData = {
INST: {
HEALTH_STATUS: {
TEMP1: 'temp1 description',
TEMP2: 1,
TEMP3: 1,
TEMP4: 1,
},
MECH: {
SLPNL1: 1,
SLPNL2: 1,
},
},
SYSTEM: {
PKT: {
ITEM: 1,
},
},
}
// Test data useful for testing ScreenCompleter
var autocompleteData = [
{
caption: 'HORIZONTAL',
meta: 'Places the widgets it encapsulates horizontally',
snippet: 'HORIZONTAL ${1:<Margin>}',
},
{
caption: 'LABELVALUE',
meta: 'Displays a LABEL with the item name followed by a VALUE',
value: 'LABELVALUE ',
command: 'startAutocomplete',
params: [
{ 'Target name': 1 },
{ 'Packet name': 1 },
{ 'Item name': 1 },
{ RAW: 1, CONVERTED: 1, FORMATTED: 1, WITH_UNITS: 1 },
{ '<Number of characters>': 'description' },
],
},
] |
Beta Was this translation helpful? Give feedback.
-
I'm using a custom autocomplete which is populated by the following API and used by our editor.
I figured out how to create a selection of options in the completer with the following syntax:
I have a setup where I want a second item that depends on the first. For example if you select 'ONE' for the first you should see '|A,B|' but if you select 'TWO' then '|C,D|', and 'THREE' is '|E,F|'. Obviously just examples but the gist is that the second parameter is dependent on the first. Is this possible?
Beta Was this translation helpful? Give feedback.
All reactions