Skip to content

DSL Editor API

createDslCodeMirror() provides a standalone Boukamp DSL text field with syntax highlighting, debounced lint, and contextual completions (element icons, p( branches, {param} templates).

Use it beside the canvas editor, in sidebars, or in framework apps without mounting the full createEditor() UI.

createDslCodeMirror

ts
import { createDslCodeMirror } from 'velo-circuit'
import { parseBoukamp } from 'velo-circuit'

let ast: ReturnType<typeof parseBoukamp> | null = null

const handle = createDslCodeMirror({
  parent: document.getElementById('dsl-panel')!,
  initialValue: 'R0{10}-p(R1{100},C1{1e-5})',
  getAst: () => (ast && 'type' in ast && ast.type !== 'lex' ? ast : null),
  themeMode: 'dark',
  onChange: (dsl) => {
    ast = parseBoukamp(dsl)
    syncCanvas(dsl)
  },
  onDiagnostics: (issues) => showIssues(issues),
})

handle.setValue('R0-C1')
handle.destroy()

Options

OptionTypeDescription
parentHTMLElementMount target
initialValuestringStarting DSL
getAst() => CircuitNode | nullAST for contextual lint/completions
onChange(value: string) => voidCalled on edit
onDiagnostics(Diagnostic[]) => voidDebounced validation (~250ms)
readOnlybooleanDisable editing
placeholderstringEmpty-state hint
themeDslCodeMirrorThemePer-field color overrides (optional)
themeMode'light' | 'dark'Autocomplete tooltips and symbol icons

Handle

MethodDescription
getValue() / setValue(text)Read/write DSL
focus() / hasFocus()Focus management
setReadOnly(bool)Toggle read-only
destroy()Tear down CodeMirror
ts
import { clearElementSymbolIconCache } from 'velo-circuit'
// Call after theme switch if completion icons look stale
clearElementSymbolIconCache()

Theme rule (important)

The DSL editor does not ship a fixed palette. Colors follow the active application theme.

ContextBehavior
Inside extended editor (dslCodemirrorPanelPlugin)Reads ce-dark on editor container; maps getTheme(mode) to CodeMirror colors; remounts on theme-changed
StandaloneYou must pass themeMode synchronized with your app/editor theme

Correct: sync with app theme

ts
function mountDsl(parent: HTMLElement, isDark: boolean) {
  return createDslCodeMirror({
    parent,
    initialValue: 'R0',
    getAst: () => null,
    themeMode: isDark ? 'dark' : 'light',
    onChange: () => {},
  })
}

// When user toggles theme:
handle.destroy()
handle = mountDsl(parent, newIsDark)

Or update themeMode by recreating the handle when the parent gains/loses ce-dark (same pattern as the built-in plugin).

Anti-pattern: hard-coded dark DSL while app is light

ts
// Avoid — completions and editor surface won't match your UI
createDslCodeMirror({ themeMode: 'dark', /* app is light */ ... })

Optional theme overrides individual fields (bg, text, border, accent, …). Prefer CSS variables from the editor (var(--ce-bg), etc.) when embedding next to themePlugin.

Features

FeatureBehavior
LintDebounced; validate with mode: 'editor' skips heavy topology while typing
Ctrl+SpaceContextual completions at cursor
After -Full element list R…HN with schematic icons
After p( or ,Element list for parallel branches
Tab after element idInserts {param} template