Skip to content

fix(desktop): improve terminal link handling with CMD+click and wrapp…#197

Merged
Kitenite merged 2 commits into
mainfrom
azure-valley-11
Dec 1, 2025
Merged

fix(desktop): improve terminal link handling with CMD+click and wrapp…#197
Kitenite merged 2 commits into
mainfrom
azure-valley-11

Conversation

@Kitenite
Copy link
Copy Markdown
Collaborator

@Kitenite Kitenite commented Dec 1, 2025

…ed line support

  • Require CMD+click (Mac) or Ctrl+click (Windows/Linux) to open URLs and file paths
  • Handle file paths that span wrapped terminal lines by checking both previous and next lines
  • Add comprehensive tests for FilePathLinkProvider covering all scenarios

🤖 Generated with Claude Code

Description

Related Issues

Type of Change

  • Bug fix
  • New feature
  • Documentation
  • Refactor
  • Other (please describe):

Testing

Screenshots (if applicable)

Additional Notes

Summary by CodeRabbit

  • New Features

    • Improved terminal file-path linking that correctly detects links spanning wrapped lines, parses line/column, and shows pointer cursor on hover.
    • Terminal links/URLs now only open when modifier key is held (Cmd on macOS, Ctrl on Windows/Linux).
  • Tests

    • Added comprehensive test suite covering detection, multi-line wrapping, activation behavior, filtering of false positives, and edge cases.

✏️ Tip: You can customize this high-level summary in your review settings.

…ed line support

- Require CMD+click (Mac) or Ctrl+click (Windows/Linux) to open URLs and file paths
- Handle file paths that span wrapped terminal lines by checking both previous and next lines
- Add comprehensive tests for FilePathLinkProvider covering all scenarios

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented Dec 1, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
website Ready Ready Preview Comment Dec 1, 2025 2:27am

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Dec 1, 2025

Walkthrough

Adds wrap-aware file-path link detection in the terminal (multi-line matching and precise multi-line ranges), requires modifier key for URL activation, and introduces comprehensive tests covering detection, wrapping, filtering, activation, and edge cases.

Changes

Cohort / File(s) Summary
File path linking (implementation & tests)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/FilePathLinkProvider.ts, apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/FilePathLinkProvider.test.ts
Implements wrap-aware path matching by composing previous/current/next wrapped lines, computes multi-line link ranges via a new helper, filters out URLs/version/npm/pure-number false positives, enforces modifier-key activation, and adds extensive tests for absolute/relative/home paths, line/column parsing, multi-path lines, wrapping (forward/backward/3-line), non-wrapped behavior, hover/leave/cursor, activation callbacks, and edge cases.
Terminal URL activation gate
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/helpers.ts
Adds a modifier-key gate to the WebLinksAddon URL handler so URLs open only when metaKey (macOS) or ctrlKey (Windows/Linux) is pressed; otherwise handler returns early.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Inspect multi-line composition and index arithmetic in FilePathLinkProvider.ts (off-by-one and wrapped-range corner cases).
  • Verify regex filters do not introduce false negatives for valid paths or false positives for URLs/version/npm tokens.
  • Review tests in FilePathLinkProvider.test.ts for coverage accuracy and brittle assumptions about terminal wrapping behavior.
  • Confirm modifier-key logic in helpers.ts correctly distinguishes macOS vs. other platforms and integrates with existing WebLinksAddon behavior.

Possibly related PRs

  • add xterm addons #124 — Modifies terminal link handling and xterm integration, touching FilePathLinkProvider and WebLinksAddon-related behavior.

Poem

🐰 With a twitch and a hop I stitched each line,

Paths that span, now perfectly align.
Hold your key, give the link a click,
I threaded wraps both thin and thick.
Happy hops — the terminal's looking fine! 🥕✨

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description check ⚠️ Warning The description includes bullet points of key changes but lacks completion of required template sections like Related Issues, Type of Change, Testing, and Additional Notes. Complete the PR description template by filling in Related Issues (if applicable), selecting the Type of Change, describing tests performed, and adding any other relevant context.
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main changes: improving terminal link handling with CMD+click modifier requirement and wrapped line support.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch azure-valley-11

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ae4841f and 0914756.

📒 Files selected for processing (2)
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/FilePathLinkProvider.test.ts (1 hunks)
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/FilePathLinkProvider.ts (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/FilePathLinkProvider.test.ts
🧰 Additional context used
📓 Path-based instructions (4)
apps/desktop/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)

For Electron interprocess communication, ALWAYS use tRPC as defined in src/lib/trpc

Files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/FilePathLinkProvider.ts
apps/desktop/**/*.{ts,tsx}

📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)

apps/desktop/**/*.{ts,tsx}: Please use alias as defined in tsconfig.json when possible
Prefer zustand for state management if it makes sense. Do not use effect unless absolutely necessary

