Add support for @ symbols in selection buffer

The selection descriptions use the format
`<buffer>@<timestamp>@<main_index>`. 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 `<timestamp>` and `<main_index>` and leaving the
remaining text for the <buffer>. This should work for any number of `@`
symbols, since `<timestamp>` and `<main_index>` are numbers and should
never contain `@` symbols.
This commit is contained in:
geppettodivacin 2020-01-25 20:02:22 -06:00
parent 2749093143
commit 5596b4b2b9
2 changed files with 34 additions and 5 deletions

View File

@ -1,5 +1,7 @@
#include "normal.hh"
#include <functional>
#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 <buffer>@<timestamp>@main_index"} {} };
const auto desc = content[0] | split<StringView>('@') | static_gather<error, 3>();
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 <buffer>@<timestamp>@main_index"} {} };
const auto desc = content[0] | split<StringView>('@') | gather<Vector>();
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);
}

View File

@ -73,6 +73,24 @@ inline auto skip(size_t count)
});
}
template<typename Range>
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<decay_range<Range>>{std::forward<Range>(range), count};
});
}
template<typename Range, typename Filter>
struct FilterView
{