Move insert/erase methods from normal.cc to member functions in SelectionList
It does look like the Editor class is attempting a sneaky comeback...
This commit is contained in:
parent
0a060b62a2
commit
b2621ca140
116
src/normal.cc
116
src/normal.cc
|
@ -22,86 +22,6 @@
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
|
||||||
void erase(Buffer& buffer, SelectionList& selections)
|
|
||||||
{
|
|
||||||
for (auto& sel : reversed(selections))
|
|
||||||
{
|
|
||||||
erase(buffer, sel);
|
|
||||||
}
|
|
||||||
selections.update();
|
|
||||||
selections.avoid_eol();
|
|
||||||
buffer.check_invariant();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<InsertMode mode>
|
|
||||||
BufferIterator prepare_insert(Buffer& buffer, const Selection& sel)
|
|
||||||
{
|
|
||||||
switch (mode)
|
|
||||||
{
|
|
||||||
case InsertMode::Insert:
|
|
||||||
return buffer.iterator_at(sel.min());
|
|
||||||
case InsertMode::Replace:
|
|
||||||
return Kakoune::erase(buffer, sel);
|
|
||||||
case InsertMode::Append:
|
|
||||||
{
|
|
||||||
// special case for end of lines, append to current line instead
|
|
||||||
auto pos = buffer.iterator_at(sel.max());
|
|
||||||
return *pos == '\n' ? pos : utf8::next(pos);
|
|
||||||
}
|
|
||||||
case InsertMode::InsertAtLineBegin:
|
|
||||||
return buffer.iterator_at(sel.min().line);
|
|
||||||
case InsertMode::AppendAtLineEnd:
|
|
||||||
return buffer.iterator_at({sel.max().line, buffer[sel.max().line].length() - 1});
|
|
||||||
case InsertMode::InsertAtNextLineBegin:
|
|
||||||
return buffer.iterator_at(sel.max().line+1);
|
|
||||||
case InsertMode::OpenLineBelow:
|
|
||||||
return buffer.insert(buffer.iterator_at(sel.max().line + 1), "\n");
|
|
||||||
case InsertMode::OpenLineAbove:
|
|
||||||
return buffer.insert(buffer.iterator_at(sel.min().line), "\n");
|
|
||||||
}
|
|
||||||
kak_assert(false);
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
template<InsertMode mode>
|
|
||||||
void insert(Buffer& buffer, SelectionList& selections, memoryview<String> strings)
|
|
||||||
{
|
|
||||||
if (strings.empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
selections.update();
|
|
||||||
for (size_t i = 0; i < selections.size(); ++i)
|
|
||||||
{
|
|
||||||
size_t index = selections.size() - 1 - i;
|
|
||||||
auto& sel = selections[index];
|
|
||||||
auto pos = prepare_insert<mode>(buffer, sel);
|
|
||||||
const String& str = strings[std::min(index, strings.size()-1)];
|
|
||||||
pos = buffer.insert(pos, str);
|
|
||||||
if (mode == InsertMode::Replace)
|
|
||||||
{
|
|
||||||
if (pos == buffer.end())
|
|
||||||
--pos;
|
|
||||||
sel.anchor() = pos.coord();
|
|
||||||
sel.cursor() = (str.empty() ?
|
|
||||||
pos : pos + str.byte_count_to(str.char_length() - 1)).coord();
|
|
||||||
|
|
||||||
// update following selections
|
|
||||||
auto changes = compute_modifications(buffer, selections.timestamp());
|
|
||||||
for (size_t j = index+1; j < selections.size(); ++j)
|
|
||||||
{
|
|
||||||
auto& sel = selections[j];
|
|
||||||
sel.anchor() = update_pos(changes, sel.anchor());
|
|
||||||
sel.cursor() = update_pos(changes, sel.cursor());
|
|
||||||
}
|
|
||||||
selections.update_timestamp();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
selections.update();
|
|
||||||
selections.avoid_eol();
|
|
||||||
selections.check_invariant();
|
|
||||||
buffer.check_invariant();
|
|
||||||
}
|
|
||||||
|
|
||||||
using namespace std::placeholders;
|
using namespace std::placeholders;
|
||||||
|
|
||||||
enum class SelectMode
|
enum class SelectMode
|
||||||
|
@ -172,7 +92,7 @@ constexpr Select<mode, T> make_select(T func)
|
||||||
}
|
}
|
||||||
|
|
||||||
template<SelectMode mode = SelectMode::Replace>
|
template<SelectMode mode = SelectMode::Replace>
|
||||||
void select_coord(const Buffer& buffer, ByteCoord coord, SelectionList& selections)
|
void select_coord(Buffer& buffer, ByteCoord coord, SelectionList& selections)
|
||||||
{
|
{
|
||||||
coord = buffer.clamp(coord);
|
coord = buffer.clamp(coord);
|
||||||
if (mode == SelectMode::Replace)
|
if (mode == SelectMode::Replace)
|
||||||
|
@ -405,7 +325,7 @@ void replace_with_char(Context& context, int)
|
||||||
CharCount count = char_length(buffer, sel);
|
CharCount count = char_length(buffer, sel);
|
||||||
strings.emplace_back(key.key, count);
|
strings.emplace_back(key.key, count);
|
||||||
}
|
}
|
||||||
insert<InsertMode::Replace>(buffer, selections, strings);
|
selections.insert(strings, InsertMode::Replace);
|
||||||
}, "replace with char", "enter char to replace with\n");
|
}, "replace with char", "enter char to replace with\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -428,7 +348,7 @@ void for_each_char(Context& context, int)
|
||||||
for (auto& c : sel)
|
for (auto& c : sel)
|
||||||
c = func(c);
|
c = func(c);
|
||||||
}
|
}
|
||||||
insert<InsertMode::Replace>(context.buffer(), context.selections(), sels);
|
context.selections().insert(sels, InsertMode::Replace);
|
||||||
}
|
}
|
||||||
|
|
||||||
void command(Context& context, int)
|
void command(Context& context, int)
|
||||||
|
@ -493,7 +413,7 @@ void pipe(Context& context, int)
|
||||||
strings.push_back(str);
|
strings.push_back(str);
|
||||||
}
|
}
|
||||||
ScopedEdition edition(context);
|
ScopedEdition edition(context);
|
||||||
insert<mode>(buffer, selections, strings);
|
selections.insert(strings, mode);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -543,7 +463,7 @@ void erase_selections(Context& context, int)
|
||||||
{
|
{
|
||||||
RegisterManager::instance()['"'] = context.selections_content();
|
RegisterManager::instance()['"'] = context.selections_content();
|
||||||
ScopedEdition edition(context);
|
ScopedEdition edition(context);
|
||||||
erase(context.buffer(), context.selections());
|
context.selections().erase();
|
||||||
}
|
}
|
||||||
|
|
||||||
void cat_erase_selections(Context& context, int)
|
void cat_erase_selections(Context& context, int)
|
||||||
|
@ -553,7 +473,7 @@ void cat_erase_selections(Context& context, int)
|
||||||
for (auto& sel : sels)
|
for (auto& sel : sels)
|
||||||
str += sel;
|
str += sel;
|
||||||
RegisterManager::instance()['"'] = memoryview<String>(str);
|
RegisterManager::instance()['"'] = memoryview<String>(str);
|
||||||
erase(context.buffer(), context.selections());
|
context.selections().erase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -587,10 +507,8 @@ void paste(Context& context, int)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ScopedEdition edition(context);
|
ScopedEdition edition(context);
|
||||||
if (linewise)
|
context.selections().insert(strings,
|
||||||
insert<adapt_for_linewise(mode)>(context.buffer(), context.selections(), strings);
|
linewise ? adapt_for_linewise(mode) : mode);
|
||||||
else
|
|
||||||
insert<mode>(context.buffer(), context.selections(), strings);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
@ -717,7 +635,7 @@ void select_regex(Context& context, int)
|
||||||
else
|
else
|
||||||
RegisterManager::instance()['/'] = String{ex.str()};
|
RegisterManager::instance()['/'] = String{ex.str()};
|
||||||
if (not ex.empty() and not ex.str().empty())
|
if (not ex.empty() and not ex.str().empty())
|
||||||
select_all_matches(context.buffer(), context.selections(), ex);
|
select_all_matches(context.selections(), ex);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -729,7 +647,7 @@ void split_regex(Context& context, int)
|
||||||
else
|
else
|
||||||
RegisterManager::instance()['/'] = String{ex.str()};
|
RegisterManager::instance()['/'] = String{ex.str()};
|
||||||
if (not ex.empty() and not ex.str().empty())
|
if (not ex.empty() and not ex.str().empty())
|
||||||
split_selections(context.buffer(), context.selections(), ex);
|
split_selections(context.selections(), ex);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -775,7 +693,7 @@ void join_select_spaces(Context& context, int)
|
||||||
return;
|
return;
|
||||||
context.selections() = selections;
|
context.selections() = selections;
|
||||||
ScopedEdition edition(context);
|
ScopedEdition edition(context);
|
||||||
insert<InsertMode::Replace>(buffer, context.selections(), " "_str);
|
context.selections().insert(" "_str, InsertMode::Replace);
|
||||||
}
|
}
|
||||||
|
|
||||||
void join(Context& context, int param)
|
void join(Context& context, int param)
|
||||||
|
@ -853,7 +771,7 @@ void indent(Context& context, int)
|
||||||
{
|
{
|
||||||
ScopedEdition edition(context);
|
ScopedEdition edition(context);
|
||||||
SelectionList selections{buffer, std::move(sels)};
|
SelectionList selections{buffer, std::move(sels)};
|
||||||
insert<InsertMode::Insert>(buffer, selections, indent);
|
selections.insert(indent, InsertMode::Insert);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -898,7 +816,7 @@ void deindent(Context& context, int)
|
||||||
{
|
{
|
||||||
ScopedEdition edition(context);
|
ScopedEdition edition(context);
|
||||||
SelectionList selections{context.buffer(), std::move(sels)};
|
SelectionList selections{context.buffer(), std::move(sels)};
|
||||||
erase(context.buffer(), selections);
|
selections.erase();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1008,7 +926,7 @@ void rotate_selections_content(Context& context, int group)
|
||||||
std::rotate(it, end-count, end);
|
std::rotate(it, end-count, end);
|
||||||
it = end;
|
it = end;
|
||||||
}
|
}
|
||||||
insert<InsertMode::Replace>(context.buffer(), context.selections(), strings);
|
context.selections().insert(strings, InsertMode::Replace);
|
||||||
context.selections().rotate_main(count);
|
context.selections().rotate_main(count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1236,7 +1154,7 @@ void spaces_to_tabs(Context& context, int ts)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static boost::optional<SelectionList> compute_modified_ranges(const Buffer& buffer, size_t timestamp)
|
static boost::optional<SelectionList> compute_modified_ranges(Buffer& buffer, size_t timestamp)
|
||||||
{
|
{
|
||||||
std::vector<Selection> ranges;
|
std::vector<Selection> ranges;
|
||||||
for (auto& change : buffer.changes_since(timestamp))
|
for (auto& change : buffer.changes_since(timestamp))
|
||||||
|
@ -1402,12 +1320,12 @@ KeyMap keymap =
|
||||||
|
|
||||||
{ '.', repeat_last_insert },
|
{ '.', repeat_last_insert },
|
||||||
|
|
||||||
{ '%', [](Context& context, int) { select_whole_buffer(context.buffer(), context.selections()); } },
|
{ '%', [](Context& context, int) { select_whole_buffer(context.selections()); } },
|
||||||
|
|
||||||
{ ':', command },
|
{ ':', command },
|
||||||
{ '|', pipe<InsertMode::Replace> },
|
{ '|', pipe<InsertMode::Replace> },
|
||||||
{ alt('|'), pipe<InsertMode::Append> },
|
{ alt('|'), pipe<InsertMode::Append> },
|
||||||
{ ' ', [](Context& context, int count) { if (count == 0) clear_selections(context.buffer(), context.selections());
|
{ ' ', [](Context& context, int count) { if (count == 0) clear_selections(context.selections());
|
||||||
else keep_selection(context.selections(), count-1); } },
|
else keep_selection(context.selections(), count-1); } },
|
||||||
{ alt(' '), [](Context& context, int count) { if (count == 0) flip_selections(context.selections());
|
{ alt(' '), [](Context& context, int count) { if (count == 0) flip_selections(context.selections());
|
||||||
else remove_selection(context.selections(), count-1); } },
|
else remove_selection(context.selections(), count-1); } },
|
||||||
|
|
|
@ -11,18 +11,6 @@ namespace Kakoune
|
||||||
|
|
||||||
class Context;
|
class Context;
|
||||||
|
|
||||||
enum class InsertMode : unsigned
|
|
||||||
{
|
|
||||||
Insert,
|
|
||||||
Append,
|
|
||||||
Replace,
|
|
||||||
InsertAtLineBegin,
|
|
||||||
InsertAtNextLineBegin,
|
|
||||||
AppendAtLineEnd,
|
|
||||||
OpenLineBelow,
|
|
||||||
OpenLineAbove
|
|
||||||
};
|
|
||||||
|
|
||||||
using KeyMap = std::unordered_map<Key, std::function<void (Context& context, int param)>>;
|
using KeyMap = std::unordered_map<Key, std::function<void (Context& context, int param)>>;
|
||||||
extern KeyMap keymap;
|
extern KeyMap keymap;
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include "utf8.hh"
|
#include "utf8.hh"
|
||||||
#include "modification.hh"
|
#include "modification.hh"
|
||||||
|
#include "buffer_utils.hh"
|
||||||
|
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
@ -102,24 +103,24 @@ struct UpdateErase
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SelectionList::SelectionList(const Buffer& buffer, Selection s, size_t timestamp)
|
SelectionList::SelectionList(Buffer& buffer, Selection s, size_t timestamp)
|
||||||
: m_buffer(&buffer), m_selections({ s }), m_timestamp(timestamp)
|
: m_buffer(&buffer), m_selections({ s }), m_timestamp(timestamp)
|
||||||
{
|
{
|
||||||
check_invariant();
|
check_invariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
SelectionList::SelectionList(const Buffer& buffer, Selection s)
|
SelectionList::SelectionList(Buffer& buffer, Selection s)
|
||||||
: SelectionList(buffer, s, buffer.timestamp())
|
: SelectionList(buffer, s, buffer.timestamp())
|
||||||
{}
|
{}
|
||||||
|
|
||||||
SelectionList::SelectionList(const Buffer& buffer, std::vector<Selection> s, size_t timestamp)
|
SelectionList::SelectionList(Buffer& buffer, std::vector<Selection> s, size_t timestamp)
|
||||||
: m_buffer(&buffer), m_selections(std::move(s)), m_timestamp(timestamp)
|
: m_buffer(&buffer), m_selections(std::move(s)), m_timestamp(timestamp)
|
||||||
{
|
{
|
||||||
kak_assert(size() > 0);
|
kak_assert(size() > 0);
|
||||||
check_invariant();
|
check_invariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
SelectionList::SelectionList(const Buffer& buffer, std::vector<Selection> s)
|
SelectionList::SelectionList(Buffer& buffer, std::vector<Selection> s)
|
||||||
: SelectionList(buffer, std::move(s), buffer.timestamp())
|
: SelectionList(buffer, std::move(s), buffer.timestamp())
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
@ -221,4 +222,83 @@ void SelectionList::avoid_eol()
|
||||||
_avoid_eol(buffer(), sel);
|
_avoid_eol(buffer(), sel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SelectionList::erase()
|
||||||
|
{
|
||||||
|
for (auto& sel : reversed(m_selections))
|
||||||
|
{
|
||||||
|
Kakoune::erase(*m_buffer, sel);
|
||||||
|
}
|
||||||
|
update();
|
||||||
|
avoid_eol();
|
||||||
|
m_buffer->check_invariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
BufferIterator prepare_insert(Buffer& buffer, const Selection& sel, InsertMode mode)
|
||||||
|
{
|
||||||
|
switch (mode)
|
||||||
|
{
|
||||||
|
case InsertMode::Insert:
|
||||||
|
return buffer.iterator_at(sel.min());
|
||||||
|
case InsertMode::Replace:
|
||||||
|
return erase(buffer, sel);
|
||||||
|
case InsertMode::Append:
|
||||||
|
{
|
||||||
|
// special case for end of lines, append to current line instead
|
||||||
|
auto pos = buffer.iterator_at(sel.max());
|
||||||
|
return *pos == '\n' ? pos : utf8::next(pos);
|
||||||
|
}
|
||||||
|
case InsertMode::InsertAtLineBegin:
|
||||||
|
return buffer.iterator_at(sel.min().line);
|
||||||
|
case InsertMode::AppendAtLineEnd:
|
||||||
|
return buffer.iterator_at({sel.max().line, buffer[sel.max().line].length() - 1});
|
||||||
|
case InsertMode::InsertAtNextLineBegin:
|
||||||
|
return buffer.iterator_at(sel.max().line+1);
|
||||||
|
case InsertMode::OpenLineBelow:
|
||||||
|
return buffer.insert(buffer.iterator_at(sel.max().line + 1), "\n");
|
||||||
|
case InsertMode::OpenLineAbove:
|
||||||
|
return buffer.insert(buffer.iterator_at(sel.min().line), "\n");
|
||||||
|
}
|
||||||
|
kak_assert(false);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelectionList::insert(memoryview<String> strings, InsertMode mode)
|
||||||
|
{
|
||||||
|
if (strings.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
update();
|
||||||
|
for (size_t i = 0; i < m_selections.size(); ++i)
|
||||||
|
{
|
||||||
|
size_t index = m_selections.size() - 1 - i;
|
||||||
|
auto& sel = m_selections[index];
|
||||||
|
auto pos = prepare_insert(*m_buffer, sel, mode);
|
||||||
|
const String& str = strings[std::min(index, strings.size()-1)];
|
||||||
|
pos = m_buffer->insert(pos, str);
|
||||||
|
if (mode == InsertMode::Replace)
|
||||||
|
{
|
||||||
|
if (pos == m_buffer->end())
|
||||||
|
--pos;
|
||||||
|
sel.anchor() = pos.coord();
|
||||||
|
sel.cursor() = (str.empty() ?
|
||||||
|
pos : pos + str.byte_count_to(str.char_length() - 1)).coord();
|
||||||
|
|
||||||
|
// update following selections
|
||||||
|
auto changes = compute_modifications(*m_buffer, timestamp());
|
||||||
|
for (size_t j = index+1; j < m_selections.size(); ++j)
|
||||||
|
{
|
||||||
|
auto& sel = m_selections[j];
|
||||||
|
sel.anchor() = update_pos(changes, sel.anchor());
|
||||||
|
sel.cursor() = update_pos(changes, sel.cursor());
|
||||||
|
}
|
||||||
|
update_timestamp();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
update();
|
||||||
|
avoid_eol();
|
||||||
|
check_invariant();
|
||||||
|
m_buffer->check_invariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,12 +55,24 @@ static bool compare_selections(const Selection& lhs, const Selection& rhs)
|
||||||
return lhs.min() < rhs.min();
|
return lhs.min() < rhs.min();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class InsertMode : unsigned
|
||||||
|
{
|
||||||
|
Insert,
|
||||||
|
Append,
|
||||||
|
Replace,
|
||||||
|
InsertAtLineBegin,
|
||||||
|
InsertAtNextLineBegin,
|
||||||
|
AppendAtLineEnd,
|
||||||
|
OpenLineBelow,
|
||||||
|
OpenLineAbove
|
||||||
|
};
|
||||||
|
|
||||||
struct SelectionList
|
struct SelectionList
|
||||||
{
|
{
|
||||||
SelectionList(const Buffer& buffer, Selection s);
|
SelectionList(Buffer& buffer, Selection s);
|
||||||
SelectionList(const Buffer& buffer, Selection s, size_t timestamp);
|
SelectionList(Buffer& buffer, Selection s, size_t timestamp);
|
||||||
SelectionList(const Buffer& buffer, std::vector<Selection> s);
|
SelectionList(Buffer& buffer, std::vector<Selection> s);
|
||||||
SelectionList(const Buffer& buffer, std::vector<Selection> s, size_t timestamp);
|
SelectionList(Buffer& buffer, std::vector<Selection> s, size_t timestamp);
|
||||||
|
|
||||||
void update();
|
void update();
|
||||||
|
|
||||||
|
@ -103,17 +115,7 @@ struct SelectionList
|
||||||
const_iterator begin() const { return m_selections.begin(); }
|
const_iterator begin() const { return m_selections.begin(); }
|
||||||
const_iterator end() const { return m_selections.end(); }
|
const_iterator end() const { return m_selections.end(); }
|
||||||
|
|
||||||
template<typename... Args>
|
void remove(size_t index) { m_selections.erase(begin() + index); }
|
||||||
iterator insert(Args... args)
|
|
||||||
{
|
|
||||||
return m_selections.insert(std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename... Args>
|
|
||||||
iterator erase(Args... args)
|
|
||||||
{
|
|
||||||
return m_selections.erase(std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t size() const { return m_selections.size(); }
|
size_t size() const { return m_selections.size(); }
|
||||||
|
|
||||||
|
@ -140,22 +142,25 @@ struct SelectionList
|
||||||
(*this)[i] = std::move((*this)[j]);
|
(*this)[i] = std::move((*this)[j]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
erase(begin() + i + 1, end());
|
m_selections.erase(begin() + i + 1, end());
|
||||||
kak_assert(std::is_sorted(begin(), end(), compare_selections));
|
kak_assert(std::is_sorted(begin(), end(), compare_selections));
|
||||||
}
|
}
|
||||||
|
|
||||||
void sort_and_merge_overlapping();
|
void sort_and_merge_overlapping();
|
||||||
|
|
||||||
const Buffer& buffer() const { return *m_buffer; }
|
Buffer& buffer() const { return *m_buffer; }
|
||||||
|
|
||||||
size_t timestamp() const { return m_timestamp; }
|
size_t timestamp() const { return m_timestamp; }
|
||||||
void update_timestamp() { m_timestamp = m_buffer->timestamp(); }
|
void update_timestamp() { m_timestamp = m_buffer->timestamp(); }
|
||||||
|
|
||||||
|
void insert(memoryview<String> strings, InsertMode mode);
|
||||||
|
void erase();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
size_t m_main = 0;
|
size_t m_main = 0;
|
||||||
std::vector<Selection> m_selections;
|
std::vector<Selection> m_selections;
|
||||||
|
|
||||||
safe_ptr<const Buffer> m_buffer;
|
safe_ptr<Buffer> m_buffer;
|
||||||
size_t m_timestamp;
|
size_t m_timestamp;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -429,15 +429,16 @@ Selection trim_partial_lines(const Buffer& buffer, const Selection& selection)
|
||||||
return Selection(first.coord(), last.coord());
|
return Selection(first.coord(), last.coord());
|
||||||
}
|
}
|
||||||
|
|
||||||
void select_whole_buffer(const Buffer& buffer, SelectionList& selections)
|
void select_whole_buffer(SelectionList& selections)
|
||||||
{
|
{
|
||||||
|
auto& buffer = selections.buffer();
|
||||||
selections = SelectionList{ buffer, Selection({0,0}, buffer.back_coord()) };
|
selections = SelectionList{ buffer, Selection({0,0}, buffer.back_coord()) };
|
||||||
}
|
}
|
||||||
|
|
||||||
void select_all_matches(const Buffer& buffer, SelectionList& selections,
|
void select_all_matches(SelectionList& selections, const Regex& regex)
|
||||||
const Regex& regex)
|
|
||||||
{
|
{
|
||||||
std::vector<Selection> result;
|
std::vector<Selection> result;
|
||||||
|
auto& buffer = selections.buffer();
|
||||||
for (auto& sel : selections)
|
for (auto& sel : selections)
|
||||||
{
|
{
|
||||||
auto sel_end = utf8::next(buffer.iterator_at(sel.max()));
|
auto sel_end = utf8::next(buffer.iterator_at(sel.max()));
|
||||||
|
@ -466,10 +467,10 @@ void select_all_matches(const Buffer& buffer, SelectionList& selections,
|
||||||
selections = std::move(result);
|
selections = std::move(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void split_selections(const Buffer& buffer, SelectionList& selections,
|
void split_selections(SelectionList& selections, const Regex& regex)
|
||||||
const Regex& regex)
|
|
||||||
{
|
{
|
||||||
std::vector<Selection> result;
|
std::vector<Selection> result;
|
||||||
|
auto& buffer = selections.buffer();
|
||||||
for (auto& sel : selections)
|
for (auto& sel : selections)
|
||||||
{
|
{
|
||||||
auto begin = buffer.iterator_at(sel.min());
|
auto begin = buffer.iterator_at(sel.min());
|
||||||
|
|
|
@ -9,14 +9,14 @@
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
|
||||||
inline void clear_selections(const Buffer& buffer, SelectionList& selections)
|
inline void clear_selections(SelectionList& selections)
|
||||||
{
|
{
|
||||||
auto& sel = selections.main();
|
auto& sel = selections.main();
|
||||||
auto& pos = sel.cursor();
|
auto& pos = sel.cursor();
|
||||||
sel.anchor() = pos;
|
sel.anchor() = pos;
|
||||||
selections.avoid_eol();
|
selections.avoid_eol();
|
||||||
|
|
||||||
selections = SelectionList{ buffer, std::move(sel) };
|
selections = SelectionList{ selections.buffer(), std::move(sel) };
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void flip_selections(SelectionList& selections)
|
inline void flip_selections(SelectionList& selections)
|
||||||
|
@ -41,7 +41,7 @@ inline void remove_selection(SelectionList& selections, int index)
|
||||||
if (selections.size() > 1 and index < selections.size())
|
if (selections.size() > 1 and index < selections.size())
|
||||||
{
|
{
|
||||||
size_t real_index = (index + selections.main_index() + 1) % selections.size();
|
size_t real_index = (index + selections.main_index() + 1) % selections.size();
|
||||||
selections.erase(selections.begin() + real_index);
|
selections.remove(real_index);
|
||||||
size_t main_index = selections.main_index();
|
size_t main_index = selections.main_index();
|
||||||
if (real_index <= main_index)
|
if (real_index <= main_index)
|
||||||
selections.set_main_index((main_index > 0 ? main_index
|
selections.set_main_index((main_index > 0 ? main_index
|
||||||
|
@ -207,7 +207,7 @@ Selection select_whole_paragraph(const Buffer& buffer, const Selection& selectio
|
||||||
Selection select_whole_indent(const Buffer& buffer, const Selection& selection,
|
Selection select_whole_indent(const Buffer& buffer, const Selection& selection,
|
||||||
ObjectFlags flags);
|
ObjectFlags flags);
|
||||||
Selection select_whole_lines(const Buffer& buffer, const Selection& selection);
|
Selection select_whole_lines(const Buffer& buffer, const Selection& selection);
|
||||||
void select_whole_buffer(const Buffer& buffer, SelectionList& selections);
|
void select_whole_buffer(SelectionList& selections);
|
||||||
Selection trim_partial_lines(const Buffer& buffer, const Selection& selection);
|
Selection trim_partial_lines(const Buffer& buffer, const Selection& selection);
|
||||||
|
|
||||||
enum Direction { Forward, Backward };
|
enum Direction { Forward, Backward };
|
||||||
|
@ -266,10 +266,10 @@ Selection find_next_match(const Buffer& buffer, const Selection& sel, const Rege
|
||||||
return {begin.coord(), end.coord(), std::move(captures)};
|
return {begin.coord(), end.coord(), std::move(captures)};
|
||||||
}
|
}
|
||||||
|
|
||||||
void select_all_matches(const Buffer& buffer, SelectionList& selections,
|
void select_all_matches(SelectionList& selections,
|
||||||
const Regex& regex);
|
const Regex& regex);
|
||||||
|
|
||||||
void split_selections(const Buffer& buffer, SelectionList& selections,
|
void split_selections(SelectionList& selections,
|
||||||
const Regex& separator_regex);
|
const Regex& separator_regex);
|
||||||
|
|
||||||
using CodepointPair = std::pair<Codepoint, Codepoint>;
|
using CodepointPair = std::pair<Codepoint, Codepoint>;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user