fix(url): extend URL detection across hard-wrap row boundaries#11613
fix(url): extend URL detection across hard-wrap row boundaries#11613rndjams wants to merge 1 commit into
Conversation
Some programs (e.g. kiro-cli) emit explicit \r\n, creating hard-wrapped rows whose WRAPLINE flag is absent. The grapheme cursor in url_at_point follows only soft wraps (Wrap::Soft), so it stops at hard-wrap row boundaries and returns a truncated URL fragment when a URL overflows the terminal width. CMD+click then silently opens the wrong address. Two-part fix: 1. url_at_point (grid_handler.rs): after the main forward scan, if the detected URL ends near the right edge of a hard-wrapped row, scan the leading token of the following row. If it looks like a URL fragment (no URL separators, does not start with an uppercase letter) extend the Link range to include it. 2. link_at_range (terminal_model.rs): strip embedded \r/\n characters that appear when the URL range spans a hard-wrapped row boundary. RFC 3986 URLs cannot contain raw newlines, so this stripping is always correct. The heuristic is conservative by design: - Only fires when the URL ends within 4 columns of the right edge - Requires the row to be hard-wrapped (WRAPLINE flag absent) - Rejects continuations starting with uppercase (new sentence, not URL) - Rejects continuations starting with whitespace (indented blocks) Closes warpdotdev#11609 See also warpdotdev#6541 (OSC 8 hyperlinks — the clean upstream fix that would supersede this heuristic once implemented) Tests added: - test_url_extends_across_hard_wrap_boundary - test_url_hard_wrap_no_extend_for_uppercase_continuation - test_url_hard_wrap_no_extend_for_space_continuation
|
This PR is not linked to an issue that is marked with Issue-state enforcement details:
Readiness check:
To continue, link this PR to a same-repo issue such as Powered by Oz |
There was a problem hiding this comment.
This PR is not linked to an issue that is marked with ready-to-implement.
Issue-state enforcement details:
-
Associated same-repo issues checked: #11609
-
Required readiness label:
ready-to-implement
Readiness check:
- #11609: missing
ready-to-implement; readiness labels present: none
To continue, link this PR to a same-repo issue such as Closes #123 in the PR description, and make sure that issue has ready-to-implement.
Powered by Oz
Fixes #11609
Summary
AI TUI tools (Kiro CLI, Claude Code, GSD) write output with explicit
\r\n, producing hard-wrapped rows whereWRAPLINEis absent. When a URL overflows the terminal width,url_at_pointreturns only the first-row fragment — CMD+click opens a truncated, invalid URL.Changes
1.
url_at_pointcontinuation probe (grid_handler.rs)After the forward scan loop completes, probes across the hard-wrap boundary when:
near_right_edge)!self.row_wraps()—WRAPLINEabsent)checked_addoverflow-safe)Guards are all O(1). Common case (short URL, soft-wrap, or URL not near edge) exits immediately at
near_right_edgewith zero additional allocations.Continuation is rejected if the first char is uppercase (new-sentence guard) or whitespace (indented-block guard).
2.
link_at_rangenewline stripping (terminal_model.rs)Strips embedded
\n/\rfrom the concatenated URL text. RFC 3986 URLs cannot contain raw newlines. All existing callers are URL-specific (guarded byGridHighlightedLink::Url). No-op for single-row URLs.Behavior invariants
row_wraps() == true→ probe does not fire)None(backward scan limitation — V1 scope)Known limitation
URLs whose continuation begins with uppercase (e.g.,
/OAuth2/callback) are not extended. Deliberate tradeoff to avoid false joins with prose. V2 can relax this when continuation immediately follows/.V1 scope boundary
Testing
4 new tests covering: extension across boundary, uppercase rejection, whitespace rejection, backward-scan limitation.
Existing
test_find_url_line_wrapping(soft-wrap) passes unchanged.Manual testing
printf "See: https://auth.example.com/oauth/v2/authorize?client_id=app&state=abc123\r\n&redirect_uri=https%%3A%%2F%%2Fapp.example.com\r\n"in Warp