SelectionList know its buffer and timestamp

This commit is contained in:
Maxime Coste 2014-05-12 23:25:15 +01:00
parent 7bc73b7ef9
commit ea3e92aa5e
17 changed files with 150 additions and 87 deletions

View File

@ -706,7 +706,7 @@ void Buffer::on_option_changed(const Option& option)
void Buffer::run_hook_in_own_context(const String& hook_name, const String& param) void Buffer::run_hook_in_own_context(const String& hook_name, const String& param)
{ {
InputHandler hook_handler(*this, { Selection{} }); InputHandler hook_handler({ *this, Selection{} });
m_hooks.run_hook(hook_name, param, hook_handler.context()); m_hooks.run_hook(hook_name, param, hook_handler.context());
} }

View File

@ -18,7 +18,7 @@ Client::Client(std::unique_ptr<UserInterface>&& ui,
EnvVarMap env_vars, EnvVarMap env_vars,
String name) String name)
: m_ui{std::move(ui)}, m_window{std::move(window)}, : m_ui{std::move(ui)}, m_window{std::move(window)},
m_input_handler{m_window->buffer(), std::move(selections), m_input_handler{std::move(selections),
std::move(name)}, std::move(name)},
m_env_vars(env_vars) m_env_vars(env_vars)
{ {
@ -102,7 +102,7 @@ static void reload_buffer(Context& context, const String& filename)
if (not buf) if (not buf)
return; return;
context.change_buffer(*buf); context.change_buffer(*buf);
context.selections() = SelectionList{buf->clamp(cursor_pos)}; context.selections() = SelectionList{ *buf, buf->clamp(cursor_pos)};
context.window().set_position(view_pos); context.window().set_position(view_pos);
context.print_status({ "'" + buf->display_name() + "' reloaded", context.print_status({ "'" + buf->display_name() + "' reloaded",
get_color("Information") }); get_color("Information") });

View File

@ -94,18 +94,18 @@ WindowAndSelections ClientManager::get_free_window(Buffer& buffer)
w->forget_timestamp(); w->forget_timestamp();
WindowAndSelections res = std::move(*it); WindowAndSelections res = std::move(*it);
m_free_windows.erase(it.base()-1); m_free_windows.erase(it.base()-1);
res.selections.update();
return res; return res;
} }
} }
return WindowAndSelections{ std::unique_ptr<Window>{new Window{buffer}}, return WindowAndSelections{ std::unique_ptr<Window>{new Window{buffer}},
DynamicSelectionList{buffer, SelectionList{ buffer, Selection{} } };
{ Selection{ {}, {} } } } };
} }
void ClientManager::add_free_window(std::unique_ptr<Window>&& window, SelectionList selections) void ClientManager::add_free_window(std::unique_ptr<Window>&& window, SelectionList selections)
{ {
Buffer& buffer = window->buffer(); Buffer& buffer = window->buffer();
m_free_windows.push_back({ std::move(window), DynamicSelectionList{ buffer, std::move(selections) } }); m_free_windows.push_back({ std::move(window), SelectionList{ std::move(selections) }, buffer.timestamp() });
} }
void ClientManager::ensure_no_client_uses_buffer(Buffer& buffer) void ClientManager::ensure_no_client_uses_buffer(Buffer& buffer)

View File

@ -12,7 +12,8 @@ struct client_removed{};
struct WindowAndSelections struct WindowAndSelections
{ {
std::unique_ptr<Window> window; std::unique_ptr<Window> window;
DynamicSelectionList selections; SelectionList selections;
size_t timestamp;
}; };
class ClientManager : public Singleton<ClientManager> class ClientManager : public Singleton<ClientManager>

View File

