From a5dd8a7935ccdc3859749d7757c6a4005b7b6a98 Mon Sep 17 00:00:00 2001 From: Frank LENORMAND Date: Sat, 11 Sep 2021 10:43:25 +0300 Subject: src: Allow `ga` to skip removed buffers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- src/context.cc | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) (limited to 'src/context.cc') diff --git a/src/context.cc b/src/context.cc index 07259c97..efa91938 100644 --- a/src/context.cc +++ b/src/context.cc @@ -172,12 +172,6 @@ void Context::change_buffer(Buffer& buffer) if (has_buffer() and m_edition_level > 0) this->buffer().commit_undo_group(); - if (has_buffer()) - { - auto* current = &this->buffer(); - m_last_buffer = contains(BufferManager::instance(), current) ? current : nullptr; - } - if (has_client()) { client().info_hide(); @@ -197,8 +191,6 @@ void Context::change_buffer(Buffer& buffer) void Context::forget_buffer(Buffer& buffer) { m_jump_list.forget_buffer(buffer); - if (m_last_buffer.get() == &buffer) - m_last_buffer = nullptr; if (&this->buffer() != &buffer) return; @@ -206,7 +198,29 @@ void Context::forget_buffer(Buffer& buffer) if (is_editing() && has_input_handler()) 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() -- cgit v1.2.3