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
|
||||
{
|
||||
RankedMatchAndBuffer(StringView w, int r = 0, const Buffer* b = nullptr)
|
||||
: RankedMatch{w, r}, buffer{b} {}
|
||||
RankedMatchAndBuffer(const RankedMatch& m, const Buffer* b = nullptr)
|
||||
: RankedMatch{m}, buffer{b} {}
|
||||
|
||||
bool operator==(const RankedMatchAndBuffer& other) const { return word == other.word; }
|
||||
bool operator<(const RankedMatchAndBuffer& other) const { return rank > other.rank; }
|
||||
bool operator==(StringView other) const { return candidate() == other; }
|
||||
|
||||
bool operator==(const RankedMatchAndBuffer& other) const { return RankedMatch::operator==(other); }
|
||||
bool operator<(const RankedMatchAndBuffer& other) const { return RankedMatch::operator<(other);; }
|
||||
|
||||
const Buffer* buffer;
|
||||
};
|
||||
|
@ -109,7 +111,7 @@ InsertCompletion complete_word(const Buffer& buffer, ByteCoord cursor_pos)
|
|||
auto& word_db = get_word_db(buf);
|
||||
auto bufmatches = word_db.find_matching(prefix);
|
||||
for (auto& m : bufmatches)
|
||||
matches.push_back({ m.word, m.rank, &buf });
|
||||
matches.push_back({ m, &buf });
|
||||
};
|
||||
|
||||
add_matches(buffer);
|
||||
|
@ -127,23 +129,12 @@ InsertCompletion complete_word(const Buffer& buffer, ByteCoord cursor_pos)
|
|||
}
|
||||
}
|
||||
unordered_erase(matches, StringView{prefix});
|
||||
// Sort by word, favoring lowercase
|
||||
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;
|
||||
});
|
||||
});
|
||||
std::sort(matches.begin(), 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 CharCount& lhs, const RankedMatchAndBuffer& rhs)
|
||||
{ return std::max(lhs, rhs.word.char_length()); });
|
||||
{ return std::max(lhs, rhs.candidate().char_length()); });
|
||||
|
||||
InsertCompletion::CandidateList candidates;
|
||||
candidates.reserve(matches.size());
|
||||
|
@ -152,17 +143,15 @@ InsertCompletion complete_word(const Buffer& buffer, ByteCoord cursor_pos)
|
|||
DisplayLine menu_entry;
|
||||
if (m.buffer)
|
||||
{
|
||||
const auto pad_len = longest + 1 - m.word.char_length();
|
||||
menu_entry.push_back(m.word.str());
|
||||
const auto pad_len = longest + 1 - m.candidate().char_length();
|
||||
menu_entry.push_back(m.candidate().str());
|
||||
menu_entry.push_back(String{' ', pad_len});
|
||||
menu_entry.push_back({ m.buffer->display_name(), get_face("MenuInfo") });
|
||||
}
|
||||
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.word.str(), "", std::move(menu_entry)});
|
||||
candidates.push_back({m.candidate().str(), "", std::move(menu_entry)});
|
||||
}
|
||||
|
||||
return { begin.coord(), cursor_pos, std::move(candidates), buffer.timestamp() };
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
namespace Kakoune
|
||||
{
|
||||
|
||||
int match_rank(StringView candidate, StringView query)
|
||||
static bool match_rank(StringView candidate, StringView query)
|
||||
{
|
||||
int rank = 0;
|
||||
auto it = candidate.begin();
|
||||
|
@ -37,4 +37,29 @@ int match_rank(StringView candidate, StringView query)
|
|||
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
|
||||
{
|
||||
StringView word;
|
||||
int rank;
|
||||
};
|
||||
using RankedMatchList = Vector<RankedMatch>;
|
||||
RankedMatch(StringView candidate, StringView query);
|
||||
|
||||
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())
|
||||
{
|
||||
res.push_back({word.first, 1 });
|
||||
res.push_back(RankedMatch{word.first, query});
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -168,8 +168,9 @@ RankedMatchList WordDB::find_matching(StringView query)
|
|||
if (not matches(to_lower(letters), to_lower(word_letters)) or
|
||||
not matches(letters & upper_mask, word_letters & upper_mask))
|
||||
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;
|
||||
|
@ -178,14 +179,14 @@ RankedMatchList WordDB::find_matching(StringView query)
|
|||
UnitTest test_word_db{[]()
|
||||
{
|
||||
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) {
|
||||
return lhs.size() == rhs.size() and
|
||||
std::equal(lhs.begin(), lhs.end(), rhs.begin(),
|
||||
[](const RankedMatch& lhs, const StringView& rhs) {
|
||||
return lhs.word == rhs;
|
||||
return lhs.candidate() == rhs;
|
||||
});
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user