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

view-commands.mddocs/

View Commands

Programmatic control over completion state, selection, and lifecycle for building custom completion interfaces and integrating with editor interactions.

Capabilities

Completion Control Commands

Commands for starting, stopping, and managing the completion interface.

/**
 * Explicitly start autocompletion
 */
const startCompletion: Command;

/**
 * Close the currently active completion
 */
const closeCompletion: Command;

/**
 * Accept the current completion selection
 */
const acceptCompletion: Command;

Usage Examples:

import { startCompletion, closeCompletion, acceptCompletion } from "@codemirror/autocomplete";
import { EditorView } from "@codemirror/view";

// Manual completion trigger
const triggerCompletion = (view: EditorView) => {
  return startCompletion(view);
};

// Close completion programmatically
const hideCompletion = (view: EditorView) => {
  return closeCompletion(view);
};

// Accept current selection
const confirmCompletion = (view: EditorView) => {
  return acceptCompletion(view);
};

// Custom completion controls
const customCompletionKeys = [
  { key: "Ctrl-Space", run: startCompletion },
  { key: "Escape", run: closeCompletion },
  { key: "Tab", run: acceptCompletion }
];

Selection Navigation

Commands for navigating through completion options programmatically.

/**
 * Move completion selection forward or backward
 */
function moveCompletionSelection(forward: boolean, by?: "option" | "page"): Command;

Usage Examples:

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

// Navigation commands
const nextOption = moveCompletionSelection(true);
const prevOption = moveCompletionSelection(false);
const nextPage = moveCompletionSelection(true, "page");
const prevPage = moveCompletionSelection(false, "page");

// Custom navigation keymap
const navigationKeys = [
  { key: "ArrowDown", run: nextOption },
  { key: "ArrowUp", run: prevOption },
  { key: "PageDown", run: nextPage },
  { key: "PageUp", run: prevPage }
];

// Smart navigation with fallback
const smartNavigation = (view: EditorView, forward: boolean) => {
  // Try completion navigation first
  if (moveCompletionSelection(forward)(view)) {
    return true;
  }
  
  // Fall back to normal cursor movement
  return false;
};

Completion State Queries

Functions to inspect the current completion state for conditional logic.

Usage Examples:

import { 
  completionStatus, 
  currentCompletions, 
  selectedCompletion, 
  selectedCompletionIndex 
} from "@codemirror/autocomplete";

// Check completion state
const handleKeyPress = (view: EditorView, event: KeyboardEvent) => {
  const status = completionStatus(view.state);
  
  if (status === "active") {
    const selected = selectedCompletion(view.state);
    const index = selectedCompletionIndex(view.state);
    const all = currentCompletions(view.state);
    
    console.log(`Selected: ${selected?.label} (${index}/${all.length})`);
    
    // Custom handling for active completion
    if (event.key === "Tab" && selected) {
      return acceptCompletion(view);
    }
  } else if (status === "pending") {
    // Completion is loading
    console.log("Completion in progress...");
  } else {
    // No active completion
    if (event.key === " " && event.ctrlKey) {
      return startCompletion(view);
    }
  }
  
  return false;
};

Custom Completion Interfaces

Building custom completion UIs using the programmatic API.

Usage Examples:

import { 
  startCompletion, 
  currentCompletions, 
  selectedCompletionIndex,
  setSelectedCompletion,
  acceptCompletion 
} from "@codemirror/autocomplete";

// Custom completion widget
class CustomCompletionWidget {
  private view: EditorView;
  private element: HTMLElement;
  
  constructor(view: EditorView) {
    this.view = view;
    this.element = this.createWidget();
  }
  
  createWidget(): HTMLElement {
    const widget = document.createElement("div");
    widget.className = "custom-completion-widget";
    
    // Update widget when state changes
    this.view.dom.addEventListener("update", () => {
      this.updateWidget();
    });
    
    return widget;
  }
  
