summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMaxime Coste <mawww@kakoune.org>2021-10-24 18:42:37 +1100
committerMaxime Coste <mawww@kakoune.org>2021-10-24 18:42:37 +1100
commit6e635ea30158c0c194750f9a6ce74f8a8ad4c1e4 (patch)
tree4bd12b539cbb9eee27ae31b4ec5b35b0b172bae6 /src
parent502e3f685722f4ce30bfa044dfa5f556b9d46ded (diff)
parent16dfe977b23e92d6317869bb4bcf4e3839516bd3 (diff)
Merge remote-tracking branch 'lenormf/fix-2164'
Diffstat (limited to 'src')
-rw-r--r--src/normal.cc45
-rw-r--r--src/ranges.hh47
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
{