diff options
| author | Maxime Coste <mawww@kakoune.org> | 2023-01-28 08:29:41 +1100 |
|---|---|---|
| committer | Maxime Coste <mawww@kakoune.org> | 2023-01-28 08:29:41 +1100 |
| commit | d5ae08498c529e8bfb22e0aaae7fee993d1e05ab (patch) | |
| tree | 25d7e6849b620aa78c4b7f845cfc3ca61c5dac72 /src/context.cc | |
| parent | 6b7ed51be1e8c18898c43b4cf6075c5e1d27364c (diff) | |
| parent | 516759bb2fd95d02134bc84130bf9060e0354310 (diff) | |
Merge remote-tracking branch 'krobelus/selection-undo-fix-standstill-after-buffer-change'
Diffstat (limited to 'src/context.cc')
| -rw-r--r-- | src/context.cc | 85 |
1 files changed, 34 insertions, 51 deletions
diff --git a/src/context.cc b/src/context.cc index fe9bd346..0c1b8aad 100644 --- a/src/context.cc +++ b/src/context.cc @@ -204,9 +204,11 @@ void Context::SelectionHistory::end_edition() if (m_history_id != HistoryId::Invalid and current_history_node().selections == m_staging->selections) { - auto& sels = m_history[(size_t)m_history_id].selections; - sels.force_timestamp(m_staging->selections.timestamp()); - sels.set_main_index(m_staging->selections.main_index()); + // No change, except maybe the index of the main selection. + // Update timestamp to potentially improve interaction with content undo. + auto& node = current_history_node(); + node.selections.force_timestamp(m_staging->selections.timestamp()); + node.selections.set_main_index(m_staging->selections.main_index()); } else { @@ -216,53 +218,36 @@ void Context::SelectionHistory::end_edition() m_staging.reset(); } +template<Direction direction> void Context::SelectionHistory::undo() { + static constexpr bool backward = direction == Backward; if (in_edition()) throw runtime_error("selection undo is only supported at top-level"); kak_assert(not empty()); - begin_edition(); - auto end = on_scope_end([&] { - kak_assert(current_history_node().selections == m_staging->selections); - end_edition(); - }); - HistoryId parent = current_history_node().parent; - if (parent == HistoryId::Invalid) - throw runtime_error("no selection change to undo"); - auto select_parent = [&, parent] { - HistoryId before_undo = m_history_id; - m_history_id = parent; - current_history_node().redo_child = before_undo; - m_staging = current_history_node(); - }; - if (&history_node(parent).selections.buffer() == &m_context.buffer()) - select_parent(); - else - m_context.change_buffer(history_node(parent).selections.buffer(), { std::move(select_parent) }); - // }); -} - -void Context::SelectionHistory::redo() -{ - if (in_edition()) - throw runtime_error("selection redo is only supported at top-level"); - kak_assert(not empty()); - begin_edition(); - auto end = on_scope_end([&] { - kak_assert(current_history_node().selections == m_staging->selections); - end_edition(); - }); - HistoryId child = current_history_node().redo_child; - if (child == HistoryId::Invalid) - throw runtime_error("no selection change to redo"); - auto select_child = [&, child] { - m_history_id = child; - m_staging = current_history_node(); - }; - if (&history_node(child).selections.buffer() == &m_context.buffer()) - select_child(); - else - m_context.change_buffer(history_node(child).selections.buffer(), { std::move(select_child) }); + SelectionList old_selections = selections(); + HistoryId next; + do + { + if constexpr (backward) + next = current_history_node().parent; + else + next = current_history_node().redo_child; + if (next == HistoryId::Invalid) + throw runtime_error(backward ? "no selection change to undo" : "no selection change to redo"); + auto select_next = [&, next] { + HistoryId previous_id = m_history_id; + m_history_id = next; + if constexpr (backward) + current_history_node().redo_child = previous_id; + }; + Buffer& destination_buffer = history_node(next).selections.buffer(); + if (&destination_buffer == &m_context.buffer()) + select_next(); + else + m_context.change_buffer(destination_buffer, { std::move(select_next) }); + } + while (selections() == old_selections); } void Context::SelectionHistory::forget_buffer(Buffer& buffer) @@ -376,15 +361,13 @@ SelectionList& Context::selections(bool update) return m_selection_history.selections(update); } +template<Direction direction> void Context::undo_selection_change() { - m_selection_history.undo(); -} - -void Context::redo_selection_change() -{ - m_selection_history.redo(); + m_selection_history.undo<direction>(); } +template void Context::undo_selection_change<Backward>(); +template void Context::undo_selection_change<Forward>(); SelectionList& Context::selections_write_only() { |