  updateWidget() {
    const completions = currentCompletions(this.view.state);
    const selectedIndex = selectedCompletionIndex(this.view.state);
    
    this.element.innerHTML = "";
    
    completions.forEach((completion, index) => {
      const item = document.createElement("div");
      item.className = "completion-item";
      item.textContent = completion.label;
      
      if (index === selectedIndex) {
        item.classList.add("selected");
      }
      
      item.addEventListener("click", () => {
        // Set selection and accept
        this.view.dispatch({
          effects: setSelectedCompletion(index)
        });
        acceptCompletion(this.view);
      });
      
      this.element.appendChild(item);
    });
  }
  
  show() {
    document.body.appendChild(this.element);
    startCompletion(this.view);
  }
  
  hide() {
    if (this.element.parentNode) {
      this.element.parentNode.removeChild(this.element);
    }
    closeCompletion(this.view);
  }
}

// Usage
const customWidget = new CustomCompletionWidget(view);
customWidget.show();

Integration with Editor Events

Handling completion in response to editor events and user interactions.

Usage Examples:

import { ViewPlugin, ViewUpdate } from "@codemirror/view";
import { completionStatus, startCompletion } from "@codemirror/autocomplete";

// Auto-completion on specific patterns
const autoCompletionPlugin = ViewPlugin.fromClass(class {
  constructor(private view: EditorView) {}
  
  update(update: ViewUpdate) {
    if (!update.docChanged) return;
    
    // Check for completion triggers
    const changes = update.changes;
    changes.iterChanges((fromA, toA, fromB, toB, inserted) => {
      const text = inserted.toString();
      
      // Trigger completion on dot notation
      if (text === "." && completionStatus(this.view.state) !== "active") {
        setTimeout(() => startCompletion(this.view), 0);
      }
      
      // Trigger completion after import statements
      if (text.includes("import") && text.includes("from")) {
        setTimeout(() => startCompletion(this.view), 100);
      }
    });
  }
});

// Completion with custom timing
const timedCompletionPlugin = ViewPlugin.fromClass(class {
  private timeout: number | null = null;
  
  constructor(private view: EditorView) {}
  
  update(update: ViewUpdate) {
    if (update.docChanged) {
      // Clear existing timeout
      if (this.timeout) {
        clearTimeout(this.timeout);
      }
      
      // Set new timeout for completion
      this.timeout = setTimeout(() => {
        const status = completionStatus(this.view.state);
        if (status !== "active" && status !== "pending") {
          startCompletion(this.view);
        }
        this.timeout = null;
      }, 500);
    }
  }
});

Advanced Command Composition

Combining completion commands with other editor operations.

Usage Examples:

// Smart Enter key handling
const smartEnter = (view: EditorView) => {
  const status = completionStatus(view.state);
  
  if (status === "active") {
    const selected = selectedCompletion(view.state);
    if (selected) {
      // Accept completion and add newline
      acceptCompletion(view);
      setTimeout(() => {
        view.dispatch({
          changes: { from: view.state.selection.main.head, insert: "\n" },
          selection: { anchor: view.state.selection.main.head + 1 }
        });
      }, 0);
      return true;
    }
  }
  
  // Normal Enter behavior
  return false;
};

// Completion with auto-formatting
const formatAfterCompletion = (view: EditorView) => {
  const selected = selectedCompletion(view.state);
  
  if (selected && acceptCompletion(view)) {
    // Apply formatting after completion
    setTimeout(() => {
      // Custom formatting logic
      if (selected.type === "function") {
        // Format function calls
        formatFunctionCall(view);
      } else if (selected.type === "class") {
        // Format class instantiation
        formatClassInstantiation(view);
      }
    }, 10);
    
    return true;
  }
  
  return false;
};

// Multi-step completion workflow
const workflowCompletion = async (view: EditorView) => {
  // Step 1: Start completion
  if (!startCompletion(view)) return false;
  
  // Step 2: Wait for completion to be active
  await new Promise(resolve => {
    const checkActive = () => {
      if (completionStatus(view.state) === "active") {
        resolve(undefined);
      } else {
        setTimeout(checkActive, 10);
      }
    };
    checkActive();
  });
  
  // Step 3: Auto-select first function option
  const completions = currentCompletions(view.state);
  const functionIndex = completions.findIndex(c => c.type === "function");
  
  if (functionIndex >= 0) {
    view.dispatch({ effects: setSelectedCompletion(functionIndex) });
  }
  
  return true;
};