Selection: refactoring, move CaptureList to Selection

This commit is contained in:
Maxime Coste 2012-11-30 18:32:49 +01:00
parent 956ac60d4a
commit b764a0a63e
10 changed files with 198 additions and 192 deletions

View File

@ -99,7 +99,7 @@ struct Context
void push_jump() void push_jump()
{ {
const SelectionAndCaptures& jump = editor().selections().back(); const Selection& jump = editor().selections().back();
if (m_current_jump != m_jump_list.end()) if (m_current_jump != m_jump_list.end())
{ {
auto begin = m_current_jump; auto begin = m_current_jump;
@ -115,7 +115,7 @@ struct Context
m_current_jump = m_jump_list.end(); m_current_jump = m_jump_list.end();
} }
SelectionAndCaptures jump_forward() Selection jump_forward()
{ {
if (m_current_jump != m_jump_list.end() and if (m_current_jump != m_jump_list.end() and
m_current_jump + 1 != m_jump_list.end()) m_current_jump + 1 != m_jump_list.end())
@ -123,7 +123,7 @@ struct Context
throw runtime_error("no next jump"); throw runtime_error("no next jump");
} }
SelectionAndCaptures jump_backward() Selection jump_backward()
{ {
if (m_current_jump != m_jump_list.begin()) if (m_current_jump != m_jump_list.begin())
{ {
@ -164,8 +164,8 @@ private:
Insertion m_last_insert = {InsertMode::Insert, {}}; Insertion m_last_insert = {InsertMode::Insert, {}};
int m_numeric_param = 0; int m_numeric_param = 0;
SelectionAndCapturesList m_jump_list; SelectionList m_jump_list;
SelectionAndCapturesList::iterator m_current_jump = m_jump_list.begin(); SelectionList::iterator m_current_jump = m_jump_list.begin();
}; };
} }

View File

@ -25,7 +25,7 @@ void Editor::erase()
for (auto& sel : m_selections) for (auto& sel : m_selections)
{ {
m_buffer->erase(sel.begin(), sel.end()); m_buffer->erase(sel.begin(), sel.end());
sel.selection.avoid_eol(); sel.avoid_eol();
} }
} }
@ -81,9 +81,9 @@ void Editor::insert(const String& string, InsertMode mode)
for (auto& sel : m_selections) for (auto& sel : m_selections)
{ {
BufferIterator pos = prepare_insert(*m_buffer, sel.selection, mode); BufferIterator pos = prepare_insert(*m_buffer, sel, mode);
m_buffer->insert(pos, string); m_buffer->insert(pos, string);
sel.selection.avoid_eol(); sel.avoid_eol();
} }
} }
@ -101,7 +101,7 @@ void Editor::insert(const memoryview<String>& strings, InsertMode mode)
for (size_t i = 0; i < selections().size(); ++i) for (size_t i = 0; i < selections().size(); ++i)
{ {
Selection& sel = m_selections[i].selection; Selection& sel = m_selections[i];
BufferIterator pos = prepare_insert(*m_buffer, sel, mode); BufferIterator pos = prepare_insert(*m_buffer, sel, mode);
size_t index = std::min(i, strings.size()-1); size_t index = std::min(i, strings.size()-1);
m_buffer->insert(pos, strings[index]); m_buffer->insert(pos, strings[index]);
@ -118,7 +118,7 @@ std::vector<String> Editor::selections_content() const
return contents; return contents;
} }
static void merge_overlapping(SelectionAndCapturesList& selections) static void merge_overlapping(SelectionList& selections)
{ {
for (size_t i = 0; i < selections.size(); ++i) for (size_t i = 0; i < selections.size(); ++i)
{ {
@ -126,7 +126,7 @@ static void merge_overlapping(SelectionAndCapturesList& selections)
{ {
if (overlaps(selections[i], selections[j])) if (overlaps(selections[i], selections[j]))
{ {
selections[i].selection.merge_with(selections[j].selection); selections[i].merge_with(selections[j]);
selections.erase(selections.begin() + j); selections.erase(selections.begin() + j);
} }
else else
@ -144,8 +144,8 @@ void Editor::move_selections(CharCount offset, SelectMode mode)
auto limit = offset < 0 ? buffer().iterator_at_line_begin(last) auto limit = offset < 0 ? buffer().iterator_at_line_begin(last)
: utf8::previous(buffer().iterator_at_line_end(last)); : utf8::previous(buffer().iterator_at_line_end(last));
last = utf8::advance(last, limit, offset); last = utf8::advance(last, limit, offset);
sel.selection = Selection(mode == SelectMode::Extend ? sel.first() : last, last); sel = Selection(mode == SelectMode::Extend ? sel.first() : last, last);
sel.selection.avoid_eol(); sel.avoid_eol();
} }
merge_overlapping(m_selections); merge_overlapping(m_selections);
} }
@ -158,8 +158,8 @@ void Editor::move_selections(LineCount offset, SelectMode mode)
BufferCoord pos = sel.last().coord(); BufferCoord pos = sel.last().coord();
pos.line += offset; pos.line += offset;
BufferIterator last = utf8::finish(m_buffer->iterator_at(pos, true)); BufferIterator last = utf8::finish(m_buffer->iterator_at(pos, true));
sel.selection = Selection(mode == SelectMode::Extend ? sel.first() : last, last); sel = Selection(mode == SelectMode::Extend ? sel.first() : last, last);
sel.selection.avoid_eol(); sel.avoid_eol();
} }
merge_overlapping(m_selections); merge_overlapping(m_selections);
} }
@ -181,7 +181,7 @@ void Editor::flip_selections()
{ {
check_invariant(); check_invariant();
for (auto& sel : m_selections) for (auto& sel : m_selections)
std::swap(sel.selection.first(), sel.selection.last()); std::swap(sel.first(), sel.last());
} }
void Editor::keep_selection(int index) void Editor::keep_selection(int index)
@ -190,7 +190,7 @@ void Editor::keep_selection(int index)
if (index < m_selections.size()) if (index < m_selections.size())
{ {
SelectionAndCaptures sel = std::move(m_selections[index]); Selection sel = std::move(m_selections[index]);
m_selections.clear(); m_selections.clear();
m_selections.push_back(std::move(sel)); m_selections.push_back(std::move(sel));
} }
@ -210,7 +210,7 @@ void Editor::select(const BufferIterator& iterator)
m_selections.push_back(Selection(iterator, iterator)); m_selections.push_back(Selection(iterator, iterator));
} }
void Editor::select(SelectionAndCapturesList selections) void Editor::select(SelectionList selections)
{ {
if (selections.empty()) if (selections.empty())
throw runtime_error("no selections"); throw runtime_error("no selections");
@ -224,23 +224,23 @@ void Editor::select(const Selector& selector, SelectMode mode)
if (mode == SelectMode::Append) if (mode == SelectMode::Append)
{ {
auto& sel = m_selections.back(); auto& sel = m_selections.back();
SelectionAndCaptures res = selector(sel.selection); Selection res = selector(sel);
if (res.captures.empty()) if (res.captures().empty())
res.captures = sel.captures; res.captures() = sel.captures();
m_selections.push_back(res); m_selections.push_back(res);
} }
else else
{ {
for (auto& sel : m_selections) for (auto& sel : m_selections)
{ {
SelectionAndCaptures res = selector(sel.selection); Selection res = selector(sel);
if (mode == SelectMode::Extend) if (mode == SelectMode::Extend)
sel.selection.merge_with(res.selection); sel.merge_with(res);
else else
sel.selection = std::move(res.selection); sel = std::move(res);
if (not res.captures.empty()) if (not res.captures().empty())
sel.captures = std::move(res.captures); sel.captures() = std::move(res.captures());
} }
} }
merge_overlapping(m_selections); merge_overlapping(m_selections);
@ -255,17 +255,18 @@ void Editor::multi_select(const MultiSelector& selector)
{ {
check_invariant(); check_invariant();
SelectionAndCapturesList new_selections; SelectionList new_selections;
for (auto& sel : m_selections) for (auto& sel : m_selections)
{ {
SelectionAndCapturesList res = selector(sel.selection); SelectionList res = selector(sel);
for (auto& sel_and_cap : res) for (auto& new_sel : res)
{ {
// preserve captures when selectors captures nothing. // preserve captures when selectors captures nothing.
if (sel_and_cap.captures.empty()) if (new_sel.captures().empty())
new_selections.emplace_back(sel_and_cap.selection, sel.captures); new_selections.emplace_back(new_sel.first(), new_sel.last(),
sel.captures());
else else
new_selections.push_back(std::move(sel_and_cap)); new_selections.push_back(std::move(new_sel));
} }
} }
if (new_selections.empty()) if (new_selections.empty())
@ -403,7 +404,7 @@ IncrementalInserter::IncrementalInserter(Editor& editor, InsertMode mode)
--first; --first;
if (last.underlying_iterator().is_end()) if (last.underlying_iterator().is_end())
--last; --last;
sel.selection = Selection(first.underlying_iterator(), last.underlying_iterator()); sel = Selection(first.underlying_iterator(), last.underlying_iterator());
} }
if (mode == InsertMode::OpenLineBelow or mode == InsertMode::OpenLineAbove) if (mode == InsertMode::OpenLineBelow or mode == InsertMode::OpenLineAbove)
{ {
@ -414,7 +415,7 @@ IncrementalInserter::IncrementalInserter(Editor& editor, InsertMode mode)
{ {
// special case, the --first line above did nothing, so we need to compensate now // special case, the --first line above did nothing, so we need to compensate now
if (sel.first() == utf8::next(buffer.begin())) if (sel.first() == utf8::next(buffer.begin()))
sel.selection = Selection(buffer.begin(), buffer.begin()); sel = Selection(buffer.begin(), buffer.begin());
} }
} }
} }
@ -426,7 +427,7 @@ IncrementalInserter::~IncrementalInserter()
{ {
if (m_mode == InsertMode::Append) if (m_mode == InsertMode::Append)
sel = Selection(sel.first(), utf8::previous(sel.last())); sel = Selection(sel.first(), utf8::previous(sel.last()));
sel.selection.avoid_eol(); sel.avoid_eol();
} }
m_editor.on_incremental_insertion_end(); m_editor.on_incremental_insertion_end();
@ -437,7 +438,7 @@ void IncrementalInserter::insert(String content)
Buffer& buffer = m_editor.buffer(); Buffer& buffer = m_editor.buffer();
for (auto& sel : m_editor.m_selections) for (auto& sel : m_editor.m_selections)
{ {
m_editor.filters()(buffer, sel.selection, content); m_editor.filters()(buffer, sel, content);
buffer.insert(sel.last(), content); buffer.insert(sel.last(), content);
} }
} }

