Merge remote-tracking branch 'krobelus/selection-undo-fix-standstill-after-buffer-change'
This commit is contained in:
commit
d5ae08498c
|
@ -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()
|
||||
SelectionList old_selections = selections();
|
||||
HistoryId next;
|
||||
do
|
||||
{
|
||||
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();
|
||||
if constexpr (backward)
|
||||
next = current_history_node().parent;
|
||||
else
|
||||
m_context.change_buffer(history_node(child).selections.buffer(), { std::move(select_child) });
|
||||
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()
|
||||
{
|
||||
|
|
|
@ -19,6 +19,8 @@ class DisplayLine;
|
|||
class KeymapManager;
|
||||
class AliasRegistry;
|
||||
|
||||
enum Direction { Backward = -1, Forward = 1 };
|
||||
|
||||
struct JumpList
|
||||
{
|
||||
void push(SelectionList jump, Optional<size_t> index = {});
|
||||
|
@ -91,8 +93,8 @@ public:
|
|||
SelectionList& selections_write_only();
|
||||
|
||||
void end_selection_edition() { m_selection_history.end_edition(); }
|
||||
template<Direction direction>
|
||||
void undo_selection_change();
|
||||
void redo_selection_change();
|
||||
|
||||
void change_buffer(Buffer& buffer, Optional<FunctionRef<void()>> set_selection = {});
|
||||
void forget_buffer(Buffer& buffer);
|
||||
|
@ -169,8 +171,8 @@ private:
|
|||
void end_edition();
|
||||
bool in_edition() const { return m_in_edition; }
|
||||
|
||||
template<Direction direction>
|
||||
void undo();
|
||||
void redo();
|
||||
void forget_buffer(Buffer& buffer);
|
||||
private:
|
||||
enum class HistoryId : size_t { First = 0, Invalid = (size_t)-1 };
|
||||
|
|
|
@ -1417,8 +1417,6 @@ void select_object(Context& context, NormalParams params)
|
|||
{{alt(';')}, "run command in object context"}}));
|
||||
}
|
||||
|
||||
enum Direction { Backward = -1, Forward = 1 };
|
||||
|
||||
template<Direction direction, bool half = false>
|
||||
void scroll(Context& context, NormalParams params)
|
||||
{
|
||||
|
@ -2039,18 +2037,12 @@ void move_in_history(Context& context, NormalParams params)
|
|||
history_id, max_history_id));
|
||||
}
|
||||
|
||||
template<Direction direction>
|
||||
void undo_selection_change(Context& context, NormalParams params)
|
||||
{
|
||||
int count = std::max(1, params.count);
|
||||
while (count--)
|
||||
context.undo_selection_change();
|
||||
}
|
||||
|
||||
void redo_selection_change(Context& context, NormalParams params)
|
||||
{
|
||||
int count = std::max(1, params.count);
|
||||
while (count--)
|
||||
context.redo_selection_change();
|
||||
context.undo_selection_change<direction>();
|
||||
}
|
||||
|
||||
void exec_user_mappings(Context& context, NormalParams params)
|
||||
|
@ -2378,8 +2370,8 @@ static constexpr HashMap<Key, NormalCmd, MemoryDomain::Undefined, KeymapBackend>
|
|||
{ {alt('u')}, {"move backward in history", move_in_history<Direction::Backward>} },
|
||||
{ {alt('U')}, {"move forward in history", move_in_history<Direction::Forward>} },
|
||||
|
||||
{ {ctrl('h')}, {"undo selection change", undo_selection_change} },
|
||||
{ {ctrl('k')}, {"redo selection change", redo_selection_change} },
|
||||
{ {ctrl('h')}, {"undo selection change", undo_selection_change<Backward>} },
|
||||
{ {ctrl('k')}, {"redo selection change", undo_selection_change<Forward>} },
|
||||
|
||||
{ {alt('i')}, {"select inner object", select_object<ObjectFlags::ToBegin | ObjectFlags::ToEnd | ObjectFlags::Inner>} },
|
||||
{ {alt('a')}, {"select whole object", select_object<ObjectFlags::ToBegin | ObjectFlags::ToEnd>} },
|
||||
|
|
1
test/normal/selection-undo/fold-redundant-entries/cmd
Normal file
1
test/normal/selection-undo/fold-redundant-entries/cmd
Normal file
|
@ -0,0 +1 @@
|
|||
|
4
test/normal/selection-undo/fold-redundant-entries/in
Normal file
4
test/normal/selection-undo/fold-redundant-entries/in
Normal file
|
@ -0,0 +1,4 @@
|
|||
1
|
||||
2
|
||||
3
|
||||
4
|
3
test/normal/selection-undo/fold-redundant-entries/out
Normal file
3
test/normal/selection-undo/fold-redundant-entries/out
Normal file
|
@ -0,0 +1,3 @@
|
|||
2
|
||||
3
|
||||
here4
|
2
test/normal/selection-undo/fold-redundant-entries/script
Normal file
2
test/normal/selection-undo/fold-redundant-entries/script
Normal file
|
@ -0,0 +1,2 @@
|
|||
ui_out -ignore 4
|
||||
ui_in '{ "jsonrpc": "2.0", "method": "keys", "params": [ "gjgkxd<c-h>ihere<esc>" ] }'
|
1
test/normal/selection-undo/redo/cmd
Normal file
1
test/normal/selection-undo/redo/cmd
Normal file
|
@ -0,0 +1 @@
|
|||
|
4
test/normal/selection-undo/redo/in
Normal file
4
test/normal/selection-undo/redo/in
Normal file
|
@ -0,0 +1,4 @@
|
|||
1
|
||||
2
|
||||
3
|
||||
4
|
4
test/normal/selection-undo/redo/out
Normal file
4
test/normal/selection-undo/redo/out
Normal file
|
@ -0,0 +1,4 @@
|
|||
1
|
||||
2
|
||||
here3
|
||||
4
|
2
test/normal/selection-undo/redo/script
Normal file
2
test/normal/selection-undo/redo/script
Normal file
|
@ -0,0 +1,2 @@
|
|||
ui_out -ignore 4
|
||||
ui_in '{ "jsonrpc": "2.0", "method": "keys", "params": [ "2jj<c-h><c-h><c-k>ihere<esc>" ] }'
|
1
test/normal/selection-undo/undo/cmd
Normal file
1
test/normal/selection-undo/undo/cmd
Normal file
|
@ -0,0 +1 @@
|
|||
|
4
test/normal/selection-undo/undo/in
Normal file
4
test/normal/selection-undo/undo/in
Normal file
|
@ -0,0 +1,4 @@
|
|||
1
|
||||
2
|
||||
3
|
||||
4
|
4
test/normal/selection-undo/undo/out
Normal file
4
test/normal/selection-undo/undo/out
Normal file
|
@ -0,0 +1,4 @@
|
|||
here1
|
||||
2
|
||||
3
|
||||
4
|
2
test/normal/selection-undo/undo/script
Normal file
2
test/normal/selection-undo/undo/script
Normal file
|
@ -0,0 +1,2 @@
|
|||
ui_out -ignore 4
|
||||
ui_in '{ "jsonrpc": "2.0", "method": "keys", "params": [ "j2j<c-h><c-h>ihere<esc>" ] }'
|
1
test/normal/selection-undo/windisplay-hook/cmd
Normal file
1
test/normal/selection-undo/windisplay-hook/cmd
Normal file
|
@ -0,0 +1 @@
|
|||
|
3
test/normal/selection-undo/windisplay-hook/in
Normal file
3
test/normal/selection-undo/windisplay-hook/in
Normal file
|
@ -0,0 +1,3 @@
|
|||
1
|
||||
2
|
||||
3
|
3
test/normal/selection-undo/windisplay-hook/out
Normal file
3
test/normal/selection-undo/windisplay-hook/out
Normal file
|
@ -0,0 +1,3 @@
|
|||
1
|
||||
2
|
||||
here3
|
1
test/normal/selection-undo/windisplay-hook/rc
Normal file
1
test/normal/selection-undo/windisplay-hook/rc
Normal file
|
@ -0,0 +1 @@
|
|||
hook global WinDisplay .*/out %{exec j}
|
2
test/normal/selection-undo/windisplay-hook/script
Normal file
2
test/normal/selection-undo/windisplay-hook/script
Normal file
|
@ -0,0 +1,2 @@
|
|||
ui_out -ignore 4
|
||||
ui_in '{ "jsonrpc": "2.0", "method": "keys", "params": [ "j:buffer *debug*<ret><c-h>ihere<esc>" ] }'
|
Loading…
Reference in New Issue
Block a user