From b51799a2b2202a1933f46cb2c085053406a43a4b Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Sat, 1 Jun 2013 14:22:57 +0200 Subject: [PATCH] Explicitly pass buffer to selectors --- src/editor.cc | 8 ++--- src/editor.hh | 4 +-- src/normal.cc | 58 ++++++++++++++++++------------------ src/selectors.cc | 76 ++++++++++++++++++++++------------------------- src/selectors.hh | 47 +++++++++++++++++------------ src/unit_tests.cc | 3 +- 6 files changed, 101 insertions(+), 95 deletions(-) diff --git a/src/editor.cc b/src/editor.cc index b1e227f0..0de58d5e 100644 --- a/src/editor.cc +++ b/src/editor.cc @@ -293,7 +293,7 @@ void Editor::select(const Selector& selector, SelectMode mode) if (mode == SelectMode::Append) { auto& sel = m_selections[m_main_sel]; - auto res = selector(sel); + auto res = selector(*m_buffer, sel); if (res.captures().empty()) res.captures() = sel.captures(); m_main_sel = m_selections.size(); @@ -302,7 +302,7 @@ void Editor::select(const Selector& selector, SelectMode mode) else if (mode == SelectMode::ReplaceMain) { auto& sel = m_selections[m_main_sel]; - auto res = selector(sel); + auto res = selector(*m_buffer, sel); sel.first() = res.first(); sel.last() = res.last(); if (not res.captures().empty()) @@ -312,7 +312,7 @@ void Editor::select(const Selector& selector, SelectMode mode) { for (auto& sel : m_selections) { - auto res = selector(sel); + auto res = selector(*m_buffer, sel); if (mode == SelectMode::Extend) sel.merge_with(res); else @@ -338,7 +338,7 @@ void Editor::multi_select(const MultiSelector& selector) SelectionList new_selections; for (auto& sel : m_selections) { - SelectionList res = selector(sel); + SelectionList res = selector(*m_buffer, sel); new_selections.reserve(new_selections.size() + res.size()); for (auto& new_sel : res) { diff --git a/src/editor.hh b/src/editor.hh index d99cb2ff..7bd5b67f 100644 --- a/src/editor.hh +++ b/src/editor.hh @@ -38,8 +38,8 @@ enum class InsertMode : unsigned class Editor : public SafeCountable { public: - typedef std::function Selector; - typedef std::function MultiSelector; + typedef std::function Selector; + typedef std::function MultiSelector; Editor(Buffer& buffer); virtual ~Editor() {} diff --git a/src/normal.cc b/src/normal.cc index f09900db..0204dc3a 100644 --- a/src/normal.cc +++ b/src/normal.cc @@ -203,7 +203,7 @@ void replace_with_char(Context& context) Editor& editor = context.editor(); SelectionList sels = editor.selections(); auto restore_sels = on_scope_end([&]{ editor.select(std::move(sels)); }); - editor.multi_select(std::bind(select_all_matches, _1, Regex{"."})); + editor.multi_select(std::bind(select_all_matches, _1, _2, Regex{"."})); editor.insert(codepoint_to_str(key.key), InsertMode::Replace); }); } @@ -282,7 +282,7 @@ void search(Context& context) else if (str.empty() or not context.options()["incsearch"].get()) return; - context.editor().select(std::bind(select_next_match, _1, ex), mode); + context.editor().select(std::bind(select_next_match, _1, _2, ex), mode); } catch (boost::regex_error& err) { @@ -315,7 +315,7 @@ void search_next(Context& context) context.push_jump(); int count = context.numeric_param(); do { - context.editor().select(std::bind(select_next_match, _1, ex), mode); + context.editor().select(std::bind(select_next_match, _1, _2, ex), mode); } while (--count > 0); } catch (boost::regex_error& err) @@ -445,7 +445,7 @@ void select_regex(Context& context) else RegisterManager::instance()['/'] = String{ex.str()}; if (not ex.empty() and not ex.str().empty()) - context.editor().multi_select(std::bind(select_all_matches, _1, ex)); + context.editor().multi_select(std::bind(select_all_matches, _1, _2, ex)); }); } @@ -457,13 +457,13 @@ void split_regex(Context& context) else RegisterManager::instance()['/'] = String{ex.str()}; if (not ex.empty() and not ex.str().empty()) - context.editor().multi_select(std::bind(split_selection, _1, ex)); + context.editor().multi_select(std::bind(split_selection, _1, _2, ex)); }); } void split_lines(Context& context) { - context.editor().multi_select(std::bind(split_selection, _1, Regex{"^"})); + context.editor().multi_select(std::bind(split_selection, _1, _2, Regex{"^"})); } void join_select_spaces(Context& context) @@ -471,9 +471,9 @@ void join_select_spaces(Context& context) Editor& editor = context.editor(); editor.select(select_whole_lines); editor.select(select_to_eol, SelectMode::Extend); - editor.multi_select([](const Selection& sel) + editor.multi_select([](const Buffer& buffer, const Selection& sel) { - SelectionList res = select_all_matches(sel, Regex{"(\n\\h*)+"}); + SelectionList res = select_all_matches(buffer, sel, Regex{"(\n\\h*)+"}); // remove last end of line if selected kak_assert(std::is_sorted(res.begin(), res.end(), [](const Selection& lhs, const Selection& rhs) @@ -521,7 +521,7 @@ void indent(Context& context) DynamicSelectionList sels{editor.buffer(), editor.selections()}; auto restore_sels = on_scope_end([&]{ editor.select((SelectionList)std::move(sels)); }); editor.select(select_whole_lines); - editor.multi_select(std::bind(select_all_matches, _1, Regex{"^[^\n]"})); + editor.multi_select(std::bind(select_all_matches, _1, _2, Regex{"^[^\n]"})); editor.insert(indent, InsertMode::Insert); } @@ -532,7 +532,7 @@ void deindent(Context& context) DynamicSelectionList sels{editor.buffer(), editor.selections()}; auto restore_sels = on_scope_end([&]{ editor.select((SelectionList)std::move(sels)); }); editor.select(select_whole_lines); - editor.multi_select(std::bind(select_all_matches, _1, + editor.multi_select(std::bind(select_all_matches, _1, _2, Regex{"^\\h{1," + to_string(width) + "}"})); editor.erase(); } @@ -556,26 +556,26 @@ void select_object(Context& context) [=](const Key& key, Context& context) { if (hide) context.ui().info_hide(); - typedef std::function Selector; + typedef std::function Selector; static const std::unordered_map key_to_selector = { - { { Key::Modifiers::None, '(' }, std::bind(select_surrounding, _1, CodepointPair{ '(', ')' }, flags) }, - { { Key::Modifiers::None, ')' }, std::bind(select_surrounding, _1, CodepointPair{ '(', ')' }, flags) }, - { { Key::Modifiers::None, 'b' }, std::bind(select_surrounding, _1, CodepointPair{ '(', ')' }, flags) }, - { { Key::Modifiers::None, '{' }, std::bind(select_surrounding, _1, CodepointPair{ '{', '}' }, flags) }, - { { Key::Modifiers::None, '}' }, std::bind(select_surrounding, _1, CodepointPair{ '{', '}' }, flags) }, - { { Key::Modifiers::None, 'B' }, std::bind(select_surrounding, _1, CodepointPair{ '{', '}' }, flags) }, - { { Key::Modifiers::None, '[' }, std::bind(select_surrounding, _1, CodepointPair{ '[', ']' }, flags) }, - { { Key::Modifiers::None, ']' }, std::bind(select_surrounding, _1, CodepointPair{ '[', ']' }, flags) }, - { { Key::Modifiers::None, 'r' }, std::bind(select_surrounding, _1, CodepointPair{ '[', ']' }, flags) }, - { { Key::Modifiers::None, '<' }, std::bind(select_surrounding, _1, CodepointPair{ '<', '>' }, flags) }, - { { Key::Modifiers::None, '>' }, std::bind(select_surrounding, _1, CodepointPair{ '<', '>' }, flags) }, - { { Key::Modifiers::None, '"' }, std::bind(select_surrounding, _1, CodepointPair{ '"', '"' }, flags) }, - { { Key::Modifiers::None, '\'' }, std::bind(select_surrounding, _1, CodepointPair{ '\'', '\'' }, flags) }, - { { Key::Modifiers::None, 'w' }, std::bind(select_whole_word, _1, flags) }, - { { Key::Modifiers::None, 'W' }, std::bind(select_whole_word, _1, flags) }, - { { Key::Modifiers::None, 's' }, std::bind(select_whole_sentence, _1, flags) }, - { { Key::Modifiers::None, 'p' }, std::bind(select_whole_paragraph, _1, flags) }, + { { Key::Modifiers::None, '(' }, std::bind(select_surrounding, _1, _2, CodepointPair{ '(', ')' }, flags) }, + { { Key::Modifiers::None, ')' }, std::bind(select_surrounding, _1, _2, CodepointPair{ '(', ')' }, flags) }, + { { Key::Modifiers::None, 'b' }, std::bind(select_surrounding, _1, _2, CodepointPair{ '(', ')' }, flags) }, + { { Key::Modifiers::None, '{' }, std::bind(select_surrounding, _1, _2, CodepointPair{ '{', '}' }, flags) }, + { { Key::Modifiers::None, '}' }, std::bind(select_surrounding, _1, _2, CodepointPair{ '{', '}' }, flags) }, + { { Key::Modifiers::None, 'B' }, std::bind(select_surrounding, _1, _2, CodepointPair{ '{', '}' }, flags) }, + { { Key::Modifiers::None, '[' }, std::bind(select_surrounding, _1, _2, CodepointPair{ '[', ']' }, flags) }, + { { Key::Modifiers::None, ']' }, std::bind(select_surrounding, _1, _2, CodepointPair{ '[', ']' }, flags) }, + { { Key::Modifiers::None, 'r' }, std::bind(select_surrounding, _1, _2, CodepointPair{ '[', ']' }, flags) }, + { { Key::Modifiers::None, '<' }, std::bind(select_surrounding, _1, _2, CodepointPair{ '<', '>' }, flags) }, + { { Key::Modifiers::None, '>' }, std::bind(select_surrounding, _1, _2, CodepointPair{ '<', '>' }, flags) }, + { { Key::Modifiers::None, '"' }, std::bind(select_surrounding, _1, _2, CodepointPair{ '"', '"' }, flags) }, + { { Key::Modifiers::None, '\'' }, std::bind(select_surrounding, _1, _2, CodepointPair{ '\'', '\'' }, flags) }, + { { Key::Modifiers::None, 'w' }, std::bind(select_whole_word, _1, _2, flags) }, + { { Key::Modifiers::None, 'W' }, std::bind(select_whole_word, _1, _2, flags) }, + { { Key::Modifiers::None, 's' }, std::bind(select_whole_sentence, _1, _2, flags) }, + { { Key::Modifiers::None, 'p' }, std::bind(select_whole_paragraph, _1, _2, flags) }, }; auto it = key_to_selector.find(key); @@ -642,7 +642,7 @@ void select_to_next_char(Context& context) context.input_handler().on_next_key([param](const Key& key, Context& context) { context.editor().select( std::bind(flags & SelectFlags::Reverse ? select_to_reverse : select_to, - _1, key.key, param, flags & SelectFlags::Inclusive), + _1, _2, key.key, param, flags & SelectFlags::Inclusive), flags & SelectFlags::Extend ? SelectMode::Extend : SelectMode::Replace); }); } diff --git a/src/selectors.cc b/src/selectors.cc index 0a53bf34..e8d23899 100644 --- a/src/selectors.cc +++ b/src/selectors.cc @@ -83,7 +83,7 @@ Range utf8_range(const Utf8Iterator& first, const Utf8Iterator& last) typedef boost::regex_iterator RegexIterator; template -Selection select_to_next_word(const Selection& selection) +Selection select_to_next_word(const Buffer& buffer, const Selection& selection) { Utf8Iterator begin = selection.last(); if (categorize(*begin) != @@ -102,11 +102,11 @@ Selection select_to_next_word(const Selection& selection) return utf8_range(begin, end-1); } -template Selection select_to_next_word(const Selection&); -template Selection select_to_next_word(const Selection&); +template Selection select_to_next_word(const Buffer&, const Selection&); +template Selection select_to_next_word(const Buffer&, const Selection&); template -Selection select_to_next_word_end(const Selection& selection) +Selection select_to_next_word_end(const Buffer& buffer, const Selection& selection) { Utf8Iterator begin = selection.last(); if (categorize(*begin) != @@ -124,11 +124,11 @@ Selection select_to_next_word_end(const Selection& selection) return utf8_range(begin, end-1); } -template Selection select_to_next_word_end(const Selection&); -template Selection select_to_next_word_end(const Selection&); +template Selection select_to_next_word_end(const Buffer&, const Selection&); +template Selection select_to_next_word_end(const Buffer&, const Selection&); template -Selection select_to_previous_word(const Selection& selection) +Selection select_to_previous_word(const Buffer& buffer, const Selection& selection) { Utf8Iterator begin = selection.last(); @@ -154,10 +154,10 @@ Selection select_to_previous_word(const Selection& selection) return utf8_range(begin, with_end ? end : end+1); } -template Selection select_to_previous_word(const Selection&); -template Selection select_to_previous_word(const Selection&); +template Selection select_to_previous_word(const Buffer&, const Selection&); +template Selection select_to_previous_word(const Buffer&, const Selection&); -Selection select_line(const Selection& selection) +Selection select_line(const Buffer& buffer, const Selection& selection) { Utf8Iterator first = selection.last(); if (*first == '\n' and not is_end(first + 1)) @@ -172,7 +172,7 @@ Selection select_line(const Selection& selection) return utf8_range(first, last); } -Selection select_matching(const Selection& selection) +Selection select_matching(const Buffer& buffer, const Selection& selection) { std::vector matching_pairs = { '(', ')', '{', '}', '[', ']', '<', '>' }; Utf8Iterator it = selection.last(); @@ -285,7 +285,7 @@ static optional find_surrounding(const BufferIterator& pos, return to_end ? utf8_range(first, last) : utf8_range(last, first); } -Selection select_surrounding(const Selection& selection, +Selection select_surrounding(const Buffer& buffer, const Selection& selection, const CodepointPair& matching, ObjectFlags flags) { @@ -303,7 +303,7 @@ Selection select_surrounding(const Selection& selection, return *res; } -Selection select_to(const Selection& selection, +Selection select_to(const Buffer& buffer, const Selection& selection, Codepoint c, int count, bool inclusive) { Utf8Iterator begin = selection.last(); @@ -320,7 +320,7 @@ Selection select_to(const Selection& selection, return utf8_range(begin, inclusive ? end : end-1); } -Selection select_to_reverse(const Selection& selection, +Selection select_to_reverse(const Buffer& buffer, const Selection& selection, Codepoint c, int count, bool inclusive) { Utf8Iterator begin = selection.last(); @@ -337,7 +337,7 @@ Selection select_to_reverse(const Selection& selection, return utf8_range(begin, inclusive ? end : end+1); } -Selection select_to_eol(const Selection& selection) +Selection select_to_eol(const Buffer& buffer, const Selection& selection) { Utf8Iterator begin = selection.last(); Utf8Iterator end = begin + 1; @@ -345,7 +345,7 @@ Selection select_to_eol(const Selection& selection) return utf8_range(begin, end-1); } -Selection select_to_eol_reverse(const Selection& selection) +Selection select_to_eol_reverse(const Buffer& buffer, const Selection& selection) { Utf8Iterator begin = selection.last(); Utf8Iterator end = begin - 1; @@ -354,7 +354,7 @@ Selection select_to_eol_reverse(const Selection& selection) } template -Selection select_whole_word(const Selection& selection, ObjectFlags flags) +Selection select_whole_word(const Buffer& buffer, const Selection& selection, ObjectFlags flags) { Utf8Iterator first = selection.last(); Utf8Iterator last = first; @@ -394,10 +394,10 @@ Selection select_whole_word(const Selection& selection, ObjectFlags flags) return (flags & ObjectFlags::ToEnd) ? utf8_range(first, last) : utf8_range(last, first); } -template Selection select_whole_word(const Selection&, ObjectFlags); -template Selection select_whole_word(const Selection&, ObjectFlags); +template Selection select_whole_word(const Buffer&, const Selection&, ObjectFlags); +template Selection select_whole_word(const Buffer&, const Selection&, ObjectFlags); -Selection select_whole_sentence(const Selection& selection, ObjectFlags flags) +Selection select_whole_sentence(const Buffer& buffer, const Selection& selection, ObjectFlags flags) { BufferIterator first = selection.last(); BufferIterator last = first; @@ -448,7 +448,7 @@ Selection select_whole_sentence(const Selection& selection, ObjectFlags flags) : Selection{last, first}; } -Selection select_whole_paragraph(const Selection& selection, ObjectFlags flags) +Selection select_whole_paragraph(const Buffer& buffer, const Selection& selection, ObjectFlags flags) { BufferIterator first = selection.last(); BufferIterator last = first; @@ -490,7 +490,7 @@ Selection select_whole_paragraph(const Selection& selection, ObjectFlags flags) : Selection{last, first}; } -Selection select_whole_lines(const Selection& selection) +Selection select_whole_lines(const Buffer& buffer, const Selection& selection) { // no need to be utf8 aware for is_eol as we only use \n as line seperator BufferIterator first = selection.first(); @@ -510,7 +510,7 @@ Selection select_whole_lines(const Selection& selection) return Selection(first, last); } -Selection trim_partial_lines(const Selection& selection) +Selection trim_partial_lines(const Buffer& buffer, const Selection& selection) { // same as select_whole_lines BufferIterator first = selection.first(); @@ -526,9 +526,8 @@ Selection trim_partial_lines(const Selection& selection) return Selection(first, last); } -Selection select_whole_buffer(const Selection& selection) +Selection select_whole_buffer(const Buffer& buffer, const Selection&) { - const Buffer& buffer = selection.first().buffer(); return Selection(buffer.begin(), utf8::previous(buffer.end())); } @@ -549,23 +548,20 @@ static bool find_last_match(BufferIterator begin, const BufferIterator& end, } template -bool find_match_in_buffer(const BufferIterator pos, MatchResults& matches, - const Regex& ex) +bool find_match_in_buffer(const Buffer& buffer, const BufferIterator pos, + MatchResults& matches, const Regex& ex) { - auto bufbeg = pos.buffer().begin(); - auto bufend = pos.buffer().end(); - if (forward) - return (boost::regex_search(pos, bufend, matches, ex) or - boost::regex_search(bufbeg, pos, matches, ex)); + return (boost::regex_search(pos, buffer.end(), matches, ex) or + boost::regex_search(buffer.begin(), pos, matches, ex)); else - return (find_last_match(bufbeg, pos, matches, ex) or - find_last_match(pos, bufend, matches, ex)); + return (find_last_match(buffer.begin(), pos, matches, ex) or + find_last_match(pos, buffer.end(), matches, ex)); } template -Selection select_next_match(const Selection& selection, const Regex& regex) +Selection select_next_match(const Buffer& buffer, const Selection& selection, const Regex& regex) { // regex matching do not use Utf8Iterator as boost::regex handle utf8 // decoding itself @@ -575,7 +571,7 @@ Selection select_next_match(const Selection& selection, const Regex& regex) MatchResults matches; - if (find_match_in_buffer(utf8::next(begin), matches, regex)) + if (find_match_in_buffer(buffer, utf8::next(begin), matches, regex)) { begin = matches[0].first; end = matches[0].second; @@ -593,10 +589,10 @@ Selection select_next_match(const Selection& selection, const Regex& regex) std::swap(begin, end); return Selection{begin, end, std::move(captures)}; } -template Selection select_next_match(const Selection&, const Regex&); -template Selection select_next_match(const Selection&, const Regex&); +template Selection select_next_match(const Buffer&, const Selection&, const Regex&); +template Selection select_next_match(const Buffer&, const Selection&, const Regex&); -SelectionList select_all_matches(const Selection& selection, const Regex& regex) +SelectionList select_all_matches(const Buffer& buffer, const Selection& selection, const Regex& regex) { auto sel_end = utf8::next(selection.max()); RegexIterator re_it(selection.min(), sel_end, regex); @@ -621,7 +617,7 @@ SelectionList select_all_matches(const Selection& selection, const Regex& regex) return result; } -SelectionList split_selection(const Selection& selection, +SelectionList split_selection(const Buffer& buffer, const Selection& selection, const Regex& regex) { auto sel_end = utf8::next(selection.max()); diff --git a/src/selectors.hh b/src/selectors.hh index b7406894..78d3bfac 100644 --- a/src/selectors.hh +++ b/src/selectors.hh @@ -8,22 +8,27 @@ namespace Kakoune { template -Selection select_to_next_word(const Selection& selection); +Selection select_to_next_word(const Buffer& buffer, + const Selection& selection); template -Selection select_to_next_word_end(const Selection& selection); +Selection select_to_next_word_end(const Buffer& buffer, + const Selection& selection); template -Selection select_to_previous_word(const Selection& selection); +Selection select_to_previous_word(const Buffer& buffer, +const Selection& selection); -Selection select_line(const Selection& selection); -Selection select_matching(const Selection& selection); +Selection select_line(const Buffer& buffer, +const Selection& selection); +Selection select_matching(const Buffer& buffer, + const Selection& selection); -Selection select_to(const Selection& selection, +Selection select_to(const Buffer& buffer, const Selection& selection, Codepoint c, int count, bool inclusive); -Selection select_to_reverse(const Selection& selection, +Selection select_to_reverse(const Buffer& buffer, const Selection& selection, Codepoint c, int count, bool inclusive); -Selection select_to_eol(const Selection& selection); -Selection select_to_eol_reverse(const Selection& selection); +Selection select_to_eol(const Buffer& buffer, const Selection& selection); +Selection select_to_eol_reverse(const Buffer& buffer, const Selection& selection); enum class ObjectFlags { @@ -37,24 +42,28 @@ constexpr ObjectFlags operator|(ObjectFlags lhs, ObjectFlags rhs) { return (ObjectFlags)((int)lhs | (int) rhs); } template -Selection select_whole_word(const Selection& selection, ObjectFlags flags); -Selection select_whole_sentence(const Selection& selection, ObjectFlags flags); -Selection select_whole_paragraph(const Selection& selection, ObjectFlags flags); -Selection select_whole_lines(const Selection& selection); -Selection select_whole_buffer(const Selection& selection); -Selection trim_partial_lines(const Selection& selection); +Selection select_whole_word(const Buffer& buffer, const Selection& selection, + ObjectFlags flags); +Selection select_whole_sentence(const Buffer& buffer, const Selection& selection, + ObjectFlags flags); +Selection select_whole_paragraph(const Buffer& buffer, const Selection& selection, + ObjectFlags flags); +Selection select_whole_lines(const Buffer& buffer, const Selection& selection); +Selection select_whole_buffer(const Buffer& buffer, const Selection& selection); +Selection trim_partial_lines(const Buffer& buffer, const Selection& selection); template -Selection select_next_match(const Selection& selection, const Regex& regex); +Selection select_next_match(const Buffer& buffer, const Selection& selection, + const Regex& regex); -SelectionList select_all_matches(const Selection& selection, +SelectionList select_all_matches(const Buffer& buffer, const Selection& selection, const Regex& regex); -SelectionList split_selection(const Selection& selection, +SelectionList split_selection(const Buffer& buffer, const Selection& selection, const Regex& separator_regex); using CodepointPair = std::pair; -Selection select_surrounding(const Selection& selection, +Selection select_surrounding(const Buffer& buffer, const Selection& selection, const CodepointPair& matching, ObjectFlags flags); diff --git a/src/unit_tests.cc b/src/unit_tests.cc index 765e2f09..77e081d6 100644 --- a/src/unit_tests.cc +++ b/src/unit_tests.cc @@ -52,13 +52,14 @@ void test_buffer() void test_editor() { + using namespace std::placeholders; Buffer buffer("test", Buffer::Flags::None, { "test\n", "\n", "youpi\n" }); Editor editor(buffer); { scoped_edition edition{editor}; editor.select(select_whole_buffer); - editor.multi_select(std::bind(select_all_matches, std::placeholders::_1, Regex{"\\n\\h*"})); + editor.multi_select(std::bind(select_all_matches, _1, _2, Regex{"\\n\\h*"})); for (auto& sel : editor.selections()) { kak_assert(*sel.min() == '\n');