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,142 +31,169 @@ private:
Container& m_container; Container& m_container;
}; };
struct ReverseFactory
{
template<typename Container> 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> inline ContainerView<ReverseFactory> reverse() { return {}; }
struct FilteredIterator : std::iterator<std::forward_iterator_tag,
typename Iterator::value_type> template<typename Container, typename Filter>
struct FilterView
{ {
FilteredIterator(Filter filter, Iterator it, Iterator end) using ContainerIt = decltype(begin(std::declval<Container>()));
: m_it{std::move(it)}, m_end{std::move(end)}, m_filter{std::move(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(); do_filter();
} }
auto operator*() -> decltype(*std::declval<Iterator>()) { return *m_it; } auto operator*() -> decltype(*std::declval<ContainerIt>()) { return *m_it; }
FilteredIterator& operator++() { ++m_it; do_filter(); return *this; } Iterator& operator++() { ++m_it; do_filter(); return *this; }
FilteredIterator operator++(int) { auto copy = *this; ++(*this); return copy; } 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; 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); return not (lhs == rhs);
} }
Iterator base() const { return m_it; } const ContainerIt& base() const { return m_it; }
private: private:
void do_filter() 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; ++m_it;
} }
Iterator m_it; ContainerIt m_it;
Iterator m_end; ContainerIt m_end;
Filter m_filter; const FilterView& m_view;
}; };
template<typename Container, typename Filter> FilterView(Container& container, Filter filter)
struct FilteredContainer
{
using iterator = FilteredIterator<decltype(begin(std::declval<Container>())), Filter>;
FilteredContainer(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> template<typename Container, typename Transform>
struct TransformedIterator : std::iterator<std::forward_iterator_tag, struct TransformView
typename std::remove_reference<TransformedResult<Iterator, Transform>>::type>
{ {
TransformedIterator(Transform transform, Iterator it) using ContainerIt = decltype(begin(std::declval<Container>()));
: m_it{std::move(it)}, m_transform{std::move(transform)} {}
auto operator*() -> TransformedResult<Iterator, Transform> { return m_transform(*m_it); } struct Iterator : std::iterator<std::forward_iterator_tag,
TransformedIterator& operator++() { ++m_it; return *this; } typename std::remove_reference<TransformedResult<ContainerIt, Transform>>::type>
TransformedIterator operator++(int) { auto copy = *this; ++m_it; return copy; } {
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; 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); return not (lhs == rhs);
} }
Iterator base() const { return m_it; } ContainerIt base() const { return m_it; }
private: private:
Iterator m_it; ContainerIt m_it;
Transform m_transform; const TransformView& m_view;
}; };
template<typename Container, typename Transform> TransformView(Container& container, Transform transform)
struct TransformedContainer
{
using iterator = TransformedIterator<decltype(begin(std::declval<Container>())), Transform>;
TransformedContainer(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)}; }
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> friend bool operator!=(const Iterator& lhs, const Iterator& rhs)
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); return not (lhs == rhs);
} }
@ -164,23 +201,16 @@ struct ConcatenatedIterator : std::iterator<std::forward_iterator_tag, ValueType
private: private:
bool is2() const { return m_it1 == m_end1; } bool is2() const { return m_it1 == m_end1; }
Iterator1 m_it1; ContainerIt1 m_it1;
Iterator1 m_end1; ContainerIt1 m_end1;
Iterator2 m_it2; ContainerIt2 m_it2;
}; };
ConcatView(Container1& container1, Container2& container2)
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)
: 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,8 +95,7 @@ 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; }));
} }

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,8 +61,8 @@ 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,
@ -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,7 +555,7 @@ 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 {};