or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

bracket-closing.mdcompletion-sources.mdconfiguration.mdindex.mdsnippets.mdview-commands.md
tile.json

snippets.mddocs/

Snippets

Template-based completions with field navigation, supporting placeholders, default values, and tab-stop functionality for creating interactive code templates.

Capabilities

Snippet Templates

Functions for creating and managing snippet-based completions with field navigation.

/**
 * Convert a snippet template to a function that can apply it
 */
function snippet(template: string): (editor: {state: EditorState, dispatch: (tr: Transaction) => void}, completion: Completion | null, from: number, to: number) => void;

/**
 * Create a completion from a snippet template
 */
function snippetCompletion(template: string, completion: Completion): Completion;

Template Syntax:

Snippets use ${} or #{} placeholders for fields:

  • ${} or #{name} - Named field with optional default content
  • ${1} or ${1:default} - Numbered field with optional default
  • \\{ or \\} - Literal braces (escaped)

Usage Examples:

import { snippet, snippetCompletion } from "@codemirror/autocomplete";

// Simple snippet templates
const forLoopSnippet = snippet("for (let ${index} = 0; ${index} < ${end}; ${index}++) {\n\t${}\n}");

const functionSnippet = snippet("function ${name}(${params}) {\n\t${body}\n\treturn ${return};\n}");

// Numbered fields for specific order
const ifElseSnippet = snippet("if (${1:condition}) {\n\t${2}\n} else {\n\t${3}\n}");

// Snippet completions
const snippetCompletions = [
  snippetCompletion("for (let ${i} = 0; ${i} < ${length}; ${i}++) {\n\t${}\n}", {
    label: "for",
    detail: "for loop",
    type: "snippet"
  }),
  
  snippetCompletion("console.log(${message});", {
    label: "log",
    detail: "console.log statement", 
    type: "snippet"
  }),
  
  snippetCompletion("try {\n\t${}\n} catch (${error}) {\n\t${}\n}", {
    label: "try",
    detail: "try-catch block",
    type: "snippet"
  })
];

Field Navigation

Commands and utilities for navigating between snippet fields.

/**
 * Move to the next snippet field
 */
const nextSnippetField: StateCommand;

/**
 * Move to the previous snippet field  
 */
const prevSnippetField: StateCommand;

/**
 * Clear the active snippet
 */
const clearSnippet: StateCommand;

/**
 * Check if there is a next field available
 */
function hasNextSnippetField(state: EditorState): boolean;

/**
 * Check if there is a previous field available
 */
function hasPrevSnippetField(state: EditorState): boolean;

Usage Examples:

import { nextSnippetField, prevSnippetField, clearSnippet, hasNextSnippetField } from "@codemirror/autocomplete";

// Check field availability and navigate
const handleTabKey = (view: EditorView) => {
  if (hasNextSnippetField(view.state)) {
    return nextSnippetField(view);
  }
  // Handle normal tab behavior
  return false;
};

// Custom snippet navigation
const customSnippetCommands = [
  {
    key: "Tab",
    run: nextSnippetField
  },
  {
    key: "Shift-Tab", 
    run: prevSnippetField
  },
  {
    key: "Escape",
    run: clearSnippet
  }
];

Snippet Keymap

Configurable key bindings for snippet field navigation.

/**
 * Facet for configuring snippet key bindings
 */
const snippetKeymap: Facet<readonly KeyBinding[], readonly KeyBinding[]>;

Default Bindings:

  • Tab - Move to next field (nextSnippetField)
  • Shift-Tab - Move to previous field (prevSnippetField)
  • Escape - Clear snippet (clearSnippet)

Usage Examples:

import { snippetKeymap } from "@codemirror/autocomplete";
import { keymap } from "@codemirror/view";

// Custom snippet key bindings
const customSnippetKeys = [
  { key: "Tab", run: nextSnippetField },
  { key: "Shift-Tab", run: prevSnippetField },
  { key: "Ctrl-Escape", run: clearSnippet }
];

const view = new EditorView({
  extensions: [
    // Override default snippet keymap
    snippetKeymap.of(customSnippetKeys),
    keymap.of(customSnippetKeys)
  ]
});

Advanced Snippet Patterns

Complex snippet templates with multiple fields, default values, and nested structures.

Usage Examples:

// Class definition with multiple fields
const classSnippet = snippetCompletion(`class \${1:ClassName} {
  constructor(\${2:params}) {
    \${3:// constructor body}
  }
  
  \${4:methodName}(\${5:params}) {
    \${6:// method body}
    return \${7:result};
  }
}`, {
  label: "class",
  detail: "class definition",
  type: "snippet"
});

// React component snippet
const reactComponentSnippet = snippetCompletion(`import React from 'react';

interface \${1:ComponentName}Props {
  \${2:prop}: \${3:string};
}

const \${1:ComponentName}: React.FC<\${1:ComponentName}Props> = ({ \${2:prop} }) => {
  return (
    <div>
      \${4:// component content}
    </div>
  );
};

export default \${1:ComponentName};`, {
  label: "rfc", 
  detail: "React functional component",
  type: "snippet"
});

// Function with JSDoc
const jsdocFunctionSnippet = snippetCompletion(`/**
 * \${1:Description}
 * @param {\${2:type}} \${3:param} \${4:Parameter description}
 * @returns {\${5:type}} \${6:Return description}
 */
function \${7:functionName}(\${3:param}) {
  \${8:// function body}
  return \${9:result};
}`, {
  label: "jsfunc",
  detail: "function with JSDoc",
  type: "snippet"
});

Snippet Integration

Integrating snippets with completion sources and language support.

Usage Examples:

import { autocompletion, snippetCompletion, completeFromList } from "@codemirror/autocomplete";

// Combine snippets with other completions
const jsCompletions = [
  // Regular completions
  ...["const", "let", "var", "function", "class"].map(kw => ({ label: kw, type: "keyword" })),
  
  // Snippet completions
  snippetCompletion("const ${name} = ${value};", {
    label: "const",
    detail: "const declaration",
    type: "snippet"
  }),
  
  snippetCompletion("function ${name}(${params}) {\n\t${}\n}", {
    label: "func",
    detail: "function declaration", 
    type: "snippet"
  })
];

// Language-specific snippet source
const jsSnippetSource = completeFromList(jsCompletions);

const view = new EditorView({
  extensions: [
    autocompletion({
      override: [jsSnippetSource]
    })
  ]
});

Dynamic Snippet Generation

Creating snippets programmatically based on context.

Usage Examples:

import { CompletionContext } from "@codemirror/autocomplete";

// Context-aware snippet generation
const dynamicSnippetSource = (context: CompletionContext) => {
  const token = context.matchBefore(/\w+$/);
  if (!token) return null;
  
  const snippets = [];
  
  // Generate different snippets based on context
  if (token.text.startsWith("for")) {
    snippets.push(
      snippetCompletion("for (let ${i} = 0; ${i} < ${arr}.length; ${i}++) {\n\t${}\n}", {
        label: "fori",
        detail: "for loop with index",
        type: "snippet"
      }),
      snippetCompletion("for (const ${item} of ${arr}) {\n\t${}\n}", {
        label: "forof", 
        detail: "for-of loop",
        type: "snippet"
      })
    );
  }
  
  if (token.text.startsWith("if")) {
    snippets.push(
      snippetCompletion("if (${condition}) {\n\t${}\n}", {
        label: "if",
        detail: "if statement",
        type: "snippet"
      })
    );
  }
  
  return snippets.length ? {
    from: token.from,
    options: snippets
  } : null;
};