@ -131,7 +131,8 @@ void edit(const ParametersParser& parser, Context& context)
int column = param_count > 2 and not parser[2].empty() ? int column = param_count > 2 and not parser[2].empty() ?
std::max(0, str_to_int(parser[2]) - 1) : 0; std::max(0, str_to_int(parser[2]) - 1) : 0;
context.selections() = context.buffer().clamp({ line, column }); auto& buffer = context.buffer();
context.selections() = { buffer, buffer.clamp({ line, column }) };
if (context.has_window()) if (context.has_window())
context.window().center_line(context.selections().main().cursor().line); context.window().center_line(context.selections().main().cursor().line);
} }
@ -962,7 +963,7 @@ void context_wrap(const ParametersParser& parser, Context& context, Func func)
for (auto& name : names) for (auto& name : names)
{ {
Buffer& buffer = BufferManager::instance().get_buffer(name); Buffer& buffer = BufferManager::instance().get_buffer(name);
InputHandler input_handler{buffer, ( Selection{} )}; InputHandler input_handler{{ buffer, Selection{} }};
func(parser, input_handler.context()); func(parser, input_handler.context());
} }
return; return;
@ -980,7 +981,7 @@ void context_wrap(const ParametersParser& parser, Context& context, Func func)
if (parser.has_option("draft")) if (parser.has_option("draft"))
{ {
InputHandler input_handler(real_context->buffer(), real_context->selections(), real_context->name()); InputHandler input_handler(real_context->selections(), real_context->name());
// We do not want this draft context to commit undo groups if the real one is // We do not want this draft context to commit undo groups if the real one is
// going to commit the whole thing later // going to commit the whole thing later
@ -989,12 +990,17 @@ void context_wrap(const ParametersParser& parser, Context& context, Func func)
if (parser.has_option("itersel")) if (parser.has_option("itersel"))
{ {
DynamicSelectionList sels{real_context->buffer(), real_context->selections()}; SelectionList sels{real_context->selections()};
ScopedEdition edition{input_handler.context()}; ScopedEdition edition{input_handler.context()};
for (auto& sel : sels) for (auto& sel : sels)
{ {
input_handler.context().selections() = sel; input_handler.context().selections() = SelectionList{ sels.buffer(), sel, sels.timestamp() };
input_handler.context().selections().update();
func(parser, input_handler.context()); func(parser, input_handler.context());
if (&sels.buffer() != &input_handler.context().buffer())
throw runtime_error("the buffer has changed while iterating on selections");
} }
} }
else else

View File

@ -10,10 +10,10 @@ namespace Kakoune
Context::Context() = default; Context::Context() = default;
Context::~Context() = default; Context::~Context() = default;
Context::Context(InputHandler& input_handler, Buffer& buffer, Context::Context(InputHandler& input_handler, SelectionList selections,
SelectionList selections, String name) String name)
: m_input_handler{&input_handler}, : m_input_handler{&input_handler},
m_selections{{buffer, std::move(selections)}}, m_selections{std::move(selections)},
m_name(std::move(name)) m_name(std::move(name))
{} {}
@ -110,7 +110,7 @@ void Context::push_jump()
} }
m_jump_list.erase(std::remove(begin(m_jump_list), end(m_jump_list), jump), m_jump_list.erase(std::remove(begin(m_jump_list), end(m_jump_list), jump),
end(m_jump_list)); end(m_jump_list));
m_jump_list.push_back({buffer(), jump}); m_jump_list.push_back(jump);
m_current_jump = m_jump_list.end(); m_current_jump = m_jump_list.end();
} }
@ -168,7 +168,7 @@ void Context::change_buffer(Buffer& buffer)
if (has_client()) if (has_client())
client().change_buffer(buffer); client().change_buffer(buffer);
else else
m_selections = DynamicSelectionList{ buffer }; m_selections = DynamicSelectionList{ { buffer, Selection{} } };
if (has_input_handler()) if (has_input_handler())
input_handler().reset_normal_mode(); input_handler().reset_normal_mode();
} }

View File

