Skip to content

Quickstart ​

This page registers one command and dispatches it from two surfaces in a web page: a button and a key chord.

Register a command ​

ts
import { OK, Registry, ok } from '@ufo-soft/caelus'
import { keybindings } from '@ufo-soft/caelus/keybindings'

let count = 0
const registry = new Registry()

registry.register({
  name: 'increment',
  command: { description: 'Add one', parameters: [] },
  handler: () => ok(++count),
})

A registration has three parts. The name is how every surface calls the command. The command describes it: a description and its parameters, here none. The handler does the work and returns an outcome: ok with data, or failed with a reason.

Dispatch it from two surfaces ​

ts
// A button per command, built from the registry
for (const { name, command } of registry.all()) {
  const button = document.createElement('button')
  button.textContent = name
  button.title = command.description
  button.onclick = () => registry.invoke(name, {})
  document.body.append(button)
}

// A key chord for the same command
keybindings(registry, { 'alt+up': 'increment' }).attach()

The buttons come from registry.all(), so every registered command gets one with no per-command code. The keymap maps the chord alt+up to the command's name. Both call registry.invoke with the name and the args.

Read the outcome ​

ts
const outcome = await registry.invoke('increment', {})
if (outcome.kind === OK) console.log(outcome.data)
txt
1

invoke always returns a promise of an outcome. Check kind before reading data: a failed outcome has a reason instead.

Next ​