Files
Automata/packages/editor-ui/src/components/CodeNodeEditor/completions/base.completions.ts

158 lines
4.7 KiB
TypeScript

import { defineComponent } from 'vue';
import { NODE_TYPES_EXCLUDED_FROM_AUTOCOMPLETION } from '../constants';
import { addVarType } from '../utils';
import type { Completion, CompletionContext, CompletionResult } from '@codemirror/autocomplete';
import type { INodeUi } from '@/Interface';
import { mapStores } from 'pinia';
import { useWorkflowsStore } from '@/stores/workflows.store';
import { escapeMappingString } from '@/utils/mappingUtils';
function getAutoCompletableNodeNames(nodes: INodeUi[]) {
return nodes
.filter((node: INodeUi) => !NODE_TYPES_EXCLUDED_FROM_AUTOCOMPLETION.includes(node.type))
.map((node: INodeUi) => node.name);
}
export const baseCompletions = defineComponent({
computed: {
...mapStores(useWorkflowsStore),
},
methods: {
itemCompletions(context: CompletionContext): CompletionResult | null {
const preCursor = context.matchBefore(/i\w*/);
if (!preCursor || (preCursor.from === preCursor.to && !context.explicit)) return null;
const options: Completion[] = [];
if (this.mode === 'runOnceForEachItem') {
options.push({
label: 'item',
info: this.$locale.baseText('codeNodeEditor.completer.$input.item'),
});
} else if (this.mode === 'runOnceForAllItems') {
options.push({
label: 'items',
info: this.$locale.baseText('codeNodeEditor.completer.$input.all'),
});
}
return {
from: preCursor.from,
options,
};
},
/**
* - Complete `$` to `$execution $input $prevNode $runIndex $workflow $now $today
* $jmespath $ifEmpt $('nodeName')` in both modes.
* - Complete `$` to `$json $binary $itemIndex` in single-item mode.
*/
baseCompletions(context: CompletionContext): CompletionResult | null {
const prefix = this.language === 'python' ? '_' : '$';
const preCursor = context.matchBefore(new RegExp(`\\${prefix}\\w*`));
if (!preCursor || (preCursor.from === preCursor.to && !context.explicit)) return null;
const TOP_LEVEL_COMPLETIONS_IN_BOTH_MODES: Completion[] = [
{
label: `${prefix}execution`,
info: this.$locale.baseText('codeNodeEditor.completer.$execution'),
},
{
label: `${prefix}ifEmpty()`,
info: this.$locale.baseText('codeNodeEditor.completer.$ifEmpty'),
},
{ label: `${prefix}input`, info: this.$locale.baseText('codeNodeEditor.completer.$input') },
{
label: `${prefix}prevNode`,
info: this.$locale.baseText('codeNodeEditor.completer.$prevNode'),
},
{
label: `${prefix}workflow`,
info: this.$locale.baseText('codeNodeEditor.completer.$workflow'),
},
{
label: `${prefix}vars`,
info: this.$locale.baseText('codeNodeEditor.completer.$vars'),
},
{
label: `${prefix}now`,
info: this.$locale.baseText('codeNodeEditor.completer.$now'),
},
{
label: `${prefix}today`,
info: this.$locale.baseText('codeNodeEditor.completer.$today'),
},
{
label: `${prefix}jmespath()`,
info: this.$locale.baseText('codeNodeEditor.completer.$jmespath'),
},
{
label: `${prefix}runIndex`,
info: this.$locale.baseText('codeNodeEditor.completer.$runIndex'),
},
];
const options: Completion[] = TOP_LEVEL_COMPLETIONS_IN_BOTH_MODES.map(addVarType);
options.push(
...getAutoCompletableNodeNames(this.workflowsStore.allNodes).map((nodeName) => {
return {
label: `${prefix}('${escapeMappingString(nodeName)}')`,
type: 'variable',
info: this.$locale.baseText('codeNodeEditor.completer.$()', {
interpolate: { nodeName },
}),
};
}),
);
if (this.mode === 'runOnceForEachItem') {
const TOP_LEVEL_COMPLETIONS_IN_SINGLE_ITEM_MODE = [
{ label: `${prefix}json` },
{ label: `${prefix}binary` },
{
label: `${prefix}itemIndex`,
info: this.$locale.baseText('codeNodeEditor.completer.$itemIndex'),
},
];
options.push(...TOP_LEVEL_COMPLETIONS_IN_SINGLE_ITEM_MODE.map(addVarType));
}
return {
from: preCursor.from,
options,
};
},
/**
* Complete `$(` to `$('nodeName')`.
*/
nodeSelectorCompletions(context: CompletionContext): CompletionResult | null {
const prefix = this.language === 'python' ? '_' : '$';
const preCursor = context.matchBefore(new RegExp(`\\${prefix}\\(.*`));
if (!preCursor || (preCursor.from === preCursor.to && !context.explicit)) return null;
const options: Completion[] = getAutoCompletableNodeNames(this.workflowsStore.allNodes).map(
(nodeName) => {
return {
label: `${prefix}('${escapeMappingString(nodeName)}')`,
type: 'variable',
info: this.$locale.baseText('codeNodeEditor.completer.$()', {
interpolate: { nodeName },
}),
};
},
);
return {
from: preCursor.from,
options,
};
},
},
});