Release v0.6.28: typo correction, partial sync and selection diagnostics
This commit is contained in:
+66
-1
@@ -164,6 +164,24 @@ std::optional<AutoSuggestion> AutoCorrector::suggest(const std::wstring &typed,
|
||||
auto sourceLanguage = layoutLanguage(layouts[source]);
|
||||
if (!dictionaries.contains(sourceLanguage))
|
||||
return {};
|
||||
const std::wstring alphabet = sourceLanguage == L"en" ? L"abcdefghijklmnopqrstuvwxyz" :
|
||||
sourceLanguage == L"uk" ? L"абвгґдеєжзиіїйклмнопрстуфхцчшщьюя" : L"абвгдеёжзийклмнопрстуфхцчшщъыьэюя";
|
||||
auto small = lower(word);
|
||||
bool sameLanguage = safeAutoWord(word, settings.autoMinLength) &&
|
||||
small.find_first_not_of(alphabet) == small.npos &&
|
||||
std::find(settings.cycle.begin(), settings.cycle.end(), layouts[source].id) != settings.cycle.end();
|
||||
auto sameLayout = [&](std::wstring text)
|
||||
{
|
||||
if (word != small) text[0] = upper(text.substr(0, 1))[0];
|
||||
return AutoSuggestion{source, source, prefix + text + suffix};
|
||||
};
|
||||
if (settings.autoReplace && sameLanguage)
|
||||
{
|
||||
auto replacement = settings.autoReplacements.find(small);
|
||||
if (replacement != settings.autoReplacements.end() &&
|
||||
replacement->second.find_first_not_of(alphabet) == small.npos)
|
||||
return sameLayout(replacement->second);
|
||||
}
|
||||
auto personal = [&](const std::wstring &language, const std::wstring &candidate)
|
||||
{
|
||||
auto found = settings.autoWords.find(language);
|
||||
@@ -203,7 +221,54 @@ std::optional<AutoSuggestion> AutoCorrector::suggest(const std::wstring &typed,
|
||||
(!candidate || priority(i) < priority(candidate->target)))
|
||||
candidate = AutoSuggestion{source, i, prefix + converted + suffix};
|
||||
}
|
||||
return candidate;
|
||||
if (candidate || matchedText || !settings.autoTypos || !sameLanguage || word.size() < 4)
|
||||
return candidate;
|
||||
// Generate only single edits. Stop at a second distinct dictionary hit,
|
||||
// including rare hits: frequency limits must never hide ambiguity.
|
||||
std::wstring found;
|
||||
int foundRank = 0;
|
||||
std::set<std::wstring> personalTargets;
|
||||
if (auto it = settings.autoWords.find(sourceLanguage); it != settings.autoWords.end())
|
||||
for (const auto &text : it->second) personalTargets.insert(lower(text));
|
||||
auto consider = [&](const std::wstring &text)
|
||||
{
|
||||
if (text == small || text == found || text.size() < 4 || text.size() > 32) return true;
|
||||
int rank = personalTargets.contains(text) ? 1 : dictionaries.at(sourceLanguage).rank(text);
|
||||
if (!rank) return true;
|
||||
if (!found.empty()) return false;
|
||||
found = text;
|
||||
foundRank = rank;
|
||||
return true;
|
||||
};
|
||||
for (size_t i = 0; i < small.size(); ++i)
|
||||
{
|
||||
auto text = small;
|
||||
text.erase(i, 1);
|
||||
if (!consider(text)) return {};
|
||||
if (i + 1 < small.size())
|
||||
{
|
||||
text = small;
|
||||
std::swap(text[i], text[i + 1]);
|
||||
if (!consider(text)) return {};
|
||||
}
|
||||
for (wchar_t c : alphabet)
|
||||
{
|
||||
text = small;
|
||||
text[i] = c;
|
||||
if (!consider(text)) return {};
|
||||
}
|
||||
}
|
||||
if (small.size() < 32)
|
||||
for (size_t i = 0; i <= small.size(); ++i)
|
||||
for (wchar_t c : alphabet)
|
||||
{
|
||||
auto text = small;
|
||||
text.insert(i, 1, c);
|
||||
if (!consider(text)) return {};
|
||||
}
|
||||
if (!found.empty() && (settings.autoMaxRank == 0 || foundRank <= settings.autoMaxRank))
|
||||
return sameLayout(found);
|
||||
return {};
|
||||
}
|
||||
int matchAutoInput(const Run &run, const std::wstring &text, const std::vector<Layout> &layouts,
|
||||
const Layout &physical, const Settings &settings)
|
||||
|
||||
Reference in New Issue
Block a user