diff --git a/src/editor.cc b/src/editor.cc index f4153122..4f925374 100644 --- a/src/editor.cc +++ b/src/editor.cc @@ -235,52 +235,12 @@ void Editor::select(SelectionList selections) check_invariant(); } -void Editor::select(const Selector& selector, SelectMode mode) -{ - if (mode == SelectMode::Append) - { - auto& sel = m_selections.main(); - auto res = selector(*m_buffer, sel); - if (res.captures().empty()) - res.captures() = sel.captures(); - m_selections.push_back(res); - m_selections.set_main_index(m_selections.size() - 1); - } - else if (mode == SelectMode::ReplaceMain) - { - auto& sel = m_selections.main(); - auto res = selector(*m_buffer, sel); - sel.first() = res.first(); - sel.last() = res.last(); - if (not res.captures().empty()) - sel.captures() = std::move(res.captures()); - } - else - { - for (auto& sel : m_selections) - { - auto res = selector(*m_buffer, sel); - if (mode == SelectMode::Extend) - sel.merge_with(res); - else - { - sel.first() = res.first(); - sel.last() = res.last(); - } - if (not res.captures().empty()) - sel.captures() = std::move(res.captures()); - } - } - m_selections.sort_and_merge_overlapping(); - check_invariant(); -} - struct nothing_selected : public runtime_error { nothing_selected() : runtime_error("nothing was selected") {} }; -void Editor::multi_select(const MultiSelector& selector) +void Editor::select(const MultiSelector& selector) { selector(*m_buffer, m_selections); check_invariant(); diff --git a/src/editor.hh b/src/editor.hh index 8e04b153..16e4eb2b 100644 --- a/src/editor.hh +++ b/src/editor.hh @@ -39,7 +39,6 @@ enum class InsertMode : unsigned class Editor : public SafeCountable { public: - typedef std::function Selector; typedef std::function MultiSelector; Editor(Buffer& buffer); @@ -66,10 +65,8 @@ public: { select(Selection{ buffer().clamp(c) }, mode); } void select(const Selection& sel, SelectMode mode = SelectMode::Replace); - void select(const Selector& selector, - SelectMode mode = SelectMode::Replace); void select(SelectionList selections); - void multi_select(const MultiSelector& selector); + void select(const MultiSelector& selector); void rotate_selections(int count) { m_selections.rotate_main(count); } diff --git a/src/normal.cc b/src/normal.cc index 14ef013d..148b0369 100644 --- a/src/normal.cc +++ b/src/normal.cc @@ -22,6 +22,62 @@ namespace Kakoune using namespace std::placeholders; +template +class Select +{ +public: + constexpr Select(T t) : m_func(t) {} + + void operator() (Context& context, int) + { + context.editor().select([this](const Buffer& buffer, SelectionList& selections) + { + if (mode == SelectMode::Append) + { + auto& sel = selections.main(); + auto res = m_func(buffer, sel); + if (res.captures().empty()) + res.captures() = sel.captures(); + selections.push_back(res); + selections.set_main_index(selections.size() - 1); + } + else if (mode == SelectMode::ReplaceMain) + { + auto& sel = selections.main(); + auto res = m_func(buffer, sel); + sel.first() = res.first(); + sel.last() = res.last(); + if (not res.captures().empty()) + sel.captures() = std::move(res.captures()); + } + else + { + for (auto& sel : selections) + { + auto res = m_func(buffer, sel); + if (mode == SelectMode::Extend) + sel.merge_with(res); + else + { + sel.first() = res.first(); + sel.last() = res.last(); + } + if (not res.captures().empty()) + sel.captures() = std::move(res.captures()); + } + } + selections.sort_and_merge_overlapping(); + selections.check_invariant(); + }); + } +private: + T m_func; +}; + +template +constexpr Select select(T func) { return Select(func); } + + template void insert(Context& context, int) { @@ -82,10 +138,10 @@ void goto_commands(Context& context, int line) editor.select(BufferCoord{0,0}, mode); break; case 'l': - editor.select(select_to_eol, mode); + select(select_to_eol)(context, 0); break; case 'h': - editor.select(select_to_eol_reverse, mode); + select(select_to_eol_reverse)(context, 0); break; case 'j': { @@ -218,7 +274,7 @@ void replace_with_char(Context& context, int) 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, _2, Regex{"."})); + editor.select(std::bind(select_all_matches, _1, _2, Regex{"."})); editor.insert(codepoint_to_str(key.key), InsertMode::Replace); }, "replace with char", "enter char to replace with\n"); } @@ -321,7 +377,7 @@ void search(Context& context, int) else if (str.empty() or not context.options()["incsearch"].get()) return; - context.editor().multi_select(std::bind(select_next_match, _1, _2, ex)); + context.editor().select(std::bind(select_next_match, _1, _2, ex)); } catch (boost::regex_error& err) { @@ -351,7 +407,7 @@ void search_next(Context& context, int param) { Regex ex{str}; do { - context.editor().multi_select(std::bind(select_next_match, _1, _2, ex)); + context.editor().select(std::bind(select_next_match, _1, _2, ex)); } while (--param > 0); } catch (boost::regex_error& err) @@ -478,7 +534,7 @@ void select_regex(Context& context, int) 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, _2, ex)); + context.editor().select(std::bind(select_all_matches, _1, _2, ex)); }); } @@ -490,13 +546,13 @@ void split_regex(Context& context, int) else RegisterManager::instance()['/'] = String{ex.str()}; if (not ex.empty() and not ex.str().empty()) - context.editor().multi_select(std::bind(split_selection, _1, _2, ex)); + context.editor().select(std::bind(split_selection, _1, _2, ex)); }); } void split_lines(Context& context, int) { - context.editor().multi_select([](const Buffer& buffer, + context.editor().select([](const Buffer& buffer, SelectionList& selections) { SelectionList res; for (auto& sel : selections) @@ -519,10 +575,10 @@ void split_lines(Context& context, int) void join_select_spaces(Context& context, int) { + select(select_whole_lines)(context, 0); + select(select_to_eol)(context, 0); Editor& editor = context.editor(); - editor.select(select_whole_lines); - editor.select(select_to_eol, SelectMode::Extend); - editor.multi_select([](const Buffer& buffer, SelectionList& sel) + editor.select([](const Buffer& buffer, SelectionList& sel) { select_all_matches(buffer, sel, Regex{"(\n\\h*)+"}); // remove last end of line if selected @@ -574,7 +630,7 @@ void indent(Context& context, int) Editor& editor = context.editor(); DynamicSelectionList sels{editor.buffer(), editor.selections()}; auto restore_sels = on_scope_end([&]{ editor.select((SelectionList)std::move(sels)); }); - editor.multi_select([&indent](const Buffer& buf, SelectionList& selections) { + editor.select([&indent](const Buffer& buf, SelectionList& selections) { SelectionList res; for (auto& sel : selections) { @@ -601,7 +657,7 @@ void deindent(Context& context, int) DynamicSelectionList sels{editor.buffer(), editor.selections()}; auto restore_sels = on_scope_end([&]{ editor.select((SelectionList)std::move(sels)); }); - editor.multi_select([indent_width,tabstop](const Buffer& buf, SelectionList& selections) { + editor.select([indent_width,tabstop](const Buffer& buf, SelectionList& selections) { SelectionList res; for (auto& sel : selections) { @@ -658,7 +714,7 @@ void select_object(Context& context, int param) for (auto& sel : selectors) { if (c == sel.key) - return context.editor().select(std::bind(sel.func, _1, _2, flags), mode); + return select(std::bind(sel.func, _1, _2, flags))(context, 0); } static constexpr struct @@ -677,8 +733,8 @@ void select_object(Context& context, int param) { if (sur.pair.first == c or sur.pair.second == c or (sur.name != 0 and sur.name == c)) - return context.editor().select(std::bind(select_surrounding, _1, _2, - sur.pair, level, flags), mode); + return select(std::bind(select_surrounding, _1, _2, + sur.pair, level, flags))(context, 0); } }, "select object", "b,(,): parenthesis block\n" @@ -758,10 +814,9 @@ template void select_to_next_char(Context& context, int param) { on_next_key_with_autoinfo(context, [param](Key key, Context& context) { - context.editor().select( + select( std::bind(flags & SelectFlags::Reverse ? select_to_reverse : select_to, - _1, _2, key.key, param, flags & SelectFlags::Inclusive), - flags & SelectFlags::Extend ? SelectMode::Extend : SelectMode::Replace); + _1, _2, key.key, param, flags & SelectFlags::Inclusive))(context, 0); }, "select to next char","enter char to select to"); } @@ -941,23 +996,6 @@ private: template constexpr Repeated repeated(T func) { return Repeated(func); } -template -class Select -{ -public: - constexpr Select(T t) : m_func(t) {} - - void operator() (Context& context, int) - { - context.editor().select(m_func, mode); - } -private: - T m_func; -}; - -template -constexpr Select select(T func) { return Select(func); } - template void move(Context& context, int count) { @@ -1013,7 +1051,7 @@ KeyMap keymap = { '.', repeat_insert }, - { '%', [](Context& context, int) { context.editor().clear_selections(); context.editor().select(select_whole_buffer); } }, + { '%', [](Context& context, int) { context.editor().select(select_whole_buffer); } }, { ':', command }, { '|', pipe }, diff --git a/src/selectors.cc b/src/selectors.cc index 31a2da6a..ac5523e7 100644 --- a/src/selectors.cc +++ b/src/selectors.cc @@ -592,9 +592,9 @@ Selection trim_partial_lines(const Buffer& buffer, const Selection& selection) return Selection(first.coord(), last.coord()); } -Selection select_whole_buffer(const Buffer& buffer, const Selection&) +void select_whole_buffer(const Buffer& buffer, SelectionList& selections) { - return Selection({0,0}, buffer.back_coord()); + selections = SelectionList{ Selection({0,0}, buffer.back_coord()) }; } void select_all_matches(const Buffer& buffer, SelectionList& selections, diff --git a/src/selectors.hh b/src/selectors.hh index 54008cc7..4005a716 100644 --- a/src/selectors.hh +++ b/src/selectors.hh @@ -54,7 +54,7 @@ Selection select_whole_paragraph(const Buffer& buffer, const Selection& selectio Selection select_whole_indent(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); +void select_whole_buffer(const Buffer& buffer, SelectionList& selections); Selection trim_partial_lines(const Buffer& buffer, const Selection& selection); enum Direction { Forward, Backward }; @@ -126,10 +126,10 @@ void select_next_match(const Buffer& buffer, SelectionList& selections, selections.sort_and_merge_overlapping(); } -void select_all_matches(const Buffer& buffer, SelectionList& selection, +void select_all_matches(const Buffer& buffer, SelectionList& selections, const Regex& regex); -void split_selection(const Buffer& buffer, SelectionList& selection, +void split_selection(const Buffer& buffer, SelectionList& selections, const Regex& separator_regex); using CodepointPair = std::pair; diff --git a/src/unit_tests.cc b/src/unit_tests.cc index 1294c0be..8d7fb908 100644 --- a/src/unit_tests.cc +++ b/src/unit_tests.cc @@ -77,7 +77,7 @@ void test_editor() { scoped_edition edition{editor}; editor.select(select_whole_buffer); - editor.multi_select(std::bind(select_all_matches, _1, _2, Regex{"\\n\\h*"})); + editor.select(std::bind(select_all_matches, _1, _2, Regex{"\\n\\h*"})); for (auto& sel : editor.selections()) { kak_assert(buffer.byte_at(sel.min()) == '\n');