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:
Maxime Coste 2016-03-08 21:35:56 +00:00
parent 21ae662151
commit 9e15181dc9
15 changed files with 185 additions and 156 deletions

View File

@ -57,7 +57,7 @@ Vector<std::pair<StringView, StringView>> AliasRegistry::flatten_aliases() const
res = m_parent->flatten_aliases(); res = m_parent->flatten_aliases();
for (auto& alias : m_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); res.emplace_back(alias.key, alias.value);
} }
return res; return res;

View File

@ -304,7 +304,7 @@ bool Buffer::undo()
--m_history_cursor; --m_history_cursor;
for (const Modification& modification : reversed(*m_history_cursor)) for (const Modification& modification : *m_history_cursor | reverse())
apply_modification(modification.inverse()); apply_modification(modification.inverse());
return true; return true;
} }

View File

@ -235,7 +235,7 @@ void Client::redraw_ifn()
void Client::force_redraw() void Client::force_redraw()
{ {
m_ui_pending |= Refresh | Draw | m_ui_pending |= Refresh | Draw | StatusLine |
(m_menu.items.empty() ? MenuHide : MenuShow | MenuSelect) | (m_menu.items.empty() ? MenuHide : MenuShow | MenuSelect) |
(m_info.content.empty() ? InfoHide : InfoShow); (m_info.content.empty() ? InfoHide : InfoShow);
} }

View File

@ -87,7 +87,7 @@ void ClientManager::remove_client(Client& client, bool graceful)
WindowAndSelections ClientManager::get_free_window(Buffer& buffer) 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) [&](const WindowAndSelections& ws)
{ return &ws.window->buffer() == &buffer; }); { return &ws.window->buffer() == &buffer; });
@ -177,10 +177,8 @@ void ClientManager::redraw_clients() const
CandidateList ClientManager::complete_client_name(StringView prefix, CandidateList ClientManager::complete_client_name(StringView prefix,
ByteCount cursor_pos) const ByteCount cursor_pos) const
{ {
auto c = transformed(m_clients, auto c = m_clients | transform([](const std::unique_ptr<Client>& c) -> const String&
[](const std::unique_ptr<Client>& c) -> const String& { return c->context().name(); });
{ return c->context().name(); });
return complete(prefix, cursor_pos, c); return complete(prefix, cursor_pos, c);
} }

View File