Files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/FilePathLinkProvider.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Avoid using any type - use explicit types instead for type safety
Use camelCase for variable and function names following existing codebase patterns
Keep diffs minimal with targeted edits only - avoid unnecessary changes when making modifications
Follow existing patterns and match the codebase style when writing new code

Files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/FilePathLinkProvider.ts
apps/desktop/src/renderer/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Never import Node.js modules (fs, path, os, net, etc.) in renderer process code - browser environment only

Files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/FilePathLinkProvider.ts
🧠 Learnings (1)
📚 Learning: 2025-11-28T01:03:47.963Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-28T01:03:47.963Z
Learning: Applies to **/*.{ts,tsx} : Keep diffs minimal with targeted edits only - avoid unnecessary changes when making modifications

Applied to files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/FilePathLinkProvider.ts
🪛 ast-grep (0.40.0)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/FilePathLinkProvider.ts

[warning] 51-51: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(this.FILE_PATH_PATTERN, "g")
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Build
🔇 Additional comments (7)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/FilePathLinkProvider.ts (7)

1-16: LGTM!

Clean imports and well-typed constructor. The FILE_PATH_PATTERN regex is properly defined as a private readonly member.


18-31: LGTM!

Proper 1-to-0 index conversion and clean early return on missing line.


33-49: LGTM!

The wrap-aware line handling is well-implemented. Correctly fetches adjacent lines only when needed and properly calculates the offset for the current line within the combined text.


51-52: Static analysis false positive - regex is from a class constant, not user input.

The warning about ReDoS is not applicable here because this.FILE_PATH_PATTERN is a hardcoded readonly class property, not variable user input. The pattern is safe.


100-121: LGTM!

Link creation is clean. The arrow function in activate correctly preserves this context for handleActivation.


123-173: LGTM!

The multi-line range calculation correctly handles 1-based xterm coordinates. The defensive branch at lines 159-162 is unreachable due to the earlier filter (as the comment notes), but it's harmless.


175-189: LGTM!

Clean modifier key gating (meta for macOS, ctrl for Windows/Linux) aligns with the PR objectives. The parseLineColumnPath integration is correct.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/FilePathLinkProvider.ts (1)

46-49: Consider documenting the 3-line wrap limitation.

The implementation combines at most 3 lines (prev + current + next) for path detection. While this covers virtually all realistic scenarios, paths spanning 4+ wrapped lines won't be fully detected. Consider adding a brief comment documenting this design choice.

-		// Combined text for matching paths that may span wrap points
-		// Format: [prevLine] + currentLine + [nextLine]
+		// Combined text for matching paths that may span wrap points (up to 3 lines)
+		// Format: [prevLine] + currentLine + [nextLine]
+		// Note: Paths spanning 4+ wrapped lines are not supported (extremely rare edge case)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c486937 and ae4841f.

📒 Files selected for processing (3)
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/FilePathLinkProvider.test.ts (1 hunks)
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/FilePathLinkProvider.ts (2 hunks)
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/helpers.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
apps/desktop/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)

For Electron interprocess communication, ALWAYS use tRPC as defined in src/lib/trpc

Files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/FilePathLinkProvider.test.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/helpers.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/FilePathLinkProvider.ts
apps/desktop/**/*.{ts,tsx}

📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)

apps/desktop/**/*.{ts,tsx}: Please use alias as defined in tsconfig.json when possible
Prefer zustand for state management if it makes sense. Do not use effect unless absolutely necessary

Files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/FilePathLinkProvider.test.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/helpers.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/FilePathLinkProvider.ts
apps/desktop/**/*.test.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)

apps/desktop/**/*.test.{ts,tsx,js,jsx}: Tests should have one assert per test
Tests should be readable
Tests should be fast
Tests should be independent
Tests should be repeatable

Files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/FilePathLinkProvider.test.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Avoid using any type - use explicit types instead for type safety
Use camelCase for variable and function names following existing codebase patterns
Keep diffs minimal with targeted edits only - avoid unnecessary changes when making modifications
Follow existing patterns and match the codebase style when writing new code

Files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/FilePathLinkProvider.test.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/helpers.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/FilePathLinkProvider.ts
apps/desktop/src/renderer/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Never import Node.js modules (fs, path, os, net, etc.) in renderer process code - browser environment only

Files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/FilePathLinkProvider.test.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/helpers.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/FilePathLinkProvider.ts
🧠 Learnings (5)
📚 Learning: 2025-11-24T21:33:13.267Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: apps/desktop/AGENTS.md:0-0
Timestamp: 2025-11-24T21:33:13.267Z
Learning: Applies to apps/desktop/**/*.test.{ts,tsx,js,jsx} : Tests should be readable

