Unify completion from container content logic

This commit is contained in:
Maxime Coste 2014-12-23 13:54:09 +00:00
parent 064fb81b8d
commit b6ff15aa75
14 changed files with 75 additions and 73 deletions

View File

@ -3,6 +3,7 @@
#include "assert.hh"
#include "buffer.hh"
#include "client_manager.hh"
#include "containers.hh"
#include "exception.hh"
#include "file.hh"
#include "string.hh"
@ -117,27 +118,19 @@ void BufferManager::backup_modified_buffers()
CandidateList BufferManager::complete_buffer_name(StringView prefix,
ByteCount cursor_pos)
{
auto real_prefix = prefix.substr(0, cursor_pos);
const bool include_dirs = contains(real_prefix, '/');
CandidateList result;
CandidateList subsequence_result;
for (auto& buffer : m_buffers)
{
const bool include_dirs = contains(prefix.substr(0, cursor_pos), '/');
auto c = transformed(m_buffers,
[include_dirs](const safe_ptr<Buffer>& buffer) -> String {
String name = buffer->display_name();
StringView match_name = name;
if (not include_dirs and buffer->flags() & Buffer::Flags::File)
{
ByteCount pos = name.find_last_of('/');
if (pos != (int)String::npos)
match_name = name.substr(pos+1);
return name.substr(pos+1);
}
if (prefix_match(match_name, real_prefix))
result.push_back(name);
if (subsequence_match(name, real_prefix))
subsequence_result.push_back(name);
}
return result.empty() ? subsequence_result : result;
return name;
});
return complete(prefix, cursor_pos, c, prefix_match, subsequence_match);
}
void BufferManager::clear_buffer_trash()

View File

@ -2,6 +2,7 @@
#include "buffer_manager.hh"
#include "command_manager.hh"
#include "containers.hh"
#include "event_manager.hh"
#include "face_registry.hh"
#include "file.hh"
@ -172,19 +173,8 @@ void ClientManager::clear_mode_trashes() const
CandidateList ClientManager::complete_client_name(StringView prefix,
ByteCount cursor_pos) const
{
auto real_prefix = prefix.substr(0, cursor_pos);
CandidateList result;
CandidateList subsequence_result;
for (auto& client : m_clients)
{
const String& name = client->context().name();
if (prefix_match(name, real_prefix))
result.push_back(name);
if (subsequence_match(name, real_prefix))
subsequence_result.push_back(name);
}
return result.empty() ? subsequence_result : result;
auto c = transformed(m_clients, [](const std::unique_ptr<Client>& c){ return c->context().name(); });
return complete(prefix, cursor_pos, c, prefix_match, subsequence_match);
}
}

View File

@ -53,5 +53,43 @@ inline Completions offset_pos(Completions completion, ByteCount offset)
std::move(completion.candidates) };
}
namespace detail
{
template<typename Str, typename Func>
void do_matches(Str&& str, StringView prefix,
CandidateList* res, Func match_func)
{
if (match_func(str, prefix))
res->push_back(str);
}
template<typename Str, typename Func, typename... Rest>
void do_matches(Str&& str, StringView prefix,
CandidateList* res, Func match_func, Rest... rest)
{
do_matches(str, prefix, res, match_func);
do_matches(str, prefix, res+1, rest...);
}
}
template<typename Container, typename... MatchFunc>
CandidateList complete(StringView prefix, ByteCount cursor_pos,
const Container& container, MatchFunc... match_func)
{
CandidateList res[sizeof...(match_func)];
auto real_prefix = prefix.substr(0, cursor_pos);
for (const auto& elem : container)
detail::do_matches(elem, real_prefix, res, match_func...);
auto it = find_if(res, [](CandidateList& c) { return not c.empty(); });
return it == end(res) ? CandidateList{} : std::move(*it);
}
template<typename Container>
CandidateList complete(StringView prefix, ByteCount cursor_pos,
const Container& container)
{
return complete(prefix, cursor_pos, container, prefix_match);
}
}
#endif // completion_hh_INCLUDED

View File