@ -515,12 +515,15 @@ CommandInfo CommandManager::command_info(const Context& context, StringView comm
Completions CommandManager::complete_command_name(const Context& context, Completions CommandManager::complete_command_name(const Context& context,
StringView query) const StringView query) const
{ {
return{0, query.length(), Kakoune::complete(query, query.length(), concatenated( auto candidates = Kakoune::complete(
transformed(filtered(m_commands, [](const CommandMap::value_type& cmd) query, query.length(), concatenated(
{ return not (cmd.second.flags & CommandFlags::Hidden); }), m_commands
[](const CommandMap::value_type& cmd) { return StringView{cmd.first}; }), | filter([](const CommandMap::value_type& cmd) { return not (cmd.second.flags & CommandFlags::Hidden); })
transformed(context.aliases().flatten_aliases(), | transform([](const CommandMap::value_type& cmd) { return StringView{cmd.first}; }),
[](AliasRegistry::AliasDesc alias) { return alias.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, Completions CommandManager::complete(const Context& context,

View File

@ -543,7 +543,7 @@ Completions add_highlighter_completer(
if (token_to_complete == 1 and params[0] == "-group") if (token_to_complete == 1 and params[0] == "-group")
return complete_highlighter(context, params[1], pos_in_token, true); 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")) 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{}; return Completions{};
} }
@ -626,7 +626,7 @@ const CommandDesc rm_highlighter_cmd = {
[](const ParametersParser& parser, Context& context, const ShellContext&) [](const ParametersParser& parser, Context& context, const ShellContext&)
{ {
StringView path = parser[0]; StringView path = parser[0];
auto sep_it = find(reversed(path), '/'); auto sep_it = find(path | reverse(), '/');
auto& group = sep_it != path.rend() ? auto& group = sep_it != path.rend() ?
get_highlighter(context, {path.begin(), sep_it.base()}) get_highlighter(context, {path.begin(), sep_it.base()})
: context.window().highlighters(); : context.window().highlighters();

View File

@ -8,11 +8,21 @@
namespace Kakoune 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> template<typename Container>
struct ReversedContainer struct ReverseView
{ {
using iterator = decltype(std::declval<Container>().rbegin()); 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 begin() { return m_container.rbegin(); }
iterator end() { return m_container.rend(); } iterator end() { return m_container.rend(); }
@ -21,166 +31,186 @@ private:
Container& m_container; Container& m_container;
}; };
template<typename Container> struct ReverseFactory
ReversedContainer<Container> reversed(Container&& container)
{ {
return ReversedContainer<Container>(container); template<typename Container>
} ReverseView<Container> operator()(Container&& container) const
template<typename Iterator, typename Filter>
struct FilteredIterator : std::iterator<std::forward_iterator_tag,
typename Iterator::value_type>
{
FilteredIterator(Filter filter, Iterator it, Iterator end)
: m_it{std::move(it)}, m_end{std::move(end)}, m_filter{std::move(filter)}
{ {
do_filter(); return {container};
} }
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; }
friend bool operator==(const FilteredIterator& lhs, const FilteredIterator& rhs)
{
return lhs.m_it == rhs.m_it;
}
friend bool operator!=(const FilteredIterator& lhs, const FilteredIterator& rhs)
{
return not (lhs == rhs);
}
Iterator base() const { return m_it; }
private:
void do_filter()
{
while (m_it != m_end and not m_filter(*m_it))
++m_it;
}
Iterator m_it;
Iterator m_end;
Filter m_filter;
}; };
inline ContainerView<ReverseFactory> reverse() { return {}; }
template<typename Container, typename Filter> template<typename Container, typename Filter>
struct FilteredContainer struct FilterView
{ {
using iterator = FilteredIterator<decltype(begin(std::declval<Container>())), Filter>; using ContainerIt = decltype(begin(std::declval<Container>()));
FilteredContainer(Container& container, Filter filter)
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<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 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 ContainerIt& base() const { return m_it; }
private:
void do_filter()
{
while (m_it != m_end and not m_view.m_filter(*m_it))
++m_it;
}
ContainerIt m_it;
ContainerIt m_end;
const FilterView& m_view;
};
FilterView(Container& container, Filter filter)
: m_container{container}, m_filter{std::move(filter)} {} : m_container{container}, m_filter{std::move(filter)} {}
iterator begin() const { return {m_filter, m_container.begin(), m_container.end()}; } Iterator begin() const { return {*this, m_container.begin(), m_container.end()}; }
iterator end() const { return {m_filter, m_container.end(), m_container.end()}; } Iterator end() const { return {*this, m_container.end(), m_container.end()}; }
private: private:
Container& m_container; Container& m_container;
Filter m_filter; Filter m_filter;
}; };
template<typename Container, typename Filter> template<typename Filter>
FilteredContainer<Container, Filter> filtered(Container&& container, Filter 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> template<typename I, typename T>
using TransformedResult = decltype(std::declval<T>()(*std::declval<I>())); 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>
{
TransformedIterator(Transform transform, Iterator it)
: m_it{std::move(it)}, m_transform{std::move(transform)} {}
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; }
friend bool operator==(const TransformedIterator& lhs, const TransformedIterator& rhs)
{
return lhs.m_it == rhs.m_it;
}
friend bool operator!=(const TransformedIterator& lhs, const TransformedIterator& rhs)
{
return not (lhs == rhs);
}
Iterator base() const { return m_it; }
private:
Iterator m_it;
Transform m_transform;
};
template<typename Container, typename Transform> template<typename Container, typename Transform>
struct TransformedContainer struct TransformView
{ {
using iterator = TransformedIterator<decltype(begin(std::declval<Container>())), Transform>; using ContainerIt = decltype(begin(std::declval<Container>()));
TransformedContainer(Container& container, Transform transform)
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} {}
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 Iterator& lhs, const Iterator& rhs)
{
return not (lhs == rhs);
}
ContainerIt base() const { return m_it; }
private:
ContainerIt m_it;
const TransformView& m_view;
};
TransformView(Container& container, Transform transform)
: m_container{container}, m_transform{std::move(transform)} {} : m_container{container}, m_transform{std::move(transform)} {}
iterator begin() const { return {m_transform, m_container.begin()}; } Iterator begin() const { return {*this, m_container.begin()}; }
iterator end() const { return {m_transform, m_container.end()}; } Iterator end() const { return {*this, m_container.end()}; }
private: private:
Container& m_container; Container& m_container;
Transform m_transform; Transform m_transform;
}; };
template<typename Container, typename Transform> template<typename Transform>
TransformedContainer<Container, Transform> transformed(Container&& container, Transform transform) struct TransformFactory
{ {
return {container, std::move(transform)}; template<typename Container>
} TransformView<Container, Transform> operator()(Container&& container) const { return {container, std::move(m_transform)}; }
template<typename Iterator1, typename Iterator2, typename ValueType = typename Iterator1::value_type> Transform m_transform;
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)
{
return not (lhs == rhs);
}
private:
bool is2() const { return m_it1 == m_end1; }
Iterator1 m_it1;
Iterator1 m_end1;
Iterator2 m_it2;
}; };
template<typename Transform>
inline ContainerView<TransformFactory<Transform>> transform(Transform t) { return {std::move(t)}; }
template<typename Container1, typename Container2> template<typename Container1, typename Container2>
struct ConcatenatedContainer struct ConcatView
{ {
using iterator = ConcatenatedIterator<decltype(begin(std::declval<Container1>())), using ContainerIt1 = decltype(begin(std::declval<Container1>()));
decltype(begin(std::declval<Container2>()))>; using ContainerIt2 = decltype(begin(std::declval<Container2>()));
using ValueType = typename ContainerIt1::value_type;
ConcatenatedContainer(Container1& container1, Container2& container2) 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;
}
friend bool operator!=(const Iterator& lhs, const Iterator& rhs)
{
return not (lhs == rhs);
}
private:
bool is2() const { return m_it1 == m_end1; }
ContainerIt1 m_it1;
ContainerIt1 m_end1;
ContainerIt2 m_it2;
};
ConcatView(Container1& container1, Container2& container2)
: m_container1{container1}, m_container2{container2} {} : m_container1{container1}, m_container2{container2} {}
iterator begin() const { return {m_container1.begin(), m_container1.end(), m_container2.begin()}; } 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 end() const { return {m_container1.end(), m_container1.end(), m_container2.end()}; }
private: private:
Container1& m_container1; Container1& m_container1;
@ -188,7 +218,7 @@ private:
}; };
template<typename Container1, typename Container2> template<typename Container1, typename Container2>
ConcatenatedContainer<Container1, Container2> concatenated(Container1&& container1, Container2&& container2) ConcatView<Container1, Container2> concatenated(Container1&& container1, Container2&& container2)
{ {
return {container1, container2}; return {container1, container2};
} }

View File

@ -95,9 +95,8 @@ CandidateList FaceRegistry::complete_alias_name(StringView prefix,
ByteCount cursor_pos) const ByteCount cursor_pos) const
{ {
return complete(prefix, cursor_pos, return complete(prefix, cursor_pos,
transformed(m_aliases, m_aliases | transform([](const AliasMap::value_type& v) -> const String&
[](const AliasMap::value_type& v) -> const String& { return v.first; }));
{ return v.first; }));
} }
FaceRegistry::FaceRegistry() FaceRegistry::FaceRegistry()

View File

@ -63,7 +63,7 @@ String parse_filename(StringView filename)
std::pair<StringView, StringView> split_path(StringView path) std::pair<StringView, StringView> split_path(StringView path)
{ {
auto it = find(reversed(path), '/'); auto it = find(path | reverse(), '/');
if (it == path.rend()) if (it == path.rend())
return { {}, path }; return { {}, path };
const char* slash = it.base()-1; const char* slash = it.base()-1;

View File

@ -52,10 +52,9 @@ Completions HighlighterGroup::complete_child(StringView path, ByteCount cursor_p
auto candidates = complete( auto candidates = complete(
path, cursor_pos, path, cursor_pos,
transformed(filtered(m_highlighters, m_highlighters | filter([=](const HighlighterMap::Element& hl)
[=](const HighlighterMap::Element& hl) { return not group or hl.value->has_children(); })
{ return not group or hl.value->has_children(); }), | transform(HighlighterMap::get_id));
HighlighterMap::get_id));
return { 0, 0, std::move(candidates) }; return { 0, 0, std::move(candidates) };
} }

View File

@ -1303,7 +1303,7 @@ public:
return offset_pos(hl.complete_child(path.substr(offset), cursor_pos - offset, group), offset); 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) }; return { 0, 0, complete(path, cursor_pos, container) };
} }

