src: Make gf open all selected paths

The buffer whose path is under the main selection will be focused
after all others have been opened.

Closes #2164
This commit is contained in:
Frank LENORMAND 2021-10-20 21:44:31 +02:00
parent 0af234a329
commit 16dfe977b2
2 changed files with 33 additions and 25 deletions

View File

@ -288,17 +288,23 @@ void goto_commands(Context& context, NormalParams params)
} }
case 'f': case 'f':
{ {
auto filename = content(buffer, context.selections().main());
static constexpr char forbidden[] = { '\'', '\\', '\0' }; static constexpr char forbidden[] = { '\'', '\\', '\0' };
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); })) if (any_of(filename, [](char c){ return contains(forbidden, c); }))
return; throw runtime_error(format("filename contains invalid characters: '{}'", filename));
auto paths = context.options()["path"].get<Vector<String, MemoryDomain::Options>>();
const StringView buffer_dir = split_path(buffer.name()).first; const StringView buffer_dir = split_path(buffer.name()).first;
String path = find_file(filename, buffer_dir, paths); String path = find_file(filename, buffer_dir, paths_opt);
if (path.empty()) if (path.empty())
throw runtime_error(format("unable to find file '{}'", filename)); throw runtime_error(format("unable to find file '{}'", filename));
return path;
});
Buffer* buffer_main = nullptr;
for (auto&& [i, path] : paths | enumerate()) {
Buffer* buffer = BufferManager::instance().get_buffer_ifp(path); Buffer* buffer = BufferManager::instance().get_buffer_ifp(path);
if (not buffer) if (not buffer)
{ {
@ -308,10 +314,13 @@ void goto_commands(Context& context, NormalParams params)
buffer->flags() &= ~Buffer::Flags::NoHooks; buffer->flags() &= ~Buffer::Flags::NoHooks;
} }
if (buffer != &context.buffer()) if (i == context.selections().main_index())
buffer_main = buffer;
}
if (buffer_main and buffer_main != &context.buffer())
{ {
context.push_jump(); context.push_jump();
context.change_buffer(*buffer); context.change_buffer(*buffer_main);
} }
break; break;
} }

View File

@ -164,16 +164,16 @@ struct EnumerateView
struct Iterator : std::iterator<std::forward_iterator_tag, struct Iterator : std::iterator<std::forward_iterator_tag,
typename std::iterator_traits<RangeIt>::value_type> typename std::iterator_traits<RangeIt>::value_type>
{ {
Iterator(size_t index, RangeIt it, RangeIt end) Iterator(size_t index, RangeIt it)
: m_index{index}, m_it{std::move(it)}, m_end{std::move(end)} {} : m_index{index}, m_it{std::move(it)} {}
decltype(auto) operator*() { return std::make_tuple(m_index, *m_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++() { ++m_index; ++m_it; return *this; }
Iterator operator++(int) { auto copy = *this; ++(*this); return copy; } Iterator operator++(int) { auto copy = *this; ++(*this); return copy; }
friend bool operator==(const Iterator& lhs, const Iterator& rhs) friend bool operator==(const Iterator& lhs, const Iterator& rhs)
{ {
return lhs.m_index == rhs.m_index and lhs.m_it == rhs.m_it; return lhs.m_it == rhs.m_it;
} }
friend bool operator!=(const Iterator& lhs, const Iterator& rhs) friend bool operator!=(const Iterator& lhs, const Iterator& rhs)
@ -186,11 +186,10 @@ struct EnumerateView
private: private:
size_t m_index; size_t m_index;
RangeIt m_it; RangeIt m_it;
RangeIt m_end;
}; };
Iterator begin() const { return {0, std::begin(m_range), std::end(m_range)}; } Iterator begin() const { return {0, std::begin(m_range)}; }
Iterator end() const { return {std::size(m_range), std::end(m_range), std::end(m_range)}; } Iterator end() const { return {(size_t)-1, std::end(m_range)}; }
Range m_range; Range m_range;
}; };