@ -26,7 +26,8 @@ class Context
{ {
public: public:
Context(); Context();
Context(InputHandler& input_handler, Buffer& buffer, SelectionList selections, String name = ""); Context(InputHandler& input_handler, SelectionList selections,
String name = "");
~Context(); ~Context();
Context(const Context&) = delete; Context(const Context&) = delete;

View File

@ -3,10 +3,9 @@
namespace Kakoune namespace Kakoune
{ {
DynamicSelectionList::DynamicSelectionList(Buffer& buffer, DynamicSelectionList::DynamicSelectionList(SelectionList selections)
SelectionList selections)
: SelectionList(std::move(selections)), : SelectionList(std::move(selections)),
BufferChangeListener_AutoRegister(buffer) BufferChangeListener_AutoRegister(const_cast<Buffer&>(buffer()))
{ {
check_invariant(); check_invariant();
} }
@ -18,32 +17,16 @@ DynamicSelectionList& DynamicSelectionList::operator=(SelectionList selections)
return *this; return *this;
} }
void DynamicSelectionList::check_invariant() const
{
#ifdef KAK_DEBUG
SelectionList::check_invariant();
const Buffer& buffer = registry();
for (size_t i = 0; i < size(); ++i)
{
auto& sel = (*this)[i];
kak_assert(buffer.is_valid(sel.anchor()));
kak_assert(buffer.is_valid(sel.cursor()));
kak_assert(not buffer.is_end(sel.anchor()));
kak_assert(not buffer.is_end(sel.cursor()));
kak_assert(utf8::is_character_start(buffer.iterator_at(sel.anchor())));
kak_assert(utf8::is_character_start(buffer.iterator_at(sel.cursor())));
}
#endif
}
void DynamicSelectionList::on_insert(const Buffer& buffer, ByteCoord begin, ByteCoord end, bool at_end) void DynamicSelectionList::on_insert(const Buffer& buffer, ByteCoord begin, ByteCoord end, bool at_end)
{ {
update_insert(begin, end, at_end); update_insert(begin, end, at_end);
set_timestamp(buffer.timestamp());
} }
void DynamicSelectionList::on_erase(const Buffer& buffer, ByteCoord begin, ByteCoord end, bool at_end) void DynamicSelectionList::on_erase(const Buffer& buffer, ByteCoord begin, ByteCoord end, bool at_end)
{ {
update_erase(begin, end, at_end); update_erase(begin, end, at_end);
set_timestamp(buffer.timestamp());
} }
} }

View File

@ -13,10 +13,11 @@ public:
using iterator = SelectionList::iterator; using iterator = SelectionList::iterator;
using const_iterator = SelectionList::const_iterator; using const_iterator = SelectionList::const_iterator;
DynamicSelectionList(Buffer& buffer, SelectionList selections = { Selection{} }); DynamicSelectionList(SelectionList selections);
DynamicSelectionList& operator=(SelectionList selections); DynamicSelectionList& operator=(SelectionList selections);
void check_invariant() const;
using SelectionList::buffer;
private: private:
void on_insert(const Buffer& buffer, ByteCoord begin, ByteCoord end, bool at_end) override; void on_insert(const Buffer& buffer, ByteCoord begin, ByteCoord end, bool at_end) override;

View File

@ -875,9 +875,9 @@ void InputMode::reset_normal_mode()
m_input_handler.reset_normal_mode(); m_input_handler.reset_normal_mode();
} }
InputHandler::InputHandler(Buffer& buffer, SelectionList selections, String name) InputHandler::InputHandler(SelectionList selections, String name)
: m_mode(new InputModes::Normal(*this)), : m_mode(new InputModes::Normal(*this)),
m_context(*this, buffer, std::move(selections), std::move(name)) m_context(*this, std::move(selections), std::move(name))
{ {
} }

View File