View File

@ -31,7 +31,7 @@ CandidateList HookManager::complete_hook_group(StringView prefix, ByteCount pos_
CandidateList res; CandidateList res;
for (auto& list : m_hook) 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)) for (auto& c : complete(prefix, pos_in_token, container))
{ {
if (!contains(res, c)) if (!contains(res, c))

View File

@ -61,9 +61,9 @@ void register_env_vars()
}, { }, {
"buflist", false, "buflist", false,
[](StringView name, const Context& context) [](StringView name, const Context& context)
{ return join(transformed(BufferManager::instance(), { return join(BufferManager::instance() |
[](const SafePtr<Buffer>& b) transform([](const SafePtr<Buffer>& b)
{ return b->display_name(); }), ':'); } { return b->display_name(); }), ':'); }
}, { }, {
"timestamp", false, "timestamp", false,
[](StringView name, const Context& context) -> String [](StringView name, const Context& context) -> String
@ -520,7 +520,7 @@ int run_server(StringView session, StringView init_command,
{ {
// create buffers in reverse order so that the first given buffer // create buffers in reverse order so that the first given buffer
// is the most recently created one. // is the most recently created one.
for (auto& file : reversed(files)) for (auto& file : files | reverse())
{ {
try try
{ {

View File

@ -555,8 +555,8 @@ String selection_to_string(const Selection& selection)
String selection_list_to_string(const SelectionList& selections) 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); }), { return selection_to_string(s); }),
':', false); ':', false);
} }

View File

@ -128,7 +128,7 @@ find_surrounding(Iterator begin, Iterator end,
{ {
using RevIt = std::reverse_iterator<Iterator>; using RevIt = std::reverse_iterator<Iterator>;
auto res = find_closing(RevIt{pos+1}, RevIt{begin}, auto res = find_closing(RevIt{pos+1}, RevIt{begin},
reversed(closing), reversed(opening), closing | reverse(), opening | reverse(),
init_level, nestable); init_level, nestable);
if (not res) if (not res)
return {}; return {};