10: Make the Keyboard Yours - transcript
Liam: The QUILL Cast, episode ten. I'm Liam. Last episode was the QUILL key, the prefix that multiplies our keyboard into a second keyboard. Today: how to take the whole keyboard and make it yours. The Keymap Editor, keyboard packs, the diagnostics that keep a customized layout healthy, and the honest story of what customization can and can't do for you.
Jessica: I'm Jessica. Recap from episode nine, in one breath: the QUILL key is control shift grave, the tilde, by default. One press arms one command, the next key. Two presses lock Browse Mode until escape. The Keymap Editor we're about to walk through is where every command in QUILL, including everything behind that prefix, is rebindable, unbindable, or assignable from scratch. If the QUILL key is the noun, the Keymap Editor is the verb that moves it.
Liam: And the bigger frame. Across the next forty-four episodes of this fifty-four-episode course, we'll keep pointing you at menus, palette entries, and shortcuts. Most of those shortcuts are defaults we chose, with care, but you can override any of them. So today is partly a tour of the surface, and partly a license: the defaults are a starting point, and the editor exists to make changing them a calm experience, not a stunt.
Jessica: Let's open it. Preferences, then Keyboard, then the Customize Keymap button at the bottom of the dialog, or directly from the Tools menu, Keymap Editor. The dialog title bar says Keymap Editor. It is a search box, a list of every command, an Edit Keybinding button, a Run Diagnostics button, and a Record Keys button. That's the whole surface, and it's plenty.
Liam: The list is long. The default keymap in the source declares roughly two hundred fifty named commands, and the editor appends a separate batch of QUILL Quick Nav single-key actions, the ones that only fire inside Browse Mode, so the editable list is the union of the command registry plus that quick-nav family. Each row shows the command's friendly title, an em dash, and the current binding, or the word Unassigned if the command has no key.
Jessica: The search box is the star, and it really is a search box. Type spell, or vault, or read aloud, and the list filters to commands whose titles or command ids contain that substring. That alone is the standard command-palette experience, brought into a dialog so you can edit, not just run.
Liam: But here's the move that changes the experience: type a key combination. Try control alt M. The list does not show commands with M in the name. It shows the command, or commands, that own control alt M right now, or, if no command owns it, the feedback line says so. The same box does command-name search and key search, and you choose which one by what you type.
Jessica: This is what we mean by reverse lookup. The eternal keyboard question, is this key taken, has an answer in the same search box you already have open. No more guessing, no more trial-and-error into a binding that was already silently claimed by something else, no more paper chart on the wall.
Liam: And the editor is forgiving about how you spell. Control, ctrl, even ctl, all mean the same thing. Modifiers in any order, shift control K equals control shift K. Any case. The parser normalizes what you type into a tidy canonical form before it stores or compares anything, so the answer you see matches the binding the app actually fires.
Jessica: That forgiveness is not just for typing. It is also the engine of conflict detection. A re-ordered or alias spelling, shift control K, control plus shift plus k, SHIFT+CTRL+K, all compare equal to a stored control shift K, and conflict detection works on that canonical form. Under the hood this lives in the core, in a module called keymap query, which is the wx-free brain that makes the keyboard manager tolerant and self-aware. None of that is your problem, but the behavior is.
Liam: A quick platform note, because it matters. On Mac, command is its own physical key and stays distinct from control. They never collapse. wx stores macOS bindings as Cmd plus the key, alongside Windows Ctrl plus the key, and the parser knows that. So a binding typed with the word command, or the abbreviation cmd, resolves to Cmd, and your Windows and Mac layouts can have the same logical shortcut sitting on different physical keys. Cross-platform work is part of the design.
Jessica: Prefer pressing to typing? Choose Record Keys. A small modal opens, the prompt invites you to press the combination you want, and the next key event with a real key, not a bare modifier, is captured. For chords that include the QUILL key, press the sequence: the leader, then the second key. The captured string lands in the search box, the list re-filters, and the reverse lookup answer is right there.
Liam: Under the hood the capture window uses wx's character hook, so a real key event is what counts. A bare modifier press, control alone, shift alone, does nothing, the dialog keeps waiting for the real key. Escape closes without recording. Enter is captured as the Enter key, which is the right thing, because a recorded Enter chord is something some of you will actually want. The cancel button carries both the affirmative and the escape id, so the modal has no keyboard trap.
Jessica: Once you have the right command selected, whether by name search or by reverse lookup, choose Edit Keybinding. A small text-entry dialog appears with the command's current binding pre-filled. Type the new binding, or Record Keys to fill it, confirm, and the editor validates, normalizes, and applies. The list refreshes in place, your cursor stays on the row you were editing, and the change is on disk before the dialog even closes.
Liam: Validation, by the way, is not just spell-check. The parser catches a binding the dispatch layer cannot fire, parses, yes, but inert. If you somehow type a chord the editor accepts but the key handler cannot route, the editor refuses the assignment with a clear error rather than silently saving a key that does nothing. Diagnostics later would catch it, but it is better caught here, at the point of edit.
Jessica: There is a special case worth hearing: QUILL Quick Nav bindings. Those are the single-key actions that only fire inside Browse Mode, H for heading, A for link, L for list, I for list item, T for table, Q for block quote, B for bookmark, apostrophe for code block, C for table of contents, P for paragraph, S for sentence, Tab and bracket characters for block and skip. The editor enforces a rule for those: a Quick Nav binding must be a single key, or Tab, with no modifiers. Try to put control H on a Quick Nav slot and the editor refuses with a one-line message. The rule is there because a modified Quick Nav binding would never fire, the Browse Mode layer looks at the bare key.
Liam: Now the conflict flow, which is the moment most keymap editors betray you. You assign a key that is already taken. QUILL does not silently refuse. It does not silently steal. It names the current owner, by its friendly title, not an internal code, and offers a yes-or-no swap. Yes means move the key here and free the other command. No means cancel, the original owner keeps its binding, the new command stays as it was. One informed step, not a guessing game.
Jessica: If the same key is held by more than one command, the dialog names them all, comma-separated, and says reassign it to the command you are editing, the others become unassigned. Plural is handled cleanly. The friendly-title lookup uses the same command registry the editor's list draws from, so the name you see in the conflict prompt is the same name you searched for. Nothing is more confusing than being told your key conflicts with a string of punctuation.
Liam: Two more properties of the conflict path worth saying out loud. First, a swap frees the other binding, it does not move it elsewhere, so the prior owner is left unassigned. If you want a chord for both, you have to do it in two passes. Second, the new binding is written through the same save path that handles the keymap on disk, atomic write, the same delta-plus-epoch shape, so the swap survives restart without a migration step.
Jessica: And the active prefix matters. The keymap is stored with the QUILL key as a literal chord, control shift grave plus comma plus second key. The parser, the conflict checker, and the display rewriter all use the prefix from your current settings. So if you rebind the QUILL key, the rest of the keymap follows, automatically. The chord stays a chord, only the leader changes.
Liam: Do this now. Pause the audio. Open the editor, search for spell check, select it, choose Edit Keybinding, type something you will not forget, confirm, then close. If you want, search for the original default, F7, and see who, if anyone, still owns it. Come back when you have done that, or when you have decided that today is not the day, and we will keep going.
Jessica: Welcome back. The change is live, the list reflects it, and any conflict that mattered was named in the swap prompt. That whole loop, search, edit, conflict, apply, is the daily experience of the editor. Everything else we cover today is the maintenance and the sharing that makes a customized keymap durable.
Liam: The editor also exposes a button, a third one in the dialog, called Run Diagnostics. Choose it and the same keymap is audited. The audit categorizes every problem it finds into one of four kinds, listed in the report. The categories are: duplicate shortcuts, the same canonical binding held by more than one command, which is a real conflict; invalid bindings, command ids whose stored string cannot be parsed, garbage in the file; unknown commands, bindings pointing at command ids the app no longer ships, typically from a removed or renamed feature; and the one we love most, missing dispatch, bindings the editor accepts but the dispatch layer cannot fire, the assigned-but-inert case.
Jessica: Each category gets a friendly-title line in the report, the same titles you see in the list, with the binding shown in the form the user sees, so a Ctrl+Shift+Grave, S chord is rendered as QUILL Key plus S. The report groups duplicates under their binding and lists every owner. Invalid entries are listed for removal. Unknown commands are listed for removal. Missing-dispatch entries are listed for you to reassign, because only you know what you want that key to do.
Liam: When the report is empty, the editor pops a small all-clear box, every shortcut is unique, readable, and wired up, and the status bar reflects it. The point of a clean bill of health is not the celebration, it is the confidence: you can keep building customizations on a known-good foundation.
Jessica: For everything that is repairable, the report ends with a one-click Heal action. Heal removes the bad entries, the unparseable bindings and the orphaned command ids, and re-applies the keymap so the menus and the accelerator table match what is actually stored on disk. Duplicates and inert keys are not auto-fixed, by design, because fixing them silently could mean choosing the wrong winner. They are listed for you to decide.
Liam: This is an important design choice. Heal is conservative. It only removes things that are guaranteed to be wrong, bindings the app cannot even read, commands that no longer exist. It does not pick a winner in a duplicate fight, because that choice belongs to you, the person who knows which command you meant. The status bar tells you exactly what Heal did, the count of bad entries it removed, and that the keymap was re-applied.
Jessica: And the audit-then-heal pair is fast. Run it after any big customization session, after importing a third-party pack, after an upgrade, the kind of moment when defaults have shifted underneath you. The report and the optional heal are measured in seconds, not minutes, and the time you save is the time you would have spent debugging a chord that mysteriously stopped working.
Liam: Think of Diagnostics as a spell checker for your keyboard. You do not need it every session, you do need it the first time something feels off. The one-minute checkup buys you confidence the rest of the week.
Jessica: Let's talk about keyboard packs. The keymap can be saved to a file, shared, and reloaded. That is more than backup. That is community infrastructure. A teacher builds a pack that matches a curriculum, every student installs the same keymap. A friend of a screen-reader user shares a layout tuned for one-handed operation. A former Emacs user ports their favorite chords. The file format is a small JSON wrapper, and it is named with a clear extension, .kqp, keyboard quill pack.
Liam: The pack format is forward-looking. The file only stores bindings that differ from the default keymap, the delta, plus a version stamp and a few descriptive fields, name, description, author, version. The intent is captured, not a snapshot of defaults that may change in the next release. Importing an older pack against a newer build is therefore safe, the import applies the delta on top of the current defaults, and unchanged defaults follow the current build. That is the same delta logic the on-disk keymap uses for the same reason.
Jessica: The pack validator is the same one the standalone tool uses, so the import path and the command-line validator agree on what counts as valid. A bad pack is rejected with a clear error, the user's existing keymap is never silently overwritten, and the only thing that lands on disk is the merged result. We learned the hard way that destructive imports with no preview are how you ruin a productive afternoon.
Liam: The Settings dialog also has a top-level choice for keyboard pack. There are several shipped packs: Quill Default, the balanced layout, and named packs tuned for writing, for navigation-heavy review work, and faithful re-creations of familiar editors: Windows Notepad, Notepad++, VS Code, Microsoft Word. Picking a pack applies it to your keymap and marks the file with a pack name. As soon as you make a manual edit, the pack name flips to Custom, because the layout is no longer exactly that pack.
Jessica: And Reset to factory defaults is always one command away. The Reset button on the Keyboard page rebuilds the default keymap, saves it, and reloads shortcuts. The whole loop is a round trip: pick a pack, use it, edit a few chords, live with the result, decide it was a bad idea, reset, try a different pack. Each leg of that loop is a single click or a single keystroke, because experimentation only works when the undo is cheap.
Liam: Strategy corner, because power invites overreach. Our honest advice: rebind sparingly and deliberately. The first thing to give a luxury key is the command you run dozens of times a day, the one that already lives in your muscle memory, the one that would benefit from being one notch closer. The second thing is the command that, today, costs you a context switch. The third thing is the command that the screen reader makes awkward in the default layout.
Jessica: The rest, leave on defaults. A keymap that is mostly standard and selectively personal is stronger than a keymap that is entirely yours. Documentation, including this podcast and the in-app control reference, will match a default key by definition. When a colleague says, hit control K, you want to do the same thing they did, not stand there interpreting a private dialect. Strong keymaps are mostly shared and selectively personal.
Liam: And the same logic applies to the QUILL key itself. If your screen reader and your QUILL key collide, move the QUILL key, do not abandon the prefix. The prefix is the namespace that frees the rest of your keyboard for real work. The cost of changing it is one rebinding; the cost of not having it is permanent, every chord that lived there is now a fight with the screen reader.
Jessica: One more piece of honesty. Some commands in QUILL do not have a binding by default. They are in the editor, and they say Unassigned. The reason is not laziness, it is a deliberate choice: those commands are useful, but not common, and giving every one of them a default would dilute the keys that matter. The editor exists for exactly this case. If you find yourself reaching for an unassigned command, bind it to something that fits your hand, and the cost is exactly the time it took to do the rebind.
Liam: Let us also say a few words about what the editor does not do, because the line between feature and overreach matters. The editor does not let you create a brand new key. It rebinds, unbinds, or assigns existing commands. It does not let you macro one chord to fire several commands in sequence; the macro layer, if you need it, lives in the snippets and abbreviations system, which we cover in episode fifteen. And it does not let you create a custom prefix with a totally new grammar; the prefix system is one prefix, the QUILL key, and a single second key, on purpose, because that is the smallest grammar that gets the multiplier effect.
Jessica: A second non-feature: the editor does not ship a per-user visual shortcut cheatsheet for your own customizations. It generates a control reference for the defaults, the same document you can open from the Help menu, but your personal changes live in the editor and the export, not in a pretty sheet. The pragmatic workaround is to record a short voice memo, in your own words, naming the chords you actually use, because that is the format you will remember anyway. Or export your pack, name the file after the date, and keep them in a folder. The pack is the cheatsheet, in JSON form.
Liam: And a third non-feature worth knowing: the editor does not auto-migrate your customizations when QUILL's defaults change. We made a deliberate choice, after some earlier pain, that the on-disk keymap stores only your overrides as a delta on top of the defaults. When the defaults move, your overrides stay where you put them, and any new default for an unassigned command shows up automatically. The downside is that a default you had overridden may now be different from what you remember, and the right response is Run Diagnostics, which will tell you the truth, followed by either Heal, which only fixes the unrecoverable entries, or a manual adjustment, for everything else.
Jessica: A small piece of code-verified honesty. The earlier short version of this episode described the conflict prompt in a particular way, and the description still holds, the dialog names the current owner by its friendly title, not its internal id, and offers a yes-or-no reassign. It also described the editor's reverse lookup as forgiving on case, modifier order, and the control-ctrl-ctl aliases. All of that is in the live keymap query module, in the alias tables, in the order-independent parsing, and in the canonical form that the conflict detector compares against. We are not making this up.
Liam: The same earlier short version said keyboard packs could mimic an editor you came from. That is true, and the catalogue ships a few of them: Windows Notepad, Notepad++, VS Code, Microsoft Word, each a small, named delta over the default keymap. Importing a pack only writes the delta, your real layout survives unchanged, and a malformed pack is rejected with a clear error rather than silently clobbering your settings. The earlier short version also said a pack is a K Q P file, which is the right extension. None of that has drifted.
Jessica: The earlier short version also said the editor searches two directions. That is right. The search box, the same widget, does command-name search when the typed text is not a binding, and reverse key lookup when the typed text parses as a binding, including when it parses as a chord. There is no second search box, no toggle, no menu. The decision is made for you by the parser, and the feedback line under the box tells you which mode you are in.
Liam: And one place the earlier short version was a touch optimistic, in a way that the code does not actually back up. It said reset to factory defaults is always one command away. The button is there, and it works, but the experience also depends on the keyboard pack setting, and a pack change and a reset are two distinct operations. You can reset, and you can also pick a pack, and the editor will let you do both. The honest picture is that recovery is cheap, not that it is invisible.
Jessica: To make the editor feel less like a tool and more like a habit, a small ritual. Whenever you customize something, take a screenshot of the keymap. Export the keymap to a JSON file with a date in the filename. Make a single change at a time and verify it does what you expect before making the next one. The cost of any one change is small; the cost of debugging a stack of changes you cannot remember is enormous.
Liam: And a screen-reader-friendly habit: when you bind a command to a new chord, say the chord out loud once, in the form you will remember it. The act of saying it is what cements the binding into motor memory, and it also surfaces any chord that is awkward to pronounce. The QUILL key plus S is easy. Some longer chord might be a mouthful. If it is hard to say, it will be hard to reach for under stress.
Jessica: One last thing before homework. The keymap editor and the keymap on disk are the same keymap. Every change in the editor is persisted through the same atomic write, with the same delta-plus-epoch shape, the same forward compatibility story. The defaults live in code, the overrides live on disk, the merge happens at load. That is the model the entire system is built on, and it is why a five-year-old customization can survive five years of releases without intervention, unless the user themselves chooses to revisit it.
Liam: Homework, four steps. One: open the Keymap Editor, reverse-look up three key combinations you have been curious about, learn who owns each, and notice whether any of them are free. Two: rebind exactly one command you actually use to a key you love, and use Record Keys to do the rebind rather than typing it. Three: run Diagnostics and either get a clean bill of health, or heal what is not, and read the report before you heal. Four: export your keymap to a .kqp file, name the file after today, and keep it in a folder you can find. Bonus, not counted: open the control reference from the Help menu, find your new binding in the table, and read the rest of the column to see what else lives near it.
Jessica: And that is the editor. Forty-five episodes to go, this is number ten of fifty-four in the full series, and the keyboard is yours.
Liam: Next episode, episode eleven: the editing power tools. Selection tricks, line surgery, case and text transforms, the mark ring revisited, and the undo you can always trust. Today was about configuring the keys, next time we use them.
Jessica: I'm Jessica.
Liam: I'm Liam. Your hands, your rules.