mirror of https://github.com/procxx/kepka.git
Accept any characters for suggestions.
This commit is contained in:
parent
817e9aa43d
commit
2dacf1b2ef
|
@ -62,10 +62,10 @@ struct LangPackData {
|
||||||
yield(Lang::DefaultLanguageId());
|
yield(Lang::DefaultLanguageId());
|
||||||
yield(Lang::CurrentCloudManager().suggestedLanguage());
|
yield(Lang::CurrentCloudManager().suggestedLanguage());
|
||||||
yield(Platform::SystemLanguage());
|
yield(Platform::SystemLanguage());
|
||||||
|
yieldLocale(QLocale::system());
|
||||||
if (const auto method = QGuiApplication::inputMethod()) {
|
if (const auto method = QGuiApplication::inputMethod()) {
|
||||||
yieldLocale(method->locale());
|
yieldLocale(method->locale());
|
||||||
}
|
}
|
||||||
yieldLocale(QLocale::system());
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,6 +118,18 @@ void AppendFoundEmoji(
|
||||||
void AppendLegacySuggestions(
|
void AppendLegacySuggestions(
|
||||||
std::vector<Result> &result,
|
std::vector<Result> &result,
|
||||||
const QString &query) {
|
const QString &query) {
|
||||||
|
const auto badSuggestionChar = [](QChar ch) {
|
||||||
|
return (ch < 'a' || ch > 'z')
|
||||||
|
&& (ch < 'A' || ch > 'Z')
|
||||||
|
&& (ch < '0' || ch > '9')
|
||||||
|
&& (ch != '_')
|
||||||
|
&& (ch != '-')
|
||||||
|
&& (ch != '+');
|
||||||
|
};
|
||||||
|
if (ranges::find_if(query, badSuggestionChar) != query.end()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const auto suggestions = GetSuggestions(QStringToUTF16(query));
|
const auto suggestions = GetSuggestions(QStringToUTF16(query));
|
||||||
auto &&add = ranges::view::all(
|
auto &&add = ranges::view::all(
|
||||||
suggestions
|
suggestions
|
||||||
|
@ -217,6 +229,7 @@ public:
|
||||||
[[nodiscard]] std::vector<Result> query(
|
[[nodiscard]] std::vector<Result> query(
|
||||||
const QString &normalized,
|
const QString &normalized,
|
||||||
bool exact) const;
|
bool exact) const;
|
||||||
|
[[nodiscard]] int maxQueryLength() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class State {
|
enum class State {
|
||||||
|
@ -389,6 +402,10 @@ std::vector<Result> EmojiKeywords::LangPack::query(
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int EmojiKeywords::LangPack::maxQueryLength() const {
|
||||||
|
return _data.maxKeyLength;
|
||||||
|
}
|
||||||
|
|
||||||
EmojiKeywords::EmojiKeywords() {
|
EmojiKeywords::EmojiKeywords() {
|
||||||
crl::on_main(&_guard, [=] {
|
crl::on_main(&_guard, [=] {
|
||||||
handleAuthSessionChanges();
|
handleAuthSessionChanges();
|
||||||
|
@ -490,6 +507,16 @@ std::vector<Result> EmojiKeywords::query(
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int EmojiKeywords::maxQueryLength() const {
|
||||||
|
if (_data.empty()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
auto &&lengths = _data | ranges::view::transform([](const auto &pair) {
|
||||||
|
return pair.second->maxQueryLength();
|
||||||
|
});
|
||||||
|
return *ranges::max_element(lengths);
|
||||||
|
}
|
||||||
|
|
||||||
void EmojiKeywords::refreshRemoteList() {
|
void EmojiKeywords::refreshRemoteList() {
|
||||||
if (!_api) {
|
if (!_api) {
|
||||||
_localList.clear();
|
_localList.clear();
|
||||||
|
|
|
@ -43,6 +43,7 @@ public:
|
||||||
[[nodiscard]] std::vector<Result> query(
|
[[nodiscard]] std::vector<Result> query(
|
||||||
const QString &query,
|
const QString &query,
|
||||||
bool exact = false) const;
|
bool exact = false) const;
|
||||||
|
[[nodiscard]] int maxQueryLength() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class LangPack;
|
class LangPack;
|
||||||
|
|
|
@ -112,7 +112,18 @@ std::vector<SuggestionsWidget::Row> SuggestionsWidget::getRowsByQuery() const {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
auto suggestions = std::vector<Row>();
|
auto suggestions = std::vector<Row>();
|
||||||
const auto results = Core::App().emojiKeywords().query(_query);
|
const auto middle = (_query[0] == ':');
|
||||||
|
const auto real = middle ? _query.mid(1) : _query;
|
||||||
|
const auto simple = [&] {
|
||||||
|
if (!middle || _query.size() > 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Suggest :D and :-P only as exact matches.
|
||||||
|
return ranges::find_if(_query, [](QChar ch) { return ch.isLower(); })
|
||||||
|
== _query.end();
|
||||||
|
}();
|
||||||
|
const auto exact = !middle || simple;
|
||||||
|
const auto results = Core::App().emojiKeywords().query(real, exact);
|
||||||
for (const auto &result : results) {
|
for (const auto &result : results) {
|
||||||
suggestions.emplace_back(
|
suggestions.emplace_back(
|
||||||
result.emoji,
|
result.emoji,
|
||||||
|
@ -480,6 +491,8 @@ QString SuggestionsController::getEmojiQuery() {
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto modernLimit = Core::App().emojiKeywords().maxQueryLength();
|
||||||
|
const auto legacyLimit = GetSuggestionMaxLength();
|
||||||
const auto position = cursor.position();
|
const auto position = cursor.position();
|
||||||
const auto findTextPart = [&] {
|
const auto findTextPart = [&] {
|
||||||
auto document = _field->document();
|
auto document = _field->document();
|
||||||
|
@ -506,69 +519,33 @@ QString SuggestionsController::getEmojiQuery() {
|
||||||
if (text.isEmpty()) {
|
if (text.isEmpty()) {
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
for (auto i = position - _queryStartPosition; i != 0;) {
|
const auto length = position - _queryStartPosition;
|
||||||
|
for (auto i = length; i != 0;) {
|
||||||
if (text[--i] == ':') {
|
if (text[--i] == ':') {
|
||||||
return text.mid(i + 1);
|
if (i + 1 == length) {
|
||||||
|
return QString();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
const auto isUpperCaseLetter = [](QChar ch) {
|
|
||||||
return (ch >= 'A' && ch <= 'Z');
|
|
||||||
};
|
|
||||||
const auto isLetter = [](QChar ch) {
|
|
||||||
return (ch >= 'a' && ch <= 'z')
|
|
||||||
|| (ch >= 'A' && ch <= 'Z')
|
|
||||||
|| (ch >= '0' && ch <= '9');
|
|
||||||
};
|
|
||||||
const auto isSuggestionChar = [](QChar ch) {
|
|
||||||
return (ch >= 'a' && ch <= 'z')
|
|
||||||
|| (ch >= 'A' && ch <= 'Z')
|
|
||||||
|| (ch >= '0' && ch <= '9')
|
|
||||||
|| (ch == '_')
|
|
||||||
|| (ch == '-')
|
|
||||||
|| (ch == '+');
|
|
||||||
};
|
|
||||||
const auto isGoodCharBeforeSuggestion = [&](QChar ch) {
|
|
||||||
return !isSuggestionChar(ch) || (ch == 0);
|
|
||||||
};
|
|
||||||
Assert(position > 0 && position <= text.size());
|
|
||||||
for (auto i = position; i != 0;) {
|
|
||||||
auto ch = text[--i];
|
|
||||||
if (ch == ':') {
|
|
||||||
auto beforeColon = (i < 1) ? QChar(0) : text[i - 1];
|
|
||||||
if (isGoodCharBeforeSuggestion(beforeColon)) {
|
|
||||||
// At least one letter after colon.
|
|
||||||
if (position > i + 1) {
|
|
||||||
// Skip colon and the first letter.
|
|
||||||
_queryStartPosition += i + 2;
|
_queryStartPosition += i + 2;
|
||||||
const auto length = position - i;
|
return text.mid(i, length - i);
|
||||||
auto result = text.mid(i, length);
|
|
||||||
const auto upperCaseLetters = std::count_if(
|
|
||||||
result.begin(),
|
|
||||||
result.end(),
|
|
||||||
isUpperCaseLetter);
|
|
||||||
const auto letters = std::count_if(
|
|
||||||
result.begin(),
|
|
||||||
result.end(),
|
|
||||||
isLetter);
|
|
||||||
if (letters == upperCaseLetters && letters == 1) {
|
|
||||||
// No upper case single letter suggestions.
|
|
||||||
// We don't want to suggest emoji on :D and :-P
|
|
||||||
return QString();
|
|
||||||
}
|
}
|
||||||
return result.toLower();
|
if (length - i > legacyLimit && length - i > modernLimit) {
|
||||||
}
|
|
||||||
}
|
|
||||||
return QString();
|
|
||||||
}
|
|
||||||
if (position - i > kSuggestionMaxLength) {
|
|
||||||
return QString();
|
|
||||||
}
|
|
||||||
if (!isSuggestionChar(ch)) {
|
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Exact query should be full input field value.
|
||||||
|
const auto end = [&] {
|
||||||
|
auto cursor = _field->textCursor();
|
||||||
|
cursor.movePosition(QTextCursor::End);
|
||||||
|
return cursor.position();
|
||||||
|
}();
|
||||||
|
if ((length > modernLimit)
|
||||||
|
|| (_queryStartPosition != 0)
|
||||||
|
|| (position != end)) {
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
return text.mid(0, length);
|
||||||
|
}
|
||||||
|
|
||||||
void SuggestionsController::replaceCurrent(const QString &replacement) {
|
void SuggestionsController::replaceCurrent(const QString &replacement) {
|
||||||
const auto suggestion = getEmojiQuery();
|
const auto suggestion = getEmojiQuery();
|
||||||
|
|
Loading…
Reference in New Issue