From 5596b4b2b9dbc56d106f1cd3d3b09ccdcd28ad88 Mon Sep 17 00:00:00 2001 From: geppettodivacin Date: Sat, 25 Jan 2020 20:02:22 -0600 Subject: [PATCH] Add support for `@` symbols in selection buffer The selection descriptions use the format `@@`. This fails when file paths have `@` symbols in them: the parser splits on `@` symbols and finds more values than it expects. We here modify the behavior to require *at least* two @ symbols, using the last two for `` and `` and leaving the remaining text for the . This should work for any number of `@` symbols, since `` and `` are numbers and should never contain `@` symbols. --- src/normal.cc | 21 ++++++++++++++++----- src/ranges.hh | 18 ++++++++++++++++++ 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/src/normal.cc b/src/normal.cc index f9b1184f..2c00fb63 100644 --- a/src/normal.cc +++ b/src/normal.cc @@ -1,5 +1,7 @@ #include "normal.hh" +#include + #include "buffer.hh" #include "buffer_manager.hh" #include "buffer_utils.hh" @@ -1774,11 +1776,20 @@ SelectionList read_selections_from_register(char reg, Context& context) if (content.size() < 2) throw runtime_error(format("register '{}' does not contain a selections desc", reg)); - struct error : runtime_error { error(size_t) : runtime_error{"expected @@main_index"} {} }; - const auto desc = content[0] | split('@') | static_gather(); - Buffer& buffer = BufferManager::instance().get_buffer(desc[0]); - const size_t timestamp = str_to_int(desc[1]); - size_t main = str_to_int(desc[2]); + // Use the last two values for timestamp and main_index to allow the buffer + // name to have @ symbols + struct error : runtime_error { error() : runtime_error{"expected @@main_index"} {} }; + const auto desc = content[0] | split('@') | gather(); + const size_t desc_size = desc.size(); + if (desc_size < 3) + throw new error; + auto const buffer_name_view = desc | drop(2); + auto const buffer_name_temp = accumulate (buffer_name_view, ""_str, + [](auto str1, auto str2) { return str1 + "@"_str + str2; }); + auto const buffer_name = buffer_name_temp.substr (CharCount (1)); + Buffer& buffer = BufferManager::instance().get_buffer(buffer_name); + const size_t timestamp = str_to_int(desc[desc_size - 2]); + size_t main = str_to_int(desc[desc_size - 1]); return selection_list_from_strings(buffer, ColumnType::Byte, content | skip(1), timestamp, main); } diff --git a/src/ranges.hh b/src/ranges.hh index 4cd85a25..6518e00e 100644 --- a/src/ranges.hh +++ b/src/ranges.hh @@ -73,6 +73,24 @@ inline auto skip(size_t count) }); } +template +struct DropView +{ + auto begin() const { return std::begin(m_range); } + auto end() const { return std::end(m_range) - m_drop_count; } + + Range m_range; + size_t m_drop_count; +}; + +inline auto drop(size_t count) +{ + return make_view_factory([count](auto&& range) { + using Range = decltype(range); + return DropView>{std::forward(range), count}; + }); +} + template struct FilterView {