Skip to content

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].

ValueDescription
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

dart
const TranscriptPosition({
    required this.blockId,
    required this.plainTextOffset,
  })
dart
TranscriptPosition(
        blockId: blockId ?? this.blockId,
        plainTextOffset: plainTextOffset ?? this.plainTextOffset,
      )

Properties

PropertyTypeDescription
blockIdString
plainTextOffsetint
operatorbool
hashCodeint get
hashCodeint 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

dart
const TranscriptSelection({required this.anchor, required this.focus})
dart
TranscriptSelection(anchor: anchor, focus: focus)

Properties

PropertyTypeDescription
anchorTranscriptPosition
focusTranscriptPosition
isEmptybool getWhether the selection covers any cells at all.
originXint
originYint
originTranscriptPosition
exceededThresholdbool
isEmptybool getWhether 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

dart
DragState({
    required this.originX,
    required this.originY,
    required this.origin,
    this.exceededThreshold = false,
  })

Properties

PropertyTypeDescription
originXint
originYint
originTranscriptPosition
exceededThresholdbool

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

PropertyTypeDescription
countint getCurrent count without modifying state. Mostly useful for tests.
countint getCurrent 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

NameTypeDescription
kStreamingAssistantIdStringSentinel 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.
kStreamingThinkingIdString
dragThresholdCellsintMinimum 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.
clickChainWindowDurationTime window inside which successive clicks at the same cell are treated as a chain. Matches token-editor's runtime/mouse.rs:50 (300 ms).

Released under the MIT License.