@ -2,6 +2,7 @@
#include "containers.hh"
#include "exception.hh"
#include "containers.hh"
namespace Kakoune
{
@ -82,14 +83,10 @@ void FaceRegistry::register_alias(const String& name, const String& facedesc,
CandidateList FaceRegistry::complete_alias_name(StringView prefix,
ByteCount cursor_pos) const
{
CandidateList res;
auto real_prefix = prefix.substr(0, cursor_pos);
for (auto& alias : m_aliases)
{
if (prefix_match(alias.first, real_prefix))
res.push_back(alias.first);
}
return res;
using ValueType = std::pair<String, FaceOrAlias>;
return complete(prefix, cursor_pos,
transformed(m_aliases,
[](const ValueType& v){ return v.first; }));
}
FaceRegistry::FaceRegistry()

View File

@ -5,6 +5,7 @@
#include "id_map.hh"
#include "string.hh"
#include "exception.hh"
#include "containers.hh"
namespace Kakoune
{
@ -35,7 +36,8 @@ public:
CandidateList complete_name(StringView prefix, ByteCount cursor_pos)
{
return m_functions.complete_id(prefix, cursor_pos);
auto c = transformed(m_functions, id_map<FunctionType>::get_id);
return complete(prefix, cursor_pos, c);
}
private:

View File

@ -48,11 +48,12 @@ Completions HighlighterGroup::complete_child(StringView path, ByteCount cursor_p
return offset_pos(hl.complete_child(path.substr(offset), cursor_pos - offset, group), offset);
}
auto condition = [=](const HighlighterMap::value_type& hl)
{
return not group or hl.second->has_children();
};
return { 0, 0, m_highlighters.complete_id_if(path, cursor_pos, condition) };
using ValueType = HighlighterMap::value_type;
auto c = transformed(filtered(m_highlighters,
[=](const ValueType& hl)
{ return not group or hl.second->has_children(); }),
HighlighterMap::get_id);
return { 0, 0, complete(path, cursor_pos, c) };
}
}

View File

@ -3,6 +3,7 @@
#include "assert.hh"
#include "buffer_utils.hh"
#include "context.hh"
#include "containers.hh"
#include "display_buffer.hh"
#include "face_registry.hh"
#include "highlighter_group.hh"
@ -957,7 +958,8 @@ public:
return offset_pos(hl.complete_child(path.substr(offset), cursor_pos - offset, group), offset);
}
return { 0, 0, m_groups.complete_id(path, cursor_pos) };
auto container = transformed(m_groups, id_map<HighlighterGroup>::get_id);
return { 0, 0, complete(path, cursor_pos, container) };
}
static HighlighterAndId create(HighlighterParameters params)

View File

@ -1,5 +1,6 @@
#include "hook_manager.hh"
#include "containers.hh"
#include "context.hh"
#include "debug.hh"
#include "regex.hh"
@ -26,8 +27,8 @@ CandidateList HookManager::complete_hook_group(StringView prefix, ByteCount pos_
CandidateList res;
for (auto& list : m_hook)
{
auto candidates = list.second.complete_id(prefix, pos_in_token);
for (auto& c : candidates)
auto container = transformed(list.second, id_map<HookFunc>::get_id);
for (auto& c : complete(prefix, pos_in_token, container))
{
if (!contains(res, c))
res.push_back(c);

View File

@ -2,6 +2,7 @@
#define hook_manager_hh_INCLUDED
#include "id_map.hh"
#include "completion.hh"
#include "unordered_map.hh"
namespace Kakoune

View File

@ -2,7 +2,6 @@
#define id_map_hh_INCLUDED
#include "containers.hh"
#include "completion.hh"
#include "string.hh"
#include <vector>
@ -63,30 +62,7 @@ public:
m_content.erase(it, end());
}
template<typename Condition>
CandidateList complete_id_if(StringView prefix,
ByteCount cursor_pos,
Condition condition) const
{
auto real_prefix = prefix.substr(0, cursor_pos);
CandidateList result;
for (auto& value : m_content)
{
if (not condition(value))
continue;
if (prefix_match(value.first, real_prefix))
result.push_back(value.first);
}
return result;
}
CandidateList complete_id(StringView prefix,
ByteCount cursor_pos) const
{
return complete_id_if(
prefix, cursor_pos, [](const value_type&) { return true; });
}
static const String& get_id(const value_type& v) { return v.first; }
bool empty() const { return m_content.empty(); }

View File

@ -1,5 +1,6 @@
#include "ncurses_ui.hh"
#include "containers.hh"
#include "display_buffer.hh"
#include "event_manager.hh"
#include "keys.hh"

View File

@ -6,7 +6,6 @@
#include "exception.hh"
#include "flags.hh"
#include "option_types.hh"
#include "utils.hh"
#include "regex.hh"
namespace Kakoune

View File

@ -1,8 +1,8 @@
#include "register_manager.hh"
#include "assert.hh"
#include "id_map.hh"
#include "exception.hh"
#include "id_map.hh"
namespace Kakoune
{

View File

@ -5,6 +5,7 @@
#include "hook_manager.hh"
#include "keymap_manager.hh"
#include "option_manager.hh"
#include "utils.hh"
namespace Kakoune
{