36 const std::string& query) {
44 std::string text_lower = text;
45 std::string query_lower = query;
46 std::transform(text_lower.begin(), text_lower.end(), text_lower.begin(),
48 std::transform(query_lower.begin(), query_lower.end(), query_lower.begin(),
52 if (text_lower == query_lower)
56 if (text_lower.find(query_lower) == 0)
60 if (text_lower.find(query_lower) != std::string::npos)
64 while (text_idx < text_lower.length() && query_idx < query_lower.length()) {
65 if (text_lower[text_idx] == query_lower[query_idx]) {
73 if (query_idx != query_lower.length())
80 const std::string& query) {
81 std::vector<std::pair<int, CommandEntry>> scored;
83 for (
const auto& [name, entry] :
commands_) {
87 score +=
FuzzyScore(entry.category, query) / 2;
88 score +=
FuzzyScore(entry.description, query) / 4;
91 score += entry.usage_count * 2;
93 auto now_ms = std::chrono::duration_cast<std::chrono::milliseconds>(
94 std::chrono::system_clock::now().time_since_epoch())
96 int64_t age_ms = now_ms - entry.last_used_ms;
99 }
else if (age_ms < 3600000) {
104 scored.push_back({score, entry});
109 std::sort(scored.begin(), scored.end(),
110 [](
const auto& a,
const auto& b) { return a.first > b.first; });
112 std::vector<CommandEntry> results;
113 for (
const auto& [score, entry] : scored) {
114 results.push_back(entry);
121 std::vector<CommandEntry> recent;
123 for (
const auto& [name, entry] :
commands_) {
124 if (entry.usage_count > 0) {
125 recent.push_back(entry);
129 std::sort(recent.begin(), recent.end(),
131 return a.last_used_ms > b.last_used_ms;
134 if (recent.size() >
static_cast<size_t>(limit)) {
135 recent.resize(limit);
142 std::vector<CommandEntry> frequent;
144 for (
const auto& [name, entry] :
commands_) {
145 if (entry.usage_count > 0) {
146 frequent.push_back(entry);
150 std::sort(frequent.begin(), frequent.end(),
152 return a.usage_count > b.usage_count;
155 if (frequent.size() >
static_cast<size_t>(limit)) {
156 frequent.resize(limit);
std::function< void()> callback