ADR 0020: Clipboard — cut/copy/paste on top of the selection model¶
Status¶
Accepted
Context¶
Phase 11 (ADR 0019) gave every cursor an optional selection range.
Cut/copy need a selection to operate on, so this phase sits directly
on top: hasSelectionAt/selectionMinAt/selectionMaxAt/
deleteSelectionAt are reused as-is, no changes to that layer.
Decision¶
Three new EditorViewport methods, wired into keyPressEvent's
existing Ctrl-modifier branch alongside S/Q/D/Z:
copySelection()(Ctrl+C): for every cursor with an active selection, reads the range straight out ofm_cache(already a full, current mirror of the buffer, per ADR 0006 — no need forase_buffer_get_text). Multiple selections join with\n, the standard multi-cursor copy convention. Sets the result viaQGuiApplication::clipboard()->setText(...). No selection anywhere → no-op, clipboard untouched (documented decision, matching the project's existing "don't guess" pattern already used forbuild_command/lsp_commandelsewhere in the plan — no implicit whole-line copy fallback). ReturnsboolsocutSelectioncan reuse it directly as its "is there anything to do" check.cutSelection()(Ctrl+X):copySelection()first, then (only if it returnedtrue) deletes every selection as one undo group — the samebegin_group/deleteSelectionAtloop/end_groupshape every other multi-cursor edit in this file already uses, so cut undoes as a single action for free.pasteClipboard()(Ctrl+V): readsQGuiApplication::clipboard()->text(), and if non-empty, hands it to the existinginsertText()unchanged — which already replaces each cursor's active selection first (ADR 0019) and already wraps the whole multi-cursor broadcast in one undo group. Deliberately inserts the same text at every cursor rather than distributing clipboard lines one-per-cursor (a real feature some editors have, e.g. pasting N copied lines onto N cursors one each) — considered and declined for v1, added complexity the "minimal" pillar doesn't need yet.- No
CMakeLists.txtchange:Qt6::Widgetsalready transitively linksQt6::Gui, which is whereQClipboard/QGuiApplication::clipboard()live — confirmed by a clean build after just adding the#includes.
Consequences¶
Verified live against the running ase_gui, driven with xdotool
under the real X session, checked against the actual system clipboard
via xclip (a process independent of the Qt app, so this proves the
data really left the process, not just an in-memory QString):
- Ctrl+C on a 5-character selection → xclip -selection clipboard -o
reads back the exact text.
- Ctrl+V — seeded the system clipboard independently via xclip
-selection clipboard (decoupled from any Qt process, since X11's
clipboard has no backing store of its own: killing the owning
process without a clipboard manager running drops the selection
immediately — a real X11 property, not an editor bug, and the reason
this test seeds the clipboard externally rather than chaining off a
same-session Ctrl+C) → pasted text landed exactly at the cursor,
confirmed via a save-to-file round trip.
- Ctrl+X removed the selection, the clipboard held exactly the cut
text, and one Ctrl+Z restored the original buffer content as a
single action.
- Multi-cursor copy: two simultaneous cursor selections (Alt+click to
add a second point cursor, then Shift+Right — which extends every
cursor's selection in the same keystroke, since the move primitives
already loop over all of m_cursors) produced a clipboard value with
the two ranges joined by \n, in buffer order.
Not built, deliberately: a system clipboard manager isn't this editor's
responsibility (same reasoning as declining an implicit copy
fallback) — pasting after the source app closes without one running is
an X11-wide limitation, not something ase_gui can or should work
around. Find/replace (Phase 13) is next, unrelated to this phase's
additions.