diff options
| author | Maxime Coste <mawww@kakoune.org> | 2021-10-24 18:42:37 +1100 |
|---|---|---|
| committer | Maxime Coste <mawww@kakoune.org> | 2021-10-24 18:42:37 +1100 |
| commit | 6e635ea30158c0c194750f9a6ce74f8a8ad4c1e4 (patch) | |
| tree | 4bd12b539cbb9eee27ae31b4ec5b35b0b172bae6 /src | |
| parent | 502e3f685722f4ce30bfa044dfa5f556b9d46ded (diff) | |
| parent | 16dfe977b23e92d6317869bb4bcf4e3839516bd3 (diff) | |
Merge remote-tracking branch 'lenormf/fix-2164'
Diffstat (limited to 'src')
| -rw-r--r-- | src/normal.cc | 45 | ||||
| -rw-r--r-- | src/ranges.hh | 47 |
2 files changed, 74 insertions, 18 deletions
diff --git a/src/normal.cc b/src/normal.cc index af6a4459..64daabc6 100644 --- a/src/normal.cc +++ b/src/normal.cc @@ -288,30 +288,39 @@ void goto_commands(Context& context, NormalParams params) } case 'f': { - auto filename = content(buffer, context.selections().main()); static constexpr char forbidden[] = { '\'', '\\', '\0' }; - if (any_of(filename, [](char c){ return contains(forbidden, c); })) - return; + const auto& paths_opt = context.options()["path"].get<Vector<String, MemoryDomain::Options>>(); + const auto paths = context.selections() | transform([&](const auto& sel) { + auto filename = content(buffer, sel); + if (any_of(filename, [](char c){ return contains(forbidden, c); })) + throw runtime_error(format("filename contains invalid characters: '{}'", filename)); + + const StringView buffer_dir = split_path(buffer.name()).first; + String path = find_file(filename, buffer_dir, paths_opt); + if (path.empty()) + throw runtime_error(format("unable to find file '{}'", filename)); + + return path; + }); - auto paths = context.options()["path"].get<Vector<String, MemoryDomain::Options>>(); - const StringView buffer_dir = split_path(buffer.name()).first; - String path = find_file(filename, buffer_dir, paths); - if (path.empty()) - throw runtime_error(format("unable to find file '{}'", filename)); + Buffer* buffer_main = nullptr; + for (auto&& [i, path] : paths | enumerate()) { + Buffer* buffer = BufferManager::instance().get_buffer_ifp(path); + if (not buffer) + { + buffer = open_file_buffer(path, context.hooks_disabled() ? + Buffer::Flags::NoHooks + : Buffer::Flags::None); + buffer->flags() &= ~Buffer::Flags::NoHooks; + } - Buffer* buffer = BufferManager::instance().get_buffer_ifp(path); - if (not buffer) - { - buffer = open_file_buffer(path, context.hooks_disabled() ? - Buffer::Flags::NoHooks - : Buffer::Flags::None); - buffer->flags() &= ~Buffer::Flags::NoHooks; + if (i == context.selections().main_index()) + buffer_main = buffer; } - - if (buffer != &context.buffer()) + if (buffer_main and buffer_main != &context.buffer()) { context.push_jump(); - context.change_buffer(*buffer); + context.change_buffer(*buffer_main); } break; } diff --git a/src/ranges.hh b/src/ranges.hh index bd3edd9b..8666510c 100644 --- a/src/ranges.hh +++ b/src/ranges.hh @@ -5,6 +5,7 @@ #include <utility> #include <iterator> #include <numeric> +#include <tuple> #include "constexpr_utils.hh" @@ -155,6 +156,52 @@ inline auto filter(Filter f) }); } +template<typename Range> +struct EnumerateView +{ + using RangeIt = IteratorOf<Range>; + + struct Iterator : std::iterator<std::forward_iterator_tag, + typename std::iterator_traits<RangeIt>::value_type> + { + Iterator(size_t index, RangeIt it) + : m_index{index}, m_it{std::move(it)} {} + + decltype(auto) operator*() { return std::tuple<size_t, decltype(*m_it)>(m_index, *m_it); } + Iterator& operator++() { ++m_index; ++m_it; return *this; } + Iterator operator++(int) { auto copy = *this; ++(*this); return copy; } + + friend bool operator==(const Iterator& lhs, const Iterator& rhs) + { + return lhs.m_it == rhs.m_it; + } + + friend bool operator!=(const Iterator& lhs, const Iterator& rhs) + { + return not (lhs == rhs); + } + + const RangeIt& base() const { return m_it; } + + private: + size_t m_index; + RangeIt m_it; + }; + + Iterator begin() const { return {0, std::begin(m_range)}; } + Iterator end() const { return {(size_t)-1, std::end(m_range)}; } + + Range m_range; +}; + +inline auto enumerate() +{ + return make_view_factory([](auto&& range) { + using Range = decltype(range); + return EnumerateView<decay_range<Range>>{std::forward<Range>(range)}; + }); +} + template<typename Range, typename Transform> struct TransformView { |
