-
Notifications
You must be signed in to change notification settings - Fork 9.2k
Fix detecting partially visible URLs #19878
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
88a363c
f797862
b113b00
28fd58d
285f19c
caf69f6
6d5031a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -513,52 +513,27 @@ std::wstring Terminal::GetHyperlinkAtViewportPosition(const til::point viewportP | |
|
|
||
| std::wstring Terminal::GetHyperlinkAtBufferPosition(const til::point bufferPos) | ||
| { | ||
| const auto& buffer = _activeBuffer(); | ||
|
|
||
| // Case 1: buffer position has a hyperlink stored in the buffer | ||
| const auto attr = _activeBuffer().GetCellDataAt(bufferPos)->TextAttr(); | ||
| const auto attr = buffer.GetCellDataAt(bufferPos)->TextAttr(); | ||
| if (attr.IsHyperlink()) | ||
| { | ||
| return _activeBuffer().GetHyperlinkUriFromId(attr.GetHyperlinkId()); | ||
| return buffer.GetHyperlinkUriFromId(attr.GetHyperlinkId()); | ||
| } | ||
|
|
||
| // Case 2: buffer position may point to an auto-detected hyperlink | ||
| // Case 2 - Step 1: get the auto-detected hyperlink | ||
| std::optional<interval_tree::Interval<til::point, size_t>> result; | ||
| const auto visibleViewport = _GetVisibleViewport(); | ||
| if (visibleViewport.IsInBounds(bufferPos)) | ||
| // Check cached interval tree (covers visible viewport +/- viewport height) | ||
| if (const auto results = _patternIntervalTree.findOverlapping({ bufferPos.x + 1, bufferPos.y }, bufferPos); !results.empty()) | ||
| { | ||
| // Hyperlink is in the current view, so let's just get it | ||
| auto viewportPos = bufferPos; | ||
| visibleViewport.ConvertToOrigin(&viewportPos); | ||
| result = GetHyperlinkIntervalFromViewportPosition(viewportPos); | ||
| if (result.has_value()) | ||
| { | ||
| result->start = _ConvertToBufferCell(result->start, false); | ||
| result->stop = _ConvertToBufferCell(result->stop, true); | ||
| } | ||
| } | ||
| else | ||
| { | ||
| // Hyperlink is outside of the current view. | ||
| // We need to find if there's a pattern at that location. | ||
| const auto patterns = _getPatterns(bufferPos.y, bufferPos.y); | ||
|
|
||
| // NOTE: patterns is stored with top y-position being 0, | ||
| // so we need to cleverly set the y-pos to 0. | ||
| const til::point viewportPos{ bufferPos.x, 0 }; | ||
| const auto results = patterns.findOverlapping(viewportPos, viewportPos); | ||
| if (!results.empty()) | ||
| for (const auto& result : results) | ||
| { | ||
| result = results.front(); | ||
| result->start.y += bufferPos.y; | ||
| result->stop.y += bufferPos.y; | ||
| if (result.value == _hyperlinkPatternId) | ||
| { | ||
| return buffer.GetPlainText(result.start, result.stop); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // Case 2 - Step 2: get the auto-detected hyperlink | ||
| if (result.has_value() && result->value == _hyperlinkPatternId) | ||
| { | ||
| return _activeBuffer().GetPlainText(result->start, result->stop); | ||
| } | ||
| return {}; | ||
| } | ||
|
|
||
|
|
@@ -578,17 +553,25 @@ uint16_t Terminal::GetHyperlinkIdAtViewportPosition(const til::point viewportPos | |
| // Arguments: | ||
| // - The position relative to the viewport | ||
| // Return value: | ||
| // - The interval representing the start and end coordinates | ||
| // - The interval representing the start and end coordinates (viewport-relative) | ||
| std::optional<PointTree::interval> Terminal::GetHyperlinkIntervalFromViewportPosition(const til::point viewportPos) | ||
| { | ||
| const auto results = _patternIntervalTree.findOverlapping({ viewportPos.x + 1, viewportPos.y }, viewportPos); | ||
| // GH#18177: The tree stores buffer-absolute coordinates | ||
| // Convert viewport-relative (y=0 at visible start) to buffer-absolute | ||
| const auto visStart = _VisibleStartIndex(); | ||
| const til::point bufferPos{ viewportPos.x, viewportPos.y + visStart }; | ||
| const auto results = _patternIntervalTree.findOverlapping({ bufferPos.x + 1, bufferPos.y }, bufferPos); | ||
| if (results.size() > 0) | ||
| { | ||
| for (const auto& result : results) | ||
| { | ||
| if (result.value == _hyperlinkPatternId) | ||
| { | ||
| return result; | ||
| // Convert back to viewport-relative coordinates | ||
| auto interval = result; | ||
| interval.start.y -= visStart; | ||
| interval.stop.y -= visStart; | ||
| return interval; | ||
| } | ||
| } | ||
| } | ||
|
|
@@ -807,11 +790,8 @@ TerminalInput::OutputType Terminal::FocusChanged(const bool focused) | |
| // - The interval tree containing regions that need to be invalidated | ||
| void Terminal::_InvalidatePatternTree() | ||
| { | ||
| const auto vis = _VisibleStartIndex(); | ||
| _patternIntervalTree.visit_all([&](const PointTree::interval& interval) { | ||
| const til::point startCoord{ interval.start.x, interval.start.y + vis }; | ||
| const til::point endCoord{ interval.stop.x, interval.stop.y + vis }; | ||
| _InvalidateFromCoords(startCoord, endCoord); | ||
| _InvalidateFromCoords(interval.start, interval.stop); | ||
| }); | ||
| } | ||
|
|
||
|
|
@@ -1209,7 +1189,16 @@ void Terminal::SetPlayMidiNoteCallback(std::function<void(const int, const int, | |
| void Terminal::UpdatePatternsUnderLock() | ||
| { | ||
| _InvalidatePatternTree(); | ||
| _patternIntervalTree = _getPatterns(_VisibleStartIndex(), _VisibleEndIndex()); | ||
| const auto visStart = _VisibleStartIndex(); | ||
| const auto visEnd = _VisibleEndIndex(); | ||
| const auto viewportHeight = visEnd - visStart; | ||
|
|
||
| // GH#18177: Scan extra rows beyond the viewport so that URLs | ||
| // wrapping across the viewport boundary are matched in full | ||
| const auto bufferSize = _activeBuffer().GetSize(); | ||
| const auto beg = std::max<til::CoordType>(0, visStart - viewportHeight); | ||
| const auto end = std::min(bufferSize.BottomInclusive(), visEnd + viewportHeight); | ||
|
Comment on lines
+1196
to
+1200
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we trim the results? For instance, we could pass both a start/end range for search, as well as a start/end range for filtering the search to
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Eh. |
||
| _patternIntervalTree = _getPatterns(beg, end); | ||
| _InvalidatePatternTree(); | ||
| } | ||
|
|
||
|
|
@@ -1424,10 +1413,8 @@ PointTree Terminal::_getPatterns(til::CoordType beg, til::CoordType end) const | |
| { | ||
| do | ||
| { | ||
| auto range = ICU::BufferRangeFromMatch(&text, re.get()); | ||
| // PointTree uses half-open ranges and viewport-relative coordinates. | ||
| range.start.y -= beg; | ||
| range.end.y -= beg; | ||
| // PointTree uses half-open ranges and buffer-absolute coordinates. | ||
| const auto range = ICU::BufferRangeFromMatch(&text, re.get()); | ||
| intervals.push_back(PointTree::interval(range.start, range.end, 0)); | ||
| } while (uregex_findNext(re.get(), &status)); | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why
x+1?