Skip to content

Commit 976a54d

Browse files
authored
Allow triple-click to select logical line (#18885)
This fixes #18877, by iteratively checking to see if a line is wrapped and moving up or down accordingly. **Current behavior:** When a user triple-clicks on a line that’s visually wrapped by the terminal, only the single physical row that was clicked gets selected. **Expected behavior:** A triple-click like in xterm, should select the entire logical line including all of its wrapped segments, from the true start through its true end, regardless of where the wrap occurred. **Why it matters:** Logical line selection is what users expect when they’re trying to grab one command or output block in full. Limiting the selection to just the current physical row can lead to copy/paste mistakes and a confusing experience whenever a long line wraps. ## Validation Steps Performed I ran the existing tests using `Invoke-OpenConsoleTests` and they were passing and I was also able to test the build on my machine. I added a test case as well ## PR Checklist Closes #18877
1 parent 06f736b commit 976a54d

File tree

2 files changed

+27
-0
lines changed

2 files changed

+27
-0
lines changed

src/cascadia/TerminalCore/TerminalSelection.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,9 +294,21 @@ std::pair<til::point, til::point> Terminal::_ExpandSelectionAnchors(std::pair<ti
294294

295295
const auto& buffer = _activeBuffer();
296296
const auto bufferSize = buffer.GetSize();
297+
const auto height = buffer.GetSize().Height();
298+
297299
switch (_multiClickSelectionMode)
298300
{
299301
case SelectionExpansion::Line:
302+
// climb up to the first row that is wrapped
303+
while (start.y > 0 && buffer.GetRowByOffset(start.y - 1).WasWrapForced())
304+
{
305+
--start.y;
306+
}
307+
// climb down to the last row that is wrapped
308+
while (end.y + 1 < height && buffer.GetRowByOffset(end.y).WasWrapForced())
309+
{
310+
++end.y;
311+
}
300312
start = { bufferSize.Left(), start.y };
301313
end = { bufferSize.RightExclusive(), end.y };
302314
break;

src/cascadia/UnitTests_TerminalCore/SelectionTest.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,21 @@ namespace TerminalCoreUnitTests
549549
ValidateLinearSelection(term, { 0, 10 }, { term.GetViewport().RightExclusive(), 10 });
550550
}
551551

552+
TEST_METHOD(TripleClick_WrappedLine)
553+
{
554+
Terminal term{ Terminal::TestDummyMarker{} };
555+
DummyRenderer renderer{ &term };
556+
term.Create({ 10, 5 }, 0, renderer);
557+
term.Write(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ");
558+
559+
// Simulate click at (x,y) = (3,1)
560+
auto clickPos = til::point{ 3, 1 };
561+
term.MultiClickSelection(clickPos, Terminal::SelectionExpansion::Line);
562+
563+
// Validate selection area
564+
ValidateLinearSelection(term, { 0, 0 }, { term.GetViewport().RightExclusive(), 2 });
565+
}
566+
552567
TEST_METHOD(TripleClickDrag_Horizontal)
553568
{
554569
Terminal term{ Terminal::TestDummyMarker{} };

0 commit comments

Comments
 (0)