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)
|
for (auto& client : m_clients)
|
||||||
{
|
{
|
||||||
|
client.context->forget_jumps_to_buffer(buffer);
|
||||||
|
|
||||||
if (&client.context->buffer() != &buffer)
|
if (&client.context->buffer() != &buffer)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
|
@ -283,6 +283,9 @@ void edit(const CommandParameters& params, Context& context)
|
||||||
|
|
||||||
BufferManager::instance().set_last_used_buffer(*buffer);
|
BufferManager::instance().set_last_used_buffer(*buffer);
|
||||||
|
|
||||||
|
if (buffer != &context.buffer() or param_count > 1)
|
||||||
|
context.push_jump();
|
||||||
|
|
||||||
if (buffer != &context.buffer())
|
if (buffer != &context.buffer())
|
||||||
{
|
{
|
||||||
auto& manager = ClientManager::instance();
|
auto& manager = ClientManager::instance();
|
||||||
|
@ -385,6 +388,7 @@ void show_buffer(const CommandParameters& params, Context& context)
|
||||||
|
|
||||||
if (buffer != &context.buffer())
|
if (buffer != &context.buffer())
|
||||||
{
|
{
|
||||||
|
context.push_jump();
|
||||||
auto& manager = ClientManager::instance();
|
auto& manager = ClientManager::instance();
|
||||||
context.change_editor(manager.get_unused_window_for_buffer(*buffer));
|
context.change_editor(manager.get_unused_window_for_buffer(*buffer));
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,6 +100,62 @@ struct Context
|
||||||
using Insertion = std::pair<InsertMode, std::vector<Key>>;
|
using Insertion = std::pair<InsertMode, std::vector<Key>>;
|
||||||
Insertion& last_insert() { return m_last_insert; }
|
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; }
|
int& numeric_param() { return m_numeric_param; }
|
||||||
private:
|
private:
|
||||||
safe_ptr<Editor> m_editor;
|
safe_ptr<Editor> m_editor;
|
||||||
|
@ -108,6 +164,10 @@ private:
|
||||||
|
|
||||||
Insertion m_last_insert = {InsertMode::Insert, {}};
|
Insertion m_last_insert = {InsertMode::Insert, {}};
|
||||||
int m_numeric_param = 0;
|
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 =
|
BufferIterator target =
|
||||||
context.editor().buffer().iterator_at_line_begin(count-1);
|
context.editor().buffer().iterator_at_line_begin(count-1);
|
||||||
|
|
||||||
|
context.push_jump();
|
||||||
context.editor().select(target);
|
context.editor().select(target);
|
||||||
if (context.has_window())
|
if (context.has_window())
|
||||||
context.window().center_selection();
|
context.window().center_selection();
|
||||||
|
@ -73,6 +74,7 @@ void do_go(Context& context)
|
||||||
{
|
{
|
||||||
case 'g':
|
case 'g':
|
||||||
case 't':
|
case 't':
|
||||||
|
context.push_jump();
|
||||||
editor.select(editor.buffer().begin());
|
editor.select(editor.buffer().begin());
|
||||||
break;
|
break;
|
||||||
case 'l':
|
case 'l':
|
||||||
|
@ -85,6 +87,7 @@ void do_go(Context& context)
|
||||||
break;
|
break;
|
||||||
case 'b':
|
case 'b':
|
||||||
{
|
{
|
||||||
|
context.push_jump();
|
||||||
const Buffer& buf = editor.buffer();
|
const Buffer& buf = editor.buffer();
|
||||||
editor.select(buf.iterator_at_line_begin(buf.line_count() - 1));
|
editor.select(buf.iterator_at_line_begin(buf.line_count() - 1));
|
||||||
break;
|
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()
|
String runtime_directory()
|
||||||
{
|
{
|
||||||
char buffer[2048];
|
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::PageUp }, do_scroll<Key::PageUp> },
|
||||||
{ { Key::Modifiers::None, Key::PageDown }, do_scroll<Key::PageDown> },
|
{ { 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