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:
parent
41b5336296
commit
801f4e740c
|
@ -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;
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
||||
}
|
||||
|
|
32
src/main.cc
32
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 },
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user