Initial selection saving/restoring support bound to ^ and alt-^
This commit is contained in:
parent
5b554ff474
commit
e1ba2991f5
|
@ -371,6 +371,13 @@ view.
|
||||||
* `vk`: scroll the window count line upward
|
* `vk`: scroll the window count line upward
|
||||||
* `vl`: scroll the window count columns right
|
* `vl`: scroll the window count columns right
|
||||||
|
|
||||||
|
Marks
|
||||||
|
~~~~~
|
||||||
|
|
||||||
|
Current selections position can be saved in a register and restored later on.
|
||||||
|
`^` followed by a register will save the current selections in that register,
|
||||||
|
`alt-^` followed by a register will restore the selections saved in it.
|
||||||
|
|
||||||
Jump list
|
Jump list
|
||||||
~~~~~~~~~
|
~~~~~~~~~
|
||||||
|
|
||||||
|
|
|
@ -121,7 +121,7 @@ void register_env_vars()
|
||||||
}, {
|
}, {
|
||||||
"selection_desc",
|
"selection_desc",
|
||||||
[](StringView name, const Context& context)
|
[](StringView name, const Context& context)
|
||||||
{ return selection_to_string(context.buffer(), context.selections().main()); }
|
{ return selection_to_string(context.selections().main()); }
|
||||||
}, {
|
}, {
|
||||||
"selections_desc",
|
"selections_desc",
|
||||||
[](StringView name, const Context& context)
|
[](StringView name, const Context& context)
|
||||||
|
|
|
@ -1132,7 +1132,7 @@ void jump(Context& context, NormalParams)
|
||||||
context.selections_write_only() = jump;
|
context.selections_write_only() = jump;
|
||||||
}
|
}
|
||||||
|
|
||||||
void save_selections(Context& context, NormalParams)
|
void push_selections(Context& context, NormalParams)
|
||||||
{
|
{
|
||||||
context.push_jump();
|
context.push_jump();
|
||||||
context.print_status({ format("saved {} selections", context.selections().size()),
|
context.print_status({ format("saved {} selections", context.selections().size()),
|
||||||
|
@ -1287,6 +1287,64 @@ void spaces_to_tabs(Context& context, NormalParams params)
|
||||||
SelectionList{ buffer, std::move(spaces) }.insert("\t"_str, InsertMode::Replace);
|
SelectionList{ buffer, std::move(spaces) }.insert("\t"_str, InsertMode::Replace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void save_selections(Context& context, NormalParams)
|
||||||
|
{
|
||||||
|
on_next_key_with_autoinfo(context, KeymapMode::None,
|
||||||
|
[](Key key, Context& context) {
|
||||||
|
if (key.modifiers != Key::Modifiers::None)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const char reg = key.key;
|
||||||
|
String desc = format("{}@{}%{}",
|
||||||
|
selection_list_to_string(context.selections()),
|
||||||
|
context.buffer().name(),
|
||||||
|
context.buffer().timestamp());
|
||||||
|
|
||||||
|
RegisterManager::instance()[reg] = desc;
|
||||||
|
|
||||||
|
context.print_status({format("Saved selections in register '{}'", reg), get_face("Information")});
|
||||||
|
}, "Save selections", "Enter register to save selections into");
|
||||||
|
}
|
||||||
|
|
||||||
|
void restore_selections(Context& context, NormalParams)
|
||||||
|
{
|
||||||
|
on_next_key_with_autoinfo(context, KeymapMode::None,
|
||||||
|
[](Key key, Context& context) {
|
||||||
|
if (key.modifiers != Key::Modifiers::None)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const char reg = key.key;
|
||||||
|
|
||||||
|
auto content = RegisterManager::instance()[reg].values(context);
|
||||||
|
|
||||||
|
if (content.size() != 1)
|
||||||
|
throw runtime_error(format("Register {} does not contain a selections desc", reg));
|
||||||
|
|
||||||
|
StringView desc = content[0];
|
||||||
|
auto arobase = find(desc, '@');
|
||||||
|
auto percent = find(desc, '%');
|
||||||
|
|
||||||
|
if (arobase == desc.end() or percent == desc.end())
|
||||||
|
throw runtime_error(format("Register {} does not contain a selections desc", reg));
|
||||||
|
|
||||||
|
Buffer& buffer = BufferManager::instance().get_buffer({arobase+1, percent});
|
||||||
|
size_t timestamp = str_to_int({percent + 1, desc.end()});
|
||||||
|
|
||||||
|
Vector<Selection> sels;
|
||||||
|
for (auto sel_desc : split({desc.begin(), arobase}, ':'))
|
||||||
|
sels.push_back(selection_from_string(sel_desc));
|
||||||
|
|
||||||
|
SelectionList sel_list{buffer, std::move(sels), timestamp};
|
||||||
|
|
||||||
|
if (&buffer != &context.buffer())
|
||||||
|
context.change_buffer(buffer);
|
||||||
|
|
||||||
|
context.selections_write_only() = std::move(sel_list);
|
||||||
|
|
||||||
|
context.print_status({format("Restored selections from register '{}'", reg), get_face("Information")});
|
||||||
|
}, "Restore selections", "Enter register to restore selections from");
|
||||||
|
}
|
||||||
|
|
||||||
void undo(Context& context, NormalParams)
|
void undo(Context& context, NormalParams)
|
||||||
{
|
{
|
||||||
Buffer& buffer = context.buffer();
|
Buffer& buffer = context.buffer();
|
||||||
|
@ -1564,7 +1622,7 @@ static NormalCmdDesc cmds[] =
|
||||||
|
|
||||||
{ ctrl('i'), "jump forward in jump list",jump<Forward> },
|
{ ctrl('i'), "jump forward in jump list",jump<Forward> },
|
||||||
{ ctrl('o'), "jump backward in jump list", jump<Backward> },
|
{ ctrl('o'), "jump backward in jump list", jump<Backward> },
|
||||||
{ ctrl('s'), "push current selections in jump list", save_selections },
|
{ ctrl('s'), "push current selections in jump list", push_selections },
|
||||||
|
|
||||||
{ '\'', "rotate main selection", rotate_selections },
|
{ '\'', "rotate main selection", rotate_selections },
|
||||||
{ alt('\''), "rotate selections content", rotate_selections_content },
|
{ alt('\''), "rotate selections content", rotate_selections_content },
|
||||||
|
@ -1599,6 +1657,9 @@ static NormalCmdDesc cmds[] =
|
||||||
|
|
||||||
{ Key::PageUp, "scroll one page up", scroll<Key::PageUp> },
|
{ Key::PageUp, "scroll one page up", scroll<Key::PageUp> },
|
||||||
{ Key::PageDown, "scroll one page down", scroll<Key::PageDown> },
|
{ Key::PageDown, "scroll one page down", scroll<Key::PageDown> },
|
||||||
|
|
||||||
|
{ '^', "restore selections", restore_selections },
|
||||||
|
{ alt('^'), "save selections", save_selections },
|
||||||
};
|
};
|
||||||
|
|
||||||
KeyMap keymap = cmds;
|
KeyMap keymap = cmds;
|
||||||
|
|
|
@ -17,9 +17,7 @@ void Selection::merge_with(const Selection& range)
|
||||||
|
|
||||||
SelectionList::SelectionList(Buffer& buffer, Selection s, size_t timestamp)
|
SelectionList::SelectionList(Buffer& buffer, Selection s, size_t timestamp)
|
||||||
: m_buffer(&buffer), m_selections({ std::move(s) }), m_timestamp(timestamp)
|
: m_buffer(&buffer), m_selections({ std::move(s) }), m_timestamp(timestamp)
|
||||||
{
|
{}
|
||||||
check_invariant();
|
|
||||||
}
|
|
||||||
|
|
||||||
SelectionList::SelectionList(Buffer& buffer, Selection s)
|
SelectionList::SelectionList(Buffer& buffer, Selection s)
|
||||||
: SelectionList(buffer, std::move(s), buffer.timestamp())
|
: SelectionList(buffer, std::move(s), buffer.timestamp())
|
||||||
|
@ -29,7 +27,6 @@ SelectionList::SelectionList(Buffer& buffer, Vector<Selection> s, size_t timesta
|
||||||
: m_buffer(&buffer), m_selections(std::move(s)), m_timestamp(timestamp)
|
: m_buffer(&buffer), m_selections(std::move(s)), m_timestamp(timestamp)
|
||||||
{
|
{
|
||||||
kak_assert(size() > 0);
|
kak_assert(size() > 0);
|
||||||
check_invariant();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SelectionList::SelectionList(Buffer& buffer, Vector<Selection> s)
|
SelectionList::SelectionList(Buffer& buffer, Vector<Selection> s)
|
||||||
|
@ -535,43 +532,45 @@ void SelectionList::erase()
|
||||||
m_buffer->check_invariant();
|
m_buffer->check_invariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
String selection_to_string(const Buffer& buffer, const Selection& selection)
|
String selection_to_string(const Selection& selection)
|
||||||
{
|
{
|
||||||
auto& cursor = selection.cursor();
|
auto& cursor = selection.cursor();
|
||||||
auto& anchor = selection.anchor();
|
auto& anchor = selection.anchor();
|
||||||
ByteCount distance = buffer.distance(anchor, cursor);
|
return format("{}.{},{}.{}", anchor.line + 1, anchor.column + 1,
|
||||||
return format("{}.{}{}{}", anchor.line + 1, anchor.column + 1,
|
cursor.line + 1, cursor.column + 1);
|
||||||
distance < 0 ? '-' : '+', abs(distance));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String selection_list_to_string(const SelectionList& selections)
|
String selection_list_to_string(const SelectionList& selections)
|
||||||
{
|
{
|
||||||
const auto& buffer = selections.buffer();
|
const auto& buffer = selections.buffer();
|
||||||
return join(transformed(selections, [&buffer](const Selection& s)
|
return join(transformed(selections, [](const Selection& s)
|
||||||
{ return selection_to_string(buffer, s); }),
|
{ return selection_to_string(s); }),
|
||||||
':', false);
|
':', false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Selection selection_from_string(const Buffer& buffer, StringView desc)
|
Selection selection_from_string(StringView desc)
|
||||||
{
|
{
|
||||||
auto dot = find(desc, '.');
|
auto comma = find(desc, ',');
|
||||||
auto sign = std::find_if(dot, desc.end(), [](char c) { return c == '+' or c == '-'; });
|
auto dot_anchor = find(StringView{desc.begin(), comma}, '.');
|
||||||
|
auto dot_cursor = find(StringView{comma, desc.end()}, '.');
|
||||||
|
|
||||||
if (dot == desc.end() or sign == desc.end())
|
if (comma == desc.end() or dot_anchor == comma or dot_cursor == desc.end())
|
||||||
throw runtime_error(format("'{}' does not follow <line>.<column>+<len> format", desc));
|
throw runtime_error(format("'{}' does not follow <line>.<column>,<line>.<column> format", desc));
|
||||||
|
|
||||||
LineCount line = str_to_int({desc.begin(), dot}) - 1;
|
ByteCoord anchor{str_to_int({desc.begin(), dot_anchor}) - 1,
|
||||||
ByteCount column = str_to_int({dot+1, sign}) - 1;
|
str_to_int({dot_anchor+1, comma}) - 1};
|
||||||
ByteCoord anchor{line, column};
|
|
||||||
ByteCount count = (*sign == '+' ? 1 : -1) * str_to_int({sign+1, desc.end()});
|
ByteCoord cursor{str_to_int({comma+1, dot_cursor}) - 1,
|
||||||
return Selection{anchor, buffer.advance(anchor, count)};
|
str_to_int({dot_cursor+1, desc.end()}) - 1};
|
||||||
|
|
||||||
|
return Selection{anchor, cursor};
|
||||||
}
|
}
|
||||||
|
|
||||||
SelectionList selection_list_from_string(Buffer& buffer, StringView desc)
|
SelectionList selection_list_from_string(Buffer& buffer, StringView desc)
|
||||||
{
|
{
|
||||||
Vector<Selection> sels;
|
Vector<Selection> sels;
|
||||||
for (auto sel_desc : split(desc, ':'))
|
for (auto sel_desc : split(desc, ':'))
|
||||||
sels.push_back(selection_from_string(buffer, sel_desc));
|
sels.push_back(selection_from_string(sel_desc));
|
||||||
return {buffer, std::move(sels)};
|
return {buffer, std::move(sels)};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -142,9 +142,9 @@ private:
|
||||||
|
|
||||||
Vector<Selection> compute_modified_ranges(Buffer& buffer, size_t timestamp);
|
Vector<Selection> compute_modified_ranges(Buffer& buffer, size_t timestamp);
|
||||||
|
|
||||||
String selection_to_string(const Buffer& buffer, const Selection& selection);
|
String selection_to_string(const Selection& selection);
|
||||||
String selection_list_to_string(const SelectionList& selection);
|
String selection_list_to_string(const SelectionList& selection);
|
||||||
Selection selection_from_string(const Buffer& buffer, StringView desc);
|
Selection selection_from_string(StringView desc);
|
||||||
SelectionList selection_list_from_string(Buffer& buffer, StringView desc);
|
SelectionList selection_list_from_string(Buffer& buffer, StringView desc);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user