TranscriptSelection
Category: App
Source: transcript_selection.dart
Transcript selection — coordinate model and gesture classification.
Selection coordinates are anchored to blocks (logical transcript entries), not to rendered-line indices. The render pipeline rebuilds outputLines from _blocks on every frame, so any (line, column) coordinate becomes stale as soon as another agent event arrives or the terminal resizes. A (blockId, plainTextOffset) pair survives both, because the block's plain-text rendering is a monotonic append while streaming and is regenerated deterministically on resize.
Enums
CharClass
Three-way char classification used by [findClassRange].
| Value | Description |
|---|---|
whitespace | |
word | |
punctuation |
Classes
TranscriptPosition
A position inside a transcript block.
[blockId] identifies the logical block (a ConversationEntry.id or a streaming sentinel). [plainTextOffset] is a 0-indexed offset into the block's rendered plain text (ANSI stripped, with the block's own header/prefix decoration included, lines joined by \n).
Constructor
const TranscriptPosition({
required this.blockId,
required this.plainTextOffset,
})TranscriptPosition(
blockId: blockId ?? this.blockId,
plainTextOffset: plainTextOffset ?? this.plainTextOffset,
)Properties
| Property | Type | Description |
|---|---|---|
blockId | String | |
plainTextOffset | int | |
operator | bool | |
hashCode | int get | |
hashCode | int get |
Methods
TranscriptPosition copyWith({String? blockId, int? plainTextOffset})
String toString()
TranscriptSelection
An active drag selection.
[anchor] is the mouse-down origin (resolved at drag start). [focus] updates with each motion event. [start]/[end] expose the ordered pair in document order, given an ordered list of block ids.
Constructor
const TranscriptSelection({required this.anchor, required this.focus})TranscriptSelection(anchor: anchor, focus: focus)Properties
| Property | Type | Description |
|---|---|---|
anchor | TranscriptPosition | |
focus | TranscriptPosition | |
isEmpty | bool get | Whether the selection covers any cells at all. |
originX | int | |
originY | int | |
origin | TranscriptPosition | |
exceededThreshold | bool | |
isEmpty | bool get | Whether the selection covers any cells at all. |
Methods
TranscriptSelection withFocus(TranscriptPosition focus)
TranscriptSelection rebindBlockId(String from, String to)
Return a new selection where any position with [from] as its blockId is rewritten to use [to]. Used to migrate a selection across the streaming-buffer → real-entry handoff without losing the anchor.
bool observeMotion(int x, int y)
Update [exceededThreshold] given the latest motion coordinates and return whether the drag has just crossed the threshold (i.e. the caller should now treat subsequent motion as a selection update).
DragState
Transient state held while the mouse button is pressed in the output zone. Promotes to a real selection once the user moves the cursor more than [dragThresholdCells] cells away from the origin — below that, the gesture is treated as a click.
Constructor
DragState({
required this.originX,
required this.originY,
required this.origin,
this.exceededThreshold = false,
})Properties
| Property | Type | Description |
|---|---|---|
originX | int | |
originY | int | |
origin | TranscriptPosition | |
exceededThreshold | bool |
Methods
bool observeMotion(int x, int y)
Update [exceededThreshold] given the latest motion coordinates and return whether the drag has just crossed the threshold (i.e. the caller should now treat subsequent motion as a selection update).
ClickChain
Tracks consecutive mouse-up events to detect double/triple clicks. Terminal mouse protocols only emit independent press/release pairs, so we synthesise the chain by accumulating clicks that are both rapid (within [clickChainWindow]) and at the exact same cell.
Returns counts in the sequence 1 → 2 → 3 → 1; subsequent clicks wrap so a fourth click resets the chain.
Properties
| Property | Type | Description |
|---|---|---|
count | int get | Current count without modifying state. Mostly useful for tests. |
count | int get | Current count without modifying state. Mostly useful for tests. |
Methods
int register(int x, int y, DateTime now)
Record a click at cell [x],[y] at time [now] and return the updated count (1, 2, or 3). Any cell change OR a slow window resets the count back to 1.
void reset()
Forget the chain — used when a drag or other gesture invalidates any accumulated clicks.
Functions
CharClass classify(int rune)
Classify a single Unicode code point. Whitespace and a fixed ASCII punctuation set act as boundaries; everything else (Unicode letters, digits, _, emoji, combining marks, CJK) counts as a word char.
Constants
| Name | Type | Description |
|---|---|---|
kStreamingAssistantId | String | Sentinel ids used for the two pseudo-blocks rendered above any real conversation entry while the agent is streaming. When the stream finalises and the buffer flushes into a real [ConversationEntry], call [TranscriptSelection.rebindBlockId] so existing selections keep pointing at the same text. |
kStreamingThinkingId | String | |
dragThresholdCells | int | Minimum Manhattan distance (in terminal cells) that the cursor must move from the mouse-down origin before a press-hold-release gesture counts as a drag rather than a click. 2 cells is small enough to feel responsive but large enough that an unintentional 1-cell wobble doesn't suppress click-to-expand on subagent groups. |
clickChainWindow | Duration | Time window inside which successive clicks at the same cell are treated as a chain. Matches token-editor's runtime/mouse.rs:50 (300 ms). |