@ -35,7 +35,7 @@ enum class InsertMode : unsigned;
class InputHandler : public SafeCountable class InputHandler : public SafeCountable
{ {
public: public:
InputHandler(Buffer& buffer, SelectionList selections, String name = ""); InputHandler(SelectionList selections, String name = "");
~InputHandler(); ~InputHandler();
// switch to insert mode // switch to insert mode

View File

@ -26,6 +26,7 @@ void erase(Buffer& buffer, SelectionList& selections)
for (auto& sel : selections) for (auto& sel : selections)
{ {
erase(buffer, sel); erase(buffer, sel);
selections.update();
avoid_eol(buffer, sel); avoid_eol(buffer, sel);
} }
selections.check_invariant(); selections.check_invariant();
@ -178,7 +179,7 @@ void select_coord(const Buffer& buffer, ByteCoord coord, SelectionList& selectio
{ {
coord = buffer.clamp(coord); coord = buffer.clamp(coord);
if (mode == SelectMode::Replace) if (mode == SelectMode::Replace)
selections = SelectionList { coord }; selections = SelectionList{ buffer, coord };
else if (mode == SelectMode::Extend) else if (mode == SelectMode::Extend)
{ {
for (auto& sel : selections) for (auto& sel : selections)
@ -598,7 +599,7 @@ void paste(Context& context, int)
template<typename T> template<typename T>
void regex_prompt(Context& context, const String prompt, T func) void regex_prompt(Context& context, const String prompt, T func)
{ {
DynamicSelectionList selections{context.buffer(), context.selections()}; DynamicSelectionList selections{context.selections()};
context.input_handler().prompt(prompt, "", get_color("Prompt"), complete_nothing, context.input_handler().prompt(prompt, "", get_color("Prompt"), complete_nothing,
[=](const String& str, PromptEvent event, Context& context) { [=](const String& str, PromptEvent event, Context& context) {
try try
@ -738,7 +739,7 @@ void split_lines(Context& context, int)
{ {
auto& selections = context.selections(); auto& selections = context.selections();
auto& buffer = context.buffer(); auto& buffer = context.buffer();
SelectionList res; SelectionList res(context.buffer());
for (auto& sel : selections) for (auto& sel : selections)
{ {
if (sel.anchor().line == sel.cursor().line) if (sel.anchor().line == sel.cursor().line)
@ -760,7 +761,7 @@ void split_lines(Context& context, int)
void join_select_spaces(Context& context, int) void join_select_spaces(Context& context, int)
{ {
auto& buffer = context.buffer(); auto& buffer = context.buffer();
SelectionList selections; SelectionList selections(buffer);
for (auto& sel : context.selections()) for (auto& sel : context.selections())
{ {
for (LineCount line = sel.min().line; line <= sel.max().line; ++line) for (LineCount line = sel.min().line; line <= sel.max().line; ++line)
@ -783,8 +784,12 @@ void join_select_spaces(Context& context, int)
void join(Context& context, int param) void join(Context& context, int param)
{ {
DynamicSelectionList sels{context.buffer(), context.selections()}; SelectionList sels{context.selections()};
auto restore_sels = on_scope_end([&]{ context.selections() = std::move(sels); }); auto restore_sels = on_scope_end([&]{
sels.update();
context.selections() = std::move(sels);
});
join_select_spaces(context, param); join_select_spaces(context, param);
} }
@ -796,7 +801,7 @@ void keep(Context& context, int)
if (ex.empty()) if (ex.empty())
return; return;
const Buffer& buffer = context.buffer(); const Buffer& buffer = context.buffer();
SelectionList keep; SelectionList keep(buffer);
for (auto& sel : context.selections()) for (auto& sel : context.selections())
{ {
if (boost::regex_search(buffer.iterator_at(sel.min()), if (boost::regex_search(buffer.iterator_at(sel.min()),
@ -818,7 +823,7 @@ void keep_pipe(Context& context, int)
return; return;
const Buffer& buffer = context.buffer(); const Buffer& buffer = context.buffer();
auto& shell_manager = ShellManager::instance(); auto& shell_manager = ShellManager::instance();
SelectionList keep; SelectionList keep(buffer);
for (auto& sel : context.selections()) for (auto& sel : context.selections())
{ {
int status = 0; int status = 0;
@ -839,7 +844,7 @@ void indent(Context& context, int)
String indent = indent_width == 0 ? "\t" : String{' ', indent_width}; String indent = indent_width == 0 ? "\t" : String{' ', indent_width};
auto& buffer = context.buffer(); auto& buffer = context.buffer();
SelectionList sels; SelectionList sels(buffer);
for (auto& sel : context.selections()) for (auto& sel : context.selections())
{ {
for (auto line = sel.min().line; line < sel.max().line+1; ++line) for (auto line = sel.min().line; line < sel.max().line+1; ++line)
@ -864,7 +869,7 @@ void deindent(Context& context, int)
indent_width = tabstop; indent_width = tabstop;
auto& buffer = context.buffer(); auto& buffer = context.buffer();
SelectionList sels; SelectionList sels(buffer);
for (auto& sel : context.selections()) for (auto& sel : context.selections())
{ {
for (auto line = sel.min().line; line < sel.max().line+1; ++line) for (auto line = sel.min().line; line < sel.max().line+1; ++line)
@ -1235,7 +1240,7 @@ void spaces_to_tabs(Context& context, int ts)
static SelectionList compute_modified_ranges(const Buffer& buffer, size_t timestamp) static SelectionList compute_modified_ranges(const Buffer& buffer, size_t timestamp)
{ {
SelectionList ranges; SelectionList ranges(buffer);
for (auto& change : buffer.changes_since(timestamp)) for (auto& change : buffer.changes_since(timestamp))
{ {
const ByteCoord& begin = change.begin; const ByteCoord& begin = change.begin;
@ -1264,6 +1269,7 @@ static SelectionList compute_modified_ranges(const Buffer& buffer, size_t timest
if (ranges.empty()) if (ranges.empty())
return ranges; return ranges;
ranges.set_timestamp(buffer.timestamp());
ranges.set_main_index(ranges.size() - 1); ranges.set_main_index(ranges.size() - 1);
auto touches = [&](const Selection& lhs, const Selection& rhs) { auto touches = [&](const Selection& lhs, const Selection& rhs) {

View File

@ -63,6 +63,7 @@ struct UpdateInsert
coord.column = end.column + coord.column - begin.column; coord.column = end.column + coord.column - begin.column;
coord.line += end.line - begin.line; coord.line += end.line - begin.line;
kak_assert(coord.line >= 0 and coord.column >= 0);
} }
}; };
@ -78,7 +79,7 @@ struct UpdateErase
kak_assert(end.line < coord.line); kak_assert(end.line < coord.line);
if (not assume_different_line and coord <= end) if (not assume_different_line and coord <= end)
{ {
if (not at_end) if (not at_end or begin == ByteCoord{0,0})
coord = begin; coord = begin;
else else
coord = begin.column ? ByteCoord{begin.line, begin.column-1} coord = begin.column ? ByteCoord{begin.line, begin.column-1}
@ -94,11 +95,33 @@ struct UpdateErase
else else
coord.line -= end.line - begin.line; coord.line -= end.line - begin.line;
} }
kak_assert(coord.line >= 0 and coord.column >= 0);
} }
}; };
} }
SelectionList::SelectionList(const Buffer& buffer)
: m_buffer(&buffer), m_timestamp(buffer.timestamp())
{
}
SelectionList::SelectionList(const Buffer& buffer, Selection s, size_t timestamp)
: m_buffer(&buffer), m_selections({ s }), m_timestamp(timestamp)
{}
SelectionList::SelectionList(const Buffer& buffer, Selection s)
: SelectionList(buffer, s, buffer.timestamp())
{}
SelectionList::SelectionList(const Buffer& buffer, std::vector<Selection> s, size_t timestamp)
: m_buffer(&buffer), m_selections(std::move(s)), m_timestamp(timestamp)
{}
SelectionList::SelectionList(const Buffer& buffer, std::vector<Selection> s)
: SelectionList(buffer, std::move(s), buffer.timestamp())
{}
void SelectionList::update_insert(ByteCoord begin, ByteCoord end, bool at_end) void SelectionList::update_insert(ByteCoord begin, ByteCoord end, bool at_end)
{ {
on_buffer_change<UpdateInsert>(*this, begin, end, at_end, begin.line); on_buffer_change<UpdateInsert>(*this, begin, end, at_end, begin.line);
@ -109,12 +132,58 @@ void SelectionList::update_erase(ByteCoord begin, ByteCoord end, bool at_end)
on_buffer_change<UpdateErase>(*this, begin, end, at_end, end.line); on_buffer_change<UpdateErase>(*this, begin, end, at_end, end.line);
} }
void SelectionList::update()
{
for (auto& change : m_buffer->changes_since(m_timestamp))
{
if (change.type == Buffer::Change::Insert)
update_insert(change.begin, change.end, change.at_end);
else
update_erase(change.begin, change.end, change.at_end);
}
m_timestamp = m_buffer->timestamp();
check_invariant();
}
void SelectionList::check_invariant() const void SelectionList::check_invariant() const
{ {
#ifdef KAK_DEBUG
auto& buffer = this->buffer();
kak_assert(size() > 0); kak_assert(size() > 0);
kak_assert(m_main < size()); kak_assert(m_main < size());
for (size_t i = 0; i+1 < size(); ++ i) for (size_t i = 0; i+1 < size(); ++ i)
kak_assert((*this)[i].min() <= (*this)[i+1].min()); kak_assert((*this)[i].min() <= (*this)[i+1].min());
for (size_t i = 0; i < size(); ++i)
{
auto& sel = (*this)[i];
kak_assert(buffer.is_valid(sel.anchor()));
kak_assert(buffer.is_valid(sel.cursor()));
kak_assert(not buffer.is_end(sel.anchor()));
kak_assert(not buffer.is_end(sel.cursor()));
kak_assert(utf8::is_character_start(buffer.iterator_at(sel.anchor())));
kak_assert(utf8::is_character_start(buffer.iterator_at(sel.cursor())));
}
#endif
}
void SelectionList::sort_and_merge_overlapping()
{
if (size() == 1)
return;
const auto& main = this->main();
const auto main_begin = main.min();
m_main = std::count_if(begin(), end(), [&](const Selection& sel) {
auto begin = sel.min();
if (begin == main_begin)
return &sel < &main;
else
return begin < main_begin;
});
std::stable_sort(begin(), end(), compare_selections);
merge_overlapping(overlaps);
} }
} }

View File

@ -12,7 +12,7 @@ using CaptureList = std::vector<String>;
struct Selection struct Selection
{ {
Selection() = default; Selection() = default;
explicit Selection(ByteCoord pos) : Selection(pos,pos) {} Selection(ByteCoord pos) : Selection(pos,pos) {}
Selection(ByteCoord anchor, ByteCoord cursor, Selection(ByteCoord anchor, ByteCoord cursor,
CaptureList captures = {}) CaptureList captures = {})
: m_anchor{anchor}, m_cursor{cursor}, : m_anchor{anchor}, m_cursor{cursor},
@ -57,13 +57,17 @@ static bool compare_selections(const Selection& lhs, const Selection& rhs)
struct SelectionList struct SelectionList
{ {
SelectionList() = default; SelectionList(const Buffer& buffer);
SelectionList(ByteCoord c) : m_selections{Selection{c,c}} {} SelectionList(const Buffer& buffer, Selection s);
SelectionList(Selection s) : m_selections{s} {} SelectionList(const Buffer& buffer, Selection s, size_t timestamp);
SelectionList(const Buffer& buffer, std::vector<Selection> s);
SelectionList(const Buffer& buffer, std::vector<Selection> s, size_t timestamp);
void update_insert(ByteCoord begin, ByteCoord end, bool at_end); void update_insert(ByteCoord begin, ByteCoord end, bool at_end);
void update_erase(ByteCoord begin, ByteCoord end, bool at_end); void update_erase(ByteCoord begin, ByteCoord end, bool at_end);
void update();
void check_invariant() const; void check_invariant() const;
const Selection& main() const { return (*this)[m_main]; } const Selection& main() const { return (*this)[m_main]; }
@ -102,8 +106,8 @@ struct SelectionList
size_t size() const { return m_selections.size(); } size_t size() const { return m_selections.size(); }
bool empty() const { return m_selections.empty(); } bool empty() const { return m_selections.empty(); }
bool operator==(const SelectionList& other) const { return m_selections == other.m_selections; } bool operator==(const SelectionList& other) const { return m_buffer == other.m_buffer and m_selections == other.m_selections; }
bool operator!=(const SelectionList& other) const { return m_selections != other.m_selections; } bool operator!=(const SelectionList& other) const { return !((*this) == other); }
template<typename OverlapsFunc> template<typename OverlapsFunc>
void merge_overlapping(OverlapsFunc overlaps) void merge_overlapping(OverlapsFunc overlaps)
@ -129,27 +133,19 @@ struct SelectionList
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();
{
if (size() == 1)
return;
const auto& main = this->main(); const Buffer& buffer() const { return *m_buffer; }
const auto main_begin = main.min();
m_main = std::count_if(begin(), end(), [&](const Selection& sel) { size_t timestamp() const { return m_timestamp; }
auto begin = sel.min(); void set_timestamp(size_t timestamp) { m_timestamp = timestamp; }
if (begin == main_begin)
return &sel < &main;
else
return begin < main_begin;
});
std::stable_sort(begin(), end(), compare_selections);
merge_overlapping(overlaps);
}
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;
size_t m_timestamp;
}; };
} }

View File

@ -431,13 +431,13 @@ Selection trim_partial_lines(const Buffer& buffer, const Selection& selection)
void select_whole_buffer(const Buffer& buffer, SelectionList& selections) void select_whole_buffer(const Buffer& buffer, SelectionList& selections)
{ {
selections = SelectionList{ 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(const Buffer& buffer, SelectionList& selections,
const Regex& regex) const Regex& regex)
{ {
SelectionList result; SelectionList result(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()));
@ -470,7 +470,7 @@ void select_all_matches(const Buffer& buffer, SelectionList& selections,
void split_selections(const Buffer& buffer, SelectionList& selections, void split_selections(const Buffer& buffer, SelectionList& selections,
const Regex& regex) const Regex& regex)
{ {
SelectionList result; SelectionList result(buffer);
for (auto& sel : selections) for (auto& sel : selections)
{ {
auto begin = buffer.iterator_at(sel.min()); auto begin = buffer.iterator_at(sel.min());

View File

@ -16,7 +16,7 @@ inline void clear_selections(const Buffer& buffer, SelectionList& selections)
avoid_eol(buffer, pos); avoid_eol(buffer, pos);
sel.anchor() = pos; sel.anchor() = pos;
selections = SelectionList{ std::move(sel) }; selections = SelectionList{ buffer, std::move(sel) };
} }
inline void flip_selections(SelectionList& selections) inline void flip_selections(SelectionList& selections)
@ -31,7 +31,7 @@ inline void keep_selection(SelectionList& selections, int index)
if (index < selections.size()) if (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 = SelectionList{ std::move(selections[real_index]) }; selections = SelectionList{ selections.buffer(), std::move(selections[real_index]) };
} }
selections.check_invariant(); selections.check_invariant();
} }

View File

@ -23,7 +23,7 @@ Window::Window(Buffer& buffer)
m_options(buffer.options()), m_options(buffer.options()),
m_keymaps(buffer.keymaps()) m_keymaps(buffer.keymaps())
{ {
InputHandler hook_handler{*m_buffer, { Selection{} } }; InputHandler hook_handler{{ *m_buffer, Selection{} }};
hook_handler.context().set_window(*this); hook_handler.context().set_window(*this);
m_hooks.run_hook("WinCreate", buffer.name(), hook_handler.context()); m_hooks.run_hook("WinCreate", buffer.name(), hook_handler.context());
m_options.register_watcher(*this); m_options.register_watcher(*this);
@ -38,7 +38,7 @@ Window::Window(Buffer& buffer)
Window::~Window() Window::~Window()
{ {
InputHandler hook_handler{*m_buffer, { Selection{} } }; InputHandler hook_handler{{ *m_buffer, Selection{} }};
hook_handler.context().set_window(*this); hook_handler.context().set_window(*this);
m_hooks.run_hook("WinClose", buffer().name(), hook_handler.context()); m_hooks.run_hook("WinClose", buffer().name(), hook_handler.context());
m_options.unregister_watcher(*this); m_options.unregister_watcher(*this);
@ -262,7 +262,7 @@ ByteCoord Window::offset_coord(ByteCoord coord, LineCount offset)
lines.emplace_back(AtomList{ {buffer(), line, line+1} }); lines.emplace_back(AtomList{ {buffer(), line, line+1} });
display_buffer.compute_range(); display_buffer.compute_range();
InputHandler hook_handler{*m_buffer, { Selection{} } }; InputHandler hook_handler{{ *m_buffer, Selection{} } };
hook_handler.context().set_window(*this); hook_handler.context().set_window(*this);
m_highlighters(hook_handler.context(), HighlightFlags::MoveOnly, display_buffer); m_highlighters(hook_handler.context(), HighlightFlags::MoveOnly, display_buffer);
m_builtin_highlighters(hook_handler.context(), HighlightFlags::MoveOnly, display_buffer); m_builtin_highlighters(hook_handler.context(), HighlightFlags::MoveOnly, display_buffer);
@ -274,7 +274,7 @@ ByteCoord Window::offset_coord(ByteCoord coord, LineCount offset)
void Window::on_option_changed(const Option& option) void Window::on_option_changed(const Option& option)
{ {
String desc = option.name() + "=" + option.get_as_string(); String desc = option.name() + "=" + option.get_as_string();
InputHandler hook_handler{*m_buffer, { Selection{} } }; InputHandler hook_handler{{ *m_buffer, Selection{} }};
hook_handler.context().set_window(*this); hook_handler.context().set_window(*this);
m_hooks.run_hook("WinSetOption", desc, hook_handler.context()); m_hooks.run_hook("WinSetOption", desc, hook_handler.context());