View File

@ -39,8 +39,8 @@ enum class InsertMode : unsigned
class Editor : public SafeCountable class Editor : public SafeCountable
{ {
public: public:
typedef std::function<SelectionAndCaptures (const Selection&)> Selector; typedef std::function<Selection (const Selection&)> Selector;
typedef std::function<SelectionAndCapturesList (const Selection&)> MultiSelector; typedef std::function<SelectionList (const Selection&)> MultiSelector;
Editor(Buffer& buffer); Editor(Buffer& buffer);
virtual ~Editor() {} virtual ~Editor() {}
@ -65,10 +65,10 @@ public:
void select(const BufferIterator& iterator); void select(const BufferIterator& iterator);
void select(const Selector& selector, void select(const Selector& selector,
SelectMode mode = SelectMode::Replace); SelectMode mode = SelectMode::Replace);
void select(SelectionAndCapturesList selections); void select(SelectionList selections);
void multi_select(const MultiSelector& selector); void multi_select(const MultiSelector& selector);
const SelectionAndCapturesList& selections() const { return m_selections; } const SelectionList& selections() const { return m_selections; }
std::vector<String> selections_content() const; std::vector<String> selections_content() const;
bool undo(); bool undo();
@ -95,7 +95,7 @@ private:
virtual void on_incremental_insertion_end() {} virtual void on_incremental_insertion_end() {}
safe_ptr<Buffer> m_buffer; safe_ptr<Buffer> m_buffer;
SelectionAndCapturesList m_selections; SelectionList m_selections;
FilterGroup m_filters; FilterGroup m_filters;
}; };

