Skip to content

Commit 44f19bd

Browse files
committed
PRE-MERGE #18347 Add support for tabbing to embedded hyperlinks
2 parents a0477d5 + d27cba9 commit 44f19bd

File tree

1 file changed

+52
-6
lines changed

1 file changed

+52
-6
lines changed

src/cascadia/TerminalCore/TerminalSelection.cpp

+52-6
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,8 @@ void Terminal::SelectHyperlink(const SearchDirection dir)
404404
}
405405

406406
// 0. Useful tools/vars
407-
const auto bufferSize = _activeBuffer().GetSize();
407+
const auto& buffer = _activeBuffer();
408+
const auto bufferSize = buffer.GetSize();
408409
const auto viewportHeight = _GetMutableViewport().Height();
409410

410411
// The patterns are stored relative to the "search area". Initially, this search area will be the viewport,
@@ -514,15 +515,60 @@ void Terminal::SelectHyperlink(const SearchDirection dir)
514515
searchArea = Viewport::FromDimensions(searchStart, { searchEnd.x + 1, searchEnd.y + 1 });
515516
}
516517
}
518+
}
517519

518-
// 1.C) Nothing was found. Bail!
519-
if (!result.has_value())
520+
// 2. We found a hyperlink from the pattern tree. Look for embedded hyperlinks too!
521+
// Use the result (if one was found) to narrow down the search.
522+
searchStart = dir == SearchDirection::Forward ?
523+
_selection->start :
524+
(result ? result->second : bufferSize.Origin());
525+
searchEnd = dir == SearchDirection::Forward ?
526+
(result ? result->first : buffer.GetLastNonSpaceCharacter()) :
527+
_selection->start;
528+
auto iter = buffer.GetCellDataAt(dir == SearchDirection::Forward ? searchStart : searchEnd);
529+
while (dir == SearchDirection::Forward ? iter.Pos() < searchEnd : iter.Pos() > searchStart)
530+
{
531+
// Don't let us select the same hyperlink again
532+
if (iter.Pos() < _selection->start || iter.Pos() > _selection->end)
520533
{
521-
return;
534+
if (auto attr = iter->TextAttr(); attr.IsHyperlink())
535+
{
536+
// Found an embedded hyperlink!
537+
const auto hyperlinkId = attr.GetHyperlinkId();
538+
539+
// Expand the start to include the entire hyperlink
540+
TextBufferCellIterator hyperlinkStartIter{ buffer, iter.Pos() };
541+
while (attr.IsHyperlink() && attr.GetHyperlinkId() == hyperlinkId)
542+
{
543+
hyperlinkStartIter--;
544+
attr = hyperlinkStartIter->TextAttr();
545+
}
546+
// undo a move to be inclusive
547+
hyperlinkStartIter++;
548+
549+
// Expand the end to include the entire hyperlink
550+
// No need to undo a move! We'll decrement in the next step anyways.
551+
TextBufferCellIterator hyperlinkEndIter{ buffer, iter.Pos() };
552+
attr = hyperlinkEndIter->TextAttr();
553+
while (attr.IsHyperlink() && attr.GetHyperlinkId() == hyperlinkId)
554+
{
555+
hyperlinkEndIter++;
556+
attr = hyperlinkEndIter->TextAttr();
557+
}
558+
559+
result = { hyperlinkStartIter.Pos(), hyperlinkEndIter.Pos() };
560+
break;
561+
}
522562
}
563+
iter += dir == SearchDirection::Forward ? 1 : -1;
523564
}
524565

525-
// 2. Select the hyperlink
566+
// 3. Select the hyperlink, if one exists
567+
if (!result.has_value())
568+
{
569+
return;
570+
}
571+
else
526572
{
527573
auto selection{ _selection.write() };
528574
wil::hide_name _selection;
@@ -534,7 +580,7 @@ void Terminal::SelectHyperlink(const SearchDirection dir)
534580
_selectionEndpoint = SelectionEndpoint::End;
535581
}
536582

537-
// 3. Scroll to the selected area (if necessary)
583+
// 4. Scroll to the selected area (if necessary)
538584
_ScrollToPoint(_selection->end);
539585
}
540586

0 commit comments

Comments
 (0)