Skip to content

feat(keybindings): вкладка редактирования keyboard shortcuts как в VS Code - #297

Open
tihonove wants to merge 8 commits into
mainfrom
worktree-keybindings-editor
Open

feat(keybindings): вкладка редактирования keyboard shortcuts как в VS Code#297
tihonove wants to merge 8 commits into
mainfrom
worktree-keybindings-editor

Conversation

@tihonove

Copy link
Copy Markdown
Collaborator

Что

Вкладка редактирования keyboard shortcuts как в VS Code. Ctrl+K Ctrl+S теперь открывает UI-таблицу всех команд (Command | Keybinding | When | Source) с поиском, рекордером комбинаций и конфликт-детекцией; сам keybindings.json — отдельной командой workbench.action.openGlobalKeybindingsFile (VS Code parity).

Скоуп (один PR, 8 коммитов)

  1. refactor(keybinding) — реестр отдаёт записи наружу: listBindings() со снапшотами, источник (default/extension/user), возврат снятых записей из removeBindings, serializeChord (обратный parseChord), публичный chordsEqual.
  2. refactor(workbench) — вынесен общий контрол FilteredListControl («поиск + список»), Extensions мигрирован на него (третий потребитель по конвенции feat(lsp): find all references — панель ссылок в сайдбаре #291).
  3. feat(keybindings) — read-only вкладка: модель и раскладка колонок чистыми функциями, схема keybindings:, дедуп по uri.
  4. feat(keybindings)KeybindingsEditorService: применяет keybindings.json на bootstrap (переезд из KeybindingDispatcher) и мутирует из UI (define/remove/reset) с мгновенным применением к реестру и записью JSONC (комментарии сохраняются). Сессионный леджер даёт reset без Reload Window.
  5. feat(keybindings) — рекордер «нажмите комбинацию» (модальный оверлей, закрытие по парному keypress), контекст-меню Change/Add/Remove/Reset/Copy/Show Conflicts, предупреждение о непереносимых на legacy-терминале комбинациях.
  6. feat(keybindings) — конфликт-детекция (та же комбинация + пересекающийся when) + фильтр @conflicts.
  7. test(e2e) — функциональный e2e на настоящем бинаре + скриншот-демо.
  8. docs — Workbench.md, Configuration.md, трекер.

Осознанно НЕ в этом PR

File-watcher на keybindings.json (ручные правки — после Reload Window, как и раньше; откатываемый user-слой не строим), валидатор keybindings.json в редакторе, миграция Search на общий контрол. Детали и упрощения (конфликт-детекция по равенству when, порядок после reset) — в docs/TODO/KeybindingsEditor.md.

Демо

Кадр рекордера ловит сразу и подсветку конфликта (две строки на Ctrl+S цветом предупреждения: File: Save/Default и Select All/User), и оверлей рекордера с заметкой про legacy-терминал.

recorder
tab

Сценарий-демо: e2e/scenarios/keyboardShortcuts.scenario.ts (кадры tab / filter / conflicts / recorder).

Проверки

  • npm run test:coverage — 100% (храповик).
  • npm run valid-layers-check — OK (contract в common / impl в node / биндинг в diode).
  • npm run test:e2e — функциональный сьют и сценарий зелёные.
  • npm run test:mutation — прогоняется.

🤖 Generated with Claude Code

tihonove and others added 8 commits September 11, 2026 06:21
…erializer

KeybindingRegistry учится отдавать свои записи наружу — фундамент вкладки
Keyboard Shortcuts: listBindings() со снапшотами, пометка источника записи
(default/extension/user) у register(), возврат снятых записей из
removeBindings() (для восстановления дефолтов при reset), публичный
chordsEqual и serializeChord — сериализатор в spec-форму keybindings.json,
обратный parseChord.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HvNGh9MrQQcDWGbrkmt8sR
…ns view

Связка «InputElement в шапке + ListViewElement со скроллбаром» дублировалась
дословно; вкладка Keyboard Shortcuts стала бы третьим потребителем — по
конвенции #291 выносим общий контрол. FilteredListControl владеет только
проводкой (запрос → onQueryChange, активация строки → onActivateRow,
плейсхолдер пустого состояния); строки и модель данных остаются за
потребителем. ExtensionsComponent мигрирован; Search не мигрируем (его шапка
сложнее связки, потребует слота под доп. элементы) — статус в ListControls.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HvNGh9MrQQcDWGbrkmt8sR
Ctrl+K Ctrl+S теперь открывает вкладку Keyboard Shortcuts (VS Code parity):
таблица всех команд с колонками Command | Keybinding | When | Source, строка
поиска с fuzzy-фильтром и префиксом @source:, команды без биндинга — строками
с тире. Прежнее поведение (открыть keybindings.json) уехало в новую команду
workbench.action.openGlobalKeybindingsFile, как в VS Code.

Вкладка — небуферная панель на FilteredListControl (схема keybindings:, дедуп
по uri в openPane); модель строк и раскладка колонок — чистые функции
(keybindingsEditorModel.ts, keybindingRows.ts), колонки пересчитываются на
смену ширины приёмом ExtensionPageElement. Открытие — через шов
KeybindingsEditorTargetDIToken (биндит новый preferencesModule).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HvNGh9MrQQcDWGbrkmt8sR
…ingsEditorService

Новый KeybindingsEditorService — единственный владелец user-слоя биндингов:
применяет правила keybindings.json на bootstrap (переезд applyUserKeybindings
из KeybindingDispatcher) и мутирует их из UI — define/remove/reset с
мгновенным применением к реестру И записью в файл. Запись — минимальные
JSONC-правки (keybindingsFileEditor: append/remove через jsonc-parser modify),
комментарии и форматирование пользователя выживают. Замена дефолта — VS
Code-пара «новое правило + -command-unbind»; сессионный леджер (что добавлено,
какие дефолты сняты) даёт reset без Reload Window. Ошибка записи — результат
{ok:false}, не исключение; null-путь (тесты/демо) — честный отказ.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HvNGh9MrQQcDWGbrkmt8sR
…uts tab

Вкладка Keyboard Shortcuts стала редактором: Enter/двойной клик по строке
открывает рекордер «Press desired key combination» — модальный оверлей,
копящий части чорда (голый Enter принимает, голый Escape отменяет, Ctrl+Enter
и прочие модифицированные — в чорд). Захват — сфокусированный корень со
stopPropagation, закрытие — по парному keypress (пиннинг keypress к цели
keydown). Контекст-меню строки: Change / Add / Remove / Reset (по леджеру
user-правок) / Copy Command ID. Мутации применяются мгновенно и пишутся в
keybindings.json; ошибка записи — строкой во вкладке.

Терминальная специфика: непереносимая на legacy комбинация (эвристика
requiresExtendedKeys) подсвечивается предупреждением, на legacy-tier рекордер
несёт постоянную заметку о неразличимых сочетаниях.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HvNGh9MrQQcDWGbrkmt8sR
Конфликт-детекция во вкладке Keyboard Shortcuts: записи с одной комбинацией
и потенциально пересекающимся when (отсутствующий when пересекается с любым,
непустые сравниваются нормализованной строкой — честное упрощение, не SAT)
подсвечиваются в колонке Keybinding цветом предупреждения. Chord-префиксы
(ctrl+k против ctrl+k ctrl+s) конфликтом не считаются — их резолвер решает
детерминированно. Фильтр @conflicts отбирает конфликтующие записи, пункт
контекст-меню «Show Conflicts» сеет его с комбинацией строки — аналог
VS Code «Show Same Keybindings».

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HvNGh9MrQQcDWGbrkmt8sR
Функциональный e2e (настоящий бинарь): открытие вкладки, поиск, запись
биндинга рекордером с проверкой keybindings.json на диске и исполнения
команды по новой комбинации в том же сеансе, фильтр @conflicts. Скриншот-демо
keyboardShortcuts.scenario.ts — кадры tab / filter / conflicts / recorder
(последний ловит и подсветку конфликта, и предупреждение legacy-терминала).
Комментарий preferencesMenu.scenario обновлён под новую команду
«Keyboard Shortcuts (JSON)».

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HvNGh9MrQQcDWGbrkmt8sR
Preferences-кластер в Workbench.md (вкладка, рекордер, сервис, конфликты,
FilteredListControl), обновлена заметка про UI настроек в Configuration.md,
добавлены KeybindingsEditor.md и строка в трекер.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HvNGh9MrQQcDWGbrkmt8sR
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant