Header menu logo issie

KeyTypes Module

The one place every keyboard shortcut in Issie is described. This module is deliberately pure: no Fable.React, no ElectronAPI, no ModelType, no Browser.Dom. It says *what* the shortcuts are, not what they do and not how they are delivered. The binding from an identity to an action lives in UI/KeyBindings.fs, which is the only module that needs the model. Keeping the two apart is what lets the help table, the renderer menus and (later) the context menus all be generated from one list instead of drifting apart, which is what happened to the hand-written table in UIPopups.fs. Platform is always a parameter, never read here, so this module has no dependency on how the host discovers it.

Types and nested modules

Type/Module Description

Mods (Module)

Names

The named keys the table is allowed to use. A closed set, so a typo is a compile error rather than a shortcut that silently never fires.

Category

Chord

KeyContext

Where the keyboard is logically pointing. Exactly one holds at any moment, and KeyBindings.contextOfModel decides which by a fixed priority. TextEntry and CodeEditor are *opaque*: a chord not bound in them does nothing rather than falling back to a more general context. That single rule is what stops Ctrl+A in a properties box selecting the whole schematic.

KeyName

A key identity, normalised away from the browser's raw strings. Raw `ev.key` cannot be used directly: on macOS Option mangles it, so Cmd+Option+A arrives as "å". Raw `ev.code` cannot be used either, since it is physical and so wrong on non-QWERTY layouts. KeyBindings.keyNameOf resolves an event into one of these using `ev.key` where it is meaningful and falling back to `ev.code` where it is not.

Mods (Type)

Modifier state, normalised so one table serves both platforms. Primary is the "command" modifier: Ctrl on Windows and Linux, Cmd on macOS. That is the one almost every shortcut wants, and normalising it here is what removes the isMac conditionals that used to be written out by hand at every binding site. Secondary is whichever of the two is left over. It exists for exactly one shortcut - macOS full screen is Cmd+Ctrl+F - and should stay that rare.

ShortcutId

Every shortcut identity in Issie. Adding a case here is a compile error until KeyBindings.actionOf binds it, which is the point: there is no way to describe a shortcut and forget to implement it. Several identities share a chord and are told apart only by context - Escape is four different actions.

ShortcutSpec

Trigger

Functions and values

Function or value Description

chordLabel isMac chord

Full Usage: chordLabel isMac chord

Parameters:
    isMac : bool
    chord : Chord

Returns: string

Compact form for a menu label, e.g. "Ctrl+Right" or "Cmd+Opt+Right".

isMac : bool
chord : Chord
Returns: string

chordParts isMac chord

Full Usage: chordParts isMac chord

Parameters:
    isMac : bool
    chord : Chord

Returns: string list

The parts of a chord, in the order they should be shown. Returned as a list so that the existing help-table renderer in UIPopups can join them with its own separator unchanged.

isMac : bool
chord : Chord
Returns: string list

chordsFor isMac spec

Full Usage: chordsFor isMac spec

Parameters:
Returns: Chord list

Chords for one platform.

isMac : bool
spec : ShortcutSpec
Returns: Chord list

idLabel isMac id

Full Usage: idLabel isMac id

Parameters:
Returns: string

The label to show beside a menu item, or "" when the shortcut has no chord on this platform.

isMac : bool
id : ShortcutId
Returns: string

lookup tbl ctx chord

Full Usage: lookup tbl ctx chord

Parameters:
Returns: ShortcutSpec option

Resolve a chord in a context. There is deliberately no fallback to a more general context. A chord that means nothing in TextEntry must reach the focused box rather than doing something to the schematic, and the same argument applies to every other context - so every shortcut states all the contexts it works in.

tbl : Map<(KeyContext * Chord), ShortcutSpec>
ctx : KeyContext
chord : Chord
Returns: ShortcutSpec option

shortcuts

Full Usage: shortcuts

Returns: ShortcutSpec list

Every shortcut in Issie. The single source of truth for the dispatcher, the help table and the shortcut labels shown on menus. Chords are unchanged from the Electron menus they replace, so nothing has to be relearned. They are safe to keep because context does the separating: Ctrl+Left rotates on the canvas and still does word-navigation inside a text box, since rotate is simply not bound in TextEntry.

Returns: ShortcutSpec list

table isMac

Full Usage: table isMac

Parameters:
    isMac : bool

Returns: Map<(KeyContext * Chord), ShortcutSpec>

(context, chord) -> spec, for one platform. Built once per platform by the caller.

isMac : bool
Returns: Map<(KeyContext * Chord), ShortcutSpec>

validate ()

Full Usage: validate ()

Parameters:
    () : unit

Returns: string list

Problems with the table, as human-readable strings. Empty means the table is sound. Called at startup in debug builds: a shortcut that can never fire because another one shadows it is invisible at runtime and very hard to notice by hand.

() : unit
Returns: string list

Type something to start searching.