Dispatch editor shortcuts through ktsu.Keybinding.Core [patch] - #210
Merged
Merged
Conversation
The editor wrote each chord down twice: once as an if/else if chain over
ImGui's key state, and again as a literal string beside the menu item it
fires ("Ctrl+Shift+S" and friends). Nothing tied the two together, so a
chord could be rebound in one place and go on being advertised as the
other.
EditorShortcuts now holds the seven bindings once. The menu labels are
rendered from the same binding the dispatcher matches, so the two cannot
drift apart. The matching is ktsu.Keybinding.Core's, which Schema.Editor
already referenced and did not use, so this takes on no new dependency.
Chord.ToString spells a chord exactly as the menu used to hard-code it,
so the menu reads as it did before.
Nothing is persisted: KeybindingService is built over an in-memory
CommandRegistry and ProfileManager, so no repository is involved and the
editor neither reads nor writes a keybinding file.
One behaviour changes deliberately. The old chain tested the modifiers
each arm cared about and ignored the rest, so Ctrl+Shift+N started a new
document just as Ctrl+N did, and Ctrl+Alt+O opened one. A chord now has
to match exactly, so those no longer fire. The chords that were always
meant to be distinguished - Ctrl+S against Ctrl+Shift+S, Ctrl+Z against
Ctrl+Shift+Z - still are, and no longer depend on the order the arms
happen to be written in.
Covered by EditorShortcutTests, which needs no frame: it pins the label
against the chord that fires the command, both ways round. The existing
frame-driven ShortcutTests are unchanged and still pass, which is what
says ImGui's real key state still reaches the table.
Fixes #201
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JjErQAuuWQwrRBqqHTkgzZ
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Fixes #201
What this changes
Schema.Editorwrote each chord down twice — once as anif/else ifchain over ImGui's key state inProcessKeyboardShortcuts, and again as a literal string beside the menu item it fires ("Ctrl+Shift+S"and friends). Nothing tied the two together, so a chord could be rebound in one place and go on being advertised as the other. That drift is the bug this prevents.EditorShortcutsnow holds the seven bindings once:The menu labels are rendered from the same binding the dispatcher matches (
Shortcuts.Label(EditorShortcuts.SaveAs)in place of"Ctrl+Shift+S"), so the two cannot disagree.Why ktsu.Keybinding.Core costs nothing here
ktsu.Keybinding.Corewas already aPackageReferenceofSchema.Editorand went entirely unused, so this adopts a dependency that is already paid for rather than taking one on.I measured the library's behaviour against what the editor needs before writing anything:
Chord.Parse/ToStringround-trip exactly on all seven chords —Ctrl+N,Ctrl+O,Ctrl+S,Ctrl+Shift+S,Ctrl+Z,Ctrl+Shift+Z,Ctrl+Yall come back as the identical string. So the menu reads exactly as it did; there is no visible change to the UI.Ctrl+Shift+S==Shift+Ctrl+S) but correctly separatesCtrl+ZfromCtrl+Shift+Z.FindCommandByChordresolves each chord to the right command, including the two shared-key pairs the old chain had to be ordered carefully to get right.Nothing is persisted.
KeybindingServiceis built over an in-memoryCommandRegistryandProfileManager— both have parameterless constructors — so noIKeybindingRepositoryis involved and the editor neither reads nor writes a keybinding file. That also means this is independent ofktsu-dev/Keybinding#93, which the triage note flagged as worth watching: since nothing here persists, a change to Keybinding's persistence shape cannot reach this code.One deliberate behaviour change
The old chain tested the modifiers each arm cared about and ignored the rest:
so Ctrl+Shift+N started a new document just as Ctrl+N did, and Ctrl+Alt+O opened one. A chord now has to match exactly, so those no longer fire. Neither is a chord the editor advertises. The chords that were always meant to be distinguished — Ctrl+S against Ctrl+Shift+S, Ctrl+Z against Ctrl+Shift+Z — still are, and no longer depend on the order the
else ifarms happen to be written in.This is pinned explicitly by
AnExtraModifierIsNotTheSameChordrather than left to be discovered.Testing
New:
Schema.Editor.Test/EditorShortcutTests.cs— 8 frameless tests.EditorShortcuts.FindCommandtakes the pressed key as a name rather than anImGuiKeyprecisely so the table can be exercised without a rasterizer. The load-bearing pair isMenuLabelIsTheChordThatFiresTheCommandandTheChordOnTheLabelSelectsThatCommand, which check the join in both directions.Proved the tests fail without the fix. Rebinding Save As from
Ctrl+Shift+StoCtrl+Alt+S— exactly the drift the old code could not catch — fails two tests:Restored, both pass.
Regression: the existing frame-driven
tests/Schema.Editor.UITests/ShortcutTestsis unchanged and still passes — that suite presses the chords into a live frame, so it is what says ImGui's real key state still reaches the table.Schema.Editor.TestSchema.Editor.UITestsThe three
app-launch-failederrors in a full-solution run are this container missing the .NET 8 and 9 runtimes for the multi-targeted suites' other legs. They reproduce identically on cleanmain, and both projects this PR touches arenet10.0-only.🤖 Generated with Claude Code
https://claude.ai/code/session_01JjErQAuuWQwrRBqqHTkgzZ
Generated by Claude Code