DevelopmentAll versions
On this page

Hyperlink detection

This contract applies to host-provided SwingHyperlinkDetector implementations. The README introduces configuration. Terminal-authored OSC 8 links use hyperlinkHandler; detected links carry their own SwingHyperlinkAction.

Execution and ownership

detect(request) is suspending and runs outside painting and Swing event handling. Return a completed List<SwingHyperlink> and do not mutate the list or results later. An empty list is successful analysis without links. Failures and cancellation must throw; propagate coroutine cancellation rather than reporting empty success. Discovery may allocate bounded strings, results, and collections. Do not access Swing state from the detector.

Calls are serialized within each context. The binding owns cancellation and rejects obsolete results after source, binding, provider, or analysis changes. A detector that ignores cancellation occupies its context until it returns. Activation and hover callbacks run on the EDT, outside painting.

Context Use when
INDEPENDENT_LINE Each logical line can be analyzed without preceding lines; unchanged lines may be omitted
ORDERED_CONTENT Provider state consumes source order or results may refer to earlier lines
INDEPENDENT_AND_ORDERED One detector supports both independently scheduled lanes and permits concurrent calls between them

Each request selects one lane. Independent text-derived links do not wait for ordered provider work.

Source coordinates and dependencies

Requests defensively copy logical text and physical-row anchors. Soft-wrapped rows form one logical line; wrap padding and wide trailing cells are omitted, and one newline is appended. Positions contain the first absolute physical row of the logical line and a UTF-16 offset in its text. They are not viewport rows, cell columns, or global console offsets.

Use request.range or request.hyperlink to create ranges. A result contains its highlighted source range, validation dependency range, action, optional complete copyable URI, prepared presentation, and activation policy. Dependencies must include all characters that affect recognition or navigation, including token delimiters. The single-line factory defaults to the whole logical line for independent results and the supplied batch for ordered results; narrow them only when the action is independent of the omitted context.

Ordered results identify the source position consumed when they were produced through consumedThrough. They may highlight earlier retained lines. Unknown or out-of-bounds coordinates are ignored. lineFirstId supplies a stable source identity for host historical metadata; platform-specific cumulative console offsets remain host-owned.

Configuration and ordered state

configurationGeneration is an equality-only invalidation value. Publish the changed configuration and a distinct generation before emitting configurationChanges. A notification with the same generation does not invalidate results; without a notification, the new generation is observed at the next reconciliation. The binding owns collection of the notification flow.

Configuration refresh keeps prepared links until replacement results arrive, including successful empty replacements. Replacing the detector instance retires its old actions immediately; use replacement when stale actions must not remain usable.

Ordered state belongs to the request's binding, source, provider, and analysis epochs. Reconstruct it when earlier content changes or an interrupted invocation has tainted it. An analysisEpoch change requires replay from retained source; ordinary eviction advances firstRetainedRow without restarting the chain. Implement discardOrderedState when retaining provider state. The owner invokes it only after the ordered call exits. It must be nonblocking, thread-independent, and separate from independent-lane state.

Retention, projection, and interaction

Binding-owned discovery retains occurrences and successful empty analysis across scrolling. Frame preparation projects prepared links into visible cells rather than calling providers. Changed dependencies invalidate activation before rediscovery; reflow and source replacement invalidate the affected source state. Temporary hiding preserves discovery. Unbinding or disposal cancels it and releases retained results.

OSC 8 links win overlap resolution, followed by visible links, narrower ranges, and stable provider order. MODIFIER activation uses Ctrl or Cmd on macOS; DIRECT uses an ordinary primary click. Activation occurs on release only when the pressed occurrence still matches and no drag occurred. Application mouse reporting takes priority; Shift restores local interaction unless the application requests Shift capture through XTSHIFTESCAPE. Hover callbacks are balanced per occurrence even if results share an action.

Resolve colors and framework presentation before publication. Painting reads prepared normal, hovered, active, and followed styles; it performs no provider lookup. Terminal-authored underline and concealment retain precedence. Supply uri when the complete destination can be copied. Context menus capture the action and URI when opened, retaining their original target across later output or rebinding.

Migration

Detectors return List<SwingHyperlink> from suspending detect(request) instead of publishing through a sink. Replace LOGICAL_LINE / VIEWPORT contexts with INDEPENDENT_LINE / ORDERED_CONTENT. Positions use logical-line row anchors and UTF-16 offsets instead of cumulative console offsets.