summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMaxime Coste <frrrwww@gmail.com>2012-11-12 19:59:25 +0100
committerMaxime Coste <frrrwww@gmail.com>2012-11-12 19:59:25 +0100
commit801f4e740c2de6676d0f9fa41c58e41adfa99c8f (patch)
tree9efa7cb1eeec5ebb4ce118be380c60feeacf90d4 /src
parent41b5336296d9259d34c7e9a1b30b963fa1d7a5f2 (diff)
Add jump list support to context
jump forward is bound to ctrl-i jump backward is bound to ctrl-o switch buffers or jumping somewhere in the buffer push the current position to the jump list. when a buffer is deleted, all entries referencing it in jump lists are erased.
Diffstat (limited to 'src')
-rw-r--r--src/client_manager.cc2
-rw-r--r--src/commands.cc4
-rw-r--r--src/context.hh60
-rw-r--r--src/main.cc32
4 files changed, 98 insertions, 0 deletions
diff --git a/src/client_manager.cc b/src/client_manager.cc
index 07322fed..c2a7dcce 100644
--- a/src/client_manager.cc
+++ b/src/client_manager.cc
@@ -67,6 +67,8 @@ void ClientManager::ensure_no_client_uses_buffer(Buffer& buffer)
{
for (auto& client : m_clients)
{
+ client.context->forget_jumps_to_buffer(buffer);
+
if (&client.context->buffer() != &buffer)
continue;
diff --git a/src/commands.cc b/src/commands.cc
index 55fcf2ff..899b4fd4 100644
--- a/src/commands.cc
+++ b/src/commands.cc
@@ -283,6 +283,9 @@ void edit(const CommandParameters& params, Context& context)
BufferManager::instance().set_last_used_buffer(*buffer);
+ if (buffer != &context.buffer() or param_count > 1)
+ context.push_jump();
+
if (buffer != &context.buffer())
{
auto& manager = ClientManager::instance();
@@ -385,6 +388,7 @@ void show_buffer(const CommandParameters& params, Context& context)
if (buffer != &context.buffer())
{
+ context.push_jump();
auto& manager = ClientManager::instance();
context.change_editor(manager.get_unused_window_for_buffer(*buffer));
}
diff --git a/src/context.hh b/src/context.hh
index 0568c6c4..844b4d04 100644
--- a/src/context.hh
+++ b/src/context.hh
@@ -100,6 +100,62 @@ struct Context
using Insertion = std::pair<InsertMode, std::vector<Key>>;
Insertion& last_insert() { return m_last_insert; }
+ using Jump = std::pair<safe_ptr<Buffer>, BufferCoord>;
+ void push_jump()
+ {
+ Jump jump{safe_ptr<Buffer>{&buffer()},
+ editor().selections().back().last().coord()};
+ if (m_current_jump != m_jump_list.end())
+ {
+ m_jump_list.erase(m_current_jump+1, m_jump_list.end());
+ if (*m_current_jump == jump)
+ return;
+ }
+
+ m_jump_list.push_back(jump);
+ m_current_jump = m_jump_list.end();
+ }
+
+ Jump jump_forward()
+ {
+ if (m_current_jump != m_jump_list.end() and
+ m_current_jump + 1 != m_jump_list.end())
+ return *++m_current_jump;
+ throw runtime_error("no next jump");
+ }
+
+ Jump jump_backward()
+ {
+ if (m_current_jump != m_jump_list.begin())
+ {
+ if (m_current_jump == m_jump_list.end())
+ {
+ push_jump();
+ --m_current_jump;
+ }
+ return *--m_current_jump;
+ }
+ throw runtime_error("no previous jump");
+ }
+
+ void forget_jumps_to_buffer(Buffer& buffer)
+ {
+ for (auto it = m_jump_list.begin(); it != m_jump_list.end();)
+ {
+ if (it->first == &buffer)
+ {
+ if (it < m_current_jump)
+ --m_current_jump;
+ else if (it == m_current_jump)
+ m_current_jump = m_jump_list.end();
+
+ it = m_jump_list.erase(it);
+ }
+ else
+ ++it;
+ }
+ }
+
int& numeric_param() { return m_numeric_param; }
private:
safe_ptr<Editor> m_editor;
@@ -108,6 +164,10 @@ private:
Insertion m_last_insert = {InsertMode::Insert, {}};
int m_numeric_param = 0;
+
+ using JumpList = std::vector<Jump>;
+ JumpList m_jump_list;
+ JumpList::iterator m_current_jump = m_jump_list.begin();
};
}
diff --git a/src/main.cc b/src/main.cc
index 95ef2f63..9f2136dc 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -59,6 +59,7 @@ void do_go(Context& context)
BufferIterator target =
context.editor().buffer().iterator_at_line_begin(count-1);
+ context.push_jump();
context.editor().select(target);
if (context.has_window())
context.window().center_selection();
@@ -73,6 +74,7 @@ void do_go(Context& context)
{
case 'g':
case 't':
+ context.push_jump();
editor.select(editor.buffer().begin());
break;
case 'l':
@@ -85,6 +87,7 @@ void do_go(Context& context)
break;
case 'b':
{
+ context.push_jump();
const Buffer& buf = editor.buffer();
editor.select(buf.iterator_at_line_begin(buf.line_count() - 1));
break;
@@ -329,6 +332,32 @@ void select_to_next_char(Context& context)
});
}
+void jump_forward(Context& context)
+{
+ auto jump = context.jump_forward();
+
+ BufferManager::instance().set_last_used_buffer(*jump.first);
+ if (jump.first != &context.buffer())
+ {
+ auto& manager = ClientManager::instance();
+ context.change_editor(manager.get_unused_window_for_buffer(*jump.first));
+ }
+ context.editor().select(jump.first->iterator_at(jump.second));
+}
+
+void jump_backward(Context& context)
+{
+ auto jump = context.jump_backward();
+
+ BufferManager::instance().set_last_used_buffer(*jump.first);
+ if (jump.first != &context.buffer())
+ {
+ auto& manager = ClientManager::instance();
+ context.change_editor(manager.get_unused_window_for_buffer(*jump.first));
+ }
+ context.editor().select(jump.first->iterator_at(jump.second));
+}
+
String runtime_directory()
{
char buffer[2048];
@@ -448,6 +477,9 @@ std::unordered_map<Key, std::function<void (Context& context)>> keymap =
{ { Key::Modifiers::None, Key::PageUp }, do_scroll<Key::PageUp> },
{ { Key::Modifiers::None, Key::PageDown }, do_scroll<Key::PageDown> },
+
+ { { Key::Modifiers::Control, 'i' }, jump_forward },
+ { { Key::Modifiers::Control, 'o' }, jump_backward },
};
}