Rework container helpers, use pipe syntax and cleanup implementation
use 'container | filter(func) | reverse() | transform(func)' instead of 'transform(reverse(filter(container), func), func)' to express container transformations.
This commit is contained in:
parent
21ae662151
commit
9e15181dc9
|
@ -57,7 +57,7 @@ Vector<std::pair<StringView, StringView>> AliasRegistry::flatten_aliases() const
|
|||
res = m_parent->flatten_aliases();
|
||||
for (auto& alias : m_aliases)
|
||||
{
|
||||
if (not contains(transformed(res, [](const AliasDesc& val) { return val.first; }), alias.key))
|
||||
if (not contains(res | transform([](const AliasDesc& val) { return val.first; }), alias.key))
|
||||
res.emplace_back(alias.key, alias.value);
|
||||
}
|
||||
return res;
|
||||
|
|
|
@ -304,7 +304,7 @@ bool Buffer::undo()
|
|||
|
||||
--m_history_cursor;
|
||||
|
||||
for (const Modification& modification : reversed(*m_history_cursor))
|
||||
for (const Modification& modification : *m_history_cursor | reverse())
|
||||
apply_modification(modification.inverse());
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -235,7 +235,7 @@ void Client::redraw_ifn()
|
|||
|
||||
void Client::force_redraw()
|
||||
{
|
||||
m_ui_pending |= Refresh | Draw |
|
||||
m_ui_pending |= Refresh | Draw | StatusLine |
|
||||
(m_menu.items.empty() ? MenuHide : MenuShow | MenuSelect) |
|
||||
(m_info.content.empty() ? InfoHide : InfoShow);
|
||||
}
|
||||
|
|
|
@ -87,7 +87,7 @@ void ClientManager::remove_client(Client& client, bool graceful)
|
|||
|
||||
WindowAndSelections ClientManager::get_free_window(Buffer& buffer)
|
||||
{
|
||||
auto it = find_if(reversed(m_free_windows),
|
||||
auto it = find_if(m_free_windows | reverse(),
|
||||
[&](const WindowAndSelections& ws)
|
||||
{ return &ws.window->buffer() == &buffer; });
|
||||
|
||||
|
@ -177,10 +177,8 @@ void ClientManager::redraw_clients() const
|
|||
CandidateList ClientManager::complete_client_name(StringView prefix,
|
||||
ByteCount cursor_pos) const
|
||||
{
|
||||
auto c = transformed(m_clients,
|
||||
[](const std::unique_ptr<Client>& c) -> const String&
|
||||
auto c = m_clients | transform([](const std::unique_ptr<Client>& c) -> const String&
|
||||
{ return c->context().name(); });
|
||||
|
||||
return complete(prefix, cursor_pos, c);
|
||||
}
|
||||
|
||||
|
|
|
@ -515,12 +515,15 @@ CommandInfo CommandManager::command_info(const Context& context, StringView comm
|
|||
Completions CommandManager::complete_command_name(const Context& context,
|
||||
StringView query) const
|
||||
{
|
||||
return{0, query.length(), Kakoune::complete(query, query.length(), concatenated(
|
||||
transformed(filtered(m_commands, [](const CommandMap::value_type& cmd)
|
||||
{ return not (cmd.second.flags & CommandFlags::Hidden); }),
|
||||
[](const CommandMap::value_type& cmd) { return StringView{cmd.first}; }),
|
||||
transformed(context.aliases().flatten_aliases(),
|
||||
[](AliasRegistry::AliasDesc alias) { return alias.first; })))};
|
||||
auto candidates = Kakoune::complete(
|
||||
query, query.length(), concatenated(
|
||||
m_commands
|
||||
| filter([](const CommandMap::value_type& cmd) { return not (cmd.second.flags & CommandFlags::Hidden); })
|
||||
| transform([](const CommandMap::value_type& cmd) { return StringView{cmd.first}; }),
|
||||
context.aliases().flatten_aliases()
|
||||
| transform([](AliasRegistry::AliasDesc alias) { return alias.first; })));
|
||||
|
||||
return {0, query.length(), std::move(candidates)};
|
||||
}
|
||||
|
||||
Completions CommandManager::complete(const Context& context,
|
||||
|
|
|
@ -543,7 +543,7 @@ Completions add_highlighter_completer(
|
|||
if (token_to_complete == 1 and params[0] == "-group")
|
||||
return complete_highlighter(context, params[1], pos_in_token, true);
|
||||
else if (token_to_complete == 0 or (token_to_complete == 2 and params[0] == "-group"))
|
||||
return { 0_byte, arg.length(), complete(arg, pos_in_token, transformed(HighlighterRegistry::instance(), HighlighterRegistry::get_id)) };
|
||||
return { 0_byte, arg.length(), complete(arg, pos_in_token, HighlighterRegistry::instance() | transform(HighlighterRegistry::get_id)) };
|
||||
return Completions{};
|
||||
}
|
||||
|
||||
|
@ -626,7 +626,7 @@ const CommandDesc rm_highlighter_cmd = {
|
|||
[](const ParametersParser& parser, Context& context, const ShellContext&)
|
||||
{
|
||||
StringView path = parser[0];
|
||||
auto sep_it = find(reversed(path), '/');
|
||||
auto sep_it = find(path | reverse(), '/');
|
||||
auto& group = sep_it != path.rend() ?
|
||||
get_highlighter(context, {path.begin(), sep_it.base()})
|
||||
: context.window().highlighters();
|
||||
|
|
|
@ -8,11 +8,21 @@
|
|||
namespace Kakoune
|
||||
{
|
||||
|
||||
template<typename Factory>
|
||||
struct ContainerView { Factory factory; };
|
||||
|
||||
template<typename Container, typename Factory>
|
||||
auto operator| (Container&& container, ContainerView<Factory> view) ->
|
||||
decltype(view.factory(std::forward<Container>(container)))
|
||||
{
|
||||
return view.factory(std::forward<Container>(container));
|
||||
}
|
||||
|
||||
template<typename Container>
|
||||
struct ReversedContainer
|
||||
struct ReverseView
|
||||
{
|
||||
using iterator = decltype(std::declval<Container>().rbegin());
|
||||
ReversedContainer(Container& container) : m_container(container) {}
|
||||
ReverseView(Container& container) : m_container(container) {}
|
||||
|
||||
iterator begin() { return m_container.rbegin(); }
|
||||
iterator end() { return m_container.rend(); }
|
||||
|
@ -21,142 +31,169 @@ private:
|
|||
Container& m_container;
|
||||
};
|
||||
|
||||
struct ReverseFactory
|
||||
{
|
||||
template<typename Container>
|
||||
ReversedContainer<Container> reversed(Container&& container)
|
||||
ReverseView<Container> operator()(Container&& container) const
|
||||
{
|
||||
return ReversedContainer<Container>(container);
|
||||
return {container};
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Iterator, typename Filter>
|
||||
struct FilteredIterator : std::iterator<std::forward_iterator_tag,
|
||||
typename Iterator::value_type>
|
||||
inline ContainerView<ReverseFactory> reverse() { return {}; }
|
||||
|
||||
template<typename Container, typename Filter>
|
||||
struct FilterView
|
||||
{
|
||||
FilteredIterator(Filter filter, Iterator it, Iterator end)
|
||||
: m_it{std::move(it)}, m_end{std::move(end)}, m_filter{std::move(filter)}
|
||||
using ContainerIt = decltype(begin(std::declval<Container>()));
|
||||
|
||||
struct Iterator : std::iterator<std::forward_iterator_tag,
|
||||
typename ContainerIt::value_type>
|
||||
{
|
||||
Iterator(const FilterView& view, ContainerIt it, ContainerIt end)
|
||||
: m_it{std::move(it)}, m_end{std::move(end)}, m_view{view}
|
||||
{
|
||||
do_filter();
|
||||
}
|
||||
|
||||
auto operator*() -> decltype(*std::declval<Iterator>()) { return *m_it; }
|
||||
FilteredIterator& operator++() { ++m_it; do_filter(); return *this; }
|
||||
FilteredIterator operator++(int) { auto copy = *this; ++(*this); return copy; }
|
||||
auto operator*() -> decltype(*std::declval<ContainerIt>()) { return *m_it; }
|
||||
Iterator& operator++() { ++m_it; do_filter(); return *this; }
|
||||
Iterator operator++(int) { auto copy = *this; ++(*this); return copy; }
|
||||
|
||||
friend bool operator==(const FilteredIterator& lhs, const FilteredIterator& rhs)
|
||||
friend bool operator==(const Iterator& lhs, const Iterator& rhs)
|
||||
{
|
||||
return lhs.m_it == rhs.m_it;
|
||||
}
|
||||
|
||||
friend bool operator!=(const FilteredIterator& lhs, const FilteredIterator& rhs)
|
||||
friend bool operator!=(const Iterator& lhs, const Iterator& rhs)
|
||||
{
|
||||
return not (lhs == rhs);
|
||||
}
|
||||
|
||||
Iterator base() const { return m_it; }
|
||||
const ContainerIt& base() const { return m_it; }
|
||||
|
||||
private:
|
||||
void do_filter()
|
||||
{
|
||||
while (m_it != m_end and not m_filter(*m_it))
|
||||
while (m_it != m_end and not m_view.m_filter(*m_it))
|
||||
++m_it;
|
||||
}
|
||||
|
||||
Iterator m_it;
|
||||
Iterator m_end;
|
||||
Filter m_filter;
|
||||
ContainerIt m_it;
|
||||
ContainerIt m_end;
|
||||
const FilterView& m_view;
|
||||
};
|
||||
|
||||
template<typename Container, typename Filter>
|
||||
struct FilteredContainer
|
||||
{
|
||||
using iterator = FilteredIterator<decltype(begin(std::declval<Container>())), Filter>;
|
||||
FilteredContainer(Container& container, Filter filter)
|
||||
FilterView(Container& container, Filter filter)
|
||||
: m_container{container}, m_filter{std::move(filter)} {}
|
||||
|
||||
iterator begin() const { return {m_filter, m_container.begin(), m_container.end()}; }
|
||||
iterator end() const { return {m_filter, m_container.end(), m_container.end()}; }
|
||||
Iterator begin() const { return {*this, m_container.begin(), m_container.end()}; }
|
||||
Iterator end() const { return {*this, m_container.end(), m_container.end()}; }
|
||||
|
||||
private:
|
||||
Container& m_container;
|
||||
Filter m_filter;
|
||||
};
|
||||
|
||||
template<typename Container, typename Filter>
|
||||
FilteredContainer<Container, Filter> filtered(Container&& container, Filter filter)
|
||||
template<typename Filter>
|
||||
struct FilterFactory
|
||||
{
|
||||
return {container, std::move(filter)};
|
||||
}
|
||||
template<typename Container>
|
||||
FilterView<Container, Filter> operator()(Container&& container) const { return {container, std::move(m_filter)}; }
|
||||
|
||||
Filter m_filter;
|
||||
};
|
||||
|
||||
template<typename Filter>
|
||||
inline ContainerView<FilterFactory<Filter>> filter(Filter f) { return {std::move(f)}; }
|
||||
|
||||
template<typename I, typename T>
|
||||
using TransformedResult = decltype(std::declval<T>()(*std::declval<I>()));
|
||||
|
||||
template<typename Iterator, typename Transform>
|
||||
struct TransformedIterator : std::iterator<std::forward_iterator_tag,
|
||||
typename std::remove_reference<TransformedResult<Iterator, Transform>>::type>
|
||||
template<typename Container, typename Transform>
|
||||
struct TransformView
|
||||
{
|
||||
TransformedIterator(Transform transform, Iterator it)
|
||||
: m_it{std::move(it)}, m_transform{std::move(transform)} {}
|
||||
using ContainerIt = decltype(begin(std::declval<Container>()));
|
||||
|
||||
auto operator*() -> TransformedResult<Iterator, Transform> { return m_transform(*m_it); }
|
||||
TransformedIterator& operator++() { ++m_it; return *this; }
|
||||
TransformedIterator operator++(int) { auto copy = *this; ++m_it; return copy; }
|
||||
struct Iterator : std::iterator<std::forward_iterator_tag,
|
||||
typename std::remove_reference<TransformedResult<ContainerIt, Transform>>::type>
|
||||
{
|
||||
Iterator(const TransformView& view, ContainerIt it)
|
||||
: m_it{std::move(it)}, m_view{view} {}
|
||||
|
||||
friend bool operator==(const TransformedIterator& lhs, const TransformedIterator& rhs)
|
||||
auto operator*() -> TransformedResult<ContainerIt, Transform> { return m_view.m_transform(*m_it); }
|
||||
Iterator& operator++() { ++m_it; return *this; }
|
||||
Iterator operator++(int) { auto copy = *this; ++m_it; return copy; }
|
||||
|
||||
friend bool operator==(const Iterator& lhs, const Iterator& rhs)
|
||||
{
|
||||
return lhs.m_it == rhs.m_it;
|
||||
}
|
||||
|
||||
friend bool operator!=(const TransformedIterator& lhs, const TransformedIterator& rhs)
|
||||
friend bool operator!=(const Iterator& lhs, const Iterator& rhs)
|
||||
{
|
||||
return not (lhs == rhs);
|
||||
}
|
||||
|
||||
Iterator base() const { return m_it; }
|
||||
ContainerIt base() const { return m_it; }
|
||||
|
||||
private:
|
||||
Iterator m_it;
|
||||
Transform m_transform;
|
||||
ContainerIt m_it;
|
||||
const TransformView& m_view;
|
||||
};
|
||||
|
||||
template<typename Container, typename Transform>
|
||||
struct TransformedContainer
|
||||
{
|
||||
using iterator = TransformedIterator<decltype(begin(std::declval<Container>())), Transform>;
|
||||
TransformedContainer(Container& container, Transform transform)
|
||||
TransformView(Container& container, Transform transform)
|
||||
: m_container{container}, m_transform{std::move(transform)} {}
|
||||
|
||||
iterator begin() const { return {m_transform, m_container.begin()}; }
|
||||
iterator end() const { return {m_transform, m_container.end()}; }
|
||||
Iterator begin() const { return {*this, m_container.begin()}; }
|
||||
Iterator end() const { return {*this, m_container.end()}; }
|
||||
|
||||
private:
|
||||
Container& m_container;
|
||||
Transform m_transform;
|
||||
};
|
||||
|
||||
template<typename Container, typename Transform>
|
||||
TransformedContainer<Container, Transform> transformed(Container&& container, Transform transform)
|
||||
template<typename Transform>
|
||||
struct TransformFactory
|
||||
{
|
||||
return {container, std::move(transform)};
|
||||
template<typename Container>
|
||||
TransformView<Container, Transform> operator()(Container&& container) const { return {container, std::move(m_transform)}; }
|
||||
|
||||
Transform m_transform;
|
||||
};
|
||||
|
||||
template<typename Transform>
|
||||
inline ContainerView<TransformFactory<Transform>> transform(Transform t) { return {std::move(t)}; }
|
||||
|
||||
|
||||
|
||||
template<typename Container1, typename Container2>
|
||||
struct ConcatView
|
||||
{
|
||||
using ContainerIt1 = decltype(begin(std::declval<Container1>()));
|
||||
using ContainerIt2 = decltype(begin(std::declval<Container2>()));
|
||||
using ValueType = typename ContainerIt1::value_type;
|
||||
|
||||
struct Iterator : std::iterator<std::forward_iterator_tag, ValueType>
|
||||
{
|
||||
static_assert(std::is_convertible<typename ContainerIt1::value_type, ValueType>::value, "");
|
||||
static_assert(std::is_convertible<typename ContainerIt2::value_type, ValueType>::value, "");
|
||||
|
||||
Iterator(ContainerIt1 it1, ContainerIt1 end1, ContainerIt2 it2)
|
||||
: m_it1(std::move(it1)), m_end1(std::move(end1)),
|
||||
m_it2(std::move(it2)) {}
|
||||
|
||||
decltype(*std::declval<ContainerIt1>()) operator*() { return is2() ? *m_it2 : *m_it1; }
|
||||
Iterator& operator++() { if (is2()) ++m_it2; else ++m_it1; return *this; }
|
||||
Iterator operator++(int) { auto copy = *this; ++*this; return copy; }
|
||||
|
||||
friend bool operator==(const Iterator& lhs, const Iterator& rhs)
|
||||
{
|
||||
return lhs.m_it1 == rhs.m_it1 and lhs.m_end1 == rhs.m_end1 and
|
||||
lhs.m_it2 == rhs.m_it2;
|
||||
}
|
||||
|
||||
template<typename Iterator1, typename Iterator2, typename ValueType = typename Iterator1::value_type>
|
||||
struct ConcatenatedIterator : std::iterator<std::forward_iterator_tag, ValueType>
|
||||
{
|
||||
static_assert(std::is_convertible<typename Iterator1::value_type, ValueType>::value, "");
|
||||
static_assert(std::is_convertible<typename Iterator2::value_type, ValueType>::value, "");
|
||||
|
||||
ConcatenatedIterator(Iterator1 it1, Iterator1 end1, Iterator2 it2)
|
||||
: m_it1(std::move(it1)), m_end1(std::move(end1)), m_it2(std::move(it2)) {}
|
||||
|
||||
decltype(*std::declval<Iterator1>()) operator*() { return is2() ? *m_it2 : *m_it1; }
|
||||
ConcatenatedIterator& operator++() { if (is2()) ++m_it2; else ++m_it1; return *this; }
|
||||
ConcatenatedIterator operator++(int) { auto copy = *this; ++*this; return copy; }
|
||||
|
||||
friend bool operator==(const ConcatenatedIterator& lhs, const ConcatenatedIterator& rhs)
|
||||
{
|
||||
return lhs.m_it1 == rhs.m_it1 and lhs.m_end1 == rhs.m_end1 and lhs.m_it2 == rhs.m_it2;
|
||||
}
|
||||
|
||||
friend bool operator!=(const ConcatenatedIterator& lhs, const ConcatenatedIterator& rhs)
|
||||
friend bool operator!=(const Iterator& lhs, const Iterator& rhs)
|
||||
{
|
||||
return not (lhs == rhs);
|
||||
}
|
||||
|
@ -164,23 +201,16 @@ struct ConcatenatedIterator : std::iterator<std::forward_iterator_tag, ValueType
|
|||
private:
|
||||
bool is2() const { return m_it1 == m_end1; }
|
||||
|
||||
Iterator1 m_it1;
|
||||
Iterator1 m_end1;
|
||||
Iterator2 m_it2;
|
||||
ContainerIt1 m_it1;
|
||||
ContainerIt1 m_end1;
|
||||
ContainerIt2 m_it2;
|
||||
};
|
||||
|
||||
|
||||
template<typename Container1, typename Container2>
|
||||
struct ConcatenatedContainer
|
||||
{
|
||||
using iterator = ConcatenatedIterator<decltype(begin(std::declval<Container1>())),
|
||||
decltype(begin(std::declval<Container2>()))>;
|
||||
|
||||
ConcatenatedContainer(Container1& container1, Container2& container2)
|
||||
ConcatView(Container1& container1, Container2& container2)
|
||||
: m_container1{container1}, m_container2{container2} {}
|
||||
|
||||
iterator begin() const { return {m_container1.begin(), m_container1.end(), m_container2.begin()}; }
|
||||
iterator end() const { return {m_container1.end(), m_container1.end(), m_container2.end()}; }
|
||||
Iterator begin() const { return {m_container1.begin(), m_container1.end(), m_container2.begin()}; }
|
||||
Iterator end() const { return {m_container1.end(), m_container1.end(), m_container2.end()}; }
|
||||
|
||||
private:
|
||||
Container1& m_container1;
|
||||
|
@ -188,7 +218,7 @@ private:
|
|||
};
|
||||
|
||||
template<typename Container1, typename Container2>
|
||||
ConcatenatedContainer<Container1, Container2> concatenated(Container1&& container1, Container2&& container2)
|
||||
ConcatView<Container1, Container2> concatenated(Container1&& container1, Container2&& container2)
|
||||
{
|
||||
return {container1, container2};
|
||||
}
|
||||
|
|
|
@ -95,8 +95,7 @@ CandidateList FaceRegistry::complete_alias_name(StringView prefix,
|
|||
ByteCount cursor_pos) const
|
||||
{
|
||||
return complete(prefix, cursor_pos,
|
||||
transformed(m_aliases,
|
||||
[](const AliasMap::value_type& v) -> const String&
|
||||
m_aliases | transform([](const AliasMap::value_type& v) -> const String&
|
||||
{ return v.first; }));
|
||||
}
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ String parse_filename(StringView filename)
|
|||
|
||||
std::pair<StringView, StringView> split_path(StringView path)
|
||||
{
|
||||
auto it = find(reversed(path), '/');
|
||||
auto it = find(path | reverse(), '/');
|
||||
if (it == path.rend())
|
||||
return { {}, path };
|
||||
const char* slash = it.base()-1;
|
||||
|
|
|
@ -52,10 +52,9 @@ Completions HighlighterGroup::complete_child(StringView path, ByteCount cursor_p
|
|||
|
||||
auto candidates = complete(
|
||||
path, cursor_pos,
|
||||
transformed(filtered(m_highlighters,
|
||||
[=](const HighlighterMap::Element& hl)
|
||||
{ return not group or hl.value->has_children(); }),
|
||||
HighlighterMap::get_id));
|
||||
m_highlighters | filter([=](const HighlighterMap::Element& hl)
|
||||
{ return not group or hl.value->has_children(); })
|
||||
| transform(HighlighterMap::get_id));
|
||||
|
||||
return { 0, 0, std::move(candidates) };
|
||||
}
|
||||
|
|
|
@ -1303,7 +1303,7 @@ public:
|
|||
return offset_pos(hl.complete_child(path.substr(offset), cursor_pos - offset, group), offset);
|
||||
}
|
||||
|
||||
auto container = transformed(m_groups, decltype(m_groups)::get_id);
|
||||
auto container = m_groups | transform(decltype(m_groups)::get_id);
|
||||
return { 0, 0, complete(path, cursor_pos, container) };
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ CandidateList HookManager::complete_hook_group(StringView prefix, ByteCount pos_
|
|||
CandidateList res;
|
||||
for (auto& list : m_hook)
|
||||
{
|
||||
auto container = transformed(list.value, decltype(list.value)::get_id);
|
||||
auto container = list.value | transform(decltype(list.value)::get_id);
|
||||
for (auto& c : complete(prefix, pos_in_token, container))
|
||||
{
|
||||
if (!contains(res, c))
|
||||
|
|
|
@ -61,8 +61,8 @@ void register_env_vars()
|
|||
}, {
|
||||
"buflist", false,
|
||||
[](StringView name, const Context& context)
|
||||
{ return join(transformed(BufferManager::instance(),
|
||||
[](const SafePtr<Buffer>& b)
|
||||
{ return join(BufferManager::instance() |
|
||||
transform([](const SafePtr<Buffer>& b)
|
||||
{ return b->display_name(); }), ':'); }
|
||||
}, {
|
||||
"timestamp", false,
|
||||
|
@ -520,7 +520,7 @@ int run_server(StringView session, StringView init_command,
|
|||
{
|
||||
// create buffers in reverse order so that the first given buffer
|
||||
// is the most recently created one.
|
||||
for (auto& file : reversed(files))
|
||||
for (auto& file : files | reverse())
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
|
@ -555,7 +555,7 @@ String selection_to_string(const Selection& selection)
|
|||
|
||||
String selection_list_to_string(const SelectionList& selections)
|
||||
{
|
||||
return join(transformed(selections, [](const Selection& s)
|
||||
return join(selections | transform([](const Selection& s)
|
||||
{ return selection_to_string(s); }),
|
||||
':', false);
|
||||
}
|
||||
|
|
|
@ -128,7 +128,7 @@ find_surrounding(Iterator begin, Iterator end,
|
|||
{
|
||||
using RevIt = std::reverse_iterator<Iterator>;
|
||||
auto res = find_closing(RevIt{pos+1}, RevIt{begin},
|
||||
reversed(closing), reversed(opening),
|
||||
closing | reverse(), opening | reverse(),
|
||||
init_level, nestable);
|
||||
if (not res)
|
||||
return {};
|
||||
|
|
Loading…
Reference in New Issue
Block a user