From e1ba2991f5e0a718d2c70f909502583c2513c1b4 Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Thu, 25 Jun 2015 14:00:50 +0100 Subject: [PATCH] Initial selection saving/restoring support bound to ^ and alt-^ --- README.asciidoc | 7 ++++++ src/main.cc | 2 +- src/normal.cc | 65 ++++++++++++++++++++++++++++++++++++++++++++++-- src/selection.cc | 41 +++++++++++++++--------------- src/selection.hh | 4 +-- 5 files changed, 93 insertions(+), 26 deletions(-) diff --git a/README.asciidoc b/README.asciidoc index cfc8e2df..822fb008 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -371,6 +371,13 @@ view. * `vk`: scroll the window count line upward * `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 ~~~~~~~~~ diff --git a/src/main.cc b/src/main.cc index 31f4f091..d92d1fda 100644 --- a/src/main.cc +++ b/src/main.cc @@ -121,7 +121,7 @@ void register_env_vars() }, { "selection_desc", [](StringView name, const Context& context) - { return selection_to_string(context.buffer(), context.selections().main()); } + { return selection_to_string(context.selections().main()); } }, { "selections_desc", [](StringView name, const Context& context) diff --git a/src/normal.cc b/src/normal.cc index 5257908e..5db0852b 100644 --- a/src/normal.cc +++ b/src/normal.cc @@ -1132,7 +1132,7 @@ void jump(Context& context, NormalParams) context.selections_write_only() = jump; } -void save_selections(Context& context, NormalParams) +void push_selections(Context& context, NormalParams) { context.push_jump(); 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); } +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 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) { Buffer& buffer = context.buffer(); @@ -1564,7 +1622,7 @@ static NormalCmdDesc cmds[] = { ctrl('i'), "jump forward in jump list",jump }, { ctrl('o'), "jump backward in jump list", jump }, - { 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 }, { alt('\''), "rotate selections content", rotate_selections_content }, @@ -1599,6 +1657,9 @@ static NormalCmdDesc cmds[] = { Key::PageUp, "scroll one page up", scroll }, { Key::PageDown, "scroll one page down", scroll }, + + { '^', "restore selections", restore_selections }, + { alt('^'), "save selections", save_selections }, }; KeyMap keymap = cmds; diff --git a/src/selection.cc b/src/selection.cc index 1ea2fdbb..b5b60528 100644 --- a/src/selection.cc +++ b/src/selection.cc @@ -17,9 +17,7 @@ void Selection::merge_with(const Selection& range) SelectionList::SelectionList(Buffer& buffer, Selection s, size_t timestamp) : m_buffer(&buffer), m_selections({ std::move(s) }), m_timestamp(timestamp) -{ - check_invariant(); -} +{} SelectionList::SelectionList(Buffer& buffer, Selection s) : SelectionList(buffer, std::move(s), buffer.timestamp()) @@ -29,7 +27,6 @@ SelectionList::SelectionList(Buffer& buffer, Vector s, size_t timesta : m_buffer(&buffer), m_selections(std::move(s)), m_timestamp(timestamp) { kak_assert(size() > 0); - check_invariant(); } SelectionList::SelectionList(Buffer& buffer, Vector s) @@ -535,43 +532,45 @@ void SelectionList::erase() 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& anchor = selection.anchor(); - ByteCount distance = buffer.distance(anchor, cursor); - return format("{}.{}{}{}", anchor.line + 1, anchor.column + 1, - distance < 0 ? '-' : '+', abs(distance)); + return format("{}.{},{}.{}", anchor.line + 1, anchor.column + 1, + cursor.line + 1, cursor.column + 1); } String selection_list_to_string(const SelectionList& selections) { const auto& buffer = selections.buffer(); - return join(transformed(selections, [&buffer](const Selection& s) - { return selection_to_string(buffer, s); }), + return join(transformed(selections, [](const Selection& s) + { return selection_to_string(s); }), ':', false); } -Selection selection_from_string(const Buffer& buffer, StringView desc) +Selection selection_from_string(StringView desc) { - auto dot = find(desc, '.'); - auto sign = std::find_if(dot, desc.end(), [](char c) { return c == '+' or c == '-'; }); + auto comma = find(desc, ','); + auto dot_anchor = find(StringView{desc.begin(), comma}, '.'); + auto dot_cursor = find(StringView{comma, desc.end()}, '.'); - if (dot == desc.end() or sign == desc.end()) - throw runtime_error(format("'{}' does not follow .+ format", desc)); + if (comma == desc.end() or dot_anchor == comma or dot_cursor == desc.end()) + throw runtime_error(format("'{}' does not follow .,. format", desc)); - LineCount line = str_to_int({desc.begin(), dot}) - 1; - ByteCount column = str_to_int({dot+1, sign}) - 1; - ByteCoord anchor{line, column}; - ByteCount count = (*sign == '+' ? 1 : -1) * str_to_int({sign+1, desc.end()}); - return Selection{anchor, buffer.advance(anchor, count)}; + ByteCoord anchor{str_to_int({desc.begin(), dot_anchor}) - 1, + str_to_int({dot_anchor+1, comma}) - 1}; + + ByteCoord cursor{str_to_int({comma+1, dot_cursor}) - 1, + str_to_int({dot_cursor+1, desc.end()}) - 1}; + + return Selection{anchor, cursor}; } SelectionList selection_list_from_string(Buffer& buffer, StringView desc) { Vector sels; 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)}; } diff --git a/src/selection.hh b/src/selection.hh index 3001a94b..2f41b06e 100644 --- a/src/selection.hh +++ b/src/selection.hh @@ -142,9 +142,9 @@ private: Vector 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); -Selection selection_from_string(const Buffer& buffer, StringView desc); +Selection selection_from_string(StringView desc); SelectionList selection_list_from_string(Buffer& buffer, StringView desc); }