Repository: microsoft/terminal
File: src/buffer/out/textBuffer.cpp (C++)

Code before:
    }
    return {};
}

// Method Description:
// - Copies the hyperlink/customID maps of the old buffer into this one,
//   also copies currentHyperlinkId
// Arguments:
// - The other buffer
void TextBuffer::CopyHyperlinkMaps(const TextBuffer& other)
{
    _hyperlinkMap = other._hyperlinkMap;
    _hyperlinkCustomIdMap = other._hyperlinkCustomIdMap;
    _currentHyperlinkId = other._currentHyperlinkId;
}

// Searches through the entire (committed) text buffer for `needle` and returns the coordinates in absolute coordinates.
// The end coordinates of the returned ranges are considered inclusive.
bool TextBuffer::SearchText(const std::wstring_view& needle, SearchFlag flags, std::vector<til::point_span>& results) const
{
    return SearchText(needle, flags, 0, til::CoordTypeMax, results);
}

// Searches through the given rows [rowBeg,rowEnd) for `needle` and returns the coordinates in absolute coordinates.
// While the end coordinates of the returned ranges are considered inclusive, the [rowBeg,rowEnd) range is half-open.
bool TextBuffer::SearchText(const std::wstring_view& needle, SearchFlag flags, til::CoordType rowBeg, til::CoordType rowEnd, std::vector<til::point_span>& results) const
{
    rowEnd = std::min(rowEnd, _estimateOffsetOfLastCommittedRow() + 1);

    results = std::decay_t<decltype(results)>{};

    // All whitespace strings would match the not-yet-written parts of the TextBuffer which would be weird.
    if (allWhitespace(needle) || rowBeg >= rowEnd)
    {
        return true;
    }

    auto text = ICU::UTextFromTextBuffer(*this, rowBeg, rowEnd);

    uint32_t icuFlags{ 0 };
    WI_SetFlagIf(icuFlags, UREGEX_CASE_INSENSITIVE, WI_IsFlagSet(flags, SearchFlag::CaseInsensitive));

    if (WI_IsFlagSet(flags, SearchFlag::RegularExpression))
    {
        WI_SetFlag(icuFlags, UREGEX_MULTILINE);
    }
    else
    {
        WI_SetFlag(icuFlags, UREGEX_LITERAL);
    }


Review comment (suggestion):
nit: Instead of using `results` as an out parameter you could consider returnining a `std::optional<std::vector<...>>`, similar in spirit to a `std::expected` in the future (C++23).
It could then be split up here via something like
```cpp
auto results = textBuffer.SearchText(needle, _flags, _results);
_ok = results.has_value();
_results = std::move(results).value_or({}); // std::optional has a && (move) overload
```

This would also potentially work well in other places like so:
```cpp
const auto results = textBuffer.SearchText(needle, _flags, _results).value_or({});
```

Code after:
    }
    return {};
}

// Method Description:
// - Copies the hyperlink/customID maps of the old buffer into this one,
//   also copies currentHyperlinkId
// Arguments:
// - The other buffer
void TextBuffer::CopyHyperlinkMaps(const TextBuffer& other)
{
    _hyperlinkMap = other._hyperlinkMap;
    _hyperlinkCustomIdMap = other._hyperlinkCustomIdMap;
    _currentHyperlinkId = other._currentHyperlinkId;
}

// Searches through the entire (committed) text buffer for `needle` and returns the coordinates in absolute coordinates.
// The end coordinates of the returned ranges are considered inclusive.
std::optional<std::vector<til::point_span>> TextBuffer::SearchText(const std::wstring_view& needle, SearchFlag flags) const
{
    return SearchText(needle, flags, 0, til::CoordTypeMax);
}

// Searches through the given rows [rowBeg,rowEnd) for `needle` and returns the coordinates in absolute coordinates.
// While the end coordinates of the returned ranges are considered inclusive, the [rowBeg,rowEnd) range is half-open.
// Returns nullopt if the parameters were invalid (e.g. regex search was requested with an invalid regex)
std::optional<std::vector<til::point_span>> TextBuffer::SearchText(const std::wstring_view& needle, SearchFlag flags, til::CoordType rowBeg, til::CoordType rowEnd) const
{
    rowEnd = std::min(rowEnd, _estimateOffsetOfLastCommittedRow() + 1);

    std::vector<til::point_span> results;

    // All whitespace strings would match the not-yet-written parts of the TextBuffer which would be weird.
    if (allWhitespace(needle) || rowBeg >= rowEnd)
    {
        return results;
    }

    auto text = ICU::UTextFromTextBuffer(*this, rowBeg, rowEnd);

    uint32_t icuFlags{ 0 };
    WI_SetFlagIf(icuFlags, UREGEX_CASE_INSENSITIVE, WI_IsFlagSet(flags, SearchFlag::CaseInsensitive));

    if (WI_IsFlagSet(flags, SearchFlag::RegularExpression))
    {
        WI_SetFlag(icuFlags, UREGEX_MULTILINE);
    }
    else
    {
        WI_SetFlag(icuFlags, UREGEX_LITERAL);
    }