Applied to files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/FilePathLinkProvider.test.ts
📚 Learning: 2025-11-24T21:33:13.267Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: apps/desktop/AGENTS.md:0-0
Timestamp: 2025-11-24T21:33:13.267Z
Learning: Applies to apps/desktop/**/*.test.{ts,tsx,js,jsx} : Tests should be independent

Applied to files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/FilePathLinkProvider.test.ts
📚 Learning: 2025-11-24T21:33:13.267Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: apps/desktop/AGENTS.md:0-0
Timestamp: 2025-11-24T21:33:13.267Z
Learning: Applies to apps/desktop/**/*.test.{ts,tsx,js,jsx} : Tests should be repeatable

Applied to files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/FilePathLinkProvider.test.ts
📚 Learning: 2025-11-28T01:03:47.963Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-28T01:03:47.963Z
Learning: Applies to **/components/**/*.tsx : Co-locate tests next to the component file they test (e.g., `ComponentName.test.tsx`)

Applied to files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/FilePathLinkProvider.test.ts
📚 Learning: 2025-11-28T01:03:47.963Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-28T01:03:47.963Z
Learning: Applies to **/*.{ts,tsx} : Keep diffs minimal with targeted edits only - avoid unnecessary changes when making modifications

Applied to files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/FilePathLinkProvider.ts
🧬 Code graph analysis (1)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/FilePathLinkProvider.test.ts (1)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/FilePathLinkProvider.ts (1)
  • FilePathLinkProvider (4-209)
🪛 ast-grep (0.40.0)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/FilePathLinkProvider.ts

[warning] 51-51: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(this.FILE_PATH_PATTERN, "g")
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Build
🔇 Additional comments (10)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/helpers.ts (1)

65-74: LGTM!

The modifier key gate correctly ensures URLs only open on CMD+click (macOS) or Ctrl+click (Windows/Linux), which aligns with the FilePathLinkProvider's activation behavior. This provides a consistent UX across both URL and file path links.

apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/FilePathLinkProvider.ts (3)

51-52: Static analysis false positive - pattern is a class constant, not user input.

The ast-grep warning about ReDoS is a false positive here. FILE_PATH_PATTERN is a readonly class constant defined at line 5-6, not constructed from user-provided input. The pattern is static and controlled by the developer.


130-180: LGTM - calculateLinkRange correctly handles multi-line coordinates.

The coordinate calculations properly account for xterm's 1-based indexing and handle all cases where paths span previous, current, and/or next lines. The defensive branch at lines 166-169 is appropriately guarded with a comment.


18-128: LGTM - Well-structured wrap-aware link detection.

The provideLinks method correctly:

  • Handles 1-based to 0-based line number conversion
  • Detects wrapped lines in both directions (prev/next)
  • Filters false positives (URLs, versions, npm refs, pure numbers)
  • Only processes matches that overlap the current line
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/FilePathLinkProvider.test.ts (6)

1-46: LGTM - Well-designed test helpers.

The mock helpers (createMockLine, createMockTerminal, getLinks) are clean and provide good abstractions for testing the FilePathLinkProvider. Each test creates its own isolated mocks, ensuring independence and repeatability as per coding guidelines.


49-124: Good coverage of basic path detection scenarios.

Tests cover all expected path formats (absolute, relative, home directory, with line/column). While some tests have 2 assertions, they're testing closely related properties of the same result, which is acceptable for readability. As per coding guidelines, tests are independent and repeatable.


126-182: LGTM - Thorough false positive filtering tests.

Each filtering test has a single assertion (expect(links.length).toBe(0)), following the "one assert per test" guideline. Good coverage of URLs, versions, npm references, and pure numbers.


184-305: Excellent coverage of wrapped line scenarios.

Tests cover forward-looking, backward-looking, and three-line wrapping cases. The range coordinate assertions (lines 202-217) test interconnected properties that logically belong together. Non-wrapped line tests correctly verify lines aren't incorrectly combined.


360-378: Multiple assertions test a single logical outcome.

Lines 374-377 have 4 assertions, but they're verifying the arguments of a single onOpen call. Per coding guidelines, splitting these into 4 separate tests would reduce readability without improving test quality. This approach is acceptable.


381-442: LGTM - Good edge case coverage.

Cursor styling tests have single assertions each. Edge cases cover empty lines, non-existent lines, and paths without leading directory markers. Tests are readable and follow the established patterns.

…kProvider

Remove hover/leave handlers that were setting cursor style - the CSS
already handles cursor:pointer for links. This simplifies the code
by keeping only the CMD+click activation logic.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@Kitenite Kitenite merged commit 325d518 into main Dec 1, 2025
7 checks passed
@Kitenite Kitenite deleted the azure-valley-11 branch December 1, 2025 02:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant