All files / src/cm6 completion-source.ts

100% Statements 47/47
100% Branches 16/16
75% Functions 3/4
100% Lines 47/47

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 661x 1x                 1x 100x 11x 11x 11x   11x   11x   11x 11x 11x   11x 11x 11x 100x     171x   171x   171x 171x 171x 171x 171x 171x   171x 171x 171x   171x 171x 171x 32x 171x 78x 171x 5x 171x 3x 171x 3x 171x 4x 171x 4x 171x 42x 171x 171x  
import { type CompletionSource, type CompletionContext } from '@codemirror/autocomplete';
import { SpelCompletionEngine, type CompletionItem, type ContextSchema } from '@agentix-e/spel-ts';
 
/**
 * Adapter: spel-ts CompletionEngine → CM6 CompletionSource.
 *
 * Maps SpelCompletionEngine items to CM6 Completion objects at the cursor position.
 * When a ContextSchema provider is registered, context-aware completions
 * (variables, properties, methods, beans, types) are included.
 */
export function spelCompletion(getContextSchema?: () => ContextSchema | null): CompletionSource {
  return (context: CompletionContext) => {
    const expression = context.state.sliceDoc();
    const position = context.pos;
    const schema = getContextSchema?.() ?? undefined;
 
    const items = SpelCompletionEngine.getCompletions(expression, position, schema);
 
    const validFor = /\w*/;
 
    return {
      from: context.matchBefore(validFor)?.from ?? position,
      options: items.map((item) => mapToCM6Completion(item)),
      // Allow completions at any position
      validFor: () => true,
    };
  };
}
 
/** Map spel-ts CompletionItem to CM6 Completion */
function mapToCM6Completion(item: CompletionItem) {
  // Map CompletionKind to CM6 type
  const type = mapKindToCM6Type(item.kind);
 
  return {
    label: item.label,
    type,
    detail: item.detail,
    info: item.documentation,
    apply: item.insertText,
    // Higher priority items appear first
    boost: item.sortPriority / 100,
  };
}
 
function mapKindToCM6Type(kind: string): string {
  switch (kind) {
    case 'keyword':
      return 'keyword';
    case 'operator':
      return 'operator';
    case 'variable':
      return 'variable';
    case 'property':
      return 'property';
    case 'method':
      return 'method';
    case 'function':
      return 'function';
    case 'type':
      return 'type';
    default:
      return 'text';
  }
}