Remove Editor::select methods, add a non-const selections getter
This commit is contained in:
parent
0c4d523b22
commit
ce0e71aacb
|
@ -81,7 +81,7 @@ static void reload_buffer(Context& context, const String& filename)
|
||||||
if (not buf)
|
if (not buf)
|
||||||
return;
|
return;
|
||||||
Window& win = ClientManager::instance().get_unused_window_for_buffer(*buf);
|
Window& win = ClientManager::instance().get_unused_window_for_buffer(*buf);
|
||||||
win.select(cursor_pos);
|
win.selections() = SelectionList{cursor_pos};
|
||||||
win.set_position(view_pos);
|
win.set_position(view_pos);
|
||||||
context.change_editor(win);
|
context.change_editor(win);
|
||||||
context.print_status({ "'" + buf->display_name() + "' reloaded",
|
context.print_status({ "'" + buf->display_name() + "' reloaded",
|
||||||
|
|
|
@ -127,7 +127,7 @@ void edit(CommandParameters params, 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.editor().select(context.buffer().clamp({ line, column }));
|
context.editor().selections() = context.buffer().clamp({ line, column });
|
||||||
if (context.has_window())
|
if (context.has_window())
|
||||||
context.window().center_selection();
|
context.window().center_selection();
|
||||||
}
|
}
|
||||||
|
@ -571,13 +571,13 @@ void context_wrap(CommandParameters params, Context& context, Func func)
|
||||||
Editor& editor = real_context->editor();
|
Editor& editor = real_context->editor();
|
||||||
InputHandler input_handler(editor, real_context->name());
|
InputHandler input_handler(editor, real_context->name());
|
||||||
DynamicSelectionList sels{editor.buffer(), editor.selections()};
|
DynamicSelectionList sels{editor.buffer(), editor.selections()};
|
||||||
auto restore_sels = on_scope_end([&]{ editor.select(sels); });
|
auto restore_sels = on_scope_end([&]{ editor.selections() = std::move(sels); });
|
||||||
|
|
||||||
if (parser.has_option("itersel"))
|
if (parser.has_option("itersel"))
|
||||||
{
|
{
|
||||||
for (auto& sel : sels)
|
for (auto& sel : sels)
|
||||||
{
|
{
|
||||||
editor.select(sel);
|
editor.selections() = sel;
|
||||||
func(parser, input_handler.context());
|
func(parser, input_handler.context());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,10 +21,8 @@ static Buffer& get_or_create_debug_buffer()
|
||||||
|
|
||||||
void write_debug(const String& str)
|
void write_debug(const String& str)
|
||||||
{
|
{
|
||||||
Buffer& debug_buffer = get_or_create_debug_buffer();
|
Buffer& buffer = get_or_create_debug_buffer();
|
||||||
Editor editor(debug_buffer);
|
buffer.insert(buffer.end(), str);
|
||||||
editor.select(debug_buffer.back_coord());
|
|
||||||
editor.insert(str + "\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ namespace Kakoune
|
||||||
Editor::Editor(Buffer& buffer)
|
Editor::Editor(Buffer& buffer)
|
||||||
: m_buffer(&buffer),
|
: m_buffer(&buffer),
|
||||||
m_edition_level(0),
|
m_edition_level(0),
|
||||||
m_selections(buffer, { {{},{}} })
|
m_selections(buffer, {BufferCoord{}})
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void Editor::erase()
|
void Editor::erase()
|
||||||
|
@ -151,45 +151,6 @@ void Editor::move_selections(LineCount offset, SelectMode mode)
|
||||||
m_selections.sort_and_merge_overlapping();
|
m_selections.sort_and_merge_overlapping();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Editor::select(const Selection& selection, SelectMode mode)
|
|
||||||
{
|
|
||||||
if (mode == SelectMode::Replace)
|
|
||||||
m_selections = SelectionList{ selection };
|
|
||||||
else if (mode == SelectMode::Extend)
|
|
||||||
{
|
|
||||||
m_selections.main().merge_with(selection);
|
|
||||||
m_selections = SelectionList{ std::move(m_selections.main()) };
|
|
||||||
}
|
|
||||||
else if (mode == SelectMode::Append)
|
|
||||||
{
|
|
||||||
m_selections.push_back(selection);
|
|
||||||
m_selections.set_main_index(m_selections.size()-1);
|
|
||||||
m_selections.sort_and_merge_overlapping();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
kak_assert(false);
|
|
||||||
check_invariant();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Editor::select(SelectionList selections)
|
|
||||||
{
|
|
||||||
if (selections.empty())
|
|
||||||
throw runtime_error("no selections");
|
|
||||||
m_selections = std::move(selections);
|
|
||||||
check_invariant();
|
|
||||||
}
|
|
||||||
|
|
||||||
struct nothing_selected : public runtime_error
|
|
||||||
{
|
|
||||||
nothing_selected() : runtime_error("nothing was selected") {}
|
|
||||||
};
|
|
||||||
|
|
||||||
void Editor::select(const Selector& selector)
|
|
||||||
{
|
|
||||||
selector(*m_buffer, m_selections);
|
|
||||||
check_invariant();
|
|
||||||
}
|
|
||||||
|
|
||||||
class ModifiedRangesListener : public BufferChangeListener_AutoRegister
|
class ModifiedRangesListener : public BufferChangeListener_AutoRegister
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -57,16 +57,11 @@ public:
|
||||||
SelectMode mode = SelectMode::Replace);
|
SelectMode mode = SelectMode::Replace);
|
||||||
void move_selections(CharCount move,
|
void move_selections(CharCount move,
|
||||||
SelectMode mode = SelectMode::Replace);
|
SelectMode mode = SelectMode::Replace);
|
||||||
void select(BufferCoord c, SelectMode mode = SelectMode::Replace)
|
|
||||||
{ select(Selection{ buffer().clamp(c) }, mode); }
|
|
||||||
void select(const Selection& sel,
|
|
||||||
SelectMode mode = SelectMode::Replace);
|
|
||||||
void select(SelectionList selections);
|
|
||||||
void select(const Selector& selector);
|
|
||||||
|
|
||||||
void rotate_selections(int count) { m_selections.rotate_main(count); }
|
void rotate_selections(int count) { m_selections.rotate_main(count); }
|
||||||
|
|
||||||
const SelectionList& selections() const { return m_selections; }
|
const SelectionList& selections() const { return m_selections; }
|
||||||
|
SelectionList& selections() { return m_selections; }
|
||||||
std::vector<String> selections_content() const;
|
std::vector<String> selections_content() const;
|
||||||
|
|
||||||
bool undo();
|
bool undo();
|
||||||
|
|
265
src/normal.cc
265
src/normal.cc
|
@ -30,45 +30,44 @@ public:
|
||||||
|
|
||||||
void operator() (Context& context, int)
|
void operator() (Context& context, int)
|
||||||
{
|
{
|
||||||
context.editor().select([this](const Buffer& buffer, SelectionList& selections)
|
auto& buffer = context.buffer();
|
||||||
|
auto& selections = context.editor().selections();
|
||||||
|
if (mode == SelectMode::Append)
|
||||||
{
|
{
|
||||||
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& sel = selections.main();
|
auto res = m_func(buffer, sel);
|
||||||
auto res = m_func(buffer, sel);
|
if (mode == SelectMode::Extend)
|
||||||
if (res.captures().empty())
|
sel.merge_with(res);
|
||||||
res.captures() = sel.captures();
|
else
|
||||||
selections.push_back(res);
|
{
|
||||||
selections.set_main_index(selections.size() - 1);
|
sel.first() = res.first();
|
||||||
}
|
sel.last() = res.last();
|
||||||
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())
|
if (not res.captures().empty())
|
||||||
sel.captures() = std::move(res.captures());
|
sel.captures() = std::move(res.captures());
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{
|
selections.sort_and_merge_overlapping();
|
||||||
for (auto& sel : selections)
|
selections.check_invariant();
|
||||||
{
|
|
||||||
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:
|
private:
|
||||||
T m_func;
|
T m_func;
|
||||||
|
@ -77,6 +76,18 @@ private:
|
||||||
template<SelectMode mode = SelectMode::Replace, typename T>
|
template<SelectMode mode = SelectMode::Replace, typename T>
|
||||||
constexpr Select<mode, T> select(T func) { return Select<mode, T>(func); }
|
constexpr Select<mode, T> select(T func) { return Select<mode, T>(func); }
|
||||||
|
|
||||||
|
template<SelectMode mode = SelectMode::Replace>
|
||||||
|
void select_coord(BufferCoord coord, SelectionList& selections)
|
||||||
|
{
|
||||||
|
if (mode == SelectMode::Replace)
|
||||||
|
selections = SelectionList { coord };
|
||||||
|
else if (mode == SelectMode::Extend)
|
||||||
|
{
|
||||||
|
for (auto& sel : selections)
|
||||||
|
sel.last() = coord;
|
||||||
|
selections.sort_and_merge_overlapping();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template<InsertMode mode>
|
template<InsertMode mode>
|
||||||
void insert(Context& context, int)
|
void insert(Context& context, int)
|
||||||
|
@ -119,7 +130,7 @@ void goto_commands(Context& context, int line)
|
||||||
if (line != 0)
|
if (line != 0)
|
||||||
{
|
{
|
||||||
context.push_jump();
|
context.push_jump();
|
||||||
context.editor().select(BufferCoord{line - 1, 0});
|
select_coord<mode>(LineCount{line - 1}, context.editor().selections());
|
||||||
if (context.has_window())
|
if (context.has_window())
|
||||||
context.window().center_selection();
|
context.window().center_selection();
|
||||||
}
|
}
|
||||||
|
@ -135,7 +146,7 @@ void goto_commands(Context& context, int line)
|
||||||
case 'g':
|
case 'g':
|
||||||
case 'k':
|
case 'k':
|
||||||
context.push_jump();
|
context.push_jump();
|
||||||
editor.select(BufferCoord{0,0}, mode);
|
select_coord<mode>(BufferCoord{0,0}, context.editor().selections());
|
||||||
break;
|
break;
|
||||||
case 'l':
|
case 'l':
|
||||||
select<mode>(select_to_eol)(context, 0);
|
select<mode>(select_to_eol)(context, 0);
|
||||||
|
@ -146,18 +157,18 @@ void goto_commands(Context& context, int line)
|
||||||
case 'j':
|
case 'j':
|
||||||
{
|
{
|
||||||
context.push_jump();
|
context.push_jump();
|
||||||
editor.select({editor.buffer().line_count() - 1, 0}, mode);
|
select_coord<mode>({editor.buffer().line_count() - 1, 0}, editor.selections());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'e':
|
case 'e':
|
||||||
context.push_jump();
|
context.push_jump();
|
||||||
editor.select(editor.buffer().back_coord(), mode);
|
select_coord<mode>(editor.buffer().back_coord(), editor.selections());
|
||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
if (context.has_window())
|
if (context.has_window())
|
||||||
{
|
{
|
||||||
auto line = context.window().position().line;
|
auto line = context.window().position().line;
|
||||||
editor.select({line, 0}, mode);
|
select_coord<mode>(line, editor.selections());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'b':
|
case 'b':
|
||||||
|
@ -165,7 +176,7 @@ void goto_commands(Context& context, int line)
|
||||||
{
|
{
|
||||||
auto& window = context.window();
|
auto& window = context.window();
|
||||||
auto line = window.position().line + window.dimensions().line - 1;
|
auto line = window.position().line + window.dimensions().line - 1;
|
||||||
editor.select({line, 0}, mode);
|
select_coord<mode>(line, editor.selections());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
|
@ -173,7 +184,7 @@ void goto_commands(Context& context, int line)
|
||||||
{
|
{
|
||||||
auto& window = context.window();
|
auto& window = context.window();
|
||||||
auto line = window.position().line + window.dimensions().line / 2;
|
auto line = window.position().line + window.dimensions().line / 2;
|
||||||
editor.select({line, 0}, mode);
|
select_coord<mode>(line, editor.selections());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'a':
|
case 'a':
|
||||||
|
@ -273,8 +284,8 @@ void replace_with_char(Context& context, int)
|
||||||
return;
|
return;
|
||||||
Editor& editor = context.editor();
|
Editor& editor = context.editor();
|
||||||
SelectionList 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.selections() = std::move(sels); });
|
||||||
editor.select(std::bind(select_all_matches, _1, _2, Regex{"."}));
|
select_all_matches(editor.buffer(), editor.selections(), Regex{"."});
|
||||||
editor.insert(codepoint_to_str(key.key), InsertMode::Replace);
|
editor.insert(codepoint_to_str(key.key), InsertMode::Replace);
|
||||||
}, "replace with char", "enter char to replace with\n");
|
}, "replace with char", "enter char to replace with\n");
|
||||||
}
|
}
|
||||||
|
@ -359,7 +370,7 @@ void search(Context& context, int)
|
||||||
[selections](const String& str, PromptEvent event, Context& context) {
|
[selections](const String& str, PromptEvent event, Context& context) {
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
context.editor().select(selections);
|
context.editor().selections() = selections;
|
||||||
|
|
||||||
if (event == PromptEvent::Abort)
|
if (event == PromptEvent::Abort)
|
||||||
return;
|
return;
|
||||||
|
@ -377,7 +388,7 @@ void search(Context& context, int)
|
||||||
else if (str.empty() or not context.options()["incsearch"].get<bool>())
|
else if (str.empty() or not context.options()["incsearch"].get<bool>())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
context.editor().select(std::bind(select_next_match<direction, mode>, _1, _2, ex));
|
select_next_match<direction, mode>(context.buffer(), context.editor().selections(), ex);
|
||||||
}
|
}
|
||||||
catch (boost::regex_error& err)
|
catch (boost::regex_error& err)
|
||||||
{
|
{
|
||||||
|
@ -388,7 +399,7 @@ void search(Context& context, int)
|
||||||
}
|
}
|
||||||
catch (runtime_error&)
|
catch (runtime_error&)
|
||||||
{
|
{
|
||||||
context.editor().select(selections);
|
context.editor().selections() = selections;
|
||||||
// only validation should propagate errors,
|
// only validation should propagate errors,
|
||||||
// incremental search should not.
|
// incremental search should not.
|
||||||
if (event == PromptEvent::Validate)
|
if (event == PromptEvent::Validate)
|
||||||
|
@ -407,7 +418,7 @@ void search_next(Context& context, int param)
|
||||||
{
|
{
|
||||||
Regex ex{str};
|
Regex ex{str};
|
||||||
do {
|
do {
|
||||||
context.editor().select(std::bind(select_next_match<direction, mode>, _1, _2, ex));
|
select_next_match<direction, mode>(context.buffer(), context.editor().selections(), ex);
|
||||||
} while (--param > 0);
|
} while (--param > 0);
|
||||||
}
|
}
|
||||||
catch (boost::regex_error& err)
|
catch (boost::regex_error& err)
|
||||||
|
@ -534,7 +545,7 @@ void select_regex(Context& context, int)
|
||||||
else
|
else
|
||||||
RegisterManager::instance()['/'] = String{ex.str()};
|
RegisterManager::instance()['/'] = String{ex.str()};
|
||||||
if (not ex.empty() and not ex.str().empty())
|
if (not ex.empty() and not ex.str().empty())
|
||||||
context.editor().select(std::bind(select_all_matches, _1, _2, ex));
|
select_all_matches(context.buffer(), context.editor().selections(), ex);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -546,48 +557,46 @@ void split_regex(Context& context, int)
|
||||||
else
|
else
|
||||||
RegisterManager::instance()['/'] = String{ex.str()};
|
RegisterManager::instance()['/'] = String{ex.str()};
|
||||||
if (not ex.empty() and not ex.str().empty())
|
if (not ex.empty() and not ex.str().empty())
|
||||||
context.editor().select(std::bind(split_selection, _1, _2, ex));
|
split_selections(context.buffer(), context.editor().selections(), ex);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void split_lines(Context& context, int)
|
void split_lines(Context& context, int)
|
||||||
{
|
{
|
||||||
context.editor().select([](const Buffer& buffer,
|
auto& selections = context.editor().selections();
|
||||||
SelectionList& selections) {
|
auto& buffer = context.buffer();
|
||||||
SelectionList res;
|
SelectionList res;
|
||||||
for (auto& sel : selections)
|
for (auto& sel : selections)
|
||||||
|
{
|
||||||
|
if (sel.first().line == sel.last().line)
|
||||||
{
|
{
|
||||||
if (sel.first().line == sel.last().line)
|
res.push_back(std::move(sel));
|
||||||
{
|
continue;
|
||||||
res.push_back(std::move(sel));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
auto min = sel.min();
|
|
||||||
auto max = sel.max();
|
|
||||||
res.push_back({min, {min.line, buffer[min.line].length()-1}});
|
|
||||||
for (auto line = min.line+1; line < max.line; ++line)
|
|
||||||
res.push_back({line, {line, buffer[line].length()-1}});
|
|
||||||
res.push_back({max.line, max});
|
|
||||||
}
|
}
|
||||||
selections = std::move(res);
|
auto min = sel.min();
|
||||||
});
|
auto max = sel.max();
|
||||||
|
res.push_back({min, {min.line, buffer[min.line].length()-1}});
|
||||||
|
for (auto line = min.line+1; line < max.line; ++line)
|
||||||
|
res.push_back({line, {line, buffer[line].length()-1}});
|
||||||
|
res.push_back({max.line, max});
|
||||||
|
}
|
||||||
|
selections = std::move(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
void join_select_spaces(Context& context, int)
|
void join_select_spaces(Context& context, int)
|
||||||
{
|
{
|
||||||
select(select_whole_lines)(context, 0);
|
select(select_whole_lines)(context, 0);
|
||||||
select<SelectMode::Extend>(select_to_eol)(context, 0);
|
select<SelectMode::Extend>(select_to_eol)(context, 0);
|
||||||
Editor& editor = context.editor();
|
auto& editor = context.editor();
|
||||||
editor.select([](const Buffer& buffer, SelectionList& sel)
|
auto& buffer = context.buffer();
|
||||||
{
|
auto& selections = editor.selections();
|
||||||
select_all_matches(buffer, sel, Regex{"(\n\\h*)+"});
|
select_all_matches(buffer, editor.selections(), Regex{"(\n\\h*)+"});
|
||||||
// remove last end of line if selected
|
// remove last end of line if selected
|
||||||
kak_assert(std::is_sorted(sel.begin(), sel.end(),
|
kak_assert(std::is_sorted(selections.begin(), selections.end(),
|
||||||
[](const Selection& lhs, const Selection& rhs)
|
[](const Selection& lhs, const Selection& rhs)
|
||||||
{ return lhs.min() < rhs.min(); }));
|
{ return lhs.min() < rhs.min(); }));
|
||||||
if (not sel.empty() and sel.back().max() == buffer.back_coord())
|
if (not selections.empty() and selections.back().max() == buffer.back_coord())
|
||||||
sel.pop_back();
|
selections.pop_back();
|
||||||
});
|
|
||||||
editor.insert(" ", InsertMode::Replace);
|
editor.insert(" ", InsertMode::Replace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -595,7 +604,7 @@ void join(Context& context, int param)
|
||||||
{
|
{
|
||||||
Editor& editor = context.editor();
|
Editor& editor = context.editor();
|
||||||
DynamicSelectionList sels{editor.buffer(), editor.selections()};
|
DynamicSelectionList sels{editor.buffer(), editor.selections()};
|
||||||
auto restore_sels = on_scope_end([&]{ editor.select((SelectionList)std::move(sels)); });
|
auto restore_sels = on_scope_end([&]{ editor.selections() = std::move(sels); });
|
||||||
join_select_spaces(context, param);
|
join_select_spaces(context, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -617,7 +626,7 @@ void keep(Context& context, int)
|
||||||
}
|
}
|
||||||
if (keep.empty())
|
if (keep.empty())
|
||||||
throw runtime_error("no selections remaining");
|
throw runtime_error("no selections remaining");
|
||||||
editor.select(std::move(keep));
|
editor.selections() = std::move(keep);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -627,21 +636,20 @@ void indent(Context& context, int)
|
||||||
CharCount indent_width = context.options()["indentwidth"].get<int>();
|
CharCount indent_width = context.options()["indentwidth"].get<int>();
|
||||||
String indent = indent_width == 0 ? "\t" : String{' ', indent_width};
|
String indent = indent_width == 0 ? "\t" : String{' ', indent_width};
|
||||||
|
|
||||||
Editor& editor = context.editor();
|
auto& editor = context.editor();
|
||||||
|
auto& buffer = context.buffer();
|
||||||
DynamicSelectionList sels{editor.buffer(), editor.selections()};
|
DynamicSelectionList sels{editor.buffer(), editor.selections()};
|
||||||
auto restore_sels = on_scope_end([&]{ editor.select((SelectionList)std::move(sels)); });
|
auto restore_sels = on_scope_end([&]{ editor.selections() = std::move(sels); });
|
||||||
editor.select([&indent](const Buffer& buf, SelectionList& selections) {
|
SelectionList res;
|
||||||
SelectionList res;
|
for (auto& sel : editor.selections())
|
||||||
for (auto& sel : 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)
|
{
|
||||||
{
|
if (indent_empty or buffer[line].length() > 1)
|
||||||
if (indent_empty or buf[line].length() > 1)
|
res.emplace_back(line, line);
|
||||||
res.emplace_back(line, line);
|
}
|
||||||
}
|
}
|
||||||
}
|
editor.selections() = std::move(res);
|
||||||
selections = std::move(res);
|
|
||||||
});
|
|
||||||
editor.insert(indent, InsertMode::Insert);
|
editor.insert(indent, InsertMode::Insert);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -653,41 +661,40 @@ void deindent(Context& context, int)
|
||||||
if (indent_width == 0)
|
if (indent_width == 0)
|
||||||
indent_width = tabstop;
|
indent_width = tabstop;
|
||||||
|
|
||||||
Editor& editor = context.editor();
|
auto& editor = context.editor();
|
||||||
|
auto& buffer = context.buffer();
|
||||||
DynamicSelectionList sels{editor.buffer(), editor.selections()};
|
DynamicSelectionList sels{editor.buffer(), editor.selections()};
|
||||||
auto restore_sels = on_scope_end([&]{ editor.select((SelectionList)std::move(sels)); });
|
auto restore_sels = on_scope_end([&]{ editor.selections() = std::move(sels); });
|
||||||
|
|
||||||
editor.select([indent_width,tabstop](const Buffer& buf, SelectionList& selections) {
|
SelectionList res;
|
||||||
SelectionList res;
|
for (auto& sel : editor.selections())
|
||||||
for (auto& sel : selections)
|
{
|
||||||
|
for (auto line = sel.min().line; line < sel.max().line+1; ++line)
|
||||||
|
{
|
||||||
|
CharCount width = 0;
|
||||||
|
auto& content = buffer[line];
|
||||||
|
for (auto column = 0_byte; column < content.length(); ++column)
|
||||||
{
|
{
|
||||||
for (auto line = sel.min().line; line < sel.max().line+1; ++line)
|
const char c = content[column];
|
||||||
|
if (c == '\t')
|
||||||
|
width = (width / tabstop + 1) * tabstop;
|
||||||
|
else if (c == ' ')
|
||||||
|
++width;
|
||||||
|
else
|
||||||
{
|
{
|
||||||
CharCount width = 0;
|
if (deindent_incomplete and width != 0)
|
||||||
auto& content = buf[line];
|
res.emplace_back(line, BufferCoord{line, column-1});
|
||||||
for (auto column = 0_byte; column < content.length(); ++column)
|
break;
|
||||||
{
|
}
|
||||||
const char c = content[column];
|
if (width == indent_width)
|
||||||
if (c == '\t')
|
{
|
||||||
width = (width / tabstop + 1) * tabstop;
|
res.emplace_back(line, BufferCoord{line, column});
|
||||||
else if (c == ' ')
|
break;
|
||||||
++width;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (deindent_incomplete and width != 0)
|
|
||||||
res.emplace_back(line, BufferCoord{line, column-1});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (width == indent_width)
|
|
||||||
{
|
|
||||||
res.emplace_back(line, BufferCoord{line, column});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
selections = std::move(res);
|
}
|
||||||
});
|
}
|
||||||
|
editor.selections() = std::move(res);
|
||||||
editor.erase();
|
editor.erase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -773,7 +780,7 @@ void scroll(Context& context, int)
|
||||||
auto cursor_pos = utf8::advance(buffer.iterator_at(position.line),
|
auto cursor_pos = utf8::advance(buffer.iterator_at(position.line),
|
||||||
buffer.iterator_at(position.line+1),
|
buffer.iterator_at(position.line+1),
|
||||||
position.column);
|
position.column);
|
||||||
window.select(cursor_pos.coord());
|
select_coord(cursor_pos.coord(), window.selections());
|
||||||
window.set_position(position);
|
window.set_position(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -868,7 +875,7 @@ void jump(Context& context, int)
|
||||||
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(SelectionList{ jump });
|
context.editor().selections() = jump;
|
||||||
}
|
}
|
||||||
|
|
||||||
void save_selections(Context& context, int)
|
void save_selections(Context& context, int)
|
||||||
|
@ -1051,14 +1058,14 @@ KeyMap keymap =
|
||||||
|
|
||||||
{ '.', repeat_insert },
|
{ '.', repeat_insert },
|
||||||
|
|
||||||
{ '%', [](Context& context, int) { context.editor().select(select_whole_buffer); } },
|
{ '%', [](Context& context, int) { select_whole_buffer(context.buffer(), context.editor().selections()); } },
|
||||||
|
|
||||||
{ ':', command },
|
{ ':', command },
|
||||||
{ '|', pipe },
|
{ '|', pipe },
|
||||||
{ ' ', [](Context& context, int count) { if (count == 0) context.editor().select(clear_selections);
|
{ ' ', [](Context& context, int count) { if (count == 0) clear_selections(context.buffer(), context.editor().selections());
|
||||||
else context.editor().select(std::bind(keep_selection, _1, _2, count-1)); } },
|
else keep_selection(context.editor().selections(), count-1); } },
|
||||||
{ alt(' '), [](Context& context, int count) { if (count == 0) context.editor().select(flip_selections);
|
{ alt(' '), [](Context& context, int count) { if (count == 0) flip_selections(context.editor().selections());
|
||||||
else context.editor().select(std::bind(remove_selection, _1, _2, count-1)); } },
|
else remove_selection(context.editor().selections(), count-1); } },
|
||||||
{ 'w', repeated(select<SelectMode::Replace>(select_to_next_word<Word>)) },
|
{ 'w', repeated(select<SelectMode::Replace>(select_to_next_word<Word>)) },
|
||||||
{ 'e', repeated(select<SelectMode::Replace>(select_to_next_word_end<Word>)) },
|
{ 'e', repeated(select<SelectMode::Replace>(select_to_next_word_end<Word>)) },
|
||||||
{ 'b', repeated(select<SelectMode::Replace>(select_to_previous_word<Word>)) },
|
{ 'b', repeated(select<SelectMode::Replace>(select_to_previous_word<Word>)) },
|
||||||
|
|
|
@ -94,6 +94,7 @@ static bool compare_selections(const Selection& lhs, const Selection& rhs)
|
||||||
struct SelectionList : std::vector<Selection>
|
struct SelectionList : std::vector<Selection>
|
||||||
{
|
{
|
||||||
SelectionList() = default;
|
SelectionList() = default;
|
||||||
|
SelectionList(BufferCoord c) : std::vector<Selection>{Selection{c,c}} {}
|
||||||
SelectionList(Selection s) : std::vector<Selection>{s} {}
|
SelectionList(Selection s) : std::vector<Selection>{s} {}
|
||||||
|
|
||||||
void update_insert(const Buffer& buffer, BufferCoord begin, BufferCoord end);
|
void update_insert(const Buffer& buffer, BufferCoord begin, BufferCoord end);
|
||||||
|
|
|
@ -438,8 +438,8 @@ void select_all_matches(const Buffer& buffer, SelectionList& selections,
|
||||||
selections = std::move(result);
|
selections = std::move(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void split_selection(const Buffer& buffer, SelectionList& selections,
|
void split_selections(const Buffer& buffer, SelectionList& selections,
|
||||||
const Regex& regex)
|
const Regex& regex)
|
||||||
{
|
{
|
||||||
SelectionList result;
|
SelectionList result;
|
||||||
for (auto& sel : selections)
|
for (auto& sel : selections)
|
||||||
|
|
|
@ -19,14 +19,14 @@ inline void clear_selections(const Buffer& buffer, SelectionList& selections)
|
||||||
selections = SelectionList{ std::move(sel) };
|
selections = SelectionList{ std::move(sel) };
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void flip_selections(const Buffer&, SelectionList& selections)
|
inline void flip_selections(SelectionList& selections)
|
||||||
{
|
{
|
||||||
for (auto& sel : selections)
|
for (auto& sel : selections)
|
||||||
std::swap(sel.first(), sel.last());
|
std::swap(sel.first(), sel.last());
|
||||||
selections.check_invariant();
|
selections.check_invariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void keep_selection(const Buffer&, SelectionList& selections, int index)
|
inline void keep_selection(SelectionList& selections, int index)
|
||||||
{
|
{
|
||||||
if (index < selections.size())
|
if (index < selections.size())
|
||||||
{
|
{
|
||||||
|
@ -36,7 +36,7 @@ inline void keep_selection(const Buffer&, SelectionList& selections, int index)
|
||||||
selections.check_invariant();
|
selections.check_invariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void remove_selection(const Buffer&, SelectionList& selections, int index)
|
inline void remove_selection(SelectionList& selections, int index)
|
||||||
{
|
{
|
||||||
if (selections.size() > 1 and index < selections.size())
|
if (selections.size() > 1 and index < selections.size())
|
||||||
{
|
{
|
||||||
|
@ -282,8 +282,8 @@ void select_next_match(const Buffer& buffer, SelectionList& selections,
|
||||||
void select_all_matches(const Buffer& buffer, SelectionList& selections,
|
void select_all_matches(const Buffer& buffer, SelectionList& selections,
|
||||||
const Regex& regex);
|
const Regex& regex);
|
||||||
|
|
||||||
void split_selection(const Buffer& buffer, SelectionList& selections,
|
void split_selections(const Buffer& buffer, SelectionList& selections,
|
||||||
const Regex& separator_regex);
|
const Regex& separator_regex);
|
||||||
|
|
||||||
using CodepointPair = std::pair<Codepoint, Codepoint>;
|
using CodepointPair = std::pair<Codepoint, Codepoint>;
|
||||||
Selection select_surrounding(const Buffer& buffer, const Selection& selection,
|
Selection select_surrounding(const Buffer& buffer, const Selection& selection,
|
||||||
|
|
|
@ -76,8 +76,8 @@ void test_editor()
|
||||||
|
|
||||||
{
|
{
|
||||||
scoped_edition edition{editor};
|
scoped_edition edition{editor};
|
||||||
editor.select(select_whole_buffer);
|
select_whole_buffer(buffer, editor.selections());
|
||||||
editor.select(std::bind(select_all_matches, _1, _2, Regex{"\\n\\h*"}));
|
select_all_matches(buffer, editor.selections(), Regex{"\\n\\h*"});
|
||||||
for (auto& sel : editor.selections())
|
for (auto& sel : editor.selections())
|
||||||
{
|
{
|
||||||
kak_assert(buffer.byte_at(sel.min()) == '\n');
|
kak_assert(buffer.byte_at(sel.min()) == '\n');
|
||||||
|
@ -87,7 +87,7 @@ void test_editor()
|
||||||
editor.undo();
|
editor.undo();
|
||||||
|
|
||||||
Selection sel{ 2_line, buffer.back_coord() };
|
Selection sel{ 2_line, buffer.back_coord() };
|
||||||
editor.select(sel, SelectMode::Replace);
|
editor.selections() = SelectionList{sel};
|
||||||
editor.insert("",InsertMode::Replace);
|
editor.insert("",InsertMode::Replace);
|
||||||
kak_assert(not buffer.is_end(editor.selections().main().first()));
|
kak_assert(not buffer.is_end(editor.selections().main().first()));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user