feat: Enhanced hyperlink system with rich metadata, selection improvements, and migration guide#207
Conversation
1. Cache invalidation for buildLineIndexCache() - Track last snapshot by identity to avoid unnecessary rebuilds - Add invalidateCache() method for manual cache clearing 2. Configurable selection alpha - Add selectionAlpha setting (default 0.6f) for transparency - Apply alpha to selectionColorValue for improved text readability 3. URL regex robustness - Support more URL schemes: ftp, ftps, ssh, file, mailto - Use RFC 3986 compliant character set - Add www URL pattern and mailto pattern 4. Unit tests for selection - 40+ tests covering URLs, emails, paths, quoted strings - Edge cases: empty strings, boundaries, whitespace - Long line windowing tests - Pattern priority verification 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Code Review - PR #207: Selection System Follow-up ImprovementsOverviewThis PR implements all 4 tasks from issue #204 with solid implementation quality. The code is well-structured, thoroughly tested, and follows the project's conventions. Overall, this is excellent work and ready to merge with only minor suggestions. ✅ Strengths
🔍 Code Quality ObservationsSelectionTracker.ktExcellent: Cache invalidation logic is clean and safe. Identity check Minor suggestion: Consider adding a comment about thread safety expectations: /**
* Invalidate the cache, forcing a rebuild on next resolveToCoordinates() call.
* Call this if external factors may have changed line positions.
* Thread safety: Must be called from UI thread only (same as other methods).
*/
fun invalidateCache() {
lastCachedSnapshot = null
}SmartWordSelection.ktVery good: The regex patterns are well thought out. However, I noticed a potential issue: regex = Regex("""(?<![/\w])www\.[\w\-._~:/?#\[\]@!$&'()*+,;=%]+""")The negative lookbehind regex = Regex("""(?<!/)(?<!\w)www\.[\w\-._~:/?#\[\]@!$&'()*+,;=%]+""")Or more elegantly: regex = Regex("""(?<![/\w])www\.[\w\-._~:/?#\[\]@!$&'()*+,;=%]+""")Actually, looking more carefully, character classes in lookbehinds DO work correctly in Kotlin regex. This is not an issue - my apologies for the confusion. The pattern is correct as-is. SmartWordSelectionTest.ktExcellent test coverage. A few suggestions:
@Test
fun testWwwUrlNotInMiddleOfPath() {
// Should NOT match www in "http://example.com/www.backup"
val text = "Check http://example.com/www.backup here"
val result = SmartWordSelection.selectWordAt(text, 30) // On "www"
assertNotNull(result)
// Should select entire URL, not just www.backup
assertTrue(text.substring(result.first, result.second + 1).startsWith("http://"))
}
@Test
fun testUrlWithTrailingPunctuation() {
// Common case: URL at end of sentence
val text = "Visit https://example.com."
val result = SmartWordSelection.selectWordAt(text, 15)
assertNotNull(result)
// Should NOT include trailing period
assertEquals("https://example.com", text.substring(result.first, result.second + 1))
}
@Test
fun testMailtoWithQueryParams() {
val text = "Send to mailto:user@example.com?subject=Hello&body=World"
val result = SmartWordSelection.selectWordAt(text, 15)
assertNotNull(result)
assertEquals("mailto:user@example.com?subject=Hello&body=World",
text.substring(result.first, result.second + 1))
}TerminalSettings.ktPerfect: The 🔒 Security Considerations✅ No security concerns identified. Regex patterns are for matching only (no eval/exec). ⚡ Performance Considerations
📝 DocumentationGood: Comments are clear and helpful. KDoc is present on public APIs. Suggestion: Add KDoc to /**
* Selection highlight opacity (0.0 to 1.0).
* Lower values make text more readable through selection highlight.
* Default 0.6 provides good contrast while keeping text visible.
* Values outside 0.0-1.0 will be clamped automatically.
*/
val selectionAlpha: Float = 0.6f,🧪 Test Coverage AssessmentExcellent: 40+ tests covering:
Missing (non-blocking, future enhancement):
🎯 RecommendationsBefore Merge:
Future Enhancements (separate PR):
✅ Final VerdictLGTM with minor documentation suggestions. This PR:
Approval Status: Approved pending successful test execution. Great work! This is a solid contribution that improves the selection system meaningfully while maintaining code quality. Reviewed by Claude Code using project guidelines from CLAUDE.md |
Implements semantic history feature allowing Ctrl+Click on file paths to open them: - Add FilePathResolver.kt for path resolution and validation - Supports absolute Unix paths (/path/to/file) - Supports Windows paths (C:\path\to\file) - Supports home-relative paths (~/path) - Supports relative paths (./path, ../path) using OSC 7 working directory - Includes caching for path existence checks (5s TTL) - Extend HyperlinkPattern with pathValidator for file path patterns - pathValidator returns resolved file:// URL if path exists, null otherwise - Patterns with pathValidator only create hyperlinks for existing paths - Add built-in path patterns to HyperlinkRegistry: - builtin:path-home (priority -5): ~/path - builtin:path-relative (priority -6): ./path, ../path - builtin:path-unix (priority -7): /absolute/path - builtin:path-windows (priority -7): C:\path - Pass workingDirectory through rendering chain: - RenderingContext.workingDirectory from TerminalSession - detectHyperlinks() and detectHyperlinksWithWrapping() accept workingDirectory - Add detectFilePaths setting to enable/disable feature (default: true) - Settings: detectFilePaths in TerminalSettings and TerminalSettingsOverride 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Code Review: Selection System Follow-up Improvements (#204)SummaryThis PR successfully implements all 4 tasks from issue #204 with high-quality code. The implementation is well-architected, thoroughly tested, and follows the project's conventions. Great work overall! ✅ Strengths1. Excellent Test Coverage (SmartWordSelectionTest.kt)
2. Clean Cache Invalidation (SelectionTracker.kt)
3. Extended URL Pattern Support (SmartWordSelection.kt)
4. Configurable Selection Alpha (TerminalSettings.kt)
5. New FilePathResolver (158 lines)
🔍 Issues & Concerns1. Test File Location Mismatch (CRITICAL)File: The test file is placed in
Recommendation: # Move to correct location
git mv compose-ui/src/commonTest/kotlin/ai/rever/bossterm/compose/selection/SmartWordSelectionTest.kt \
compose-ui/src/desktopTest/kotlin/ai/rever/bossterm/compose/selection/SmartWordSelectionTest.kt2. File Path Hyperlink Detection May Have Performance ImpactFiles: The new file path detection adds 4 patterns that perform filesystem I/O:
Concerns:
Recommendations:
3. Path Validation InconsistencyFile: val url = if (pattern.pathValidator != null) {
pattern.pathValidator.invoke(match.value, workingDirectory) ?: continue
} else {
pattern.urlTransformer(match.value)
}When
Question: Is this the intended behavior? Consider:
4. Regex Pattern Edge CasesFile: regex = Regex("""(?:https?|ftps?|ssh|file)://[\w\-._~:/?#\[\]@!$&'()*+,;=%]+""")Issues:
Example failure cases:
Recommendation: Consider iTerm2's approach:
5. Missing Test Coverage for FilePathResolverFile: No test file for This is a complex utility with:
Recommendation: Add
🎯 Best Practices & Style✅ Good
|
Tests for FilePathResolver: - Path resolution (absolute, home, relative, Windows) - Path validation with caching - URL conversion - Quick check methods - Edge cases (special chars, Unicode, blank paths) Tests for HyperlinkDetector path detection: - Absolute Unix path detection - Home path (~/) detection - Relative path (./,../) detection with working directory - detectFilePaths setting (enable/disable) - Pattern priority (URLs take precedence) - Registry pattern validation 114 total tests, all passing. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Updated Code Review - PR #207 (Final Review)I've reviewed the latest changes (commits c04ce50 and f91c2b3). Great work addressing the previous feedback! The addition of FilePathResolverTest.kt (233 lines) and HyperlinkDetectorPathTest.kt (335 lines) significantly improves test coverage. 🎯 Status: Almost Ready to Merge✅ What's Been Fixed Since Last Review
|
Change onLinkClick signature from ((String) -> Unit)? to ((HyperlinkInfo) -> Unit)?
to provide comprehensive link metadata including:
- HyperlinkType enum: HTTP, FILE, FOLDER, EMAIL, FTP, CUSTOM
- isFile/isFolder: File system validation results
- scheme: URL scheme (http, https, file, mailto, etc.)
- patternId: Pattern that matched (e.g., "builtin:http", "jira")
- matchedText: Original text that was matched
- isBuiltin: Whether matched by builtin pattern
This enables host applications to handle different link types appropriately:
- Open files in editor vs folders in Finder
- Track analytics by link type
- Handle custom patterns (e.g., JIRA tickets) specially
Breaking change: Existing onLinkClick users must update from
`{ url -> ... }` to `{ info -> ... }` (use info.url for the URL).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
…istry - Change onLinkClick signature to return Boolean (true=handled, false=use default) - Unhandled links now fall back to default behavior (open in browser/finder) - Document hyperlinkRegistry parameter for custom hyperlink patterns - Update all docs: embedding.md, tabbed-terminal.md, wiki guides 🤖 Generated with [Claude Code](https://claude.com/claude-code)
PR Review: Selection System Follow-up Improvements (#204)Overall AssessmentThis is a well-implemented, comprehensive PR that addresses all 4 tasks from issue #204. The code quality is excellent, with strong test coverage, proper documentation, and thoughtful architectural decisions. ✅ Recommended for merge after addressing a few minor points below. Task-by-Task Review✅ Task 1: Cache Invalidation for
|
- Skip Unix-specific path test on Windows - Use platform-agnostic path construction with File() - Use contains() assertions instead of exact path comparisons 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Code Review: PR #207 - Enhanced Hyperlink SystemThis is an excellent, well-architected PR that significantly enhances BossTerm's hyperlink capabilities. The code quality is high, with comprehensive testing and thoughtful performance optimization. StrengthsArchitecture & Design
Performance Optimizations
Test Coverage
Cross-Platform Support
Issues & Suggestions1. Security: Path Traversal Risk (Medium Priority)Location: FilePathResolver.kt:56-59 While .canonicalFile resolves ../ sequences, there is no validation that resolved paths stay within safe boundaries. Consider adding optional whitelist validation for security-conscious deployments. Severity: Medium - requires user Cmd/Ctrl+Click action 2. Cache Eviction Race Condition (Low Priority)Location: FilePathResolver.kt:85-89 ConcurrentHashMap.entries.removeIf() is not atomic. Consider synchronized block with double-check locking. Impact: Minimal - worst case is redundant evictions 3. Edge Case: Symlink Loops (Low Priority)Location: FilePathResolver.kt:58, 65 .canonicalFile throws IOException on symlink loops. Wrap in try-catch to silently ignore. 4. Documentation: Missing Examples (Low Priority)Add KDoc examples for onLinkClick callback showing different link type handling. 5. Testing: macOS /tmp Symlink Edge CaseTest acknowledges /tmp -> /private/tmp on macOS but does not verify both paths work. Overall AssessmentRating: 5/5 - Production Ready The architecture is excellent, testing is comprehensive, and the feature set is well-designed. Issues are mostly edge cases unlikely to occur in practice. Recommended Actions Before Merge:
Approved for MergeGreat work! This is exactly the kind of thoughtful, well-tested enhancement that makes a terminal emulator production-grade. |
- Update HTTP, FTP, www patterns to use two-part regex - Final character must be non-punctuation (excludes ., ,, ;, !, etc.) - Add 7 tests for trailing punctuation exclusion - Fixes: "Visit https://example.com." now correctly extracts URL without period 🤖 Generated with [Claude Code](https://claude.com/claude-code)
PR Review: Enhanced Hyperlink System with Rich MetadataSummaryThis is a well-architected and thoughtful PR that significantly enhances BossTerm's hyperlink system. The implementation follows best practices with strong thread safety, comprehensive testing, and excellent documentation. ✅ Strengths1. Excellent Architecture
2. Thread Safety
3. Performance Optimizations
4. Comprehensive Testing
5. Documentation
🔍 Code Quality Observations1. API Design - Return Boolean PatternThe new
onLinkClick = { info ->
when (info.type) {
HyperlinkType.FILE -> {
customEditor.open(info.url)
true // Handled
}
HyperlinkType.HTTP -> false // Use default browser
else -> false
}
}2. Path Validation PatternThe
3. Wrapped Line DetectionThe
|
Summary
Hyperlink Enhancements
onLinkClickcallback now receivesHyperlinkInfowith full metadata (type, url, patternId, isFile, isFolder, scheme)onLinkClickreturnsBoolean- returntrueif handled,falseto use default browser/finder behaviorhyperlinkRegistryparameter for per-instance custom patterns (JIRA, GitHub issues, etc.).,,,;,!) from URL matchesSelection System Improvements
selectionAlphasetting (0.0-1.0, default 0.6)Documentation
onLinkClicksignature change fromUnittoBooleanOther Fixes
workingDirectoryparameterBreaking Changes
onLinkClickSignature Change (v1.0.65+)See Migration Guide for details.
Test plan
./gradlew :compose-ui:desktopTestonLinkClickcan returnfalseto trigger default behavior🤖 Generated with Claude Code