Skip to content

"Ctrl+Esc" never matches "Ctrl+Escape" (nor Up/UpArrow, Return/Enter, Del/Delete, 1/D1): only modifier aliases are canonicalized #162

Description

@matt-edmondson

What's wrong

Note canonicalizes modifier aliases only (Keybinding/Models/MusicalTypes.cs:67-72, CanonicalizeKey):

"CONTROL" => "CTRL",
"WIN" or "WINDOWS" or "CMD" or "COMMAND" => "META",
_ => key

Every other key is stored exactly as typed, only uppercased, and chord equality compares those stored names. So the same physical key can be written several ways that never match each other.

Nothing in the library defines the canonical spelling either. Keybinding/Models/SpecialKeys.cs declares a public SpecialKeys enum (Escape, ArrowUp, PageUp, F1, ...), but no code references it.

Failure scenario

  • A user config binds "Ctrl+Esc", which is stored as notes {CTRL, ESC}.
  • The host builds chords from System.ConsoleKey via ToString(), so Escape becomes "Escape" and the chord is {CTRL, ESCAPE}.
  • ExecuteChord(Chord.Parse("Ctrl+Escape")) returns null. The binding shows in GetAllChords() but never fires, and nothing reports the mismatch.

Other spellings of the same key miss in the same way:

  • Up / ArrowUp (the SpecialKeys name) / UpArrow (the ConsoleKey name)
  • Return / Enter
  • Del / Delete
  • PgUp / PageUp
  • Ins / Insert
  • Ctrl+1 versus ConsoleKey's D1
  • the modifiers Option / Alt and Super / Meta

Why it matters

#107 fixed exactly this kind of silent mismatch for modifiers. Non-modifier keys are where hosts, config files and users disagree most, and the library gives them no canonical name to converge on.

Suggested fix / acceptance criteria

  • Extend CanonicalizeKey with an alias table that maps each key to one canonical name. At minimum:
    • Esc/Escape, Return/Enter, Del/Delete, Ins/Insert, PgUp/PageUp, PgDn/PageDown
    • Up/UpArrow/ArrowUp and the other arrow keys
    • D0–D9 → 0–9
    • Option → ALT, Super → META
  • Base the canonical names on SpecialKeys, or remove that enum if it is not meant to be public API.
  • Optionally, add Note.FromConsoleKey(ConsoleKey) / Chord.FromConsoleKeyInfo(ConsoleKeyInfo) so hosts get canonical chords without writing their own mapping.
  • Tests:
    • Chord.Parse("Ctrl+Esc") == Chord.Parse("Ctrl+Escape")
    • Chord.Parse("Up") == Chord.Parse("UpArrow")
    • A stored profile that uses an alias still matches after it is loaded.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions