<commit_before>#include "display_buffer.hh"

#include "assert.hh"
#include <algorithm>

namespace Kakoune
{

String DisplayAtom::content() const
{
    switch (m_content_mode)
    {
    case BufferText:
        return m_begin.buffer().string(m_begin, m_end);
    case ReplacementText:
        return m_replacement_text;
    }
    assert(false);
    return "";
}

static DisplayCoord advance_coord(const DisplayCoord& pos,
                                  const BufferIterator& begin,
                                  const BufferIterator& end)
{
    if (begin.line() == end.line())
        return DisplayCoord(pos.line, pos.column + end.column() - begin.column());
    else
        return DisplayCoord(pos.line + end.line() - begin.line(), end.column());
}

static DisplayCoord advance_coord(const DisplayCoord& pos,
                                  const String& str)
{
    DisplayCoord res = pos;
    for (auto c : str)
    {
        if (c == '\n')
        {
            ++res.line;
            res.column = 0;
        }
        else
            ++res.column;
    }
    return res;
}

DisplayCoord DisplayAtom::end_coord() const
{
    switch (m_content_mode)
    {
    case BufferText:
        return advance_coord(m_coord, m_begin, m_end);
    case ReplacementText:
        return advance_coord(m_coord, m_replacement_text);
    }
    assert(false);
    return { 0, 0 };
}

BufferIterator DisplayAtom::iterator_at(const DisplayCoord& coord) const
{
    if (m_content_mode != BufferText or coord <= m_coord)
        return m_begin;

    DisplayCoord pos = m_coord;
    for (BufferIterator it = m_begin; it != m_end; ++it)
    {
        if (*it == '\n')
        {
            ++pos.line;
            pos.column = 0;
        }
        else
            ++pos.column;

        if (coord <= pos)
            return it+1;
    }
    return m_end;
}

DisplayCoord DisplayAtom::line_and_column_at(const BufferIterator& iterator) const
{
    assert(iterator >= m_begin and iterator < m_end);

    if (m_content_mode != BufferText)
        return m_coord;

    return advance_coord(m_coord, m_begin, iterator);
}

DisplayBuffer::DisplayBuffer()
{
}

DisplayBuffer::iterator DisplayBuffer::insert(iterator where, const DisplayAtom& atom)
{
    iterator res = m_atoms.insert(where, atom);
    // check_invariant();
    return res;
}

DisplayBuffer::iterator DisplayBuffer::atom_containing(const BufferIterator& where)
{
    return atom_containing(where, m_atoms.begin());
}

DisplayBuffer::iterator DisplayBuffer::atom_containing(const BufferIterator& where,
                                                       iterator start)
{
    if (where < start->begin())
        return end();

    return std::upper_bound(start, end(), where,
                            [](const BufferIterator& where, const DisplayAtom& atom)
                            { return where < atom.end(); });
}

DisplayBuffer::iterator DisplayBuffer::split(iterator atom, const BufferIterator& pos)
{<commit_msg>make DisplayBuffer::atom_containing easier to understand<commit_after>#include "display_buffer.hh"

#include "assert.hh"
#include <algorithm>

namespace Kakoune
{

String DisplayAtom::content() const
{
    switch (m_content_mode)
    {
    case BufferText:
        return m_begin.buffer().string(m_begin, m_end);
    case ReplacementText:
        return m_replacement_text;
    }
    assert(false);
    return "";
}

static DisplayCoord advance_coord(const DisplayCoord& pos,
                                  const BufferIterator& begin,
                                  const BufferIterator& end)
{
    if (begin.line() == end.line())
        return DisplayCoord(pos.line, pos.column + end.column() - begin.column());
    else
        return DisplayCoord(pos.line + end.line() - begin.line(), end.column());
}

static DisplayCoord advance_coord(const DisplayCoord& pos,
                                  const String& str)
{
    DisplayCoord res = pos;
    for (auto c : str)
    {
        if (c == '\n')
        {
            ++res.line;
            res.column = 0;
        }
        else
            ++res.column;
    }
    return res;
}

DisplayCoord DisplayAtom::end_coord() const
{
    switch (m_content_mode)
    {
    case BufferText:
        return advance_coord(m_coord, m_begin, m_end);
    case ReplacementText:
        return advance_coord(m_coord, m_replacement_text);
    }
    assert(false);
    return { 0, 0 };
}

BufferIterator DisplayAtom::iterator_at(const DisplayCoord& coord) const
{
    if (m_content_mode != BufferText or coord <= m_coord)
        return m_begin;

    DisplayCoord pos = m_coord;
    for (BufferIterator it = m_begin; it != m_end; ++it)
    {
        if (*it == '\n')
        {
            ++pos.line;
            pos.column = 0;
        }
        else
            ++pos.column;

        if (coord <= pos)
            return it+1;
    }
    return m_end;
}

DisplayCoord DisplayAtom::line_and_column_at(const BufferIterator& iterator) const
{
    assert(iterator >= m_begin and iterator < m_end);

    if (m_content_mode != BufferText)
        return m_coord;

    return advance_coord(m_coord, m_begin, iterator);
}

DisplayBuffer::DisplayBuffer()
{
}

DisplayBuffer::iterator DisplayBuffer::insert(iterator where, const DisplayAtom& atom)
{
    iterator res = m_atoms.insert(where, atom);
    // check_invariant();
    return res;
}

DisplayBuffer::iterator DisplayBuffer::atom_containing(const BufferIterator& where)
{
    return atom_containing(where, m_atoms.begin());
}

DisplayBuffer::iterator DisplayBuffer::atom_containing(const BufferIterator& where,
                                                       iterator start)
{
    if (start == end() or where < start->begin())
        return end();

    while (start != end())
    {
        if (start->end() > where)
            break;
        ++start;
    }
    return start;
}

DisplayBuffer::iterator DisplayBuffer::split(iterator atom, const BufferIterator& pos)
{
{'fraction_non_alphanumeric': 0.11101766190075694, 'fraction_numerical': 0.001682085786375105, 'mean_word_length': 2.33109243697479, 'pattern_counts': {'":': 0, '<': 14, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6018811', 'n_tokens_mistral': 1752, 'n_tokens_neox': 1718, 'n_words': 408}