summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMaxime Coste <frrrwww@gmail.com>2013-10-30 08:46:15 +0000
committerMaxime Coste <frrrwww@gmail.com>2013-11-04 22:02:43 +0000
commit3e1250763613a14ec2d4fbca915ee95dcba1981e (patch)
tree8d6e522ff6a3736aad4df36b127d3cbfbd3e6947 /src
parent3e1bb777ce9c8de3dbe55dee4e454241eddc98d1 (diff)
Remove IncrementalInserter and move it's code to InputModes::Insert
Diffstat (limited to 'src')
-rw-r--r--src/client.cc151
-rw-r--r--src/editor.cc130
-rw-r--r--src/editor.hh31
-rw-r--r--src/unit_tests.cc25
4 files changed, 145 insertions, 192 deletions
diff --git a/src/client.cc b/src/client.cc
index d999816f..649b22dc 100644
--- a/src/client.cc
+++ b/src/client.cc
@@ -850,7 +850,8 @@ class Insert : public InputMode
public:
Insert(Client& client, InsertMode mode)
: InputMode(client),
- m_inserter(context().editor(), mode),
+ m_insert_mode(mode),
+ m_edition(context().editor()),
m_completer(context()),
m_idle_timer{Clock::now() + idle_timeout,
[this](Timer& timer) {
@@ -861,6 +862,7 @@ public:
last_insert().first = mode;
last_insert().second.clear();
context().hooks().run_hook("InsertBegin", "", context());
+ prepare(m_insert_mode);
}
void on_key(Key key) override
@@ -869,7 +871,7 @@ public:
if (m_mode == Mode::InsertReg)
{
if (key.modifiers == Key::Modifiers::None)
- m_inserter.insert(RegisterManager::instance()[key.key].values(context()));
+ insert(RegisterManager::instance()[key.key].values(context()));
m_mode = Mode::Default;
return;
}
@@ -896,38 +898,35 @@ public:
reset_normal_mode();
}
else if (key == Key::Backspace)
- m_inserter.erase();
+ erase();
else if (key == Key::Left)
{
- m_inserter.move_cursors(-1_char);
+ m_edition.editor().move_selections(-1_char, SelectMode::Replace);
moved = true;
}
else if (key == Key::Right)
{
- m_inserter.move_cursors(1_char);
+ m_edition.editor().move_selections(1_char, SelectMode::Replace);
moved = true;
}
else if (key == Key::Up)
{
- m_inserter.move_cursors(-1_line);
+ m_edition.editor().move_selections(-1_line, SelectMode::Replace);
moved = true;
}
else if (key == Key::Down)
{
- m_inserter.move_cursors(1_line);
+ m_edition.editor().move_selections(1_line, SelectMode::Replace);
moved = true;
}
else if (key.modifiers == Key::Modifiers::None)
- {
- m_inserter.insert(codepoint_to_str(key.key));
- context().hooks().run_hook("InsertKey", key_to_str(key), context());
- }
+ insert(key.key);
else if (key == ctrl('r'))
m_mode = Mode::InsertReg;
else if ( key == ctrl('m'))
- m_inserter.insert(String() + '\n');
+ insert('\n');
else if ( key == ctrl('i'))
- m_inserter.insert(String() + '\t');
+ insert('\t');
else if ( key == ctrl('n'))
{
m_completer.select(1);
@@ -957,11 +956,131 @@ public:
KeymapMode keymap_mode() const override { return KeymapMode::Insert; }
private:
+ void erase() const
+ {
+ auto& buffer = m_edition.editor().buffer();
+ for (auto& sel : m_edition.editor().selections())
+ {
+ if (sel.last() == BufferCoord{0,0})
+ continue;
+ auto pos = buffer.iterator_at(sel.last());
+ buffer.erase(utf8::previous(pos), pos);
+ }
+ }
+
+ void insert(memoryview<String> strings)
+ {
+ auto& buffer = m_edition.editor().buffer();
+ auto& selections = m_edition.editor().selections();
+ for (size_t i = 0; i < selections.size(); ++i)
+ {
+ size_t index = std::min(i, strings.size()-1);
+ buffer.insert(buffer.iterator_at(selections[i].last()),
+ strings[index]);
+ }
+ }
+
+ void insert(Codepoint key)
+ {
+ auto& buffer = m_edition.editor().buffer();
+ for (auto& sel : m_edition.editor().m_selections)
+ {
+ auto content = codepoint_to_str(key);
+ m_edition.editor().filters()(buffer, sel, content);
+ buffer.insert(buffer.iterator_at(sel.last()), content);
+ }
+ context().hooks().run_hook("InsertKey", codepoint_to_str(key), context());
+ }
+
+ void prepare(InsertMode mode)
+ {
+ Editor& editor = m_edition.editor();
+ Buffer& buffer = editor.buffer();
+
+ for (auto& sel : editor.m_selections)
+ {
+ BufferCoord first, last;
+ switch (mode)
+ {
+ case InsertMode::Insert:
+ first = sel.max();
+ last = sel.min();
+ break;
+ case InsertMode::Replace:
+ first = last = Kakoune::erase(buffer, sel).coord();
+ break;
+ case InsertMode::Append:
+ first = sel.min();
+ last = sel.max();
+ // special case for end of lines, append to current line instead
+ if (last.column != buffer[last.line].length() - 1)
+ last = buffer.char_next(last);
+ break;
+
+ case InsertMode::OpenLineBelow:
+ case InsertMode::AppendAtLineEnd:
+ first = last = BufferCoord{sel.max().line, buffer[sel.max().line].length() - 1};
+ break;
+
+ case InsertMode::OpenLineAbove:
+ case InsertMode::InsertAtLineBegin:
+ first = sel.min().line;
+ if (mode == InsertMode::OpenLineAbove)
+ first = buffer.char_prev(first);
+ else
+ {
+ auto first_non_blank = buffer.iterator_at(first);
+ while (*first_non_blank == ' ' or *first_non_blank == '\t')
+ ++first_non_blank;
+ if (*first_non_blank != '\n')
+ first = first_non_blank.coord();
+ }
+ last = first;
+ break;
+ case InsertMode::InsertAtNextLineBegin:
+ kak_assert(false); // not implemented
+ break;
+ }
+ if (buffer.is_end(first))
+ first = buffer.char_prev(first);
+ if (buffer.is_end(last))
+ last = buffer.char_prev(last);
+ sel.first() = first;
+ sel.last() = last;
+ }
+ if (mode == InsertMode::OpenLineBelow or mode == InsertMode::OpenLineAbove)
+ {
+ insert('\n');
+ if (mode == InsertMode::OpenLineAbove)
+ {
+ for (auto& sel : editor.m_selections)
+ {
+ // special case, the --first line above did nothing, so we need to compensate now
+ if (sel.first() == buffer.char_next({0,0}))
+ sel.first() = sel.last() = BufferCoord{0,0};
+ }
+ }
+ }
+ sort_and_merge_overlapping(editor.m_selections, editor.m_main_sel);
+ editor.check_invariant();
+ }
+
+ void on_replaced() override
+ {
+ for (auto& sel : m_edition.editor().m_selections)
+ {
+ if (m_insert_mode == InsertMode::Append and sel.last().column > 0)
+ sel.last() = m_edition.editor().buffer().char_prev(sel.last());
+ avoid_eol(m_edition.editor().buffer(), sel);
+ }
+ }
+
enum class Mode { Default, Complete, InsertReg };
Mode m_mode = Mode::Default;
- IncrementalInserter m_inserter;
- BufferCompleter m_completer;
- Timer m_idle_timer;
+ InsertMode m_insert_mode;
+ scoped_edition m_edition;
+ BufferCompleter m_completer;
+ Timer m_idle_timer;
};
}
diff --git a/src/editor.cc b/src/editor.cc
index 225d5413..6ee3f433 100644
--- a/src/editor.cc
+++ b/src/editor.cc
@@ -20,7 +20,7 @@ Editor::Editor(Buffer& buffer)
m_main_sel = 0;
}
-static void avoid_eol(const Buffer& buffer, BufferCoord& coord)
+void avoid_eol(const Buffer& buffer, BufferCoord& coord)
{
const auto column = coord.column;
const auto& line = buffer[coord.line];
@@ -28,7 +28,7 @@ static void avoid_eol(const Buffer& buffer, BufferCoord& coord)
coord.column = line.byte_count_to(line.char_length() - 2);
}
-static void avoid_eol(const Buffer& buffer, Range& sel)
+void avoid_eol(const Buffer& buffer, Range& sel)
{
avoid_eol(buffer, sel.first());
avoid_eol(buffer, sel.last());
@@ -450,130 +450,4 @@ void Editor::end_edition()
--m_edition_level;
}
-IncrementalInserter::IncrementalInserter(Editor& editor, InsertMode mode)
- : m_editor(editor), m_edition(editor), m_mode(mode)
-{
- Buffer& buffer = *editor.m_buffer;
-
- for (auto& sel : m_editor.m_selections)
- {
- BufferCoord first, last;
- switch (mode)
- {
- case InsertMode::Insert:
- first = sel.max();
- last = sel.min();
- break;
- case InsertMode::Replace:
- first = last = Kakoune::erase(buffer, sel).coord();
- break;
- case InsertMode::Append:
- first = sel.min();
- last = sel.max();
- // special case for end of lines, append to current line instead
- if (last.column != buffer[last.line].length() - 1)
- last = buffer.char_next(last);
- break;
-
- case InsertMode::OpenLineBelow:
- case InsertMode::AppendAtLineEnd:
- first = last = BufferCoord{sel.max().line, buffer[sel.max().line].length() - 1};
- break;
-
- case InsertMode::OpenLineAbove:
- case InsertMode::InsertAtLineBegin:
- first = sel.min().line;
- if (mode == InsertMode::OpenLineAbove)
- first = buffer.char_prev(first);
- else
- {
- auto first_non_blank = buffer.iterator_at(first);
- while (*first_non_blank == ' ' or *first_non_blank == '\t')
- ++first_non_blank;
- if (*first_non_blank != '\n')
- first = first_non_blank.coord();
- }
- last = first;
- break;
- case InsertMode::InsertAtNextLineBegin:
- kak_assert(false); // not implemented
- break;
- }
- if (buffer.is_end(first))
- first = buffer.char_prev(first);
- if (buffer.is_end(last))
- last = buffer.char_prev(last);
- sel.first() = first;
- sel.last() = last;
- }
- if (mode == InsertMode::OpenLineBelow or mode == InsertMode::OpenLineAbove)
- {
- insert("\n");
- if (mode == InsertMode::OpenLineAbove)
- {
- for (auto& sel : m_editor.m_selections)
- {
- // special case, the --first line above did nothing, so we need to compensate now
- if (sel.first() == buffer.char_next({0,0}))
- sel.first() = sel.last() = BufferCoord{0,0};
- }
- }
- }
- sort_and_merge_overlapping(editor.m_selections, editor.m_main_sel);
- editor.check_invariant();
-}
-
-IncrementalInserter::~IncrementalInserter()
-{
- for (auto& sel : m_editor.m_selections)
- {
- if (m_mode == InsertMode::Append and sel.last().column > 0)
- sel.last() = m_editor.buffer().char_prev(sel.last());
- avoid_eol(m_editor.buffer(), sel);
- }
-}
-
-void IncrementalInserter::insert(String content)
-{
- auto& buffer = m_editor.buffer();
- for (auto& sel : m_editor.m_selections)
- {
- m_editor.filters()(buffer, sel, content);
- buffer.insert(buffer.iterator_at(sel.last()), content);
- }
-}
-
-void IncrementalInserter::insert(memoryview<String> strings)
-{
- auto& buffer = m_editor.buffer();
- for (size_t i = 0; i < m_editor.m_selections.size(); ++i)
- {
- size_t index = std::min(i, strings.size()-1);
- buffer.insert(buffer.iterator_at(m_editor.m_selections[i].last()),
- strings[index]);
- }
-}
-
-void IncrementalInserter::erase()
-{
- auto& buffer = m_editor.buffer();
- for (auto& sel : m_editor.m_selections)
- {
- if (sel.last() == BufferCoord{0,0})
- continue;
- auto pos = buffer.iterator_at(sel.last());
- buffer.erase(utf8::previous(pos), pos);
- }
-}
-
-void IncrementalInserter::move_cursors(CharCount move)
-{
- m_editor.move_selections(move, SelectMode::Replace);
-}
-
-void IncrementalInserter::move_cursors(LineCount move)
-{
- m_editor.move_selections(move, SelectMode::Replace);
-}
-
}
diff --git a/src/editor.hh b/src/editor.hh
index 0104d43d..95ef2f52 100644
--- a/src/editor.hh
+++ b/src/editor.hh
@@ -9,6 +9,8 @@
namespace Kakoune
{
+namespace InputModes { class Insert; }
+
class Register;
enum class SelectMode
@@ -88,6 +90,7 @@ public:
bool is_editing() const { return m_edition_level!= 0; }
private:
friend struct scoped_edition;
+ friend class InputModes::Insert;
void begin_edition();
void end_edition();
@@ -98,8 +101,6 @@ private:
void check_invariant() const;
- friend class IncrementalInserter;
-
safe_ptr<Buffer> m_buffer;
DynamicSelectionList m_selections;
size_t m_main_sel;
@@ -114,32 +115,16 @@ struct scoped_edition
~scoped_edition()
{ m_editor.end_edition(); }
-private:
- Editor& m_editor;
-};
-// An IncrementalInserter manage insert mode
-class IncrementalInserter
-{
-public:
- IncrementalInserter(Editor& editor, InsertMode mode = InsertMode::Insert);
- ~IncrementalInserter();
-
- void insert(String content);
- void insert(memoryview<String> strings);
- void erase();
- void move_cursors(CharCount move);
- void move_cursors(LineCount move);
-
- Buffer& buffer() const { return m_editor.buffer(); }
Editor& editor() const { return m_editor; }
-
private:
- InsertMode m_mode;
- Editor& m_editor;
- scoped_edition m_edition;
+ Editor& m_editor;
};
+void avoid_eol(const Buffer& buffer, BufferCoord& coord);
+void avoid_eol(const Buffer& buffer, Range& sel);
+void sort_and_merge_overlapping(SelectionList& selections, size_t& main_selection);
+
}
#endif // editor_hh_INCLUDED
diff --git a/src/unit_tests.cc b/src/unit_tests.cc
index e49f7b3a..4a6b149d 100644
--- a/src/unit_tests.cc
+++ b/src/unit_tests.cc
@@ -92,30 +92,6 @@ void test_editor()
kak_assert(not buffer.is_end(editor.main_selection().first()));
}
-void test_incremental_inserter()
-{
- Buffer buffer("test", Buffer::Flags::None, { "test\n", "\n", "yoüpi\n", "matin\n" });
- Editor editor(buffer);
-
- editor.select({0,0});
- {
- IncrementalInserter inserter(editor, InsertMode::OpenLineAbove);
- kak_assert(editor.is_editing());
- kak_assert(editor.selections().size() == 1);
- kak_assert(editor.selections().front().first() == BufferCoord{0 COMMA 0});
- kak_assert(editor.selections().front().last() == BufferCoord{0 COMMA 0});
- kak_assert(*buffer.begin() == L'\n');
- }
- // check utf-8 erase
- editor.select({3,4});
- {
- IncrementalInserter inserter(editor, InsertMode::Insert);
- inserter.erase();
- kak_assert(editor.selections().back().last() == BufferCoord{3 COMMA 2});
- }
- kak_assert(not editor.is_editing());
-}
-
void test_utf8()
{
String str = "maïs mélange bientôt";
@@ -171,5 +147,4 @@ void run_unit_tests()
test_buffer();
test_undo_group_optimizer();
test_editor();
- test_incremental_inserter();
}