Merge captures into registers, implements register insertion
This commit is contained in:
parent
04a37d8895
commit
d84d085cc2
144
src/editor.cc
144
src/editor.cc
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
#include "exception.hh"
|
#include "exception.hh"
|
||||||
#include "utils.hh"
|
#include "utils.hh"
|
||||||
|
#include "register.hh"
|
||||||
|
#include "register_manager.hh"
|
||||||
|
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
@ -11,7 +13,7 @@ Editor::Editor(Buffer& buffer)
|
||||||
m_edition_level(0)
|
m_edition_level(0)
|
||||||
{
|
{
|
||||||
m_selections.push_back(SelectionList());
|
m_selections.push_back(SelectionList());
|
||||||
selections().push_back(Selection(buffer.begin(), buffer.begin()));
|
m_selections.back().push_back(Selection(buffer.begin(), buffer.begin()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Editor::erase()
|
void Editor::erase()
|
||||||
|
@ -21,18 +23,51 @@ void Editor::erase()
|
||||||
m_buffer.modify(Modification::make_erase(sel.begin(), sel.end()));
|
m_buffer.modify(Modification::make_erase(sel.begin(), sel.end()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<bool append>
|
||||||
|
static void do_insert(Editor& editor, const Editor::String& string)
|
||||||
|
{
|
||||||
|
scoped_edition edition(editor);
|
||||||
|
for (auto& sel : editor.selections())
|
||||||
|
{
|
||||||
|
BufferIterator pos = append ? sel.end() : sel.begin();
|
||||||
|
editor.buffer().modify(Modification::make_insert(pos, string));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<bool append>
|
||||||
|
static void do_insert(Editor& editor, const memoryview<Editor::String>& strings)
|
||||||
|
{
|
||||||
|
if (strings.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
scoped_edition edition(editor);
|
||||||
|
for (size_t i = 0; i < editor.selections().size(); ++i)
|
||||||
|
{
|
||||||
|
BufferIterator pos = append ? editor.selections()[i].end()
|
||||||
|
: editor.selections()[i].begin();
|
||||||
|
size_t index = std::min(i, strings.size()-1);
|
||||||
|
editor.buffer().modify(Modification::make_insert(pos, strings[index]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Editor::insert(const String& string)
|
void Editor::insert(const String& string)
|
||||||
{
|
{
|
||||||
scoped_edition edition(*this);
|
do_insert<false>(*this, string);
|
||||||
for (auto& sel : selections())
|
}
|
||||||
m_buffer.modify(Modification::make_insert(sel.begin(), string));
|
|
||||||
|
void Editor::insert(const memoryview<String>& strings)
|
||||||
|
{
|
||||||
|
do_insert<false>(*this, strings);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Editor::append(const String& string)
|
void Editor::append(const String& string)
|
||||||
{
|
{
|
||||||
scoped_edition edition(*this);
|
do_insert<true>(*this, string);
|
||||||
for (auto& sel : selections())
|
}
|
||||||
m_buffer.modify(Modification::make_insert(sel.end(), string));
|
|
||||||
|
void Editor::append(const memoryview<String>& strings)
|
||||||
|
{
|
||||||
|
do_insert<true>(*this, strings);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Editor::replace(const std::string& string)
|
void Editor::replace(const std::string& string)
|
||||||
|
@ -42,9 +77,17 @@ void Editor::replace(const std::string& string)
|
||||||
insert(string);
|
insert(string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<Editor::String> Editor::selections_content() const
|
||||||
|
{
|
||||||
|
std::vector<String> contents;
|
||||||
|
for (auto& sel : selections())
|
||||||
|
contents.push_back(m_buffer.string(sel.begin(), sel.end()));
|
||||||
|
return contents;
|
||||||
|
}
|
||||||
|
|
||||||
void Editor::push_selections()
|
void Editor::push_selections()
|
||||||
{
|
{
|
||||||
SelectionList current_selections = selections();
|
SelectionList current_selections = m_selections.back();
|
||||||
m_selections.push_back(std::move(current_selections));
|
m_selections.push_back(std::move(current_selections));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +101,7 @@ void Editor::pop_selections()
|
||||||
|
|
||||||
void Editor::move_selections(const BufferCoord& offset, bool append)
|
void Editor::move_selections(const BufferCoord& offset, bool append)
|
||||||
{
|
{
|
||||||
for (auto& sel : selections())
|
for (auto& sel : m_selections.back())
|
||||||
{
|
{
|
||||||
BufferCoord pos = m_buffer.line_and_column_at(sel.last());
|
BufferCoord pos = m_buffer.line_and_column_at(sel.last());
|
||||||
BufferIterator last = m_buffer.iterator_at(pos + BufferCoord(offset));
|
BufferIterator last = m_buffer.iterator_at(pos + BufferCoord(offset));
|
||||||
|
@ -75,8 +118,8 @@ void Editor::clear_selections()
|
||||||
--pos;
|
--pos;
|
||||||
|
|
||||||
Selection sel = Selection(pos, pos);
|
Selection sel = Selection(pos, pos);
|
||||||
selections().clear();
|
m_selections.back().clear();
|
||||||
selections().push_back(std::move(sel));
|
m_selections.back().push_back(std::move(sel));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Editor::keep_selection(int index)
|
void Editor::keep_selection(int index)
|
||||||
|
@ -86,30 +129,42 @@ void Editor::keep_selection(int index)
|
||||||
if (index < selections().size())
|
if (index < selections().size())
|
||||||
{
|
{
|
||||||
Selection sel = selections()[index];
|
Selection sel = selections()[index];
|
||||||
selections().clear();
|
m_selections.back().clear();
|
||||||
selections().push_back(std::move(sel));
|
m_selections.back().push_back(std::move(sel));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Editor::select(const BufferIterator& iterator)
|
void Editor::select(const BufferIterator& iterator)
|
||||||
{
|
{
|
||||||
selections().clear();
|
m_selections.back().clear();
|
||||||
selections().push_back(Selection(iterator, iterator));
|
m_selections.back().push_back(Selection(iterator, iterator));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Editor::select(const Selector& selector, bool append)
|
void Editor::select(const Selector& selector, bool append)
|
||||||
{
|
{
|
||||||
check_invariant();
|
check_invariant();
|
||||||
|
|
||||||
if (not append)
|
std::vector<std::vector<String>> captures;
|
||||||
|
|
||||||
|
for (auto& sel : m_selections.back())
|
||||||
{
|
{
|
||||||
for (auto& sel : selections())
|
SelectionAndCaptures res = selector(sel);
|
||||||
sel = selector(sel);
|
if (append)
|
||||||
|
sel.merge_with(res.selection);
|
||||||
|
else
|
||||||
|
sel = std::move(res.selection);
|
||||||
|
|
||||||
|
assert(captures.empty() or captures.size() == res.captures.size());
|
||||||
|
captures.resize(res.captures.size());
|
||||||
|
|
||||||
|
for (size_t i = 0; i < res.captures.size(); ++i)
|
||||||
|
captures[i].push_back(res.captures[i]);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if (not captures.empty())
|
||||||
{
|
{
|
||||||
for (auto& sel : selections())
|
for (size_t i = 0; i < captures.size(); ++i)
|
||||||
sel.merge_with(selector(sel));
|
RegisterManager::instance()['0' + i] = std::move(captures[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,25 +177,33 @@ void Editor::multi_select(const MultiSelector& selector)
|
||||||
{
|
{
|
||||||
check_invariant();
|
check_invariant();
|
||||||
|
|
||||||
|
std::vector<std::vector<String>> captures;
|
||||||
|
|
||||||
SelectionList new_selections;
|
SelectionList new_selections;
|
||||||
for (auto& sel : selections())
|
for (auto& sel : m_selections.back())
|
||||||
{
|
{
|
||||||
SelectionList selections = selector(sel);
|
SelectionAndCapturesList res = selector(sel);
|
||||||
std::copy(selections.begin(), selections.end(),
|
for (auto& sel_and_cap : res)
|
||||||
std::back_inserter(new_selections));
|
{
|
||||||
|
new_selections.push_back(sel_and_cap.selection);
|
||||||
|
|
||||||
|
assert(captures.empty() or captures.size() == sel_and_cap.captures.size());
|
||||||
|
captures.resize(sel_and_cap.captures.size());
|
||||||
|
|
||||||
|
for (size_t i = 0; i < sel_and_cap.captures.size(); ++i)
|
||||||
|
captures[i].push_back(sel_and_cap.captures[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (new_selections.empty())
|
if (new_selections.empty())
|
||||||
throw nothing_selected();
|
throw nothing_selected();
|
||||||
|
|
||||||
selections() = std::move(new_selections);
|
m_selections.back() = std::move(new_selections);
|
||||||
}
|
|
||||||
|
|
||||||
BufferString Editor::selection_content() const
|
if (not captures.empty())
|
||||||
{
|
{
|
||||||
check_invariant();
|
for (size_t i = 0; i < captures.size(); ++i)
|
||||||
|
RegisterManager::instance()['0' + i] = std::move(captures[i]);
|
||||||
return m_buffer.string(selections().back().begin(),
|
}
|
||||||
selections().back().end());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Editor::undo()
|
bool Editor::undo()
|
||||||
|
@ -207,7 +270,7 @@ IncrementalInserter::IncrementalInserter(Editor& editor, Mode mode)
|
||||||
if (mode == Mode::Change)
|
if (mode == Mode::Change)
|
||||||
editor.erase();
|
editor.erase();
|
||||||
|
|
||||||
for (auto& sel : m_editor.selections())
|
for (auto& sel : m_editor.m_selections.back())
|
||||||
{
|
{
|
||||||
BufferIterator pos;
|
BufferIterator pos;
|
||||||
switch (mode)
|
switch (mode)
|
||||||
|
@ -228,7 +291,7 @@ IncrementalInserter::IncrementalInserter(Editor& editor, Mode mode)
|
||||||
--pos;
|
--pos;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
sel = Selection(pos, pos, sel.captures());
|
sel = Selection(pos, pos);
|
||||||
|
|
||||||
if (mode == Mode::OpenLineBelow or mode == Mode::OpenLineAbove)
|
if (mode == Mode::OpenLineBelow or mode == Mode::OpenLineAbove)
|
||||||
apply(Modification::make_insert(pos, "\n"));
|
apply(Modification::make_insert(pos, "\n"));
|
||||||
|
@ -248,23 +311,20 @@ void IncrementalInserter::apply(Modification&& modification) const
|
||||||
m_editor.buffer().modify(std::move(modification));
|
m_editor.buffer().modify(std::move(modification));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void IncrementalInserter::insert(const Editor::String& string)
|
void IncrementalInserter::insert(const Editor::String& string)
|
||||||
{
|
{
|
||||||
for (auto& sel : m_editor.selections())
|
for (auto& sel : m_editor.selections())
|
||||||
apply(Modification::make_insert(sel.begin(), string));
|
apply(Modification::make_insert(sel.begin(), string));
|
||||||
}
|
}
|
||||||
|
|
||||||
void IncrementalInserter::insert_capture(size_t index)
|
void IncrementalInserter::insert(const Register& reg)
|
||||||
{
|
{
|
||||||
for (auto& sel : m_editor.selections())
|
m_editor.insert(reg);
|
||||||
m_editor.m_buffer.modify(Modification::make_insert(sel.begin(),
|
|
||||||
sel.capture(index)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IncrementalInserter::erase()
|
void IncrementalInserter::erase()
|
||||||
{
|
{
|
||||||
for (auto& sel : m_editor.selections())
|
for (auto& sel : m_editor.m_selections.back())
|
||||||
{
|
{
|
||||||
sel = Selection(sel.first() - 1, sel.last() - 1);
|
sel = Selection(sel.first() - 1, sel.last() - 1);
|
||||||
apply(Modification::make_erase(sel.begin(), sel.end()));
|
apply(Modification::make_erase(sel.begin(), sel.end()));
|
||||||
|
@ -273,7 +333,7 @@ void IncrementalInserter::erase()
|
||||||
|
|
||||||
void IncrementalInserter::move_cursors(const BufferCoord& offset)
|
void IncrementalInserter::move_cursors(const BufferCoord& offset)
|
||||||
{
|
{
|
||||||
for (auto& sel : m_editor.selections())
|
for (auto& sel : m_editor.m_selections.back())
|
||||||
{
|
{
|
||||||
BufferCoord pos = m_editor.m_buffer.line_and_column_at(sel.last());
|
BufferCoord pos = m_editor.m_buffer.line_and_column_at(sel.last());
|
||||||
BufferIterator it = m_editor.m_buffer.iterator_at(pos + offset);
|
BufferIterator it = m_editor.m_buffer.iterator_at(pos + offset);
|
||||||
|
|
|
@ -5,12 +5,12 @@
|
||||||
#include "selection.hh"
|
#include "selection.hh"
|
||||||
#include "filter.hh"
|
#include "filter.hh"
|
||||||
#include "idvaluemap.hh"
|
#include "idvaluemap.hh"
|
||||||
#include "hooks_manager.hh"
|
#include "memoryview.hh"
|
||||||
|
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
|
||||||
class IncrementalInserter;
|
class Register;
|
||||||
|
|
||||||
// An Editor is a buffer mutator
|
// An Editor is a buffer mutator
|
||||||
//
|
//
|
||||||
|
@ -20,8 +20,8 @@ class Editor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef BufferString String;
|
typedef BufferString String;
|
||||||
typedef std::function<Selection (const Selection&)> Selector;
|
typedef std::function<SelectionAndCaptures (const Selection&)> Selector;
|
||||||
typedef std::function<SelectionList (const Selection&)> MultiSelector;
|
typedef std::function<SelectionAndCapturesList (const Selection&)> MultiSelector;
|
||||||
|
|
||||||
Editor(Buffer& buffer);
|
Editor(Buffer& buffer);
|
||||||
virtual ~Editor() {}
|
virtual ~Editor() {}
|
||||||
|
@ -29,8 +29,13 @@ public:
|
||||||
Buffer& buffer() const { return m_buffer; }
|
Buffer& buffer() const { return m_buffer; }
|
||||||
|
|
||||||
void erase();
|
void erase();
|
||||||
|
|
||||||
void insert(const String& string);
|
void insert(const String& string);
|
||||||
|
void insert(const memoryview<String>& strings);
|
||||||
|
|
||||||
void append(const String& string);
|
void append(const String& string);
|
||||||
|
void append(const memoryview<String>& strings);
|
||||||
|
|
||||||
void replace(const String& string);
|
void replace(const String& string);
|
||||||
|
|
||||||
void push_selections();
|
void push_selections();
|
||||||
|
@ -43,8 +48,8 @@ public:
|
||||||
void select(const Selector& selector, bool append = false);
|
void select(const Selector& selector, bool append = false);
|
||||||
void multi_select(const MultiSelector& selector);
|
void multi_select(const MultiSelector& selector);
|
||||||
|
|
||||||
BufferString selection_content() const;
|
|
||||||
const SelectionList& selections() const { return m_selections.back(); }
|
const SelectionList& selections() const { return m_selections.back(); }
|
||||||
|
std::vector<String> selections_content() const;
|
||||||
|
|
||||||
bool undo();
|
bool undo();
|
||||||
bool redo();
|
bool redo();
|
||||||
|
@ -64,8 +69,6 @@ private:
|
||||||
|
|
||||||
int m_edition_level;
|
int m_edition_level;
|
||||||
|
|
||||||
SelectionList& selections() { return m_selections.back(); }
|
|
||||||
|
|
||||||
void check_invariant() const;
|
void check_invariant() const;
|
||||||
|
|
||||||
friend class IncrementalInserter;
|
friend class IncrementalInserter;
|
||||||
|
@ -108,7 +111,7 @@ public:
|
||||||
~IncrementalInserter();
|
~IncrementalInserter();
|
||||||
|
|
||||||
void insert(const Editor::String& string);
|
void insert(const Editor::String& string);
|
||||||
void insert_capture(size_t index);
|
void insert(const Register& reg);
|
||||||
void erase();
|
void erase();
|
||||||
void move_cursors(const BufferCoord& offset);
|
void move_cursors(const BufferCoord& offset);
|
||||||
|
|
||||||
|
|
23
src/main.cc
23
src/main.cc
|
@ -392,15 +392,6 @@ bool insert_char(IncrementalInserter& inserter, const Key& key)
|
||||||
case Key::Modifiers::Control:
|
case Key::Modifiers::Control:
|
||||||
switch (key.key)
|
switch (key.key)
|
||||||
{
|
{
|
||||||
case 'b':
|
|
||||||
{
|
|
||||||
Key next_key = get_key();
|
|
||||||
last_insert_sequence.keys.push_back(next_key);
|
|
||||||
if (next_key.modifiers == Key::Modifiers::None and
|
|
||||||
next_key.key >= '0' and next_key.key <= '9')
|
|
||||||
inserter.insert_capture(next_key.key - '0');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'r':
|
case 'r':
|
||||||
{
|
{
|
||||||
Key next_key = get_key();
|
Key next_key = get_key();
|
||||||
|
@ -413,7 +404,7 @@ bool insert_char(IncrementalInserter& inserter, const Key& key)
|
||||||
inserter.insert(inserter.buffer().name());
|
inserter.insert(inserter.buffer().name());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
inserter.insert(RegisterManager::instance()[next_key.key].get());
|
inserter.insert(RegisterManager::instance()[next_key.key]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -836,7 +827,7 @@ void do_search(Editor& editor)
|
||||||
if (ex.empty())
|
if (ex.empty())
|
||||||
ex = RegisterManager::instance()['/'].get();
|
ex = RegisterManager::instance()['/'].get();
|
||||||
else
|
else
|
||||||
RegisterManager::instance()['/'].set(ex);
|
RegisterManager::instance()['/'] = ex;
|
||||||
|
|
||||||
editor.select(std::bind(select_next_match, _1, ex));
|
editor.select(std::bind(select_next_match, _1, ex));
|
||||||
}
|
}
|
||||||
|
@ -854,18 +845,18 @@ void do_search_next(Editor& editor)
|
||||||
|
|
||||||
void do_yank(Editor& editor, int count)
|
void do_yank(Editor& editor, int count)
|
||||||
{
|
{
|
||||||
RegisterManager::instance()['"'].set(editor.selection_content());
|
RegisterManager::instance()['"'] = editor.selections_content();
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_erase(Editor& editor, int count)
|
void do_erase(Editor& editor, int count)
|
||||||
{
|
{
|
||||||
RegisterManager::instance()['"'].set(editor.selection_content());
|
RegisterManager::instance()['"'] = editor.selections_content();
|
||||||
editor.erase();
|
editor.erase();
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_change(Editor& editor, int count)
|
void do_change(Editor& editor, int count)
|
||||||
{
|
{
|
||||||
RegisterManager::instance()['"'].set(editor.selection_content());
|
RegisterManager::instance()['"'] = editor.selections_content();
|
||||||
do_insert(editor, IncrementalInserter::Mode::Change);
|
do_insert(editor, IncrementalInserter::Mode::Change);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -873,9 +864,9 @@ template<bool append>
|
||||||
void do_paste(Editor& editor, int count)
|
void do_paste(Editor& editor, int count)
|
||||||
{
|
{
|
||||||
if (append)
|
if (append)
|
||||||
editor.append(RegisterManager::instance()['"'].get());
|
editor.append(RegisterManager::instance()['"']);
|
||||||
else
|
else
|
||||||
editor.insert(RegisterManager::instance()['"'].get());
|
editor.insert(RegisterManager::instance()['"']);
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_select_regex(Editor& editor, int count)
|
void do_select_regex(Editor& editor, int count)
|
||||||
|
|
|
@ -5,15 +5,17 @@ namespace Kakoune
|
||||||
|
|
||||||
const std::string Register::ms_empty;
|
const std::string Register::ms_empty;
|
||||||
|
|
||||||
void Register::set(const std::string& value)
|
Register& Register::operator=(const std::string& value)
|
||||||
{
|
{
|
||||||
m_content.clear();
|
m_content.clear();
|
||||||
m_content.push_back(value);
|
m_content.push_back(value);
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Register::set(const memoryview<std::string>& values)
|
Register& Register::operator=(const memoryview<std::string>& values)
|
||||||
{
|
{
|
||||||
m_content = std::vector<std::string>(values.begin(), values.end());
|
m_content = std::vector<std::string>(values.begin(), values.end());
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& Register::get() const
|
const std::string& Register::get() const
|
||||||
|
|
|
@ -12,11 +12,15 @@ namespace Kakoune
|
||||||
class Register
|
class Register
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void set(const std::string& value);
|
Register& operator=(const std::string& value);
|
||||||
void set(const memoryview<std::string>& values);
|
Register& operator=(const memoryview<std::string>& values);
|
||||||
|
|
||||||
const std::string& get() const;
|
const std::string& get() const;
|
||||||
const std::string& get(size_t index) const;
|
const std::string& get(size_t index) const;
|
||||||
|
|
||||||
|
operator memoryview<std::string>() const
|
||||||
|
{ return memoryview<std::string>(m_content); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<std::string> m_content;
|
std::vector<std::string> m_content;
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
#include "register.hh"
|
#include "register.hh"
|
||||||
#include "utils.hh"
|
#include "utils.hh"
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
|
@ -3,30 +3,14 @@
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
|
||||||
Selection::Selection(const BufferIterator& first, const BufferIterator& last,
|
Selection::Selection(const BufferIterator& first, const BufferIterator& last)
|
||||||
const CaptureList& captures)
|
: m_first(first), m_last(last)
|
||||||
: m_first(first), m_last(last), m_captures(captures)
|
|
||||||
{
|
|
||||||
register_with_buffer();
|
|
||||||
}
|
|
||||||
|
|
||||||
Selection::Selection(const BufferIterator& first, const BufferIterator& last,
|
|
||||||
CaptureList&& captures)
|
|
||||||
: m_first(first), m_last(last), m_captures(captures)
|
|
||||||
{
|
{
|
||||||
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),
|
: m_first(other.m_first), m_last(other.m_last)
|
||||||
m_captures(other.m_captures)
|
|
||||||
{
|
|
||||||
register_with_buffer();
|
|
||||||
}
|
|
||||||
|
|
||||||
Selection::Selection(Selection&& other)
|
|
||||||
: m_first(other.m_first), m_last(other.m_last),
|
|
||||||
m_captures(other.m_captures)
|
|
||||||
{
|
{
|
||||||
register_with_buffer();
|
register_with_buffer();
|
||||||
}
|
}
|
||||||
|
@ -44,7 +28,6 @@ Selection& Selection::operator=(const Selection& other)
|
||||||
|
|
||||||
m_first = other.m_first;
|
m_first = other.m_first;
|
||||||
m_last = other.m_last;
|
m_last = other.m_last;
|
||||||
m_captures = other.m_captures;
|
|
||||||
|
|
||||||
if (new_buffer)
|
if (new_buffer)
|
||||||
register_with_buffer();
|
register_with_buffer();
|
||||||
|
@ -71,13 +54,6 @@ void Selection::merge_with(const Selection& selection)
|
||||||
m_last = selection.m_last;
|
m_last = selection.m_last;
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferString Selection::capture(size_t index) const
|
|
||||||
{
|
|
||||||
if (index < m_captures.size())
|
|
||||||
return m_captures[index];
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
static void update_iterator(const Modification& modification,
|
static void update_iterator(const Modification& modification,
|
||||||
BufferIterator& iterator)
|
BufferIterator& iterator)
|
||||||
{
|
{
|
||||||
|
|
|
@ -8,17 +8,8 @@ namespace Kakoune
|
||||||
|
|
||||||
struct Selection : public ModificationListener
|
struct Selection : public ModificationListener
|
||||||
{
|
{
|
||||||
typedef std::vector<BufferString> CaptureList;
|
Selection(const BufferIterator& first, const BufferIterator& last);
|
||||||
|
|
||||||
Selection(const BufferIterator& first, const BufferIterator& last,
|
|
||||||
const CaptureList& captures = CaptureList());
|
|
||||||
|
|
||||||
Selection(const BufferIterator& first, const BufferIterator& last,
|
|
||||||
CaptureList&& captures);
|
|
||||||
|
|
||||||
Selection(const Selection& other);
|
Selection(const Selection& other);
|
||||||
Selection(Selection&& other);
|
|
||||||
|
|
||||||
~Selection();
|
~Selection();
|
||||||
|
|
||||||
Selection& operator=(const Selection& other);
|
Selection& operator=(const Selection& other);
|
||||||
|
@ -31,24 +22,35 @@ struct Selection : public ModificationListener
|
||||||
|
|
||||||
void merge_with(const Selection& selection);
|
void merge_with(const Selection& selection);
|
||||||
|
|
||||||
BufferString capture(size_t index) const;
|
|
||||||
const CaptureList& captures() const { return m_captures; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BufferIterator m_first;
|
BufferIterator m_first;
|
||||||
BufferIterator m_last;
|
BufferIterator m_last;
|
||||||
|
|
||||||
CaptureList m_captures;
|
|
||||||
|
|
||||||
void on_modification(const Modification& modification);
|
void on_modification(const Modification& modification);
|
||||||
|
|
||||||
void register_with_buffer();
|
void register_with_buffer();
|
||||||
void unregister_with_buffer();
|
void unregister_with_buffer();
|
||||||
|
|
||||||
void check_invariant();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector<Selection> SelectionList;
|
typedef std::vector<Selection> SelectionList;
|
||||||
|
typedef std::vector<BufferString> CaptureList;
|
||||||
|
|
||||||
|
struct SelectionAndCaptures
|
||||||
|
{
|
||||||
|
Selection selection;
|
||||||
|
CaptureList captures;
|
||||||
|
|
||||||
|
SelectionAndCaptures(const BufferIterator& first,
|
||||||
|
const BufferIterator& last,
|
||||||
|
CaptureList&& captures_list)
|
||||||
|
: selection(first, last), captures(captures_list) {}
|
||||||
|
SelectionAndCaptures(const Selection& sel)
|
||||||
|
: selection(sel) {}
|
||||||
|
SelectionAndCaptures(Selection&& sel)
|
||||||
|
: selection(sel) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::vector<SelectionAndCaptures> SelectionAndCapturesList;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,7 +71,7 @@ bool skip_while_reverse(BufferIterator& it, T condition)
|
||||||
return condition(*it);
|
return condition(*it);
|
||||||
}
|
}
|
||||||
|
|
||||||
Selection select_to_next_word(const Selection& selection)
|
SelectionAndCaptures select_to_next_word(const Selection& selection)
|
||||||
{
|
{
|
||||||
BufferIterator begin = selection.last();
|
BufferIterator begin = selection.last();
|
||||||
if (categorize(*begin) != categorize(*(begin+1)))
|
if (categorize(*begin) != categorize(*(begin+1)))
|
||||||
|
@ -91,7 +91,7 @@ Selection select_to_next_word(const Selection& selection)
|
||||||
return Selection(begin, with_end ? end : end-1);
|
return Selection(begin, with_end ? end : end-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Selection select_to_next_word_end(const Selection& selection)
|
SelectionAndCaptures select_to_next_word_end(const Selection& selection)
|
||||||
{
|
{
|
||||||
BufferIterator begin = selection.last();
|
BufferIterator begin = selection.last();
|
||||||
if (categorize(*begin) != categorize(*(begin+1)))
|
if (categorize(*begin) != categorize(*(begin+1)))
|
||||||
|
@ -110,7 +110,7 @@ Selection select_to_next_word_end(const Selection& selection)
|
||||||
return Selection(begin, with_end ? end : end-1);
|
return Selection(begin, with_end ? end : end-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Selection select_to_previous_word(const Selection& selection)
|
SelectionAndCaptures select_to_previous_word(const Selection& selection)
|
||||||
{
|
{
|
||||||
BufferIterator begin = selection.last();
|
BufferIterator begin = selection.last();
|
||||||
|
|
||||||
|
@ -130,7 +130,7 @@ Selection select_to_previous_word(const Selection& selection)
|
||||||
return Selection(begin, with_end ? end : end+1);
|
return Selection(begin, with_end ? end : end+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Selection select_to_next_WORD(const Selection& selection)
|
SelectionAndCaptures select_to_next_WORD(const Selection& selection)
|
||||||
{
|
{
|
||||||
BufferIterator begin = selection.last();
|
BufferIterator begin = selection.last();
|
||||||
if (categorize<false>(*begin) != categorize<false>(*(begin+1)))
|
if (categorize<false>(*begin) != categorize<false>(*(begin+1)))
|
||||||
|
@ -146,7 +146,7 @@ Selection select_to_next_WORD(const Selection& selection)
|
||||||
return Selection(begin, with_end ? end : end-1);
|
return Selection(begin, with_end ? end : end-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Selection select_to_next_WORD_end(const Selection& selection)
|
SelectionAndCaptures select_to_next_WORD_end(const Selection& selection)
|
||||||
{
|
{
|
||||||
BufferIterator begin = selection.last();
|
BufferIterator begin = selection.last();
|
||||||
if (categorize<false>(*begin) != categorize<false>(*(begin+1)))
|
if (categorize<false>(*begin) != categorize<false>(*(begin+1)))
|
||||||
|
@ -163,7 +163,7 @@ Selection select_to_next_WORD_end(const Selection& selection)
|
||||||
return Selection(begin, with_end ? end : end-1);
|
return Selection(begin, with_end ? end : end-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Selection select_to_previous_WORD(const Selection& selection)
|
SelectionAndCaptures select_to_previous_WORD(const Selection& selection)
|
||||||
{
|
{
|
||||||
BufferIterator begin = selection.last();
|
BufferIterator begin = selection.last();
|
||||||
if (categorize<false>(*begin) != categorize<false>(*(begin-1)))
|
if (categorize<false>(*begin) != categorize<false>(*(begin-1)))
|
||||||
|
@ -178,7 +178,7 @@ Selection select_to_previous_WORD(const Selection& selection)
|
||||||
return Selection(begin, with_end ? end : end+1);
|
return Selection(begin, with_end ? end : end+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Selection select_line(const Selection& selection)
|
SelectionAndCaptures select_line(const Selection& selection)
|
||||||
{
|
{
|
||||||
BufferIterator first = selection.last();
|
BufferIterator first = selection.last();
|
||||||
if (*first == '\n' and not (first + 1).is_end())
|
if (*first == '\n' and not (first + 1).is_end())
|
||||||
|
@ -193,7 +193,7 @@ Selection select_line(const Selection& selection)
|
||||||
return Selection(first, last);
|
return Selection(first, last);
|
||||||
}
|
}
|
||||||
|
|
||||||
Selection select_matching(const Selection& selection)
|
SelectionAndCaptures select_matching(const Selection& selection)
|
||||||
{
|
{
|
||||||
std::vector<char> matching_pairs = { '(', ')', '{', '}', '[', ']', '<', '>' };
|
std::vector<char> matching_pairs = { '(', ')', '{', '}', '[', ']', '<', '>' };
|
||||||
BufferIterator it = selection.last();
|
BufferIterator it = selection.last();
|
||||||
|
@ -242,7 +242,7 @@ Selection select_matching(const Selection& selection)
|
||||||
return selection;
|
return selection;
|
||||||
}
|
}
|
||||||
|
|
||||||
Selection select_surrounding(const Selection& selection,
|
SelectionAndCaptures select_surrounding(const Selection& selection,
|
||||||
const std::pair<char, char>& matching,
|
const std::pair<char, char>& matching,
|
||||||
bool inside)
|
bool inside)
|
||||||
{
|
{
|
||||||
|
@ -291,8 +291,8 @@ Selection select_surrounding(const Selection& selection,
|
||||||
return Selection(first, last);
|
return Selection(first, last);
|
||||||
}
|
}
|
||||||
|
|
||||||
Selection select_to(const Selection& selection,
|
SelectionAndCaptures select_to(const Selection& selection,
|
||||||
char c, int count, bool inclusive)
|
char c, int count, bool inclusive)
|
||||||
{
|
{
|
||||||
BufferIterator begin = selection.last();
|
BufferIterator begin = selection.last();
|
||||||
BufferIterator end = begin;
|
BufferIterator end = begin;
|
||||||
|
@ -308,8 +308,8 @@ Selection select_to(const Selection& selection,
|
||||||
return Selection(begin, inclusive ? end : end-1);
|
return Selection(begin, inclusive ? end : end-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Selection select_to_reverse(const Selection& selection,
|
SelectionAndCaptures select_to_reverse(const Selection& selection,
|
||||||
char c, int count, bool inclusive)
|
char c, int count, bool inclusive)
|
||||||
{
|
{
|
||||||
BufferIterator begin = selection.last();
|
BufferIterator begin = selection.last();
|
||||||
BufferIterator end = begin;
|
BufferIterator end = begin;
|
||||||
|
@ -325,7 +325,7 @@ Selection select_to_reverse(const Selection& selection,
|
||||||
return Selection(begin, inclusive ? end : end+1);
|
return Selection(begin, inclusive ? end : end+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Selection select_to_eol(const Selection& selection)
|
SelectionAndCaptures select_to_eol(const Selection& selection)
|
||||||
{
|
{
|
||||||
BufferIterator begin = selection.last();
|
BufferIterator begin = selection.last();
|
||||||
BufferIterator end = begin + 1;
|
BufferIterator end = begin + 1;
|
||||||
|
@ -333,7 +333,7 @@ Selection select_to_eol(const Selection& selection)
|
||||||
return Selection(begin, end-1);
|
return Selection(begin, end-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Selection select_to_eol_reverse(const Selection& selection)
|
SelectionAndCaptures select_to_eol_reverse(const Selection& selection)
|
||||||
{
|
{
|
||||||
BufferIterator begin = selection.last();
|
BufferIterator begin = selection.last();
|
||||||
BufferIterator end = begin - 1;
|
BufferIterator end = begin - 1;
|
||||||
|
@ -341,7 +341,7 @@ Selection select_to_eol_reverse(const Selection& selection)
|
||||||
return Selection(begin, end.is_begin() ? end : end+1);
|
return Selection(begin, end.is_begin() ? end : end+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Selection select_whole_lines(const Selection& selection)
|
SelectionAndCaptures select_whole_lines(const Selection& selection)
|
||||||
{
|
{
|
||||||
BufferIterator first = selection.first();
|
BufferIterator first = selection.first();
|
||||||
BufferIterator last = selection.last();
|
BufferIterator last = selection.last();
|
||||||
|
@ -358,20 +358,20 @@ Selection select_whole_lines(const Selection& selection)
|
||||||
return Selection(first, last);
|
return Selection(first, last);
|
||||||
}
|
}
|
||||||
|
|
||||||
Selection select_whole_buffer(const Selection& selection)
|
SelectionAndCaptures select_whole_buffer(const Selection& selection)
|
||||||
{
|
{
|
||||||
const Buffer& buffer = selection.first().buffer();
|
const Buffer& buffer = selection.first().buffer();
|
||||||
return Selection(buffer.begin(), buffer.end()-1);
|
return Selection(buffer.begin(), buffer.end()-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Selection select_next_match(const Selection& selection,
|
SelectionAndCaptures select_next_match(const Selection& selection,
|
||||||
const std::string& regex)
|
const std::string& regex)
|
||||||
{
|
{
|
||||||
boost::regex ex(regex);
|
boost::regex ex(regex);
|
||||||
|
|
||||||
BufferIterator begin = selection.last();
|
BufferIterator begin = selection.last();
|
||||||
BufferIterator end = begin;
|
BufferIterator end = begin;
|
||||||
Selection::CaptureList captures;
|
CaptureList captures;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -403,41 +403,41 @@ Selection select_next_match(const Selection& selection,
|
||||||
if (begin == end)
|
if (begin == end)
|
||||||
++end;
|
++end;
|
||||||
|
|
||||||
return Selection(begin, end - 1, std::move(captures));
|
return SelectionAndCaptures(begin, end - 1, std::move(captures));
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef boost::regex_iterator<BufferIterator> RegexIterator;
|
typedef boost::regex_iterator<BufferIterator> RegexIterator;
|
||||||
|
|
||||||
SelectionList select_all_matches(const Selection& selection,
|
SelectionAndCapturesList select_all_matches(const Selection& selection,
|
||||||
const std::string& regex)
|
const std::string& regex)
|
||||||
{
|
{
|
||||||
boost::regex ex(regex);
|
boost::regex ex(regex);
|
||||||
RegexIterator re_it(selection.begin(), selection.end(), ex);
|
RegexIterator re_it(selection.begin(), selection.end(), ex);
|
||||||
RegexIterator re_end;
|
RegexIterator re_end;
|
||||||
|
|
||||||
SelectionList result;
|
SelectionAndCapturesList 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;
|
||||||
BufferIterator end = (*re_it)[0].second;
|
BufferIterator end = (*re_it)[0].second;
|
||||||
|
|
||||||
Selection::CaptureList captures(re_it->begin(), re_it->end());
|
CaptureList captures(re_it->begin(), re_it->end());
|
||||||
|
|
||||||
result.push_back(Selection(begin, begin == end ? end : end-1,
|
result.push_back(SelectionAndCaptures(begin, begin == end ? end : end-1,
|
||||||
std::move(captures)));
|
std::move(captures)));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
SelectionList split_selection(const Selection& selection,
|
SelectionAndCapturesList split_selection(const Selection& selection,
|
||||||
const std::string& separator_regex)
|
const std::string& separator_regex)
|
||||||
{
|
{
|
||||||
boost::regex ex(separator_regex);
|
boost::regex ex(separator_regex);
|
||||||
RegexIterator re_it(selection.begin(), selection.end(), ex,
|
RegexIterator re_it(selection.begin(), selection.end(), ex,
|
||||||
boost::regex_constants::match_nosubs);
|
boost::regex_constants::match_nosubs);
|
||||||
RegexIterator re_end;
|
RegexIterator re_end;
|
||||||
|
|
||||||
SelectionList result;
|
SelectionAndCapturesList result;
|
||||||
BufferIterator begin = selection.begin();
|
BufferIterator begin = selection.begin();
|
||||||
for (; re_it != re_end; ++re_it)
|
for (; re_it != re_end; ++re_it)
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,37 +6,37 @@
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
|
||||||
Selection select_to_next_word(const Selection& selection);
|
SelectionAndCaptures select_to_next_word(const Selection& selection);
|
||||||
Selection select_to_next_word_end(const Selection& selection);
|
SelectionAndCaptures select_to_next_word_end(const Selection& selection);
|
||||||
Selection select_to_previous_word(const Selection& selection);
|
SelectionAndCaptures select_to_previous_word(const Selection& selection);
|
||||||
Selection select_to_next_WORD(const Selection& selection);
|
SelectionAndCaptures select_to_next_WORD(const Selection& selection);
|
||||||
Selection select_to_next_WORD_end(const Selection& selection);
|
SelectionAndCaptures select_to_next_WORD_end(const Selection& selection);
|
||||||
Selection select_to_previous_WORD(const Selection& selection);
|
SelectionAndCaptures select_to_previous_WORD(const Selection& selection);
|
||||||
Selection select_line(const Selection& selection);
|
SelectionAndCaptures select_line(const Selection& selection);
|
||||||
Selection select_matching(const Selection& selection);
|
SelectionAndCaptures select_matching(const Selection& selection);
|
||||||
Selection select_surrounding(const Selection& selection,
|
SelectionAndCaptures select_surrounding(const Selection& selection,
|
||||||
const std::pair<char, char>& matching,
|
const std::pair<char, char>& matching,
|
||||||
bool inside);
|
bool inside);
|
||||||
|
|
||||||
Selection select_to(const Selection& selection,
|
SelectionAndCaptures select_to(const Selection& selection,
|
||||||
char c, int count, bool inclusive);
|
char c, int count, bool inclusive);
|
||||||
Selection select_to_reverse(const Selection& selection,
|
SelectionAndCaptures select_to_reverse(const Selection& selection,
|
||||||
char c, int count, bool inclusive);
|
char c, int count, bool inclusive);
|
||||||
|
|
||||||
Selection select_to_eol(const Selection& selection);
|
SelectionAndCaptures select_to_eol(const Selection& selection);
|
||||||
Selection select_to_eol_reverse(const Selection& selection);
|
SelectionAndCaptures select_to_eol_reverse(const Selection& selection);
|
||||||
|
|
||||||
Selection select_whole_lines(const Selection& selection);
|
SelectionAndCaptures select_whole_lines(const Selection& selection);
|
||||||
Selection select_whole_buffer(const Selection& selection);
|
SelectionAndCaptures select_whole_buffer(const Selection& selection);
|
||||||
|
|
||||||
Selection select_next_match(const Selection& selection,
|
SelectionAndCaptures select_next_match(const Selection& selection,
|
||||||
const std::string& regex);
|
const std::string& regex);
|
||||||
|
|
||||||
SelectionList select_all_matches(const Selection& selection,
|
SelectionAndCapturesList select_all_matches(const Selection& selection,
|
||||||
const std::string& regex);
|
const std::string& regex);
|
||||||
|
|
||||||
SelectionList split_selection(const Selection& selection,
|
SelectionAndCapturesList split_selection(const Selection& selection,
|
||||||
const std::string& separator_regex);
|
const std::string& separator_regex);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "completion.hh"
|
#include "completion.hh"
|
||||||
#include "highlighter.hh"
|
#include "highlighter.hh"
|
||||||
#include "highlighter_group.hh"
|
#include "highlighter_group.hh"
|
||||||
|
#include "hooks_manager.hh"
|
||||||
|
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
@ -36,8 +37,6 @@ public:
|
||||||
|
|
||||||
void update_display_buffer();
|
void update_display_buffer();
|
||||||
|
|
||||||
const SelectionList& selections() const { return Editor::selections(); }
|
|
||||||
|
|
||||||
std::string status_line() const;
|
std::string status_line() const;
|
||||||
|
|
||||||
HighlighterGroup& highlighters() { return m_highlighters; }
|
HighlighterGroup& highlighters() { return m_highlighters; }
|
||||||
|
|
Loading…
Reference in New Issue
Block a user