Move more logic into RankedMatch
This commit is contained in:
parent
2eba789610
commit
89d22f3335
|
@ -95,11 +95,13 @@ InsertCompletion complete_word(const Buffer& buffer, ByteCoord cursor_pos)
|
||||||
|
|
||||||
struct RankedMatchAndBuffer : RankedMatch
|
struct RankedMatchAndBuffer : RankedMatch
|
||||||
{
|
{
|
||||||
RankedMatchAndBuffer(StringView w, int r = 0, const Buffer* b = nullptr)
|
RankedMatchAndBuffer(const RankedMatch& m, const Buffer* b = nullptr)
|
||||||
: RankedMatch{w, r}, buffer{b} {}
|
: RankedMatch{m}, buffer{b} {}
|
||||||
|
|
||||||
bool operator==(const RankedMatchAndBuffer& other) const { return word == other.word; }
|
bool operator==(StringView other) const { return candidate() == other; }
|
||||||
bool operator<(const RankedMatchAndBuffer& other) const { return rank > other.rank; }
|
|
||||||
|
bool operator==(const RankedMatchAndBuffer& other) const { return RankedMatch::operator==(other); }
|
||||||
|
bool operator<(const RankedMatchAndBuffer& other) const { return RankedMatch::operator<(other);; }
|
||||||
|
|
||||||
const Buffer* buffer;
|
const Buffer* buffer;
|
||||||
};
|
};
|
||||||
|
@ -109,7 +111,7 @@ InsertCompletion complete_word(const Buffer& buffer, ByteCoord cursor_pos)
|
||||||
auto& word_db = get_word_db(buf);
|
auto& word_db = get_word_db(buf);
|
||||||
auto bufmatches = word_db.find_matching(prefix);
|
auto bufmatches = word_db.find_matching(prefix);
|
||||||
for (auto& m : bufmatches)
|
for (auto& m : bufmatches)
|
||||||
matches.push_back({ m.word, m.rank, &buf });
|
matches.push_back({ m, &buf });
|
||||||
};
|
};
|
||||||
|
|
||||||
add_matches(buffer);
|
add_matches(buffer);
|
||||||
|
@ -127,23 +129,12 @@ InsertCompletion complete_word(const Buffer& buffer, ByteCoord cursor_pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
unordered_erase(matches, StringView{prefix});
|
unordered_erase(matches, StringView{prefix});
|
||||||
// Sort by word, favoring lowercase
|
std::sort(matches.begin(), matches.end());
|
||||||
std::sort(matches.begin(), matches.end(),
|
|
||||||
[](const RankedMatchAndBuffer& lhs, const RankedMatchAndBuffer& rhs) {
|
|
||||||
return std::lexicographical_compare(
|
|
||||||
lhs.word.begin(), lhs.word.end(), rhs.word.begin(), rhs.word.end(),
|
|
||||||
[](char a, char b) {
|
|
||||||
const bool low_a = islower(a), low_b = islower(b);
|
|
||||||
return low_a == low_b ? a < b : low_a;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
matches.erase(std::unique(matches.begin(), matches.end()), matches.end());
|
matches.erase(std::unique(matches.begin(), matches.end()), matches.end());
|
||||||
// Stable sort by rank to preserve by word sorting
|
|
||||||
std::stable_sort(matches.begin(), matches.end());
|
|
||||||
|
|
||||||
const auto longest = std::accumulate(matches.begin(), matches.end(), 0_char,
|
const auto longest = std::accumulate(matches.begin(), matches.end(), 0_char,
|
||||||
[](const CharCount& lhs, const RankedMatchAndBuffer& rhs)
|
[](const CharCount& lhs, const RankedMatchAndBuffer& rhs)
|
||||||
{ return std::max(lhs, rhs.word.char_length()); });
|
{ return std::max(lhs, rhs.candidate().char_length()); });
|
||||||
|
|
||||||
InsertCompletion::CandidateList candidates;
|
InsertCompletion::CandidateList candidates;
|
||||||
candidates.reserve(matches.size());
|
candidates.reserve(matches.size());
|
||||||
|
@ -152,17 +143,15 @@ InsertCompletion complete_word(const Buffer& buffer, ByteCoord cursor_pos)
|
||||||
DisplayLine menu_entry;
|
DisplayLine menu_entry;
|
||||||
if (m.buffer)
|
if (m.buffer)
|
||||||
{
|
{
|
||||||
const auto pad_len = longest + 1 - m.word.char_length();
|
const auto pad_len = longest + 1 - m.candidate().char_length();
|
||||||
menu_entry.push_back(m.word.str());
|
menu_entry.push_back(m.candidate().str());
|
||||||
menu_entry.push_back(String{' ', pad_len});
|
menu_entry.push_back(String{' ', pad_len});
|
||||||
menu_entry.push_back({ m.buffer->display_name(), get_face("MenuInfo") });
|
menu_entry.push_back({ m.buffer->display_name(), get_face("MenuInfo") });
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
menu_entry.push_back(m.word.str());
|
menu_entry.push_back(m.candidate().str());
|
||||||
|
|
||||||
menu_entry.push_back({ " " + to_string(m.rank), get_face("cyan") });
|
candidates.push_back({m.candidate().str(), "", std::move(menu_entry)});
|
||||||
|
|
||||||
candidates.push_back({m.word.str(), "", std::move(menu_entry)});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return { begin.coord(), cursor_pos, std::move(candidates), buffer.timestamp() };
|
return { begin.coord(), cursor_pos, std::move(candidates), buffer.timestamp() };
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
|
||||||
int match_rank(StringView candidate, StringView query)
|
static bool match_rank(StringView candidate, StringView query)
|
||||||
{
|
{
|
||||||
int rank = 0;
|
int rank = 0;
|
||||||
auto it = candidate.begin();
|
auto it = candidate.begin();
|
||||||
|
@ -37,4 +37,29 @@ int match_rank(StringView candidate, StringView query)
|
||||||
return rank;
|
return rank;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RankedMatch::RankedMatch(StringView candidate, StringView query)
|
||||||
|
{
|
||||||
|
if (candidate.empty() or query.empty())
|
||||||
|
{
|
||||||
|
m_candidate = candidate;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_match_rank = match_rank(candidate, query);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RankedMatch::operator<(const RankedMatch& other) const
|
||||||
|
{
|
||||||
|
if (m_match_rank == other.m_match_rank)
|
||||||
|
return std::lexicographical_compare(
|
||||||
|
m_candidate.begin(), m_candidate.end(),
|
||||||
|
other.m_candidate.begin(), other.m_candidate.end(),
|
||||||
|
[](char a, char b) {
|
||||||
|
const bool low_a = islower(a), low_b = islower(b);
|
||||||
|
return low_a == low_b ? a < b : low_a;
|
||||||
|
});
|
||||||
|
|
||||||
|
return m_match_rank < other.m_match_rank;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,12 +9,20 @@ namespace Kakoune
|
||||||
|
|
||||||
struct RankedMatch
|
struct RankedMatch
|
||||||
{
|
{
|
||||||
StringView word;
|
RankedMatch(StringView candidate, StringView query);
|
||||||
int rank;
|
|
||||||
};
|
|
||||||
using RankedMatchList = Vector<RankedMatch>;
|
|
||||||
|
|
||||||
int match_rank(StringView candidate, StringView query);
|
const StringView& candidate() const { return m_candidate; }
|
||||||
|
bool operator<(const RankedMatch& other) const;
|
||||||
|
bool operator==(const RankedMatch& other) const { return m_candidate == other.m_candidate; }
|
||||||
|
|
||||||
|
explicit operator bool() const { return not m_candidate.empty(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
StringView m_candidate;
|
||||||
|
int m_match_rank = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
using RankedMatchList = Vector<RankedMatch>;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -160,7 +160,7 @@ RankedMatchList WordDB::find_matching(StringView query)
|
||||||
{
|
{
|
||||||
if (query.empty())
|
if (query.empty())
|
||||||
{
|
{
|
||||||
res.push_back({word.first, 1 });
|
res.push_back(RankedMatch{word.first, query});
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,8 +168,9 @@ RankedMatchList WordDB::find_matching(StringView query)
|
||||||
if (not matches(to_lower(letters), to_lower(word_letters)) or
|
if (not matches(to_lower(letters), to_lower(word_letters)) or
|
||||||
not matches(letters & upper_mask, word_letters & upper_mask))
|
not matches(letters & upper_mask, word_letters & upper_mask))
|
||||||
continue;
|
continue;
|
||||||
if (int rank = match_rank(word.first, query))
|
|
||||||
res.push_back({ word.first, rank });
|
if (RankedMatch match{word.first, query})
|
||||||
|
res.push_back(match);
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
@ -178,14 +179,14 @@ RankedMatchList WordDB::find_matching(StringView query)
|
||||||
UnitTest test_word_db{[]()
|
UnitTest test_word_db{[]()
|
||||||
{
|
{
|
||||||
auto cmp_words = [](const RankedMatch& lhs, const RankedMatch& rhs) {
|
auto cmp_words = [](const RankedMatch& lhs, const RankedMatch& rhs) {
|
||||||
return lhs.word < rhs.word;
|
return lhs.candidate() < rhs.candidate();
|
||||||
};
|
};
|
||||||
|
|
||||||
auto eq = [](ArrayView<const RankedMatch> lhs, const WordList& rhs) {
|
auto eq = [](ArrayView<const RankedMatch> lhs, const WordList& rhs) {
|
||||||
return lhs.size() == rhs.size() and
|
return lhs.size() == rhs.size() and
|
||||||
std::equal(lhs.begin(), lhs.end(), rhs.begin(),
|
std::equal(lhs.begin(), lhs.end(), rhs.begin(),
|
||||||
[](const RankedMatch& lhs, const StringView& rhs) {
|
[](const RankedMatch& lhs, const StringView& rhs) {
|
||||||
return lhs.word == rhs;
|
return lhs.candidate() == rhs;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user