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();
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;

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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,

View File

@ -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();

View File

@ -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};
}

View File

@ -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; }));
}

View File

@ -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;

View File

@ -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) };
}

View File

@ -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) };
}

View File

@ -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))

View File

@ -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
{

View File

@ -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);
}

View File

@ -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 {};