| 1 | # Нотация записи аккордов и последовательностей (рекомендация для CascadeIDE) |
| 2 | |
| 3 | Документ задаёт **единый способ писать** комбинации клавиш в текстах проекта: ADR, комментарии к `hotkeys.toml`, подсказки в UI, MCP-описания команд. Стиль близок к **Vim** (`:help key-notation`), но подстроен под **FMS-мышление**, **CascadeChord** и фактический формат жестов в конфиге ([ADR 0060](adr/0060-keyboard-chord-stack-fms-tactical-strategic.md), [ADR 0030](adr/0030-command-ids-hotkeys-and-ui-registry-layers.md)). |
| 4 | |
| 5 | **Реализация разбора:** `Services/ChordNotation/` — см. слои ниже; Vim-EBNF в `ChordNotationGrammar.cs` ([Eto.Parse](https://www.nuget.org/packages/Eto.Parse)). |
| 6 | |
| 7 | **Философия читаемости:** нотация — для людей; где уместно, рядом с цепочкой шагов даётся **мнемоника намерений** (см. [ADR 0060 §10](adr/0060-keyboard-chord-stack-fms-tactical-strategic.md#adr0060-p10) — невидимый инструмент, overlay как суфлёр; **три входа** команд: палитра, аккорд, слэш в Intercom — [philosophy §7](design/cascadeide-philosophy-v1.md)). Конкретные буквы и количество шагов зависят от версии грамматики и `hotkeys.toml`; смысл §10 не привязан к одной таблице. |
| 8 | |
| 9 | **Command Melody в палитре:** префикс строки поиска **`c:`** — отдельный текстовый namespace ([ADR 0060 §11](adr/0060-keyboard-chord-stack-fms-tactical-strategic.md#adr0060-p11)), не путать с Vim-нотацией `<C-…>`: `c:` не описывает физические клавиши, а задаёт **alias** к тому же `command_id`, что и аккорд (`Ctrl+K` + буквы семейства/действия). Формальное описание языка и раздел для обсуждения эволюции — [intent-melody-language-v1.md](intent-melody-language-v1.md). |
| 10 | |
| 11 | --- |
| 12 | |
| 13 | ## Слои: синтаксис, семантика, рендер |
| 14 | |
| 15 | 1. **Синтаксис (несколько поверхностей)** — разные **текстовые формы** для людей и доков, без прошивки платформы в одну грамматику: |
| 16 | - **Vim-стиль** с угловыми скобками: `<C-k> s p` — разбор `ChordNotationParser` + EBNF ниже. |
| 17 | - **UI / hotkeys-стиль**: `Ctrl+K`, `Ctrl + Shift + P`, `⌘K`, `Ctrl+K Ctrl+C` — разбор `KeyGestureChordSyntax` (шаги разделяются пробелами; внутри шага — `+` между частями; **пробелы вокруг `+` схлопываются**, чтобы `Ctrl + Shift + P` был одним аккордом, а не пятью токенами). |
| 18 | |
| 19 | 2. **Семантика (единая модель)** — `NormalizedKeySequence`: список шагов `NormalizedChordStep(ChordModifierKeys, KeySymbol)` и `NormalizedPlainKeyStep(KeySymbol)`. Строится через `ChordSemanticNormalizer.FromVimSteps(…)` или напрямую из KeyGesture-синтаксиса. |
| 20 | |
| 21 | 3. **Рендер (отображение)** — `IChordNotationRenderer`: **`ChordNotationRenderer.Windows`** (`Ctrl+…+Win+K`) и **`ChordNotationRenderer.MacSymbols`** (глифы ⌃⌥⇧⌘ + ключ); один аккорд без последовательности — `ChordNotationRenderer.FormatChord(…)`. |
| 22 | |
| 23 | 4. **Рендер «клавишами» (кэпы)** — третий вид: **`ChordKeycapLayoutBuilder.Build`** / **`ChordNotationRenderer.BuildKeycapLayout`** → `ChordKeycapSequence` (шаги → сегменты с подписью). В UI — **`ChordKeycapStrip`**: отдельные скруглённые плашки на модификатор и на клавишу, шаги в ряд с отступом (как на подсказках в IDE/ОС). Подписи: `ChordKeycapLabelFlavor.WindowsWords` или `MacGlyphs`. Платформенный вид не смешивается с парсером и с `hotkeys.toml`. |
| 24 | |
| 25 | Соответствие `hotkeys.toml` / `KeyGesture.Parse` остаётся **отдельным шагом** (строка вида `Ctrl+K` из модели или из конфига), чтобы не смешивать Avalonia с документной нотацией. |
| 26 | |
| 27 | --- |
| 28 | |
| 29 | ## EBNF (канон для кода и доков; синтаксис Vim-стиля) |
| 30 | |
| 31 | Нотация в духе W3C/ISO: `=` правило, `|` альтернатива, `{` `}` ноль или более повторов, `"…"` литерал, `(* … *)` комментарий. |
| 32 | |
| 33 | ```ebnf |
| 34 | (* корневая последовательность: шаги через пробельные разделители *) |
| 35 | chord_sequence ::= ws_opt step { step_sep step } ws_opt ; |
| 36 | |
| 37 | ws_opt ::= { whitespace } ; |
| 38 | step_sep ::= whitespace { whitespace } ; |
| 39 | whitespace ::= (* любой пробельный символ по правилам Eto.Parse Terminals.WhiteSpace *) |
| 40 | |
| 41 | step ::= bracket_chord | plain_token ; |
| 42 | |
| 43 | bracket_chord ::= '<' bracket_inner '>' ; |
| 44 | bracket_inner ::= { modifier_prefix } key ; |
| 45 | |
| 46 | modifier_prefix ::= "Alt-" | "C-" | "M-" | "A-" | "S-" | "D-" ; |
| 47 | |
| 48 | (* ключ: непустая цепочка букв/цифр — односимвольная k или имя F1, Esc, Tab, … *) |
| 49 | plain_token ::= key ; |
| 50 | key ::= letter_or_digit { letter_or_digit } ; |
| 51 | letter_or_digit ::= (* Eto.Parse.Terminals.LetterOrDigit *) |
| 52 | ``` |
| 53 | |
| 54 | **Ограничения v1:** между шагами нужен **пробел** (например `<C-k> m`, не `<C-k>m`). Внутри `<…>` пробелы не допускаются. Токены FMS без угловых скобок (`L1`, `EXEC`) попадают в то же правило `key`, что и plain-шаги. |
| 55 | |
| 56 | --- |
| 57 | |
| 58 | ## Таблица нотации |
| 59 | |
| 60 | | Что записываем | Нотация | Пример | |
| 61 | |----------------|---------|--------| |
| 62 | | Одновременное нажатие (modifier + key) | `<C-x>`, `<M-x>`, `<S-x>`, `<D-x>` | `<C-k>` = Ctrl+K, `<M-s>` = Alt+S (если нужна буква в разборе) | |
| 63 | | Одновременное нажатие с несколькими модификаторами | `<C-M-x>`, `<C-A-x>` или явно `<C-Alt-x>` | `<C-Alt-n>` = Ctrl+Alt+N (то же, что `<C-M-n>`) | |
| 64 | | Последовательность шагов (не одновременно) | шаги через **пробел** | `<C-k> <C-s>` — сначала Ctrl+K, отпустить, затем Ctrl+S | |
| 65 | | Клавиша без модификаторов в роли шага | как символ или имя | `m`, `s`, `F1`, `Enter`, `Esc` — **без** угловых скобок | |
| 66 | | Имена клавиш, которые иначе неоднозначны | `Space`, `Tab`, `Up`, `Down` | по аналогии с Vim | |
| 67 | | FMS / «кнопки на MFD» (сценарный слой, не Win32-VK) | именованные линии/кнопки | `L1`, `R2`, `EXEC` — в доках про аппаратный/сюжетный FMS, не смешивать с `<C-…>` без пояснения | |
| 68 | |
| 69 | **Модификаторы в угловых скобках (кратко):** |
| 70 | |
| 71 | | Префикс в `<…>` | Значение | |
| 72 | |-----------------|----------| |
| 73 | | `C-` | Control | |
| 74 | | `M-` | Meta / Alt | |
| 75 | | `S-` | Shift | |
| 76 | | `D-` | Super / Win | |
| 77 | |
| 78 | --- |
| 79 | |
| 80 | ## Два разных смысла «аккорда» |
| 81 | |
| 82 | 1. **В конфиге и коде IDE** термин **CascadeChord** ([ADR 0060](adr/0060-keyboard-chord-stack-fms-tactical-strategic.md)) — это **последовательность**: корневой жест из `hotkeys.toml` (по умолчанию `Ctrl+K`), затем одна или несколько **обычных** клавиш **без** Ctrl/Alt в текущей реализации. В нотации документации это удобно писать так: |
| 83 | `<C-k> m m` — префикс, затем `m` (вход в зоны кокпита), затем `m` (MFD). |
| 84 | Пробел между шагами обязателен, если хотя бы один шаг — это `<…>` или именованная клавиша из нескольких букв. |
| 85 | |
| 86 | 2. **Угловые скобки `<C-k>`** здесь означают именно **одновременное** удержание модификаторов с клавишей, а не «имя команды Vim». |
| 87 | |
| 88 | 3. **Палитра, melody (`c:`)** — строка в поле command palette: `c:` + mnemonic (например `c: gs`). Это **не** шаг клавиатурной последовательности и **не** подмножество EBNF выше; см. [ADR 0060 §11](adr/0060-keyboard-chord-stack-fms-tactical-strategic.md#adr0060-p11). Тот же смысл может дублироваться аккордом вида `<C-k> g s` при intent-first грамматике. |
| 89 | |
| 90 | --- |
| 91 | |
| 92 | ## Соответствие `hotkeys.toml` |
| 93 | |
| 94 | В файлах конфигурации по-прежнему используется разбор жестов в стиле **KeyGesture** (как в поставке: `Ctrl+K`, `Ctrl+Q`). Табличная нотация `<C-k>` — **для человекочитаемых текстов**; при переносе в TOML запись остаётся `Ctrl+K`, не `<C-k>`. |
| 95 | |
| 96 | --- |
| 97 | |
| 98 | ## Примеры для текущей машины CascadeChord |
| 99 | |
| 100 | | Действие (смысл) | В документации | |
| 101 | |------------------|----------------| |
| 102 | | Semantic Map: сменить вид | `<C-k> s p` | |
| 103 | | Semantic Map: уровень / детализация | `<C-k> s f`, `<C-k> s d` | |
| 104 | | Зоны кокпита: MFD / PFD / Forward | `<C-k> m m`, `<C-k> m p`, `<C-k> m f` | |
| 105 | | Отмена ожидания шага | `Esc` | |
| 106 | |
| 107 | --- |
| 108 | |
| 109 | ## FMS-стиль (MFD) |
| 110 | |
| 111 | Обозначения `L1`, `R2`, `EXEC` оставляем для сценариев, где важна **аналогия с реальным CDU/FMS** (левый/правый ряд, исполнение). Их **не** подставляют вместо `<C-…>` в описании хоткеев IDE, если только явно не делается связка «экранный тренажёр ↔ жест в CascadeIDE». |
| 112 | |
| 113 | --- |
| 114 | |
| 115 | ## Ссылки |
| 116 | |
| 117 | - [ADR 0060 — аккордный слой, таймаут, overlay](adr/0060-keyboard-chord-stack-fms-tactical-strategic.md) |
| 118 | - [ADR 0030 — command_id, hotkeys, реестр](adr/0030-command-ids-hotkeys-and-ui-registry-layers.md) |
| 119 | - [Eto.Parse](https://github.com/picoe/Eto.Parse) — парсер, fluent API и EBNF-грамматики |
| 120 | - Vim: `:help key-notation` (ориентир по угловым скобкам и модификаторам) |
| 121 | |