diff options
| author | Maxime Coste <mawww@kakoune.org> | 2019-11-23 21:50:58 +1100 |
|---|---|---|
| committer | Maxime Coste <mawww@kakoune.org> | 2019-11-23 21:50:58 +1100 |
| commit | 19e1be8e0d1946bbff02412ec703be33c7f4fede (patch) | |
| tree | 1c65a86fd78edae7cfdd2e5a8983055656d93df4 /src/string_utils.cc | |
| parent | 936bd923eae554d83dc77ab788d84b6d83c108f9 (diff) | |
Make wrap_lines a lazy range view
Avoid the need to allocate a vector by using the ranges
framework.
Diffstat (limited to 'src/string_utils.cc')
| -rw-r--r-- | src/string_utils.cc | 51 |
1 files changed, 27 insertions, 24 deletions
diff --git a/src/string_utils.cc b/src/string_utils.cc index 43e7ef18..3ce98940 100644 --- a/src/string_utils.cc +++ b/src/string_utils.cc @@ -235,58 +235,61 @@ String expand_tabs(StringView line, ColumnCount tabstop, ColumnCount col) return res; } -Vector<StringView> wrap_lines(StringView text, ColumnCount max_width) +WrapView::Iterator::Iterator(StringView text, ColumnCount max_width) + : m_remaining{text}, m_max_width{max_width} { if (max_width <= 0) throw runtime_error("Invalid max width"); + ++*this; +} +WrapView::Iterator& WrapView::Iterator::operator++() +{ using Utf8It = utf8::iterator<const char*>; - Utf8It it{text.begin(), text}; - Utf8It end{text.end(), text}; - Utf8It line_begin = it; + Utf8It it{m_remaining.begin(), m_remaining}; Utf8It last_word_end = it; - Vector<StringView> lines; - while (it != end) + while (it != m_remaining.end()) { const CharCategories cat = categorize(*it, {'_'}); if (cat == CharCategories::EndOfLine) { - lines.emplace_back(line_begin.base(), it.base()); - line_begin = it = it+1; - continue; + m_current = StringView{m_remaining.begin(), it.base()}; + m_remaining = StringView{(it+1).base(), m_remaining.end()}; + return *this; } Utf8It word_end = it+1; - while (word_end != end and categorize(*word_end, {'_'}) == cat) + while (word_end != m_remaining.end() and categorize(*word_end, {'_'}) == cat) ++word_end; - while (word_end > line_begin and - utf8::column_distance(line_begin.base(), word_end.base()) >= max_width) + if (word_end > m_remaining.begin() and + utf8::column_distance(m_remaining.begin(), word_end.base()) >= m_max_width) { - auto line_end = last_word_end <= line_begin ? - Utf8It{utf8::advance(line_begin.base(), text.end(), max_width), text} + auto line_end = last_word_end <= m_remaining.begin() ? + Utf8It{utf8::advance(m_remaining.begin(), m_remaining.end(), m_max_width), m_remaining} : last_word_end; - lines.emplace_back(line_begin.base(), line_end.base()); + m_current = StringView{m_remaining.begin(), line_end.base()}; - while (line_end != end and is_horizontal_blank(*line_end)) + while (line_end != m_remaining.end() and is_horizontal_blank(*line_end)) ++line_end; - if (line_end != end and *line_end == '\n') + if (line_end != m_remaining.end() and *line_end == '\n') ++line_end; - it = line_begin = line_end; + m_remaining = StringView{line_end.base(), m_remaining.end()}; + return *this; } if (cat == CharCategories::Word or cat == CharCategories::Punctuation) last_word_end = word_end; - if (word_end > line_begin) + if (word_end > m_remaining.begin()) it = word_end; } - if (line_begin != end) - lines.emplace_back(line_begin.base(), text.end()); - return lines; + m_current = m_remaining; + m_remaining = StringView{}; + return *this; } template<typename AppendFunc> @@ -378,7 +381,7 @@ UnitTest test_string{[]() { kak_assert(String("youpi ") + "matin" == "youpi matin"); - Vector<StringView> wrapped = wrap_lines("wrap this paragraph\n respecting whitespaces and much_too_long_words", 16); + auto wrapped = "wrap this paragraph\n respecting whitespaces and much_too_long_words" | wrap_at(16) | gather<Vector>(); kak_assert(wrapped.size() == 6); kak_assert(wrapped[0] == "wrap this"); kak_assert(wrapped[1] == "paragraph"); @@ -387,7 +390,7 @@ UnitTest test_string{[]() kak_assert(wrapped[4] == "much_too_long_wo"); kak_assert(wrapped[5] == "rds"); - Vector<StringView> wrapped2 = wrap_lines("error: unknown type", 7); + auto wrapped2 = "error: unknown type" | wrap_at(7) | gather<Vector>(); kak_assert(wrapped2.size() == 3); kak_assert(wrapped2[0] == "error:"); kak_assert(wrapped2[1] == "unknown"); |
