diff options
| author | geppettodivacin <ericdilmore@gmail.com> | 2020-01-25 20:02:22 -0600 |
|---|---|---|
| committer | geppettodivacin <ericdilmore@gmail.com> | 2020-01-26 16:03:03 -0600 |
| commit | 5596b4b2b9dbc56d106f1cd3d3b09ccdcd28ad88 (patch) | |
| tree | 38eefbd6bca9d7117386c37f9c1299f584ad15f9 /src | |
| parent | 2749093143fe5cdbda306569bdb88ff8162486e9 (diff) | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/normal.cc | 21 | ||||
| -rw-r--r-- | 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 <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); } 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<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 { |
