Repository: microsoft/terminal
File: src/cascadia/TerminalCore/TerminalSelection.cpp (C++)

Code before:
    // signifying that the other endpoint is the one we want to move.
    const auto movingEnd{ _selection->start == _selection->pivot };
    auto targetPos{ movingEnd ? _selection->end : _selection->start };

    // 2. Perform the movement
    switch (mode)
    {
    case SelectionExpansion::Char:
        _MoveByChar(direction, targetPos);
        break;
    case SelectionExpansion::Word:
        _MoveByWord(direction, targetPos);
        break;
    case SelectionExpansion::Viewport:
        _MoveByViewport(direction, targetPos);
        break;
    case SelectionExpansion::Buffer:
        _MoveByBuffer(direction, targetPos);
        break;
    }

    // 3. Actually modify the selection
    if (_markMode && !mods.IsShiftPressed())
    {
        // [Mark Mode] + shift unpressed --> move all three (i.e. just use arrow keys)
        _selection->start = targetPos;
        _selection->end = targetPos;
        _selection->pivot = targetPos;
    }
    else
    {
        // [Mark Mode] + shift --> updating a standard selection
        // NOTE: targetStart doesn't matter here
        auto targetStart = false;
        std::tie(_selection->start, _selection->end) = _PivotSelection(targetPos, targetStart);
    }

    // 4. Scroll (if necessary)
    if (const auto viewport = _GetVisibleViewport(); !viewport.IsInBounds(targetPos))
    {
        if (const auto amtAboveView = viewport.Top() - targetPos.Y; amtAboveView > 0)
        {
            // anchor is above visible viewport, scroll by that amount
            _scrollOffset += amtAboveView;
        }
        else
        {
            // anchor is below visible viewport, scroll by that amount
            const auto amtBelowView = targetPos.Y - viewport.BottomInclusive();
            _scrollOffset -= amtBelowView;
        }

Review comment (suggestion):
Changes to this function may seem a little odd and unrelated, but they're necessary. Now that we're displaying the relevant y-beam end based on which endpoint we're moving, we need to make sure we're moving the correct one. Before, we could cheat it a bit since we didn't really have a concept of "start" and "end" (more just point 1 and 2).

Code after:
    }
    return std::nullopt;
}

bool Terminal::MovingEnd() const noexcept
{
    // true --> we're moving end endpoint ("lower")
    // false --> we're moving start endpoint ("higher")
    return _selection->start == _selection->pivot;
}

bool Terminal::MovingCursor() const noexcept
{
    // Relevant for keyboard selection:
    // true --> the selection is just a "cursor"; we're moving everything together with arrow keys
    // false --> otherwise
    return _selection->start == _selection->pivot && _selection->pivot == _selection->end;
}

// Method Description:
// - updates the selection endpoints based on a direction and expansion mode. Primarily used for keyboard selection.
// Arguments:
// - direction: the direction to move the selection endpoint in
// - mode: the type of movement to be performed (i.e. move by word)
// - mods: the key modifiers pressed when performing this update
void Terminal::UpdateSelection(SelectionDirection direction, SelectionExpansion mode, ControlKeyStates mods)
{
    // 1. Figure out which endpoint to update
    // One of the endpoints is the pivot,
    // signifying that the other endpoint is the one we want to move.
    auto targetPos{ MovingEnd() ? _selection->end : _selection->start };

    // 2. Perform the movement
    switch (mode)
    {
    case SelectionExpansion::Char:
        _MoveByChar(direction, targetPos);
        break;
    case SelectionExpansion::Word:
        _MoveByWord(direction, targetPos);
        break;
    case SelectionExpansion::Viewport:
        _MoveByViewport(direction, targetPos);
        break;
    case SelectionExpansion::Buffer:
        _MoveByBuffer(direction, targetPos);
        break;
    }

    // 3. Actually modify the selection
    if (_markMode && !mods.IsShiftPressed())