src: Allow ga to skip removed buffers

This commit prevents `ga` from returning a “no last buffer” error
when the previously displayed buffer was removed.

Since the jumps list keeps track of the order in which buffers were
displayed already, handling arbitrary `delete-buffer`s as well,
cycle through it to implement `ga` instead of storing a pointer.

Note that this commit doesn't take into account buffer flags that
might exclude some buffers from being cycled over by commands.

Fixes #1840
This commit is contained in:
Frank LENORMAND 2021-09-11 10:43:25 +03:00
parent 09f4ef0917
commit a5dd8a7935
2 changed files with 26 additions and 11 deletions

View File

@ -172,12 +172,6 @@ void Context::change_buffer(Buffer& buffer)
if (has_buffer() and m_edition_level > 0) if (has_buffer() and m_edition_level > 0)
this->buffer().commit_undo_group(); this->buffer().commit_undo_group();
if (has_buffer())
{
auto* current = &this->buffer();
m_last_buffer = contains(BufferManager::instance(), current) ? current : nullptr;
}
if (has_client()) if (has_client())
{ {
client().info_hide(); client().info_hide();
@ -197,8 +191,6 @@ void Context::change_buffer(Buffer& buffer)
void Context::forget_buffer(Buffer& buffer) void Context::forget_buffer(Buffer& buffer)
{ {
m_jump_list.forget_buffer(buffer); m_jump_list.forget_buffer(buffer);
if (m_last_buffer.get() == &buffer)
m_last_buffer = nullptr;
if (&this->buffer() != &buffer) if (&this->buffer() != &buffer)
return; return;
@ -206,7 +198,29 @@ void Context::forget_buffer(Buffer& buffer)
if (is_editing() && has_input_handler()) if (is_editing() && has_input_handler())
input_handler().reset_normal_mode(); input_handler().reset_normal_mode();
change_buffer(m_last_buffer ? *m_last_buffer : BufferManager::instance().get_first_buffer()); auto last_buffer = this->last_buffer();
change_buffer(last_buffer ? *last_buffer : BufferManager::instance().get_first_buffer());
}
Buffer* Context::last_buffer() const
{
const auto jump_list = m_jump_list.get_as_list();
if (jump_list.empty())
return nullptr;
auto predicate = [this](const auto& sels) {
return &sels.buffer() != &this->buffer();
};
auto next_buffer = find_if(jump_list.subrange(m_jump_list.current_index()-1),
predicate);
if (next_buffer != jump_list.end())
return &next_buffer->buffer();
auto previous_buffer = find_if(jump_list.subrange(0, m_jump_list.current_index()) | reverse(),
predicate);
return previous_buffer != jump_list.rend() ? &previous_buffer->buffer() : nullptr;
} }
SelectionList& Context::selections() SelectionList& Context::selections()

View File

@ -35,6 +35,8 @@ struct JumpList
size_t current_index() const { return m_current; } size_t current_index() const { return m_current; }
ConstArrayView<SelectionList> get_as_list() const { return m_jumps; }
private: private:
using Contents = Vector<SelectionList, MemoryDomain::Selections>; using Contents = Vector<SelectionList, MemoryDomain::Selections>;
Contents m_jumps; Contents m_jumps;
@ -135,7 +137,7 @@ public:
void repeat_last_select() { if (m_last_select) m_last_select(*this); } void repeat_last_select() { if (m_last_select) m_last_select(*this); }
Buffer* last_buffer() const { return m_last_buffer.get(); } Buffer* last_buffer() const;
private: private:
void begin_edition(); void begin_edition();
void end_edition(); void end_edition();
@ -149,7 +151,6 @@ private:
SafePtr<InputHandler> m_input_handler; SafePtr<InputHandler> m_input_handler;
SafePtr<Window> m_window; SafePtr<Window> m_window;
SafePtr<Client> m_client; SafePtr<Client> m_client;
SafePtr<Buffer> m_last_buffer;
Optional<SelectionList> m_selections; Optional<SelectionList> m_selections;