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.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
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