diff --git a/CMakeLists.txt b/CMakeLists.txt index 5686f38d1b01ee830bc3bba80b55c17b948cad20..b4efaf423075a0bdbed04c379e747905ac2fb54b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.6.0) -project(fcitx5-chinese-addons VERSION 5.1.3) +project(fcitx5-chinese-addons VERSION 5.1.4) find_package(ECM REQUIRED 1.0.0) set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) @@ -35,7 +35,7 @@ option(ENABLE_GUI "Enable Configure Gui" On) option(ENABLE_BROWSER "Enable built-in browser." On) option(USE_WEBKIT "Use WebKit as browser backend." Off) option(ENABLE_CLOUDPINYIN "Build cloud pinyin addon" On) -option(USE_QT6 "Build with Qt6" Off) +option(USE_QT6 "Build with Qt6" On) option(ENABLE_DATA "Build data" On) if (ENABLE_OPENCC) diff --git a/im/pinyin/customphrase.cpp b/im/pinyin/customphrase.cpp index 12b88d2d1fa1bd9b93b389f4d7e61b3a28770225..ed6d0e1725e0a491dc2bad7c6591be46577fc398 100644 --- a/im/pinyin/customphrase.cpp +++ b/im/pinyin/customphrase.cpp @@ -64,7 +64,7 @@ std::optional parseCustomPhraseLine(std::string_view line) { return std::nullopt; } - std::string_view alpha = line.substr(0, i); + const std::string_view alpha = line.substr(0, i); if (i >= line.size() || line[i] != ',') { return std::nullopt; } @@ -83,7 +83,7 @@ std::optional parseCustomPhraseLine(std::string_view line) { int order = 0; if (auto result = parseInt(line.substr(orderStart, i - orderStart))) { - order = result.value(); + order = *result; } // Zero is invalid value. if (order == 0) { @@ -111,9 +111,9 @@ inline std::tm currentTm() { timePoint.tm_sec = 6; return timePoint; #else - std::chrono::system_clock::time_point now = + const std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); - std::time_t currentTime = std::chrono::system_clock::to_time_t(now); + const std::time_t currentTime = std::chrono::system_clock::to_time_t(now); return fmt::localtime(currentTime); #endif } @@ -126,7 +126,7 @@ int currentHour() { return currentTm().tm_hour; } int currentMinute() { return currentTm().tm_min; } int currentSecond() { return currentTm().tm_sec; } int currentHalfHour() { - int hour = currentHour() % 12; + const int hour = currentHour() % 12; return (hour == 0) ? 12 : hour; } @@ -136,7 +136,7 @@ std::string toChineseYear(std::string_view num) { }; std::string result; result.reserve(num.size() * 3); - for (char c : num) { + for (const char c : num) { assert(charutils::isdigit(c)); result += chineseDigit[c - '0']; } @@ -159,8 +159,8 @@ std::string toChineseTwoDigitNumber(int num, bool leadingZero) { if (num == 0) { return std::string(chineseDigit[0]); } - int tens = num / 10; - int ones = num % 10; + const int tens = num / 10; + const int ones = num % 10; std::string prefix; if (tens == 0) { if (leadingZero) { @@ -201,21 +201,8 @@ std::string CustomPhrase::evaluate( auto state = State::Normal; - for (size_t i = 0; i < content.size(); i++) { - char c = content[i]; - - if (state == State::Variable) { - if (charutils::islower(c) || charutils::isupper(c) || - charutils::isdigit(c) || c == '_') { - variableNameLength += 1; - state = State::Variable; - continue; - } else { - output += evaluator( - content.substr(variableNameStart, variableNameLength)); - state = State::Normal; - } - } + for (size_t i = 0; i < content.size();) { + const char c = content[i]; switch (state) { case State::Normal: @@ -224,6 +211,7 @@ std::string CustomPhrase::evaluate( } else { output += c; } + i += 1; break; case State::VariableStart: @@ -239,7 +227,12 @@ std::string CustomPhrase::evaluate( variableNameStart = i; variableNameLength = 1; state = State::Variable; + } else { + output += '$'; + output += c; + state = State::Normal; } + i += 1; break; case State::BracedVariable: @@ -251,15 +244,38 @@ std::string CustomPhrase::evaluate( variableNameLength += 1; state = State::BracedVariable; } + i += 1; break; case State::Variable: + if (charutils::islower(c) || charutils::isupper(c) || + charutils::isdigit(c) || c == '_') { + variableNameLength += 1; + state = State::Variable; + i += 1; + } else { + output += evaluator( + content.substr(variableNameStart, variableNameLength)); + state = State::Normal; + } break; } } - if (state == State::Variable) { + + switch (state) { + case State::Normal: + break; + case State::VariableStart: + output += '$'; + break; + case State::BracedVariable: + output += "${"; + output += content.substr(variableNameStart, variableNameLength); + break; + case State::Variable: output += evaluator(content.substr(variableNameStart, variableNameLength)); + break; } return output; @@ -332,7 +348,7 @@ std::string CustomPhrase::builtinEvaluator(std::string_view key) { return ""; } -CustomPhraseDict::CustomPhraseDict() {} +CustomPhraseDict::CustomPhraseDict() = default; void CustomPhraseDict::load(std::istream &in, bool loadDisabled) { clear(); @@ -369,7 +385,7 @@ void CustomPhraseDict::load(std::istream &in, bool loadDisabled) { if (value.size() >= 2 && stringutils::startsWith(value, '"') && stringutils::endsWith(value, '"')) { if (auto unescape = stringutils::unescapeForValue(value)) { - value = unescape.value(); + value = *unescape; } } @@ -380,7 +396,7 @@ void CustomPhraseDict::load(std::istream &in, bool loadDisabled) { continue; } auto index = index_.exactMatchSearch(key); - if (index_.isNoValue(index)) { + if (TrieType::isNoValue(index)) { if (data_.size() >= std::numeric_limits::max()) { break; } @@ -408,7 +424,7 @@ void CustomPhraseDict::load(std::istream &in, bool loadDisabled) { const std::vector * CustomPhraseDict::lookup(std::string_view key) const { auto index = index_.exactMatchSearch(key); - if (index_.isNoValue(index)) { + if (TrieType::isNoValue(index)) { return nullptr; } @@ -418,7 +434,7 @@ CustomPhraseDict::lookup(std::string_view key) const { void CustomPhraseDict::addPhrase(std::string_view key, std::string_view value, int order) { auto index = index_.exactMatchSearch(key); - if (index_.isNoValue(index)) { + if (TrieType::isNoValue(index)) { if (data_.size() >= std::numeric_limits::max()) { return; } diff --git a/im/pinyin/customphrase.h b/im/pinyin/customphrase.h index 5af458805706c08db17ea03d416b841c7db65bfd..782747193a2575fc7483c0ff1fb7570d6708e744 100644 --- a/im/pinyin/customphrase.h +++ b/im/pinyin/customphrase.h @@ -16,7 +16,7 @@ namespace fcitx { class CustomPhrase { public: explicit CustomPhrase(int order, std::string value) - : order_(order), value_(value) {} + : order_(order), value_(std::move(value)) {} FCITX_INLINE_DEFINE_DEFAULT_DTOR_COPY_AND_MOVE_WITH_SPEC(CustomPhrase, noexcept) @@ -37,6 +37,7 @@ private: class CustomPhraseDict { public: + using TrieType = libime::DATrie; CustomPhraseDict(); void load(std::istream &in, bool loadDisabled = false); @@ -50,9 +51,8 @@ public: template void foreach(const T &callback) { std::string buf; - index_.foreach([this, &buf, &callback]( - uint32_t index, size_t len, - libime::DATrie::position_type pos) { + index_.foreach([this, &buf, &callback](uint32_t index, size_t len, + TrieType::position_type pos) { index_.suffix(buf, len, pos); callback(buf, data_[index]); return true; @@ -60,7 +60,7 @@ public: } private: - libime::DATrie index_; + TrieType index_; std::vector> data_; }; diff --git a/im/pinyin/pinyin.cpp b/im/pinyin/pinyin.cpp index ad6c1ffdb092f8ad413850e3c9307f89ca760066..8166040809a03841077890b3e4b60a2655f06810 100644 --- a/im/pinyin/pinyin.cpp +++ b/im/pinyin/pinyin.cpp @@ -11,7 +11,6 @@ // We want to keep cloudpinyin logic but don't call it. #include "../../modules/cloudpinyin/cloudpinyin_public.h" #include "config.h" -#include "punctuation.h" #include #include #include @@ -225,7 +224,7 @@ public: } else { text.append(word_); } - setText(text); + setText(std::move(text)); } void select(InputContext *inputContext) const override { @@ -373,7 +372,7 @@ public: : CloudPinyinCandidateWord(engine->cloudpinyin(), pinyin, selectedSentence, *engine->config().keepCloudPinyinPlaceHolder, - inputContext, callback), + inputContext, std::move(callback)), PinyinAbstractExtraCandidateWordInterface(*this, order) { if (filled() || !*engine->config().cloudPinyinAnimation) { return; @@ -1171,7 +1170,8 @@ void PinyinEngine::populateConfig() { EventSource *) { if (cloudpinyin() && !*config_.cloudPinyinEnabled && notifications()) { - auto key = cloudpinyin()->call(); + const auto &key = + cloudpinyin()->call(); std::string msg; if (key.empty()) { @@ -1756,11 +1756,12 @@ bool PinyinEngine::handleStrokeFilter(KeyEvent &event) { auto candidateList = inputContext->inputPanel().candidateList(); auto *state = inputContext->propertyFor(&factory_); if (state->mode_ == PinyinMode::Normal) { - if (candidateList && candidateList->size() && candidateList->toBulk() && + if (candidateList && !candidateList->empty() && + candidateList->toBulk() && event.key().checkKeyList(*config_.selectByStroke) && pinyinhelper()) { resetStroke(inputContext); - state->strokeCandidateList_ = candidateList; + state->strokeCandidateList_ = std::move(candidateList); state->mode_ = PinyinMode::StrokeFilter; updateStroke(inputContext); handleNextPage(event); @@ -1847,7 +1848,7 @@ bool PinyinEngine::handleForgetCandidate(KeyEvent &event) { candidateList->toBulk() && event.key().checkKeyList(*config_.forgetWord)) { resetForgetCandidate(inputContext); - state->forgetCandidateList_ = candidateList; + state->forgetCandidateList_ = std::move(candidateList); state->mode_ = PinyinMode::ForgetCandidate; updateForgetCandidate(inputContext); event.filterAndAccept(); @@ -2225,29 +2226,26 @@ void PinyinEngine::keyEvent(const InputMethodEntry &entry, KeyEvent &event) { } } } - } else { - if (event.key().check(FcitxKey_BackSpace)) { - if (lastIsPunc) { - auto puncStr = punctuation()->call( - "zh_CN", inputContext); - if (!puncStr.empty()) { - // forward the original key is the best choice. - auto ref = inputContext->watch(); - state->cancelLastEvent_ = - instance()->eventLoop().addTimeEvent( - CLOCK_MONOTONIC, now(CLOCK_MONOTONIC) + 300, 0, - [this, ref, puncStr](EventSourceTime *, uint64_t) { - if (auto *inputContext = ref.get()) { - inputContext->commitString(puncStr); - auto *state = - inputContext->propertyFor(&factory_); - state->cancelLastEvent_.reset(); - } - return true; - }); - event.filter(); - return; - } + } else if (event.key().check(FcitxKey_BackSpace)) { + if (lastIsPunc) { + const std::string &puncStr = + punctuation()->call("zh_CN", + inputContext); + if (!puncStr.empty()) { + // forward the original key is the best choice. + state->cancelLastEvent_ = instance()->eventLoop().addTimeEvent( + CLOCK_MONOTONIC, now(CLOCK_MONOTONIC) + 300, 0, + [this, ref = inputContext->watch(), + puncStr = puncStr](EventSourceTime *, uint64_t) { + if (auto *inputContext = ref.get()) { + inputContext->commitString(puncStr); + auto *state = inputContext->propertyFor(&factory_); + state->cancelLastEvent_.reset(); + } + return true; + }); + event.filter(); + return; } } } @@ -2260,7 +2258,9 @@ void PinyinEngine::keyEvent(const InputMethodEntry &entry, KeyEvent &event) { } } -void PinyinEngine::setSubConfig(const std::string &path, const RawConfig &) { +void PinyinEngine::setSubConfig(const std::string &path, + const RawConfig &config) { + FCITX_UNUSED(config); if (path == "dictmanager") { loadExtraDict(); } else if (path == "clearuserdict") { diff --git a/im/pinyin/pinyin.h b/im/pinyin/pinyin.h index 4e89323c158f877794efa0362199b00a95707d86..35226643756166f2950067fc7cdc3987a2f3a073 100644 --- a/im/pinyin/pinyin.h +++ b/im/pinyin/pinyin.h @@ -260,7 +260,7 @@ class CandidateList; class PinyinEngine final : public InputMethodEngineV3 { public: PinyinEngine(Instance *instance); - ~PinyinEngine(); + ~PinyinEngine() override; Instance *instance() { return instance_; } void activate(const InputMethodEntry &entry, InputContextEvent &event) override; @@ -289,7 +289,7 @@ public: } void setSubConfig(const std::string &path, - const fcitx::RawConfig &) override; + const fcitx::RawConfig &config) override; libime::PinyinIME *ime() { return ime_.get(); } const auto &config() const { return config_; } diff --git a/im/table/context.cpp b/im/table/context.cpp index bcb0e5a339192ff16d053a3fdec3d1ef58832bbe..ba3741b8e7a8b726bcacae765f909a784e6958df 100644 --- a/im/table/context.cpp +++ b/im/table/context.cpp @@ -37,7 +37,7 @@ Text TableContext::preeditText(bool hint, bool clientPreedit) const { format}; } - text.append(segText, flags); + text.append(std::move(segText), flags); } } } @@ -49,7 +49,7 @@ Text TableContext::preeditText(bool hint, bool clientPreedit) const { codeText = hint ? customHint(currentCode()) : currentCode(); } - text.append(codeText, {format}); + text.append(std::move(codeText), {format}); if (clientPreedit && *config_.preeditCursorPositionAtBeginning) { text.setCursor(0); diff --git a/im/table/engine.cpp b/im/table/engine.cpp index 011ba1aa906fd7c276a1bb6f1d08e9683014ca79..ac6b7ee573993140b6263b12f20cd485b084fd0b 100644 --- a/im/table/engine.cpp +++ b/im/table/engine.cpp @@ -8,7 +8,6 @@ #include "config.h" #include "context.h" #include "ime.h" -#include "punctuation_public.h" #include "state.h" #include #include @@ -20,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -58,13 +58,14 @@ TableEngine::TableEngine(Instance *instance) names.insert(im.name()); } ime_->releaseUnusedDict(names); + preload(); })); events_.emplace_back(instance_->watchEvent( EventType::InputContextKeyEvent, EventWatcherPhase::PreInputMethod, [this](Event &event) { auto &keyEvent = static_cast(event); auto *inputContext = keyEvent.inputContext(); - auto *entry = instance_->inputMethodEntry(inputContext); + const auto *entry = instance_->inputMethodEntry(inputContext); if (!entry || entry->addon() != "table") { return; } @@ -90,9 +91,15 @@ TableEngine::TableEngine(Instance *instance) }); instance_->userInterfaceManager().registerAction("table-prediction", &predictionAction_); + + preloadEvent_ = instance_->eventLoop().addDeferEvent([this](EventSource *) { + preload(); + preloadEvent_.reset(); + return true; + }); } -TableEngine::~TableEngine() {} +TableEngine::~TableEngine() = default; void TableEngine::reloadConfig() { readAsIni(config_, "conf/table.conf"); @@ -316,6 +323,31 @@ void TableEngine::reloadDict() { ime_->reloadAllDict(); } +void TableEngine::preload() { + if (!instance_->globalConfig().preloadInputMethod()) { + return; + } + + auto &imManager = instance_->inputMethodManager(); + const auto &group = imManager.currentGroup(); + + // Preload first input method. + if (!group.inputMethodList().empty()) { + if (const auto *entry = + imManager.entry(group.inputMethodList()[0].name()); + entry && entry->addon() == "table") { + ime_->requestDict(entry->uniqueName()); + } + } + // Preload default input method. + if (!group.defaultInputMethod().empty()) { + if (const auto *entry = imManager.entry(group.defaultInputMethod()); + entry && entry->addon() == "table") { + ime_->requestDict(entry->uniqueName()); + } + } +} + } // namespace fcitx FCITX_ADDON_FACTORY(fcitx::TableEngineFactory) diff --git a/im/table/engine.h b/im/table/engine.h index 0719dcceb1618ecf24caba5613dabbed2cafa505..3724f76f0bf75ad0203873fb5511526237c482e2 100644 --- a/im/table/engine.h +++ b/im/table/engine.h @@ -10,6 +10,7 @@ #include "ime.h" #include #include +#include #include #include #include @@ -124,6 +125,7 @@ private: void releaseStates(); void reloadDict(); + void preload(); Instance *instance_; std::unique_ptr ime_; @@ -137,6 +139,7 @@ private: libime::PinyinDictionary pinyinDict_; bool pinyinLoaded_ = false; std::unique_ptr pinyinLM_; + std::unique_ptr preloadEvent_; }; class TableEngineFactory : public AddonFactory { diff --git a/im/table/ime.cpp b/im/table/ime.cpp index 852e91a0e02596e2d7958c61dde4a80d6eb79cb6..7925ce6b899a096ceab4871c72c70ccdc9430eaf 100644 --- a/im/table/ime.cpp +++ b/im/table/ime.cpp @@ -5,12 +5,12 @@ * */ #include "ime.h" -#include "config.h" #include #include #include #include #include +#include #include #include #include @@ -25,7 +25,10 @@ FCITX_DEFINE_LOG_CATEGORY(table_logcategory, "table") namespace { struct BinaryOrTextDict { - bool operator()(const std::string &path, const std::string &, bool) const { + bool operator()(const std::string &path, const std::string &dir, + bool isUser) const { + FCITX_UNUSED(dir); + FCITX_UNUSED(isUser); return stringutils::endsWith(path, ".txt") || stringutils::endsWith(path, ".dict"); } @@ -64,7 +67,7 @@ void populateOptions(libime::TableBasedDictionary *dict, endKeys.insert(chr); } } - options.setEndKey(endKeys); + options.setEndKey(std::move(endKeys)); options.setExactMatch(*root.config->exactMatch); options.setLearning(*root.config->learning); options.setAutoPhraseLength(*root.config->autoPhraseLength); @@ -74,7 +77,7 @@ void populateOptions(libime::TableBasedDictionary *dict, options.setLanguageCode(*root.im->languageCode); options.setSortByCodeLength(*root.config->sortByCodeLength); - dict->setTableOptions(options); + dict->setTableOptions(std::move(options)); } } // namespace @@ -92,7 +95,7 @@ TableIME::requestDict(const std::string &name) { .first; auto &root = iter->second.root; - std::string filename = stringutils::joinPath( + const std::string filename = stringutils::joinPath( "inputmethod", stringutils::concat(name, ".conf")); auto files = StandardPath::global().openAll(StandardPath::Type::PkgData, filename, O_RDONLY); @@ -106,7 +109,7 @@ TableIME::requestDict(const std::string &name) { // So "Default" can be reset to current value. root.syncDefaultValueToCurrent(); - std::string customization = + const std::string customization = stringutils::joinPath("table", stringutils::concat(name, ".conf")); files = StandardPath::global().openAll(StandardPath::Type::PkgConfig, customization, O_RDONLY); diff --git a/im/table/ime.h b/im/table/ime.h index 64feae62efd15b1c46d1f8e278252f663f0efb97..d06a0a2389da1118ee3015c7807dd9be890f09b0 100644 --- a/im/table/ime.h +++ b/im/table/ime.h @@ -28,7 +28,7 @@ FCITX_CONFIG_ENUM_NAME_WITH_I18N(CandidateLayoutHint, N_("Not set"), struct NoSaveAnnotation { bool skipDescription() { return true; } bool skipSave() { return true; } - void dumpDescription(RawConfig &) const {} + void dumpDescription(RawConfig &config) const { FCITX_UNUSED(config); } }; template diff --git a/im/table/state.cpp b/im/table/state.cpp index 32f8350015010b5323fa1c0eacd5a8ad9fc19744..b955dfc5f33d6e2660587a43ad2b45ba2c272e82 100644 --- a/im/table/state.cpp +++ b/im/table/state.cpp @@ -30,9 +30,10 @@ class CommitAfterSelectWrapper { public: CommitAfterSelectWrapper(TableState *state) : state_(state) { if (auto *context = state->updateContext(nullptr)) { - commitFrom_ = context->selectedSize(); + commitFrom_ = static_cast(context->selectedSize()); } } + ~CommitAfterSelectWrapper() { if (commitFrom_ >= 0) { state_->commitAfterSelect(commitFrom_); @@ -61,7 +62,7 @@ public: return; } { - CommitAfterSelectWrapper commitAfterSelectRAII(state); + const CommitAfterSelectWrapper commitAfterSelectRAII(state); context->select(idx_); } if (context->selected()) { @@ -83,13 +84,12 @@ public: Text text; text.append(word_); if (utf8::lengthValidated(word_) == 1) { - auto code = dict.reverseLookup(word_); - if (!code.empty()) { + if (auto code = dict.reverseLookup(word_); !code.empty()) { text.append(" ~ "); if (customHint) { text.append(dict.hint(code)); } else { - text.append(code); + text.append(std::move(code)); } } } @@ -111,14 +111,14 @@ class TablePunctuationCandidateWord : public CandidateWord { public: TablePunctuationCandidateWord(TableState *state, std::string word, bool isHalf) - : CandidateWord(), state_(state), word_(std::move(word)) { + : state_(state), word_(std::move(word)) { Text text; if (isHalf) { text.append(fmt::format(_("{0} (Half)"), word_)); } else { text.append(word_); } - setText(text); + setText(std::move(text)); } void select(InputContext *inputContext) const override { @@ -287,7 +287,7 @@ TableState::predictCandidateList(const std::vector &words) { } candidateList->setSelectionKey(*context_->config().selection); candidateList->setPageSize(*context_->config().pageSize); - if (candidateList->size()) { + if (!candidateList->empty()) { candidateList->setGlobalCursorIndex(0); } return candidateList; @@ -323,7 +323,7 @@ void TableState::predict() { if (predictWord.empty()) { return; } - std::vector predictWords = {predictWord}; + const std::vector predictWords{std::move(predictWord)}; auto words = context_->prediction()->predict( predictWords, *engine_->config().predictionSize); if (auto candidateList = predictCandidateList(words)) { @@ -344,9 +344,9 @@ bool TableState::isContextEmpty() const { return context_->empty(); } -bool TableState::autoSelectCandidate() { +bool TableState::autoSelectCandidate() const { auto candidateList = ic_->inputPanel().candidateList(); - if (candidateList && candidateList->size()) { + if (candidateList && !candidateList->empty()) { int idx = candidateList->cursorIndex(); if (idx < 0) { idx = 0; @@ -369,7 +369,7 @@ bool TableState::handleCandidateList(const TableConfig &config, return false; } - int idx = event.key().keyListIndex(*config.selection); + const int idx = event.key().keyListIndex(*config.selection); if (idx >= 0) { event.filterAndAccept(); if (idx < candidateList->size()) { @@ -529,7 +529,7 @@ bool TableState::handlePinyinMode(KeyEvent &event) { *config.displayCustomHint); } - if (candidateList->size()) { + if (!candidateList->empty()) { candidateList->setGlobalCursorIndex(0); inputPanel.setCandidateList(std::move(candidateList)); } @@ -560,7 +560,7 @@ bool TableState::handlePinyinMode(KeyEvent &event) { bool TableState::handleForgetWord(KeyEvent &event) { auto *inputContext = event.inputContext(); auto candidateList = inputContext->inputPanel().candidateList(); - if (!candidateList || candidateList->size() == 0 || + if (!candidateList || candidateList->empty() || !dynamic_cast( &candidateList->candidate(0))) { return false; @@ -632,7 +632,7 @@ bool TableState::handleLookupPinyinOrModifyDictionaryMode(KeyEvent &event) { if (event.key().check(FcitxKey_Left) || event.key().check(FcitxKey_KP_Left)) { needUpdate = true; - if (lookupPinyinString_.size() != 0) { + if (!lookupPinyinString_.empty()) { lookupPinyinIndex_ += 1; if (lookupPinyinIndex_ >= lookupPinyinString_.size()) { lookupPinyinIndex_ = lookupPinyinString_.size() - 1; @@ -641,7 +641,7 @@ bool TableState::handleLookupPinyinOrModifyDictionaryMode(KeyEvent &event) { } else if (event.key().check(FcitxKey_Right) || event.key().check(FcitxKey_KP_Right)) { needUpdate = true; - if (lookupPinyinString_.size() != 0) { + if (!lookupPinyinString_.empty()) { if (lookupPinyinIndex_ >= lookupPinyinString_.size()) { lookupPinyinIndex_ = lookupPinyinString_.size() - 1; } else if (lookupPinyinIndex_ > 0) { @@ -681,7 +681,8 @@ bool TableState::handleLookupPinyinOrModifyDictionaryMode(KeyEvent &event) { libime::PhraseFlag::User); reset(); return true; - } else if (wordFlag == libime::PhraseFlag::Auto) { + } + if (wordFlag == libime::PhraseFlag::Auto) { context_->mutableDict().removeWord(result, subString.first); context_->mutableDict().insert(result, subString.first, libime::PhraseFlag::User); @@ -747,7 +748,7 @@ bool TableState::handleLookupPinyinOrModifyDictionaryMode(KeyEvent &event) { } std::vector sp; - if (auto *reverseShuangPinTable = + if (const auto *reverseShuangPinTable = engine_->reverseShuangPinTable()) { const auto normalizedFullPinyin = stringutils::replaceAll(fullPinyin, "ü", "v"); @@ -768,7 +769,7 @@ bool TableState::handleLookupPinyinOrModifyDictionaryMode(KeyEvent &event) { stringutils::join(sp, " "))); } } - inputPanel.setAuxDown(Text(text)); + inputPanel.setAuxDown(Text(std::move(text))); } else { inputPanel.setAuxDown(Text(_("Could not find pinyin."))); } @@ -822,7 +823,8 @@ bool TableState::handleLookupPinyinOrModifyDictionaryMode(KeyEvent &event) { void TableState::forgetCandidateWord(size_t idx) { mode_ = TableMode::Normal; - auto oldCode = context_->currentCode(); + // Make a copy of old code since it will be cleared later. + const std::string oldCode = context_->currentCode(); auto code = TableContext::code(context_->candidates()[idx]); if (!code.empty()) { auto word = context_->candidates()[idx].toString(); @@ -834,7 +836,7 @@ void TableState::forgetCandidateWord(size_t idx) { } context_->clear(); { - CommitAfterSelectWrapper commitAfterSelectRAII(this); + const CommitAfterSelectWrapper commitAfterSelectRAII(this); context_->type(oldCode); } @@ -844,7 +846,7 @@ void TableState::forgetCandidateWord(size_t idx) { void TableState::keyEvent(const InputMethodEntry &entry, KeyEvent &event) { bool needUpdate = false; auto *inputContext = event.inputContext(); - bool lastIsPunc = lastIsPunc_; + const bool lastIsPunc = lastIsPunc_; auto *context = updateContext(&entry); if (!context) { return; @@ -952,10 +954,10 @@ void TableState::keyEvent(const InputMethodEntry &entry, KeyEvent &event) { (!event.key().isKeyPad() || *config.keypadAsInput)) { auto candidateList = ic_->inputPanel().candidateList(); auto autoSelectHint = 0; - if (candidateList && candidateList->size()) { - int idx = candidateList->cursorIndex(); + if (candidateList && !candidateList->empty()) { + const int idx = candidateList->cursorIndex(); if (idx >= 0) { - auto cand = dynamic_cast( + const auto *cand = dynamic_cast( &candidateList->candidate(idx)); if (cand) { autoSelectHint = cand->idx_; @@ -964,7 +966,7 @@ void TableState::keyEvent(const InputMethodEntry &entry, KeyEvent &event) { } context->setAutoSelectIndex(autoSelectHint); { - CommitAfterSelectWrapper commitAfterSelectRAII(this); + const CommitAfterSelectWrapper commitAfterSelectRAII(this); context->type(str); } if (!context->dict().hasMatchingWords(context->currentCode()) && @@ -994,8 +996,8 @@ void TableState::keyEvent(const InputMethodEntry &entry, KeyEvent &event) { } else if (event.key().check(FcitxKey_Tab) || event.key().check(FcitxKey_KP_Tab)) { { - CommitAfterSelectWrapper commitAfterSelectRAII(this); - autoSelectCandidate(); + const CommitAfterSelectWrapper commitAfterSelectRAII(this); + (void)autoSelectCandidate(); } event.filterAndAccept(); if (context->selected()) { @@ -1062,16 +1064,16 @@ void TableState::keyEvent(const InputMethodEntry &entry, KeyEvent &event) { } } } else if (event.key().check(FcitxKey_BackSpace) && lastIsPunc) { - auto puncStr = + const std::string &puncStr = engine_->punctuation()->call( entry.languageCode(), inputContext); if (!puncStr.empty()) { // forward the original key is the best choice. - auto ref = inputContext->watch(); cancelLastEvent_ = engine_->instance()->eventLoop().addTimeEvent( CLOCK_MONOTONIC, now(CLOCK_MONOTONIC) + 300, 0, - [this, ref, puncStr](EventSourceTime *, uint64_t) { + [this, ref = inputContext->watch(), + puncStr = puncStr](EventSourceTime *, uint64_t) { if (auto *inputContext = ref.get()) { inputContext->commitString(puncStr); } @@ -1119,7 +1121,8 @@ void TableState::keyEvent(const InputMethodEntry &entry, KeyEvent &event) { commitBuffer(true); needUpdate = true; } - std::string punc, puncAfter; + std::string punc; + std::string puncAfter; if (!*context->config().ignorePunc && !event.key().isKeyPad()) { auto candidates = engine_->punctuation() @@ -1158,7 +1161,7 @@ void TableState::keyEvent(const InputMethodEntry &entry, KeyEvent &event) { auto paired = punc + puncAfter; if (inputContext->capabilityFlags().test( CapabilityFlag::CommitStringWithCursor)) { - if (size_t length = utf8::lengthValidated(punc); + if (const size_t length = utf8::lengthValidated(punc); length != 0 && length != utf8::INVALID_LENGTH) { inputContext->commitStringWithCursor(paired, length); } else { @@ -1166,7 +1169,7 @@ void TableState::keyEvent(const InputMethodEntry &entry, KeyEvent &event) { } } else { inputContext->commitString(paired); - if (size_t length = utf8::lengthValidated(puncAfter); + if (const size_t length = utf8::lengthValidated(puncAfter); length != 0 && length != utf8::INVALID_LENGTH) { for (size_t i = 0; i < length; i++) { inputContext->forwardKey(Key(FcitxKey_Left)); @@ -1175,7 +1178,7 @@ void TableState::keyEvent(const InputMethodEntry &entry, KeyEvent &event) { } } lastIsPunc_ = true; - } while (0); + } while (false); if ((event.filtered() && event.accepted()) || needUpdate) { updateUI(/*keepOldCursor=*/false, /*maybePredict=*/maybePredict); @@ -1199,8 +1202,8 @@ bool TableState::handle2nd3rdCandidate(const TableConfig &config, {*config.thirdCandidate, 2}, }; - int keyReleased = keyReleased_; - int keyReleasedIndex = keyReleasedIndex_; + const int keyReleased = keyReleased_; + const int keyReleasedIndex = keyReleasedIndex_; // Keep these two values, and reset them in the state keyReleased_ = -1; keyReleasedIndex_ = -2; @@ -1269,8 +1272,8 @@ bool TableState::handlePuncCandidate(const TableConfig &config, } if (!event.isVirtual()) { - int idx = event.key().keyListIndex(config.selection.value()); - if (idx >= 0) { + if (const int idx = event.key().keyListIndex(config.selection.value()); + idx >= 0) { event.filterAndAccept(); if (idx < candidateList->size()) { candidateList->candidate(idx).select(inputContext); @@ -1338,8 +1341,8 @@ void TableState::commitBuffer(bool commitCode, bool noRealCommit) { } // If commitAfterSelect && !useContextBasedOrder, learnLast will be used. if (!ic_->capabilityFlags().testAny(CapabilityFlag::PasswordOrSensitive) && - !(*context->config().commitAfterSelect && - !*context->config().useContextBasedOrder)) { + (!*context->config().commitAfterSelect || + *context->config().useContextBasedOrder)) { context->learn(); } context->clear(); @@ -1355,7 +1358,7 @@ void TableState::commitAfterSelect(int commitFrom) { if (!*config.commitAfterSelect) { return; } - std::string sentence = + const std::string sentence = commitSegements(commitFrom, context_->selectedSize()); if (sentence.empty()) { return; @@ -1370,11 +1373,10 @@ void TableState::commitAfterSelect(int commitFrom) { } void TableState::updateUI(bool keepOldCursor, bool maybePredict) { - int cursor = 0; if (keepOldCursor) { if (auto candidateList = ic_->inputPanel().candidateList()) { - if (auto commonCandidateList = + if (auto *commonCandidateList = dynamic_cast(candidateList.get())) { cursor = commonCandidateList->globalCursorIndex(); } @@ -1404,9 +1406,8 @@ void TableState::updateUI(bool keepOldCursor, bool maybePredict) { candidateList->setPageSize(*config.pageSize); for (const auto &candidate : candidates) { - auto candidateString = candidate.toString(); Text text; - text.append(candidateString); + text.append(candidate.toString()); std::string hint; if (*config.hint) { hint = @@ -1414,7 +1415,7 @@ void TableState::updateUI(bool keepOldCursor, bool maybePredict) { } if (!hint.empty()) { text.append(*config.hintSeparator); - text.append(hint); + text.append(std::move(hint)); } if (!config.markerForAutoPhrase->empty() && TableContext::isAuto(candidate.sentence())) { @@ -1424,7 +1425,7 @@ void TableState::updateUI(bool keepOldCursor, bool maybePredict) { std::move(text), idx); idx++; } - if (candidateList->size()) { + if (!candidateList->empty()) { auto page = cursor / *config.pageSize; if (page >= candidateList->totalPages()) { page = candidateList->totalPages() - 1; @@ -1447,7 +1448,7 @@ void TableState::updateUI(bool keepOldCursor, bool maybePredict) { inputPanel.setPreedit( context->preeditText(/*hint=*/true, /*clientPreedit=*/false)); } else { - Text preeditText = + const Text preeditText = context->preeditText(/*hint=*/false, useClientPreedit); if (useClientPreedit) { inputPanel.setClientPreedit(preeditText); @@ -1498,9 +1499,9 @@ void TableState::updatePuncPreedit(InputContext *inputContext) { if (candidateList->cursorIndex() >= 0) { Text preedit; - auto &candidate = + const auto &candidate = candidateList->candidate(candidateList->cursorIndex()); - if (auto *puncCandidate = + if (const auto *puncCandidate = dynamic_cast( &candidate)) { preedit.append(puncCandidate->word()); diff --git a/im/table/state.h b/im/table/state.h index b6dd72abfaff76e044af83b258e45f002b03e93d..86e1e4dac3b5206f80a2529ce58b448b34a74fd5 100644 --- a/im/table/state.h +++ b/im/table/state.h @@ -77,7 +77,7 @@ private: bool handleLookupPinyinOrModifyDictionaryMode(KeyEvent &event); bool isContextEmpty() const; - bool autoSelectCandidate(); + bool autoSelectCandidate() const; std::unique_ptr predictCandidateList(const std::vector &words); std::string commitSegements(size_t from, size_t to); diff --git a/modules/cloudpinyin/cloudpinyin.cpp b/modules/cloudpinyin/cloudpinyin.cpp index 6d2481c6e66571278c6b514fc0d814de5b37f475..4a2e04b34f6d582a69a77681af64778f96418d51 100644 --- a/modules/cloudpinyin/cloudpinyin.cpp +++ b/modules/cloudpinyin/cloudpinyin.cpp @@ -23,27 +23,33 @@ FCITX_DEFINE_LOG_CATEGORY(cloudpinyin, "cloudpinyin"); #define CLOUDPINYIN_DEBUG() FCITX_LOGC(cloudpinyin, Debug) +namespace { + class GoogleBackend : public Backend { public: - GoogleBackend(const std::string &url) : url_(url) {} + GoogleBackend(std::string url) : url_(std::move(url)) {} - void prepareRequest(CurlQueue *queue, const std::string &pinyin) override { - UniqueCPtr escaped( - curl_escape(pinyin.c_str(), pinyin.size())); - std::string url = url_; - url += escaped.get(); + bool prepareRequest(CurlQueue *queue, const std::string &pinyin) override { + const UniqueCPtr escaped( + curl_escape(pinyin.c_str(), static_cast(pinyin.size()))); + if (!escaped) { + return false; + } + const std::string url = stringutils::concat(url_, escaped.get()); CLOUDPINYIN_DEBUG() << "Request URL: " << url; - curl_easy_setopt(queue->curl(), CURLOPT_URL, url.c_str()); + return (curl_easy_setopt(queue->curl(), CURLOPT_URL, url.c_str()) == + CURLE_OK); } std::string parseResult(CurlQueue *queue) override { - std::string result(queue->result().begin(), queue->result().end()); + const std::string_view result(queue->result().data(), + queue->result().size()); CLOUDPINYIN_DEBUG() << "Request result: " << result; auto start = result.find("\",[\""); std::string hanzi; - if (start != std::string::npos) { + if (start != std::string_view::npos) { start += strlen("\",[\""); auto end = result.find('\"', start); - if (end != std::string::npos && end > start) { + if (end != std::string_view::npos && end > start) { hanzi = result.substr(start, end - start); } } @@ -56,17 +62,22 @@ private: class BaiduBackend : public Backend { public: - void prepareRequest(CurlQueue *queue, const std::string &pinyin) override { - std::string url = "https://olime.baidu.com/py?rn=0&pn=1&ol=1&py="; - std::unique_ptr escaped( - curl_escape(pinyin.c_str(), pinyin.size()), &curl_free); - url += escaped.get(); + bool prepareRequest(CurlQueue *queue, const std::string &pinyin) override { + const UniqueCPtr escaped( + curl_escape(pinyin.c_str(), static_cast(pinyin.size()))); + if (!escaped) { + return false; + } + const std::string url = stringutils::concat( + "https://olime.baidu.com/py?rn=0&pn=1&ol=1&py=", escaped.get()); CLOUDPINYIN_DEBUG() << "Request URL: " << url; - curl_easy_setopt(queue->curl(), CURLOPT_URL, url.c_str()); + return (curl_easy_setopt(queue->curl(), CURLOPT_URL, url.c_str()) == + CURLE_OK); } std::string parseResult(CurlQueue *queue) override { - std::string result(queue->result().begin(), queue->result().end()); + const std::string_view result(queue->result().data(), + queue->result().size()); CLOUDPINYIN_DEBUG() << "Request result: " << result; auto start = result.find("[[\""); std::string hanzi; @@ -82,7 +93,9 @@ public: }; constexpr int MAX_ERROR = 10; -constexpr int minInUs = 60000000; +constexpr uint64_t minInUs = 60000000; + +} // namespace CloudPinyin::CloudPinyin(fcitx::AddonManager *manager) : eventLoop_(manager->eventLoop()) { @@ -138,16 +151,18 @@ void CloudPinyin::request(const std::string &pinyin, auto *b = iter->second.get(); if (!thread_->addRequest([proxy = *config_.proxy, b, &pinyin, &callback](CurlQueue *queue) { - b->prepareRequest(queue, pinyin); - if (proxy.empty()) { - curl_easy_setopt(queue->curl(), CURLOPT_PROXY, nullptr); - } else { - curl_easy_setopt(queue->curl(), CURLOPT_PROXY, - proxy.data()); + if (!b->prepareRequest(queue, pinyin)) { + return false; + } + if (curl_easy_setopt( + queue->curl(), CURLOPT_PROXY, + (proxy.empty() ? nullptr : proxy.data())) != CURLE_OK) { + return false; } queue->setPinyin(pinyin); queue->setBusy(); queue->setCallback(callback); + return true; })) { callback(pinyin, ""); }; diff --git a/modules/cloudpinyin/cloudpinyin.h b/modules/cloudpinyin/cloudpinyin.h index 2a3fe232bc23bcbc01372b316191f0a1f0b3d6b3..7a13955776fa81efa4568d23a28b3433aaef6b78 100644 --- a/modules/cloudpinyin/cloudpinyin.h +++ b/modules/cloudpinyin/cloudpinyin.h @@ -45,8 +45,8 @@ FCITX_CONFIGURATION( class Backend { public: - virtual void prepareRequest(CurlQueue *queue, - const std::string &pinyin) = 0; + FCITX_NODISCARD virtual bool prepareRequest(CurlQueue *queue, + const std::string &pinyin) = 0; virtual std::string parseResult(CurlQueue *queue) = 0; virtual ~Backend() = default; }; @@ -54,7 +54,7 @@ public: class CloudPinyin : public fcitx::AddonInstance { public: CloudPinyin(fcitx::AddonManager *manager); - ~CloudPinyin(); + ~CloudPinyin() override; void reloadConfig() override; const fcitx::Configuration *getConfig() const override { return &config_; } diff --git a/modules/cloudpinyin/cloudpinyin_public.h b/modules/cloudpinyin/cloudpinyin_public.h index 6e5c8f9c76300eec234691347a6aa2a3b7b91691..4a307b63adac6998133aaf06468b0d753747f246 100644 --- a/modules/cloudpinyin/cloudpinyin_public.h +++ b/modules/cloudpinyin/cloudpinyin_public.h @@ -17,13 +17,12 @@ #include #include -typedef std::function - CloudPinyinCallback; +using CloudPinyinCallback = + std::function; -typedef std::function - CloudPinyinSelectedCallback; +using CloudPinyinSelectedCallback = + std::function; FCITX_ADDON_DECLARE_FUNCTION(CloudPinyin, request, void(const std::string &pinyin, @@ -37,17 +36,18 @@ class CloudPinyinCandidateWord public: CloudPinyinCandidateWord(fcitx::AddonInstance *cloudpinyin_, const std::string &pinyin, - const std::string &selectedSentence, bool keep, + std::string selectedSentence, bool keep, fcitx::InputContext *inputContext, CloudPinyinSelectedCallback callback) - : CandidateWord(fcitx::Text{}), selectedSentence_(selectedSentence), + : CandidateWord(fcitx::Text{}), + selectedSentence_(std::move(selectedSentence)), inputContext_(inputContext), callback_(std::move(callback)), keep_(keep) { // use cloud unicode char setText(fcitx::Text("\xe2\x98\x81")); - auto ref = watch(); cloudpinyin_->call( - pinyin, [ref](const std::string &pinyin, const std::string &hanzi) { + pinyin, [ref = watch()](const std::string &pinyin, + const std::string &hanzi) { FCITX_UNUSED(pinyin); auto *self = ref.get(); if (self) { @@ -114,7 +114,7 @@ private: if (idx == 0) { if (dupIndex) { modifiable->remove(0); - modifiable->move(dupIndex.value() - 1, 0); + modifiable->move(*dupIndex - 1, 0); } else { // result is empty. // Remove empty. diff --git a/modules/cloudpinyin/fetch.cpp b/modules/cloudpinyin/fetch.cpp index c006f5c2145f83a70c00bdafcec1da73396fa043..cc797f679b74ec534075acc38aedc099232a8043 100644 --- a/modules/cloudpinyin/fetch.cpp +++ b/modules/cloudpinyin/fetch.cpp @@ -52,9 +52,11 @@ FetchThread::~FetchThread() { } void FetchThread::runThread(FetchThread *self) { self->run(); } -int FetchThread::curlCallback(CURL *, curl_socket_t s, int action, void *userp, - void *) { - FetchThread *self = static_cast(userp); +int FetchThread::curlCallback(CURL *curl, curl_socket_t s, int action, + void *userp, void *socketp) { + FCITX_UNUSED(curl); + FCITX_UNUSED(socketp); + auto *self = static_cast(userp); self->curl(s, action); return 0; @@ -84,14 +86,13 @@ void FetchThread::processMessages() { int num_messages = 0; CURLMsg *curl_message = curl_multi_info_read(curlm_, &num_messages); - while (curl_message != NULL) { + while (curl_message != nullptr) { if (curl_message->msg == CURLMSG_DONE) { - int curl_result = curl_message->data.result; void *p = nullptr; curl_easy_getinfo(curl_message->easy_handle, CURLINFO_PRIVATE, &p); auto *queue = static_cast(p); curl_multi_remove_handle(curlm_, queue->curl()); - queue->finish(curl_result); + queue->finish(curl_message->data.result); queue->remove(); finished(queue); } @@ -136,7 +137,8 @@ void FetchThread::curl(curl_socket_t s, int action) { } } -int FetchThread::curlTimerCallback(CURLM *, long timeout_ms, void *user) { +int FetchThread::curlTimerCallback(CURLM *multi, long timeout_ms, void *user) { + FCITX_UNUSED(multi); auto *self = static_cast(user); self->curlTimer(timeout_ms); return 0; @@ -168,7 +170,7 @@ void FetchThread::curlTimer(long timeout_ms) { void FetchThread::finished(CurlQueue *queue) { { - std::lock_guard lock(finishQueueLock); + const std::lock_guard lock(finishQueueLock); finishingQueue.push_back(*queue); } cloudPinyin_->notifyFinished(); @@ -188,13 +190,13 @@ bool FetchThread::addRequest(const SetupRequestCallback &callback) { callback(queue); { - std::lock_guard lock(pendingQueueLock); + const std::lock_guard lock(pendingQueueLock); pendingQueue.push_back(*queue); } // Handle pending queue in fetch thread. dispatcher_.schedule([this]() { - std::lock_guard lock(pendingQueueLock); + const std::lock_guard lock(pendingQueueLock); while (!pendingQueue.empty()) { auto *queue = &pendingQueue.front(); @@ -214,7 +216,7 @@ void FetchThread::exit() { } CurlQueue *FetchThread::popFinished() { - std::lock_guard lock(finishQueueLock); + const std::lock_guard lock(finishQueueLock); CurlQueue *result = nullptr; if (!finishingQueue.empty()) { result = &finishingQueue.front(); @@ -224,7 +226,7 @@ CurlQueue *FetchThread::popFinished() { } void FetchThread::run() { - loop_.reset(new fcitx::EventLoop); + loop_ = std::make_unique(); dispatcher_.attach(loop_.get()); loop_->exec(); diff --git a/modules/cloudpinyin/fetch.h b/modules/cloudpinyin/fetch.h index fc33207f71ed5bdaf011ebe4fe3aff23ba84b53a..fc2e6b02b6bcf6a5cc342a531bc9c27107e2c028 100644 --- a/modules/cloudpinyin/fetch.h +++ b/modules/cloudpinyin/fetch.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -25,35 +26,41 @@ class CloudPinyin; class CurlQueue : public fcitx::IntrusiveListNode { public: - CurlQueue(bool keep = true) : keep_(keep), curl_(curl_easy_init()) { - curl_easy_setopt(curl_, CURLOPT_PRIVATE, this); - curl_easy_setopt(curl_, CURLOPT_WRITEDATA, this); - curl_easy_setopt(curl_, CURLOPT_WRITEFUNCTION, - &CurlQueue::curlWriteFunction); - curl_easy_setopt(curl_, CURLOPT_TIMEOUT, 10l); - curl_easy_setopt(curl_, CURLOPT_NOSIGNAL, 1); + CurlQueue() : curl_(curl_easy_init()) { + if (!curl_) { + throw std::runtime_error("Failed to init CURL handle."); + } + + // These options should be pretty safe to set, throw exception + // to de-init cloudpinyin. + const bool result = + (curl_easy_setopt(curl_, CURLOPT_PRIVATE, this) == CURLE_OK) && + (curl_easy_setopt(curl_, CURLOPT_WRITEDATA, this) == CURLE_OK) && + (curl_easy_setopt(curl_, CURLOPT_WRITEFUNCTION, + &CurlQueue::curlWriteFunction) == CURLE_OK) && + (curl_easy_setopt(curl_, CURLOPT_TIMEOUT, 10L) == CURLE_OK) && + (curl_easy_setopt(curl_, CURLOPT_NOSIGNAL, 1L) == CURLE_OK); + if (!result) { + throw std::runtime_error("Failed setup CURL handle options."); + } } - ~CurlQueue() { curl_easy_cleanup(curl_); } + ~CurlQueue() override { curl_easy_cleanup(curl_); } void release() { busy_ = false; - if (!keep_) { - delete this; - } else { - data_.clear(); - pinyin_.clear(); - // make sure lambda is free'd - callback_ = CloudPinyinCallback(); - httpCode_ = 0; - } + data_.clear(); + pinyin_.clear(); + // make sure lambda is free'd + callback_ = CloudPinyinCallback(); + httpCode_ = 0; } const auto &pinyin() const { return pinyin_; } - void setPinyin(const std::string &pinyin) { pinyin_ = pinyin; } + void setPinyin(std::string pinyin) { pinyin_ = std::move(pinyin); } auto curl() { return curl_; } - void finish(int result) { + void finish(CURLcode result) { curlResult_ = result; curl_easy_getinfo(curl_, CURLINFO_RESPONSE_CODE, &httpCode_); } @@ -68,7 +75,7 @@ public: callback_ = std::move(callback); } - int httpCode() const { return httpCode_; } + auto httpCode() const { return httpCode_; } private: static size_t curlWriteFunction(char *ptr, size_t size, size_t nmemb, @@ -105,17 +112,16 @@ private: return realsize; } - bool keep_ = true; bool busy_ = false; CURL *curl_ = nullptr; - int curlResult_ = 0; + CURLcode curlResult_ = CURLE_OK; long httpCode_ = 0; std::vector data_; std::string pinyin_; CloudPinyinCallback callback_; }; -typedef std::function SetupRequestCallback; +using SetupRequestCallback = std::function; class FetchThread { public: diff --git a/modules/cloudpinyin/lrucache.h b/modules/cloudpinyin/lrucache.h index 3d79d1d56fad2f7b4f2d161dc3dc043bf571a7df..a0a6e2eaa5557ed3ec4938389b55cabd42fee879 100644 --- a/modules/cloudpinyin/lrucache.h +++ b/modules/cloudpinyin/lrucache.h @@ -12,13 +12,10 @@ template class LRUCache { - typedef K key_type; - typedef V value_type; - typedef std::unordered_map::iterator>> - dict_type; - dict_type dict_; - std::list order_; - size_t sz_; + using key_type = K; + using value_type = V; + using dict_type = + std::unordered_map::iterator>>; public: LRUCache(size_t sz = 80) : sz_(sz) {} @@ -94,6 +91,9 @@ private: } return &i->second.first; } + dict_type dict_; + std::list order_; + size_t sz_; }; #endif // _FCITX_LIBIME_LRU_H_ diff --git a/org.fcitx.Fcitx5.Addon.ChineseAddons.metainfo.xml.in b/org.fcitx.Fcitx5.Addon.ChineseAddons.metainfo.xml.in index aab40fe5af2b930a92b7a12dab1f3a8f2af02b58..b54554f42afab0166c9434253fc7c8452723c8a1 100644 --- a/org.fcitx.Fcitx5.Addon.ChineseAddons.metainfo.xml.in +++ b/org.fcitx.Fcitx5.Addon.ChineseAddons.metainfo.xml.in @@ -10,6 +10,7 @@ https://github.com/fcitx/fcitx5-chinese-addons/issues Fcitx + diff --git a/po/he.po b/po/he.po index 17ac6331f397cd5cd81b001428e0925eb69af4e8..972b227e3617a890a1c57dbbff63d193f8513773 100644 --- a/po/he.po +++ b/po/he.po @@ -9,7 +9,7 @@ msgid "" msgstr "" "Project-Id-Version: fcitx5-chinese-addons\n" "Report-Msgid-Bugs-To: fcitx-dev@googlegroups.com\n" -"POT-Creation-Date: 2023-12-02 20:24+0000\n" +"POT-Creation-Date: 2024-02-20 20:24+0000\n" "PO-Revision-Date: 2017-11-23 04:30+0000\n" "Last-Translator: 63f334ffc0709ba0fc2361b80bf3c0f0_00ffd1e " ", 2021\n" @@ -18,14 +18,14 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n == 2 && n % " +"Plural-Forms: nplurals=3; plural=(n == 1 && n % 1 == 0) ? 0 : (n == 2 && n % " "1 == 0) ? 1: (n % 10 == 0 && n % 1 == 0 && n > 10) ? 2 : 3;\n" -#: im/table/state.cpp:1148 +#: im/table/state.cpp:1151 msgid " Return for " msgstr "" -#: im/table/state.cpp:1145 +#: im/table/state.cpp:1148 msgid " for " msgstr "" @@ -103,12 +103,12 @@ msgstr "" msgid "&Usage" msgstr "" -#: im/table/state.cpp:746 +#: im/table/state.cpp:747 msgctxt "Pinyin lookup delimeter" msgid ", " msgstr "" -#: im/table/engine.h:41 im/pinyin/pinyin.h:71 +#: im/table/engine.h:42 im/pinyin/pinyin.h:71 msgid "ABC" msgstr "א״ב" @@ -281,7 +281,7 @@ msgstr "" msgid "Converter crashed." msgstr "" -#: im/table/state.cpp:773 +#: im/table/state.cpp:774 msgid "Could not find pinyin." msgstr "" @@ -299,7 +299,7 @@ msgstr "" msgid "Creating temp file failed. Please check the permission or disk space." msgstr "" -#: im/table/engine.h:43 im/pinyin/pinyin.h:73 +#: im/table/engine.h:44 im/pinyin/pinyin.h:73 msgid "Custom" msgstr "" @@ -328,7 +328,7 @@ msgstr "" msgid "Display Hint for word" msgstr "" -#: im/table/engine.h:64 +#: im/table/engine.h:65 msgid "Display Shuangpin when looking up pinyin" msgstr "" @@ -336,7 +336,7 @@ msgstr "" msgid "Display custom hint" msgstr "" -#: im/table/engine.h:40 +#: im/table/engine.h:41 msgid "Do not display" msgstr "" @@ -393,7 +393,7 @@ msgstr "" msgid "Enable Emoji" msgstr "" -#: im/table/engine.h:67 im/pinyin/pinyin.h:147 +#: im/table/engine.h:68 im/pinyin/pinyin.h:147 msgid "Enable Prediction" msgstr "" @@ -478,7 +478,7 @@ msgstr "" msgid "Fix embedded preedit cursor at the beginning of the preedit" msgstr "" -#: im/table/engine.h:53 im/pinyin/pinyin.h:158 +#: im/table/engine.h:54 im/pinyin/pinyin.h:158 msgid "Forget word" msgstr "" @@ -628,11 +628,11 @@ msgstr "" msgid "Length limit of selecting the only candidate" msgstr "" -#: im/table/engine.h:58 +#: im/table/engine.h:59 msgid "Look up pinyin" msgstr "" -#: im/table/engine.h:40 im/pinyin/pinyin.h:70 +#: im/table/engine.h:41 im/pinyin/pinyin.h:70 msgid "MS" msgstr "" @@ -664,7 +664,7 @@ msgstr "" msgid "Minimum Pinyin Length" msgstr "" -#: im/table/engine.h:48 +#: im/table/engine.h:49 msgid "Modify dictionary" msgstr "" @@ -692,7 +692,7 @@ msgstr "לא" msgid "No browsing outside pinyin.sogou.com, now redirect to home page." msgstr "" -#: im/table/engine.cpp:209 +#: im/table/engine.cpp:216 msgid "Not available" msgstr "" @@ -751,25 +751,25 @@ msgstr "פיניין:" msgid "Pinyin dictionary manager" msgstr "" -#: im/table/engine.h:42 im/pinyin/pinyin.h:72 +#: im/table/engine.h:43 im/pinyin/pinyin.h:72 msgid "PinyinJiajia" msgstr "" -#: im/table/state.cpp:722 +#: im/table/state.cpp:723 msgid "Please use this functionality after typing some text." msgstr "" -#: im/table/engine.cpp:77 im/table/engine.cpp:85 im/pinyin/pinyin.cpp:1019 -#: im/pinyin/pinyin.cpp:1029 +#: im/table/engine.cpp:78 im/table/engine.cpp:86 im/pinyin/pinyin.cpp:1018 +#: im/pinyin/pinyin.cpp:1028 msgid "Prediction Disabled" msgstr "" -#: im/table/engine.cpp:76 im/table/engine.cpp:84 im/pinyin/pinyin.cpp:1018 -#: im/pinyin/pinyin.cpp:1028 +#: im/table/engine.cpp:77 im/table/engine.cpp:85 im/pinyin/pinyin.cpp:1017 +#: im/pinyin/pinyin.cpp:1027 msgid "Prediction Enabled" msgstr "" -#: im/table/engine.h:70 im/pinyin/pinyin.h:150 +#: im/table/engine.h:71 im/pinyin/pinyin.h:150 msgid "Prediction Size" msgstr "" @@ -781,24 +781,24 @@ msgstr "" msgid "Prefix key to trigger Pinyin" msgstr "" -#: im/table/state.cpp:792 +#: im/table/state.cpp:793 msgid "Press Backspace to forget." msgstr "" -#: im/table/state.cpp:795 +#: im/table/state.cpp:796 msgid "Press Delete to remove." msgstr "" -#: im/table/state.cpp:789 +#: im/table/state.cpp:790 msgid "Press space or enter to insert." msgstr "" -#: im/pinyin/pinyin.cpp:1931 +#: im/pinyin/pinyin.cpp:1933 #, c++-format msgid "Press {} for {}" msgstr "" -#: im/pinyin/pinyin.cpp:1928 +#: im/pinyin/pinyin.cpp:1930 #, c++-format msgid "Press {} for {} and Return for {}" msgstr "" @@ -884,7 +884,7 @@ msgstr "" msgid "Select Third Candidate" msgstr "" -#: im/table/state.cpp:1461 +#: im/table/state.cpp:1462 msgid "Select candidate to be removed from history:" msgstr "" @@ -912,7 +912,7 @@ msgstr "" msgid "Show current shuangpin mode" msgstr "" -#: im/table/engine.cpp:78 im/pinyin/pinyin.cpp:1020 +#: im/table/engine.cpp:79 im/pinyin/pinyin.cpp:1019 msgid "Show prediction words" msgstr "" @@ -1030,11 +1030,11 @@ msgstr "" msgid "Use Keypad as Selection key" msgstr "" -#: im/table/state.cpp:728 +#: im/table/state.cpp:729 msgid "Use Left and Right to select character: " msgstr "" -#: im/table/state.cpp:776 +#: im/table/state.cpp:777 msgid "Use Left and Right to select text. " msgstr "" @@ -1121,7 +1121,7 @@ msgstr "" msgid "Wubi Pinyin" msgstr "" -#: im/table/engine.h:43 im/pinyin/pinyin.h:73 +#: im/table/engine.h:44 im/pinyin/pinyin.h:73 msgid "Xiaohe" msgstr "" @@ -1129,15 +1129,15 @@ msgstr "" msgid "Yes" msgstr "" -#: im/table/engine.h:42 im/pinyin/pinyin.h:72 +#: im/table/engine.h:43 im/pinyin/pinyin.h:72 msgid "Zhongwenzhixing" msgstr "" -#: im/table/engine.h:41 im/pinyin/pinyin.h:71 +#: im/table/engine.h:42 im/pinyin/pinyin.h:71 msgid "Ziguang" msgstr "" -#: im/table/engine.h:40 im/pinyin/pinyin.h:70 im/table/zrm.conf.in.in:3 +#: im/table/engine.h:41 im/pinyin/pinyin.h:70 im/table/zrm.conf.in.in:3 msgid "Ziranma" msgstr "" @@ -1210,33 +1210,33 @@ msgstr "" msgid "z <-> zh" msgstr "" -#: im/table/state.cpp:117 im/pinyin/pinyin.cpp:224 +#: im/table/state.cpp:117 im/pinyin/pinyin.cpp:223 #, c++-format msgid "{0} (Half)" msgstr "" -#: im/pinyin/pinyin.cpp:183 modules/pinyinhelper/pinyinhelper.cpp:80 +#: im/pinyin/pinyin.cpp:182 modules/pinyinhelper/pinyinhelper.cpp:80 #, c++-format msgid "{0} ({1})" msgstr "" -#: im/table/state.cpp:767 +#: im/table/state.cpp:768 #, c++-format msgctxt "Pinyin & Shuangpin" msgid "{0} ({1})" msgstr "" -#: im/table/state.cpp:810 +#: im/table/state.cpp:811 #, c++-format msgid "{0} is not in table." msgstr "" -#: im/table/state.cpp:799 +#: im/table/state.cpp:800 #, c++-format msgid "{0}: No corresponding code." msgstr "" -#: im/table/state.cpp:783 im/table/state.cpp:807 +#: im/table/state.cpp:784 im/table/state.cpp:808 #, c++-format msgid "{0}: {1}" msgstr "" diff --git a/test/testchttrans.cpp b/test/testchttrans.cpp index ac08efe5a8d7e6309f9b24b8f14cd124850efee2..7be1704a6f036dfa40e6c36cbfbf7c7113611b4d 100644 --- a/test/testchttrans.cpp +++ b/test/testchttrans.cpp @@ -60,7 +60,7 @@ void scheduleEvent(EventDispatcher *dispatcher, Instance *instance) { inputmethodgroup.inputMethodList().emplace_back("sim"); inputmethodgroup.inputMethodList().emplace_back("trad"); inputmethodgroup.setDefaultInputMethod("sim"); - instance->inputMethodManager().setGroup(inputmethodgroup); + instance->inputMethodManager().setGroup(std::move(inputmethodgroup)); FCITX_INFO() << instance->inputMethodManager() .currentGroup() diff --git a/test/testcustomphrase.cpp b/test/testcustomphrase.cpp index dbcb0a467bd6281a441387fa2ead71714933fc7c..d1bf9d84cb0cfc7ab95e49fe71d139f2ebc57388 100644 --- a/test/testcustomphrase.cpp +++ b/test/testcustomphrase.cpp @@ -67,7 +67,8 @@ void test_evaluator() { FCITX_ASSERT(phrase.evaluate(evaluator) == "$a $b"); phrase.mutableValue() = "#$a $b"; - FCITX_ASSERT(phrase.evaluate(evaluator) == "xx yy"); + FCITX_ASSERT(phrase.evaluate(evaluator) == "xx yy") + << phrase.evaluate(evaluator); phrase.mutableValue() = "#$a$b"; FCITX_ASSERT(phrase.evaluate(evaluator) == "xxyy"); @@ -89,6 +90,19 @@ void test_evaluator() { phrase.mutableValue() = "#${a}${b}"; FCITX_ASSERT(phrase.evaluate(evaluator) == "xxyy"); + + phrase.mutableValue() = "#$}${b}"; + FCITX_ASSERT(phrase.evaluate(evaluator) == "$}yy"); + + phrase.mutableValue() = "#$ ${b}"; + FCITX_ASSERT(phrase.evaluate(evaluator) == "$ yy"); + + phrase.mutableValue() = "#$a$"; + FCITX_ASSERT(phrase.evaluate(evaluator) == "xx$") + << phrase.evaluate(evaluator); + + phrase.mutableValue() = "#$a${b"; + FCITX_ASSERT(phrase.evaluate(evaluator) == "xx${b"); } void test_builtin_evaluator() { diff --git a/test/testpinyin.cpp b/test/testpinyin.cpp index 72942a313e07e12450715af8bb918218fe91ee98..4f7f1d0877f6c7231a5e05962e54db0f79040ab5 100644 --- a/test/testpinyin.cpp +++ b/test/testpinyin.cpp @@ -34,7 +34,7 @@ void testBasic(EventDispatcher *dispatcher, Instance *instance) { defaultGroup.inputMethodList().push_back( InputMethodGroupItem("pinyin")); defaultGroup.setDefaultInputMethod(""); - instance->inputMethodManager().setGroup(defaultGroup); + instance->inputMethodManager().setGroup(std::move(defaultGroup)); auto *testfrontend = instance->addonManager().addon("testfrontend"); auto uuid = testfrontend->call("testapp"); diff --git a/test/testtable.cpp b/test/testtable.cpp index 65cb4a98d15577bb4a38af770c28c061f4e93f03..5a42f8a1b62e128bd93ddd99fa3994aaed75826a 100644 --- a/test/testtable.cpp +++ b/test/testtable.cpp @@ -31,7 +31,7 @@ void scheduleEvent(EventDispatcher *dispatcher, Instance *instance) { InputMethodGroupItem("keyboard-us")); defaultGroup.inputMethodList().push_back(InputMethodGroupItem("erbi")); defaultGroup.setDefaultInputMethod(""); - instance->inputMethodManager().setGroup(defaultGroup); + instance->inputMethodManager().setGroup(std::move(defaultGroup)); auto *testfrontend = instance->addonManager().addon("testfrontend"); testfrontend->call("萌"); testfrontend->call("豚"); @@ -46,7 +46,7 @@ void scheduleEvent(EventDispatcher *dispatcher, Instance *instance) { testfrontend->call(uuid, Key("b"), false); testfrontend->call(uuid, Key("t"), false); testfrontend->call(uuid, Key("d"), false); - auto ic = instance->inputContextManager().findByUUID(uuid); + auto *ic = instance->inputContextManager().findByUUID(uuid); // Check no candidate. FCITX_ASSERT(!ic->inputPanel().candidateList()); testfrontend->call(uuid, Key(FcitxKey_Escape), @@ -90,12 +90,13 @@ void scheduleEvent(EventDispatcher *dispatcher, Instance *instance) { InputMethodGroupItem("keyboard-us")); defaultGroup.inputMethodList().push_back(InputMethodGroupItem("wbx")); defaultGroup.setDefaultInputMethod(""); - instance->inputMethodManager().setGroup(defaultGroup); + instance->inputMethodManager().setGroup(std::move(defaultGroup)); auto *table = instance->addonManager().addon("table", true); RawConfig config; - auto wbxConfig = reinterpret_cast(table) - ->getConfigForInputMethod( - *instance->inputMethodManager().entry("wbx")); + const auto *wbxConfig = + reinterpret_cast(table) + ->getConfigForInputMethod( + *instance->inputMethodManager().entry("wbx")); wbxConfig->save(config); config.setValueByPath("AutoPhraseWithPhrase", "True"); reinterpret_cast(table)->setConfigForInputMethod( @@ -113,7 +114,7 @@ void scheduleEvent(EventDispatcher *dispatcher, Instance *instance) { testfrontend->call(uuid, Key("a"), false); testfrontend->call(uuid, Key("a"), false); testfrontend->call(uuid, Key("a"), false); - auto ic = instance->inputContextManager().findByUUID(uuid); + auto *ic = instance->inputContextManager().findByUUID(uuid); testfrontend->call(uuid, Key("a"), false); testfrontend->call(uuid, Key("a"), false); @@ -144,8 +145,6 @@ void scheduleEvent(EventDispatcher *dispatcher, Instance *instance) { }); } -void runInstance() {} - int main() { setupTestingEnvironment(TESTING_BINARY_DIR, {TESTING_BINARY_DIR "/modules/pinyinhelper",