| 1 | <!-- English translation of adr/0081-parametric-intent-melodies-editor-line-ranges.md. Canonical Russian: ../../adr/0081-parametric-intent-melodies-editor-line-ranges.md --> |
| 2 | |
| 3 | # ADR 0081: Parametric Intent Melody - Editor Line Ranges (`:start:end`) |
| 4 | |
| 5 | **Status:** Accepted · Implemented |
| 6 | **Date:** 2026-04-20 |
| 7 | ## Related ADRs |
| 8 | |
| 9 | | ADR | Role | |
| 10 | |-----|------| |
| 11 | | [0060](0060-keyboard-chord-stack-fms-tactical-strategic.md) | Command Melody, CascadeChord, keyboard-first | |
| 12 | | [0030](0030-command-ids-hotkeys-and-ui-registry-layers.md) | `command_id` and UI layers | |
| 13 | | [0013](0013-command-surface-and-discoverability.md) | palette and discoverability | |
| 14 | | [0070](0070-command-palette-direct-overlay-surface.md) | palette as overlay | |
| 15 | | [0079](0079-ide-display-system-ids-overlay-pipeline.md) | IDS - input overlay composition | |
| 16 | | [0072](0072-chat-topic-cards-intent-melody-keyboard-contract.md) | intent-first logins in the chat domain | |
| 17 | | [0075](0075-ui-topic-index-and-mfd-page-conventions.md) | attention zones / MFD | |
| 18 | | [0039](0039-workspace-navigation-affordances.md) | Workspace navigation - multiple views and "current file + related" | |
| 19 | | [0080](0080-intercom-naming-and-multi-party-channel-model.md#adr0080-future-modalities) | anchors to code - a related topic, does not duplicate this ADR | |
| 20 | | [0110](0110-roslyn-refactor-intent-melody-bridge.md) | Roslyn Range Refactorings - Intent Melody/IDE Bridge and Roslyn MCP | |
| 21 | |
| 22 | ## Summary |
| 23 | |
| 24 | - Parametric **Intent Melody:** suffix `:startLine:endLine` for operations on text. |
| 25 | - Range validation; bridge to Roslyn - [0110](0110-roslyn-refactor-intent-melody-bridge.md). |
| 26 | |
| 27 | |
| 28 | ### Outside ADR |
| 29 | |
| 30 | | Document | Role | |
| 31 | |----------|------| |
| 32 | | [intent-melody-language-v1.md](../../intent-melody-language-v1.md) | IML v1: `c:` grammar and registry alias | |
| 33 | | [`IntentMelody/intent-melody-aliases.toml`](../../IntentMelody/intent-melody-aliases.toml) | overlay alias → `command_id` | |
| 34 | | [Roslyn MCP](../../../roslyn-mcp/README.md) | Roslyn MCP | |
| 35 | |
| 36 | --- |
| 37 | ## Context |
| 38 | |
| 39 | In IML v1, the tail after `c:` is a **mnemonic** that resolves to **`command_id`** via the registry ([`intent-melody-aliases.toml`](../../IntentMelody/intent-melody-aliases.toml), [ADR 0060 §11](0060-keyboard-chord-stack-fms-tactical-strategic.md#adr0060-p11)). For commands like “Git status” or “open Chat page” this is enough: the context is set by the focus and the current solution. |
| 40 | |
| 41 | Operations on **active editor text** (select line range, delete range, **Extract Method** and other Roslyn range refactorings) fundamentally require a **parameter** - at least **line range** - otherwise the same mnemonic is ambiguous or is forced to rely only on the current selection, which is worse for “know the line numbers” scenarios. |
| 42 | |
| 43 | --- |
| 44 | |
| 45 | ## Problem |
| 46 | |
| 47 | 1. **Intent → command gap:** without parameters, the user is forced to first select the text with the mouse/keyboard, then call the command; for power-user with numbers from the log/diff this is slower than **one line of input** with a range. |
| 48 | 2. **Surface parity:** if the option is only available through a menu or a separate dialog, the principle of **same `command_id` and same inputs** as palette and Melody ([0060](0060-keyboard-chord-stack-fms-tactical-strategic.md) suffers, [0008](0008-mcp-contracts-and-testable-infrastructure.md)). |
| 49 | 3. **Input errors:** out-of-file range or `start > end` should not have a **silent** destructive effect or cause you to edit the wrong part. |
| 50 | |
| 51 | --- |
| 52 | |
| 53 | ## Solution (suggested) |
| 54 | |
| 55 | <a id="adr0081-p1"></a> |
| 56 | |
| 57 | ### 1. String range suffix |
| 58 | |
| 59 | After a **registered** short alias (melody root without `c:` in registry terms) an **optional** suffix of the form **`:startLine:endLine`** is allowed: |
| 60 | |
| 61 | - **`startLine`**, **`endLine`** — integers, **1-based**, **inclusive** (consistent with line numbers in the editor and typical compiler messages). |
| 62 | - Field separator - **`:`**; the parser, after matching the base alias **first**, resolves the prefix into a `command_id`/domain operation, then, if the tail continues with the pattern `:digits:digits`, interprets the pair as a range of strings. |
| 63 | |
| 64 | **Illustrative examples** (final mnemonics and binding to `command_id` - a registry and product decision, not hardcoded into the parser): |
| 65 | |
| 66 | | Input (fragment after `c:`) | Intent (landmark) | |
| 67 | |--------------------------|---------------------| |
| 68 | | `els:5:15` | Editor → Line → Select lines 5–15 in the active document | |
| 69 | | `eld:5:15` | Editor → Line → Delete in the specified range | |
| 70 | |
| 71 | Canon of this ADR thread: |
| 72 | - For operations on a range of lines, use the **Editor → Line** (`el*`) model, without legacy/synonyms `es*`. |
| 73 | - Family of melodies **Refactor → …** by range (`rmx`, `rix`, …) and a combination with Roslyn / **Roslyn MCP** (`roslyn_get_code_actions` / `roslyn_apply_code_action`) **are not included in the required minimum of this ADR** - see. [0110](0110-roslyn-refactor-intent-melody-bridge.md). |
| 74 | |
| 75 | Expansion of **IML v1** in [`intent-melody-language-v1.md`](../../intent-melody-language-v1.md) (new sub-clause about the parametric tail) - **in a separate step** after stabilizing the format; Until then, this ADR is a **direction standard** for implementation and documentation. |
| 76 | |
| 77 | <a id="adr0081-p2"></a> |
| 78 | |
| 79 | ### 2. Validation and refusal |
| 80 | |
| 81 | - The range **must** fit within the current length of the document (in lines); in case of violation - **explicit feedback** (palette status line, short annunciator in IDS - according to [0079](0079-ide-display-system-ids-overlay-pipeline.md)), **without** using a destructive action “as it happens”. |
| 82 | - Condition **`startLine <= endLine`**; otherwise, the same error class as out-of-bounds. |
| 83 | |
| 84 | <a id="adr0081-p3"></a> |
| 85 | |
| 86 | ### 3. Roslyn refactorings (Extract Method and analogues) |
| 87 | |
| 88 | Commands that in the IDE already expect **selection** in the editor (including Roslyn: `roslyn_get_code_actions` with a range for Extract method and analogues) should behave predictably: |
| 89 | |
| 90 | - If there is a **non-empty selection** in the active document, **selection priority** is possible over the numeric suffix (product rule: “an explicit gesture wins”) **or** an unambiguous policy “the suffix always sets the range” - **fix during implementation** and reflect in help. |
| 91 | - If there is no selection - **synthetic selection** along the lines `startLine`–`endLine` (whole lines, including line breaks according to the rule accepted in the editor) before calling the same path as from the UI. |
| 92 | |
| 93 | <a id="adr0081-p4"></a> |
| 94 | |
| 95 | ### 4. UX: discoverability and input mode |
| 96 | |
| 97 | - **Indicator of recognized melody:** with active **command mode** / input in the palette, show a brief analysis: basic alias + numeric range (and if an error occurs, the reason). The goal is to reduce “I thought I entered something else” errors without requiring a long log. |
| 98 | - **Chord vs palette only:** An open question is whether to allow a parametric tail in **CascadeChord** (`Ctrl+K` → sequence of letters) or limit it to **palette** for the sake of fewer typos without previews. The solution is separate; this ADR allows both options as implementations. |
| 99 | |
| 100 | --- |
| 101 | |
| 102 | ## Consequences |
| 103 | |
| 104 | - Palette/Melody string parser extension and VM binding: editor commands that accept a range receive a **single** contract from IML, not just from pointer. |
| 105 | - The registry [`intent-melody-aliases.toml`](../../IntentMelody/intent-melody-aliases.toml) can reference the **same** `command_id` as without parameters; semantics “with/without parameter” - in the command handler or thin adapter. |
| 106 | - MCP Documentation / `IdeCommands`: for the corresponding commands, **args** or a parallel path “from palette with range” are specified if necessary. |
| 107 | |
| 108 | --- |
| 109 | |
| 110 | ## Rejected alternatives |
| 111 | |
| 112 | - **MCP with explicit arguments only** - breaks keyboard-first and the single intent line in the human IDE. |
| 113 | - **Only space as delimiter** (`5 15`) - conflicts with the IML v1 direction "spaces inside the tail do not cut tokens" ([§3.4](../../intent-melody-language-v1.md#34-spaces)); suffixing with **`:`** after a full match alias is more reproducible. |
| 114 | - **Binding to mouse/gutter only** - does not cancel, but does not replace parametric input for users without a pointer on the line. |
| 115 | |
| 116 | --- |
| 117 | |
| 118 | ## Open questions |
| 119 | |
| 120 | 1. Limit parametric shapes to **palette only** on the first release or immediately allow chord input. |
| 121 | 2. Are **columns** or **subranges inside a row** needed in the next iteration? Move beyond the minimum `:start:end` across rows. |
| 122 | 3. Synchronization with future **anchors to code** from [0080](0080-intercom-naming-and-multi-party-channel-model.md) (deep link): general “range in document” layer or individual contracts. |