View File

@ -28,6 +28,7 @@ colalias identifier cyan
colalias string magenta colalias string magenta
colalias error default,red colalias error default,red
colalias keyword blue colalias keyword blue
colalias operator yellow
colalias attribute green colalias attribute green
colalias comment cyan colalias comment cyan
colalias macro magenta colalias macro magenta

View File

@ -242,7 +242,7 @@ void do_indent(Context& context)
String indent(' ', width); String indent(' ', width);
Editor& editor = context.editor(); Editor& editor = context.editor();
SelectionAndCapturesList sels = editor.selections(); SelectionList sels = editor.selections();
auto restore_sels = on_scope_end([&]{ editor.select(std::move(sels)); }); auto restore_sels = on_scope_end([&]{ editor.select(std::move(sels)); });
editor.select(select_whole_lines); editor.select(select_whole_lines);
editor.multi_select(std::bind(select_all_matches, _1, "^[^\n]")); editor.multi_select(std::bind(select_all_matches, _1, "^[^\n]"));
@ -253,7 +253,7 @@ void do_deindent(Context& context)
{ {
int width = context.options()["indentwidth"].as_int(); int width = context.options()["indentwidth"].as_int();
Editor& editor = context.editor(); Editor& editor = context.editor();
SelectionAndCapturesList sels = editor.selections(); SelectionList sels = editor.selections();
auto restore_sels = on_scope_end([&]{ editor.select(std::move(sels)); }); auto restore_sels = on_scope_end([&]{ editor.select(std::move(sels)); });
editor.select(select_whole_lines); editor.select(select_whole_lines);
editor.multi_select(std::bind(select_all_matches, _1, editor.multi_select(std::bind(select_all_matches, _1,
@ -266,7 +266,7 @@ void do_select_object(Context& context)
{ {
context.input_handler().on_next_key( context.input_handler().on_next_key(
[](const Key& key, Context& context) { [](const Key& key, Context& context) {
typedef std::function<SelectionAndCaptures (const Selection&)> Selector; typedef std::function<Selection (const Selection&)> Selector;
static const std::unordered_map<Key, Selector> key_to_selector = static const std::unordered_map<Key, Selector> key_to_selector =
{ {
{ { Key::Modifiers::None, '(' }, std::bind(select_surrounding, _1, std::pair<char, char>{ '(', ')' }, inner) }, { { Key::Modifiers::None, '(' }, std::bind(select_surrounding, _1, std::pair<char, char>{ '(', ')' }, inner) },
@ -376,7 +376,7 @@ void jump(Context& context)
auto& manager = ClientManager::instance(); auto& manager = ClientManager::instance();
context.change_editor(manager.get_unused_window_for_buffer(buffer)); context.change_editor(manager.get_unused_window_for_buffer(buffer));
} }
context.editor().select(SelectionAndCapturesList{ jump }); context.editor().select(SelectionList{ jump });
} }
String runtime_directory() String runtime_directory()
@ -592,8 +592,8 @@ void register_registers()
register_manager.register_dynamic_register('0'+i, register_manager.register_dynamic_register('0'+i,
[i](const Context& context) { [i](const Context& context) {
std::vector<String> result; std::vector<String> result;
for (auto& sel_and_cap : context.editor().selections()) for (auto& sel : context.editor().selections())
result.emplace_back(i < sel_and_cap.captures.size() ? sel_and_cap.captures[i] : ""); result.emplace_back(i < sel.captures().size() ? sel.captures()[i] : "");
return result; return result;
}); });
} }

View File

@ -5,15 +5,42 @@
namespace Kakoune namespace Kakoune
{ {
Selection::Selection(const BufferIterator& first, const BufferIterator& last) void Range::merge_with(const Range& range)
: m_first(first), m_last(last) {
if (m_first < m_last)
m_first = std::min(m_first, range.m_first);
if (m_first > m_last)
m_first = std::max(m_first, range.m_first);
m_last = range.m_last;
}
BufferIterator Range::begin() const
{
return std::min(m_first, m_last);
}
BufferIterator Range::end() const
{
return utf8::next(std::max(m_first, m_last));
}
Selection::Selection(const BufferIterator& first, const BufferIterator& last,
CaptureList captures)
: Range{first, last}, m_captures{std::move(captures)}
{ {
check_invariant(); check_invariant();
register_with_buffer(); register_with_buffer();
} }
Selection::Selection(const Selection& other) Selection::Selection(const Selection& other)
: m_first(other.m_first), m_last(other.m_last) : Range(other), m_captures(other.m_captures)
{
register_with_buffer();
}
Selection::Selection(Selection&& other)
: Range{other},
m_captures{std::move(other.m_captures)}
{ {
register_with_buffer(); register_with_buffer();
} }
@ -25,12 +52,13 @@ Selection::~Selection()
Selection& Selection::operator=(const Selection& other) Selection& Selection::operator=(const Selection& other)
{ {
const bool new_buffer = &m_first.buffer() != &other.m_first.buffer(); const bool new_buffer = &first().buffer() != &other.first().buffer();
if (new_buffer) if (new_buffer)
unregister_with_buffer(); unregister_with_buffer();
m_first = other.m_first; first() = other.first();
m_last = other.m_last; last() = other.last();
m_captures = other.m_captures;
if (new_buffer) if (new_buffer)
register_with_buffer(); register_with_buffer();
@ -38,23 +66,20 @@ Selection& Selection::operator=(const Selection& other)
return *this; return *this;
} }
BufferIterator Selection::begin() const Selection& Selection::operator=(Selection&& other)
{ {
return std::min(m_first, m_last); const bool new_buffer = &first().buffer() != &other.first().buffer();
} if (new_buffer)
unregister_with_buffer();
BufferIterator Selection::end() const first() = other.first();
{ last() = other.last();
return utf8::next(std::max(m_first, m_last)); m_captures = std::move(other.m_captures);
}
void Selection::merge_with(const Selection& selection) if (new_buffer)
{ register_with_buffer();
if (m_first < m_last)
m_first = std::min(m_first, selection.m_first); return *this;
if (m_first > m_last)
m_first = std::max(m_first, selection.m_first);
m_last = selection.m_last;
} }
static void avoid_eol(BufferIterator& it) static void avoid_eol(BufferIterator& it)
@ -66,38 +91,38 @@ static void avoid_eol(BufferIterator& it)
void Selection::avoid_eol() void Selection::avoid_eol()
{ {
Kakoune::avoid_eol(m_first); Kakoune::avoid_eol(first());
Kakoune::avoid_eol(m_last); Kakoune::avoid_eol(last());
} }
void Selection::on_insert(const BufferIterator& begin, const BufferIterator& end) void Selection::on_insert(const BufferIterator& begin, const BufferIterator& end)
{ {
m_first.on_insert(begin.coord(), end.coord()); first().on_insert(begin.coord(), end.coord());
m_last.on_insert(begin.coord(), end.coord()); last().on_insert(begin.coord(), end.coord());
check_invariant(); check_invariant();
} }
void Selection::on_erase(const BufferIterator& begin, const BufferIterator& end) void Selection::on_erase(const BufferIterator& begin, const BufferIterator& end)
{ {
m_first.on_erase(begin.coord(), end.coord()); first().on_erase(begin.coord(), end.coord());
m_last.on_erase(begin.coord(), end.coord()); last().on_erase(begin.coord(), end.coord());
check_invariant(); check_invariant();
} }
void Selection::register_with_buffer() void Selection::register_with_buffer()
{ {
m_first.buffer().add_change_listener(*this); first().buffer().add_change_listener(*this);
} }
void Selection::unregister_with_buffer() void Selection::unregister_with_buffer()
{ {
m_first.buffer().remove_change_listener(*this); first().buffer().remove_change_listener(*this);
} }
void Selection::check_invariant() const void Selection::check_invariant() const
{ {
assert(utf8::is_character_start(m_first)); assert(utf8::is_character_start(first()));
assert(utf8::is_character_start(m_last)); assert(utf8::is_character_start(last()));
} }
} }

View File

@ -6,34 +6,51 @@
namespace Kakoune namespace Kakoune
{ {
// A Selection holds a buffer range // An oriented, inclusive buffer range
// struct Range
// The Selection class manage a (first, last) buffer iterators pair.
// Selections are oriented, first may be > last, and inclusive.
// Selection updates it's iterators according to modifications made
// in the buffer.
struct Selection : public BufferChangeListener
{ {
Selection(const BufferIterator& first, const BufferIterator& last); public:
Selection(const Selection& other); Range(const BufferIterator& first, const BufferIterator& last)
~Selection(); : m_first{first}, m_last{last} {}
Selection& operator=(const Selection& other); void merge_with(const Range& range);
BufferIterator& first() { return m_first; }
BufferIterator& last() { return m_last; }
const BufferIterator& first() const { return m_first; }
const BufferIterator& last() const { return m_last; }
// returns min(first, last) // returns min(first, last)
BufferIterator begin() const; BufferIterator begin() const;
// returns max(first, last) + 1 // returns max(first, last) + 1
BufferIterator end() const; BufferIterator end() const;
const BufferIterator& first() const { return m_first; } private:
const BufferIterator& last() const { return m_last; } BufferIterator m_first;
BufferIterator m_last;
};
BufferIterator& first() { return m_first; } using CaptureList = std::vector<String>;
BufferIterator& last() { return m_last; }
// A selection is a Range, associated with a CaptureList
// that updates itself when the buffer it points to gets modified.
struct Selection : public Range, public BufferChangeListener
{
Selection(const BufferIterator& first, const BufferIterator& last,
CaptureList captures = {});
Selection(Selection&& other);
Selection(const Selection& other);
~Selection();
Selection& operator=(const Selection& other);
Selection& operator=(Selection&& other);
void merge_with(const Selection& selection);
void avoid_eol(); void avoid_eol();
CaptureList& captures() { return m_captures; }
const CaptureList& captures() const { return m_captures; }
private: private:
void on_insert(const BufferIterator& begin, void on_insert(const BufferIterator& begin,
const BufferIterator& end) override; const BufferIterator& end) override;
@ -42,50 +59,19 @@ private:
void check_invariant() const; void check_invariant() const;
BufferIterator m_first;
BufferIterator m_last;
void register_with_buffer(); void register_with_buffer();
void unregister_with_buffer(); void unregister_with_buffer();
CaptureList m_captures;
}; };
using SelectionList = std::vector<Selection>;
typedef std::vector<Selection> SelectionList; inline bool overlaps(const Selection& lhs, const Selection& rhs)
typedef std::vector<String> CaptureList;
// Selections are often associated with a capture list
// like when they are created from a regex match with
// capture groups.
struct SelectionAndCaptures
{
Selection selection;
CaptureList captures;
SelectionAndCaptures(const BufferIterator& first,
const BufferIterator& last,
CaptureList captures_list = {})
: selection(first, last), captures(std::move(captures_list)) {}
SelectionAndCaptures(const Selection& sel,
CaptureList captures_list = {})
: selection(sel), captures(std::move(captures_list)) {}
// helper to access the selection
BufferIterator begin() const { return selection.begin(); }
BufferIterator end() const { return selection.end(); }
const BufferIterator& first() const { return selection.first(); }
const BufferIterator& last() const { return selection.last(); }
};
inline bool overlaps(const SelectionAndCaptures& lhs,
const SelectionAndCaptures& rhs)
{ {
return (lhs.first() <= rhs.first() and lhs.last() >= rhs.first()) or return (lhs.first() <= rhs.first() and lhs.last() >= rhs.first()) or
(lhs.first() <= rhs.last() and lhs.last() >= rhs.last()); (lhs.first() <= rhs.last() and lhs.last() >= rhs.last());
} }
typedef std::vector<SelectionAndCaptures> SelectionAndCapturesList;
} }
#endif // selection_hh_INCLUDED #endif // selection_hh_INCLUDED

View File

@ -84,7 +84,7 @@ Selection utf8_selection(const Utf8Iterator& first, const Utf8Iterator& last)
typedef boost::regex_iterator<BufferIterator> RegexIterator; typedef boost::regex_iterator<BufferIterator> RegexIterator;
template<bool punctuation_is_word> template<bool punctuation_is_word>
SelectionAndCaptures select_to_next_word(const Selection& selection) Selection select_to_next_word(const Selection& selection)
{ {
Utf8Iterator begin = selection.last(); Utf8Iterator begin = selection.last();
if (categorize<punctuation_is_word>(*begin) != if (categorize<punctuation_is_word>(*begin) !=
@ -103,11 +103,11 @@ SelectionAndCaptures select_to_next_word(const Selection& selection)
return utf8_selection(begin, with_end ? end : end-1); return utf8_selection(begin, with_end ? end : end-1);
} }
template SelectionAndCaptures select_to_next_word<false>(const Selection&); template Selection select_to_next_word<false>(const Selection&);
template SelectionAndCaptures select_to_next_word<true>(const Selection&); template Selection select_to_next_word<true>(const Selection&);
template<bool punctuation_is_word> template<bool punctuation_is_word>
SelectionAndCaptures select_to_next_word_end(const Selection& selection) Selection select_to_next_word_end(const Selection& selection)
{ {
Utf8Iterator begin = selection.last(); Utf8Iterator begin = selection.last();
if (categorize<punctuation_is_word>(*begin) != if (categorize<punctuation_is_word>(*begin) !=
@ -126,11 +126,11 @@ SelectionAndCaptures select_to_next_word_end(const Selection& selection)
return utf8_selection(begin, with_end ? end : end-1); return utf8_selection(begin, with_end ? end : end-1);
} }
template SelectionAndCaptures select_to_next_word_end<false>(const Selection&); template Selection select_to_next_word_end<false>(const Selection&);
template SelectionAndCaptures select_to_next_word_end<true>(const Selection&); template Selection select_to_next_word_end<true>(const Selection&);
template<bool punctuation_is_word> template<bool punctuation_is_word>
SelectionAndCaptures select_to_previous_word(const Selection& selection) Selection select_to_previous_word(const Selection& selection)
{ {
Utf8Iterator begin = selection.last(); Utf8Iterator begin = selection.last();
@ -150,10 +150,10 @@ SelectionAndCaptures select_to_previous_word(const Selection& selection)
return utf8_selection(begin, with_end ? end : end+1); return utf8_selection(begin, with_end ? end : end+1);
} }
template SelectionAndCaptures select_to_previous_word<false>(const Selection&); template Selection select_to_previous_word<false>(const Selection&);
template SelectionAndCaptures select_to_previous_word<true>(const Selection&); template Selection select_to_previous_word<true>(const Selection&);
SelectionAndCaptures select_line(const Selection& selection) Selection select_line(const Selection& selection)
{ {
Utf8Iterator first = selection.last(); Utf8Iterator first = selection.last();
if (*first == '\n' and not is_end(first + 1)) if (*first == '\n' and not is_end(first + 1))
@ -168,7 +168,7 @@ SelectionAndCaptures select_line(const Selection& selection)
return utf8_selection(first, last); return utf8_selection(first, last);
} }
SelectionAndCaptures select_matching(const Selection& selection) Selection select_matching(const Selection& selection)
{ {
std::vector<Codepoint> matching_pairs = { '(', ')', '{', '}', '[', ']', '<', '>' }; std::vector<Codepoint> matching_pairs = { '(', ')', '{', '}', '[', ']', '<', '>' };
Utf8Iterator it = selection.last(); Utf8Iterator it = selection.last();
@ -217,9 +217,9 @@ SelectionAndCaptures select_matching(const Selection& selection)
return selection; return selection;
} }
SelectionAndCaptures select_surrounding(const Selection& selection, Selection select_surrounding(const Selection& selection,
const CodepointPair& matching, const CodepointPair& matching,
bool inside) bool inside)
{ {
int level = 0; int level = 0;
Utf8Iterator first = selection.last(); Utf8Iterator first = selection.last();
@ -266,8 +266,8 @@ SelectionAndCaptures select_surrounding(const Selection& selection,
return utf8_selection(first, last); return utf8_selection(first, last);
} }
SelectionAndCaptures select_to(const Selection& selection, Selection select_to(const Selection& selection,
Codepoint c, int count, bool inclusive) Codepoint c, int count, bool inclusive)
{ {
Utf8Iterator begin = selection.last(); Utf8Iterator begin = selection.last();
Utf8Iterator end = begin; Utf8Iterator end = begin;
@ -283,8 +283,8 @@ SelectionAndCaptures select_to(const Selection& selection,
return utf8_selection(begin, inclusive ? end : end-1); return utf8_selection(begin, inclusive ? end : end-1);
} }
SelectionAndCaptures select_to_reverse(const Selection& selection, Selection select_to_reverse(const Selection& selection,
Codepoint c, int count, bool inclusive) Codepoint c, int count, bool inclusive)
{ {
Utf8Iterator begin = selection.last(); Utf8Iterator begin = selection.last();
Utf8Iterator end = begin; Utf8Iterator end = begin;
@ -300,7 +300,7 @@ SelectionAndCaptures select_to_reverse(const Selection& selection,
return utf8_selection(begin, inclusive ? end : end+1); return utf8_selection(begin, inclusive ? end : end+1);
} }
SelectionAndCaptures select_to_eol(const Selection& selection) Selection select_to_eol(const Selection& selection)
{ {
Utf8Iterator begin = selection.last(); Utf8Iterator begin = selection.last();
Utf8Iterator end = begin + 1; Utf8Iterator end = begin + 1;
@ -308,7 +308,7 @@ SelectionAndCaptures select_to_eol(const Selection& selection)
return utf8_selection(begin, end-1); return utf8_selection(begin, end-1);
} }
SelectionAndCaptures select_to_eol_reverse(const Selection& selection) Selection select_to_eol_reverse(const Selection& selection)
{ {
Utf8Iterator begin = selection.last(); Utf8Iterator begin = selection.last();
Utf8Iterator end = begin - 1; Utf8Iterator end = begin - 1;
@ -317,7 +317,7 @@ SelectionAndCaptures select_to_eol_reverse(const Selection& selection)
} }
template<bool punctuation_is_word> template<bool punctuation_is_word>
SelectionAndCaptures select_whole_word(const Selection& selection, bool inner) Selection select_whole_word(const Selection& selection, bool inner)
{ {
Utf8Iterator first = selection.last(); Utf8Iterator first = selection.last();
Utf8Iterator last = first; Utf8Iterator last = first;
@ -341,10 +341,10 @@ SelectionAndCaptures select_whole_word(const Selection& selection, bool inner)
--last; --last;
return utf8_selection(first, last); return utf8_selection(first, last);
} }
template SelectionAndCaptures select_whole_word<false>(const Selection&, bool); template Selection select_whole_word<false>(const Selection&, bool);
template SelectionAndCaptures select_whole_word<true>(const Selection&, bool); template Selection select_whole_word<true>(const Selection&, bool);
SelectionAndCaptures select_whole_lines(const Selection& selection) Selection select_whole_lines(const Selection& selection)
{ {
// no need to be utf8 aware for is_eol as we only use \n as line seperator // no need to be utf8 aware for is_eol as we only use \n as line seperator
BufferIterator first = selection.first(); BufferIterator first = selection.first();
@ -361,14 +361,13 @@ SelectionAndCaptures select_whole_lines(const Selection& selection)
return Selection(first, last); return Selection(first, last);
} }
SelectionAndCaptures select_whole_buffer(const Selection& selection) Selection select_whole_buffer(const Selection& selection)
{ {
const Buffer& buffer = selection.first().buffer(); const Buffer& buffer = selection.first().buffer();
return Selection(buffer.begin(), utf8::previous(buffer.end())); return Selection(buffer.begin(), utf8::previous(buffer.end()));
} }
SelectionAndCaptures select_next_match(const Selection& selection, Selection select_next_match(const Selection& selection, const String& regex)
const String& regex)
{ {
try try
{ {
@ -403,7 +402,7 @@ SelectionAndCaptures select_next_match(const Selection& selection,
if (begin == end) if (begin == end)
++end; ++end;
return SelectionAndCaptures(begin, utf8::previous(end), std::move(captures)); return Selection(begin, utf8::previous(end), std::move(captures));
} }
catch (boost::regex_error& err) catch (boost::regex_error& err)
{ {
@ -411,8 +410,7 @@ SelectionAndCaptures select_next_match(const Selection& selection,
} }
} }
SelectionAndCapturesList select_all_matches(const Selection& selection, SelectionList select_all_matches(const Selection& selection, const String& regex)
const String& regex)
{ {
try try
{ {
@ -420,7 +418,7 @@ SelectionAndCapturesList select_all_matches(const Selection& selection,
RegexIterator re_it(selection.begin(), selection.end(), ex); RegexIterator re_it(selection.begin(), selection.end(), ex);
RegexIterator re_end; RegexIterator re_end;
SelectionAndCapturesList result; SelectionList result;
for (; re_it != re_end; ++re_it) for (; re_it != re_end; ++re_it)
{ {
BufferIterator begin = (*re_it)[0].first; BufferIterator begin = (*re_it)[0].first;
@ -433,9 +431,8 @@ SelectionAndCapturesList select_all_matches(const Selection& selection,
for (auto& match : *re_it) for (auto& match : *re_it)
captures.push_back(String(match.first, match.second)); captures.push_back(String(match.first, match.second));
result.push_back(SelectionAndCaptures(begin, result.push_back(Selection(begin, begin == end ? end : utf8::previous(end),
begin == end ? end : utf8::previous(end), std::move(captures)));
std::move(captures)));
} }
return result; return result;
} }
@ -445,8 +442,8 @@ SelectionAndCapturesList select_all_matches(const Selection& selection,
} }
} }
SelectionAndCapturesList split_selection(const Selection& selection, SelectionList split_selection(const Selection& selection,
const String& separator_regex) const String& separator_regex)
{ {
try try
{ {
@ -455,7 +452,7 @@ SelectionAndCapturesList split_selection(const Selection& selection,
boost::regex_constants::match_nosubs); boost::regex_constants::match_nosubs);
RegexIterator re_end; RegexIterator re_end;
SelectionAndCapturesList result; SelectionList result;
BufferIterator begin = selection.begin(); BufferIterator begin = selection.begin();
for (; re_it != re_end; ++re_it) for (; re_it != re_end; ++re_it)
{ {

View File

@ -8,44 +8,40 @@ namespace Kakoune
{ {
template<bool punctuation_is_word> template<bool punctuation_is_word>
SelectionAndCaptures select_to_next_word(const Selection& selection); Selection select_to_next_word(const Selection& selection);
template<bool punctuation_is_word> template<bool punctuation_is_word>
SelectionAndCaptures select_to_next_word_end(const Selection& selection); Selection select_to_next_word_end(const Selection& selection);
template<bool punctuation_is_word> template<bool punctuation_is_word>
SelectionAndCaptures select_to_previous_word(const Selection& selection); Selection select_to_previous_word(const Selection& selection);
SelectionAndCaptures select_line(const Selection& selection);
SelectionAndCaptures select_matching(const Selection& selection);
Selection select_line(const Selection& selection);
Selection select_matching(const Selection& selection);
using CodepointPair = std::pair<Codepoint, Codepoint>; using CodepointPair = std::pair<Codepoint, Codepoint>;
SelectionAndCaptures select_surrounding(const Selection& selection, Selection select_surrounding(const Selection& selection,
const CodepointPair& matching, const CodepointPair& matching, bool inside);
bool inside);
SelectionAndCaptures select_to(const Selection& selection, Selection select_to(const Selection& selection,
Codepoint c, Codepoint c, int count, bool inclusive);
int count, bool inclusive); Selection select_to_reverse(const Selection& selection,
SelectionAndCaptures select_to_reverse(const Selection& selection, Codepoint c, int count, bool inclusive);
Codepoint c,
int count, bool inclusive);
SelectionAndCaptures select_to_eol(const Selection& selection); Selection select_to_eol(const Selection& selection);
SelectionAndCaptures select_to_eol_reverse(const Selection& selection); Selection select_to_eol_reverse(const Selection& selection);
template<bool punctuation_is_word> template<bool punctuation_is_word>
SelectionAndCaptures select_whole_word(const Selection& selection, bool inner); Selection select_whole_word(const Selection& selection, bool inner);
SelectionAndCaptures select_whole_lines(const Selection& selection); Selection select_whole_lines(const Selection& selection);
SelectionAndCaptures select_whole_buffer(const Selection& selection); Selection select_whole_buffer(const Selection& selection);
SelectionAndCaptures select_next_match(const Selection& selection, Selection select_next_match(const Selection& selection,
const String& regex); const String& regex);
SelectionAndCapturesList select_all_matches(const Selection& selection, SelectionList select_all_matches(const Selection& selection,
const String& regex); const String& regex);
SelectionAndCapturesList split_selection(const Selection& selection, SelectionList split_selection(const Selection& selection,
const String& separator_regex); const String& separator_regex);
} }

View File

@ -175,7 +175,7 @@ String Window::status_line() const
void Window::on_incremental_insertion_end() void Window::on_incremental_insertion_end()
{ {
SelectionAndCapturesList backup(selections()); SelectionList backup(selections());
hooks().run_hook("InsertEnd", "", Context(*this)); hooks().run_hook("InsertEnd", "", Context(*this));
select(backup); select(backup);
} }