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.
This commit is contained in:
Maxime Coste 2012-11-12 19:59:25 +01:00
parent 41b5336296
commit 801f4e740c
4 changed files with 98 additions and 0 deletions

View File

@ -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;

View File

@ -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));
}

View File

@ -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();
};
}

View File

@ -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 },
};
}