Skip to content
tactile

Context & when expressions

Every rule can carry a when expression — a boolean gate evaluated against a context-key store. The same keystroke can do different things in different contexts, without ad-hoc flags.

kb.context.set('scope', 'editor');
kb.context.set('readOnly', false);
kb.add({
id: 'editor.bold',
keys: 'mod+b',
when: "scope == 'editor' && !readOnly",
handler: toggleBold,
});

When you press ⌘B, the engine evaluates when against the current context and only fires if it’s true.

Modeled on VS Code’s when clauses:

Feature Example
Truthiness editorFocus
Equality scope == 'editor', mode != 'insert'
Boolean a && b, a || b, !a
Grouping a && (b || c)
Membership lang in 'ts js tsx'

Identifiers may contain dots (editor.langId) to match how hosts namespace context keys.

There’s no separate “scope” concept to learn. A named scope is a context key:

kb.context.set('scope', 'editor'); // when: "scope == 'editor'"
kb.context.set('scope.terminal', true); // when: "scope.terminal"

In React, useScope gives you setScope, enableScope, and friends as a thin convenience over exactly this.

kb.context.set('scope', 'editor');
kb.context.set('readOnly', false);
kb.add({ id: 'bold', keys: 'mod+b', when: "scope == 'editor' && !readOnly", handler: bold });
kb.add({ id: 'save', keys: 'mod+s', when: "scope == 'editor' && !readOnly", handler: save });
kb.context.set('modalOpen', true);
kb.add({ id: 'palette', keys: 'mod+k', when: '!modalOpen', handler: palette });
kb.add({ id: 'modal.close', keys: 'escape', when: 'modalOpen', handler: closeModal });
kb.context.set('editor.langId', 'typescript');
kb.add({
id: 'rename',
keys: 'f2',
when: "editor.langId == 'typescript'",
handler: rename,
});
kb.context.set('mode', 'insert');
kb.add({
id: 'normal-mode',
keys: 'escape',
when: "mode in 'insert replace'",
handler: () => kb.context.set('mode', 'normal'),
});
  • useScope — the React convenience layer over context keys
  • Collision detection — what happens when two gated rules overlap
  • Recipes — palettes and modals built on when-gating