feat(terminal): open file paths on Cmd/Ctrl+click#117
Conversation
Recognize file-path references in terminal output and open them in the editor on Cmd/Ctrl+click, showing a picker when a path matches more than one file in the task. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
49bf2ee to
e4a64ec
Compare
simion
left a comment
There was a problem hiding this comment.
Nothing blocking, nits only. None of these gate a merge.
- Wrap-boundary off-by-one in the provider: a token ending exactly at a soft wrap makes
toPos(end)advance to the next row at offset 0, so the range ends atx: 0in xterm's 1-based coordinates. Clamp to the previous row's last cell. - AuxTerminal still arms on path targets:
onDownswallows the gesture, then the aux callback drops it, so Cmd+click on path-like text in the scratch shell eats the click and does nothing (including for a TUI with mouse reporting that wanted it). Either a URLs-only mode that skips arming, or support path-open there too, AuxTerminal hastaskId. handlePathTarget's.catch(() => {})swallows a failed file-list fetch: the click does nothing with no explanation. A toast matches how the Git panel reports IPC failures.- Nit: "and/or" and bare domains ("termic.dev") match the token regex, so they hover-underline and click through to a "No matches" picker. Fine for v1.
- Nit: after the picker closes, focus lands on the invisible anchor (not focusable), so the terminal drops focus. Refocus the terminal in
onPick/onClose.
Checked the integration: openPreviewTab/revealAt and the task-relative path form match the store and EditorPane, so single-match opens and line jumps work as written. The capture opener swallows the whole gesture, so the provider's activate can't double-fire; the WebLinksAddon new URL() rationale is accurate.
Wrap-boundary link range, scratch shell no longer swallows path clicks, toast on a failed file-list fetch, refocus after the picker, and split linkAt into url/path matchers. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Bound each path-segment run to {1,255} so a long slash-less/dot-less
blob (base64, a hash) can't drive the token regex into O(n^2)
backtracking and stall the hover-underline pass.
Replace the single path scan with one url|junk|path regex so a fragment
of one can't leak as another:
url consume schemed URLs (WebLinksAddon already underlines them) to
stop the double underline on the host/path inside a URL.
junk consume scp-style host:path git remotes so neither half
underlines; the colon only disqualifies when glued to a path
char, keeping :line:col refs and "(path): description" colons.
path now allows @ so retina assets (logo@2x.png) and scoped packages
(@types/node) resolve.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Resolved 1,2,3 and 5 and also found some extra edge cases regarding regexes in the follow up review. Some common formats (domains, emails) are technically valid paths so for simplicity I've just left them matching. Worst case UX is a "No matches" popup. |
simion
left a comment
There was a problem hiding this comment.
Merged. No follow-up needed.
The key insight (splitting linkAt into url|junk|path and folding the scan into one regex) is exactly right — it kills the class of bug where a URL fragment leaks through as a bogus path. The {1,255} segment bound is the real win: caught the O(n²) hover-underline stall before it shipped, and there's a 40k-char blob timing test guarding it. 20/20 tests pass, tsc clean.
Checked the two things I'd worry about:
- urlsOnly on the scratch shell → path tokens no longer arm the opener in AuxTerminal, so no swallowed clicks under a mouse-reporting TUI. Confirmed.
- picker focus → onCloseAutoFocus routes to termRef on dismiss, leaves it for the editor on pick.
One cosmetic note: Windows C:/ drive paths get eaten by the scp-remote branch — don't care, this is a Mac app. Bare domains/emails still underline and resolve to nothing, already called out. Fine tradeoff.
Thanks, nice work.
Cmd/Ctrl+click a file path printed in a terminal to open it in the editor. Agents reference files (src/foo.ts:42); this makes those references jump straight to the file instead of requiring a manual search.
The flow
pathclick-demo.mp4
Design notes
xterm-link-providerrejected to avoid unjustified dependency.Testing
Unit tests for path parsing and suffix matching. make check-all clean.
Also have an uncommitted e2e test script and demo recording script.