Skip to content

Commit

Permalink
Remove the old string based trigger and replace everything with regex
Browse files Browse the repository at this point in the history
If not talking about performance, feature-wise it is super set and the
thing we want to add has overlap with existing options (any "." will
enter quickphrase mode).

So just simply remove the old option seems to be a much clearer solution
and even if it will reset users existing configuration.
  • Loading branch information
wengxt committed Jan 11, 2025
1 parent 504b76f commit affd4c1
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 72 deletions.
71 changes: 15 additions & 56 deletions im/pinyin/pinyin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <exception>
#include <fcitx-config/rawconfig.h>
#include <fcitx-utils/capabilityflags.h>
#include <fcitx-utils/eventloopinterface.h>
#include <fcitx-utils/key.h>
#include <fcitx-utils/keysym.h>
#include <fcitx-utils/keysymgen.h>
Expand All @@ -42,6 +43,7 @@
#include <fstream>
#include <functional>
#include <future>
#include <ios>
#include <istream>
#include <iterator>
#include <libime/core/languagemodel.h>
Expand Down Expand Up @@ -1079,34 +1081,6 @@ void PinyinEngine::populateConfig() {
ime_->correctionProfile().get()));
}

quickphraseTriggerDict_.clear();
for (std::string_view prefix : *config_.quickphraseTrigger) {
if (prefix.empty()) {
continue;
}
auto length = utf8::lengthValidated(prefix);
if (length == utf8::INVALID_LENGTH || length < 1) {
continue;
}
auto latinPartLength =
utf8::ncharByteLength(prefix.begin(), length - 1);
auto latinPart = prefix.substr(0, latinPartLength);

if (std::any_of(latinPart.begin(), latinPart.end(), [](char c) {
return !charutils::islower(c) && !charutils::isupper(c);
})) {
continue;
}

const uint32_t trigger =
utf8::getChar(prefix.begin() + latinPartLength, prefix.end());
if (trigger && trigger != utf8::INVALID_CHAR &&
trigger != utf8::NOT_ENOUGH_SPACE) {
quickphraseTriggerDict_[std::string(latinPart)].insert(trigger);
}
}
PINYIN_DEBUG() << "Quick Phrase Trigger Dict: " << quickphraseTriggerDict_;

quickphraseTriggerRegex_.clear();
for (const std::string &regStr : *config_.quickphraseTriggerRegex) {
try {
Expand Down Expand Up @@ -1997,34 +1971,19 @@ void PinyinEngine::keyEvent(const InputMethodEntry &entry, KeyEvent &event) {
shuangpinProfile->validInitial().count(chr));
};

if (!event.key().hasModifier() && quickphrase()) {
const auto iter =
quickphraseTriggerDict_.find(state->context_.userInput());
if (iter != quickphraseTriggerDict_.end() && !iter->second.empty() &&
iter->second.count(keyChr.get())) {
std::string text =
stringutils::concat(state->context_.userInput(), keyStr.get());
doReset(inputContext);
quickphrase()->call<IQuickPhrase::trigger>(inputContext, "", "", "",
"", Key());
quickphrase()->call<IQuickPhrase::setBuffer>(inputContext, text);

return event.filterAndAccept();
}

if (!quickphraseTriggerRegex_.empty() && !keyStr.get().empty()) {
std::string text =
stringutils::concat(state->context_.userInput(), keyStr.get());
for (const auto &reg : quickphraseTriggerRegex_) {
if (std::regex_search(text, reg,
std::regex_constants::match_default)) {
doReset(inputContext);
quickphrase()->call<IQuickPhrase::trigger>(
inputContext, "", "", "", "", Key());
quickphrase()->call<IQuickPhrase::setBuffer>(inputContext,
text);
return event.filterAndAccept();
}
if (!event.key().hasModifier() && quickphrase() &&
!quickphraseTriggerRegex_.empty() && !keyStr.get().empty()) {
std::string text =
stringutils::concat(state->context_.userInput(), keyStr.get());
for (const auto &reg : quickphraseTriggerRegex_) {
if (std::regex_search(text, reg,
std::regex_constants::match_default)) {
doReset(inputContext);
quickphrase()->call<IQuickPhrase::trigger>(inputContext, "", "",
"", "", Key());
quickphrase()->call<IQuickPhrase::setBuffer>(inputContext,
text);
return event.filterAndAccept();
}
}
}
Expand Down
17 changes: 2 additions & 15 deletions im/pinyin/pinyin.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <fcitx-config/option.h>
#include <fcitx-config/rawconfig.h>
#include <fcitx-utils/event.h>
#include <fcitx-utils/eventloopinterface.h>
#include <fcitx-utils/handlertable.h>
#include <fcitx-utils/i18n.h>
#include <fcitx-utils/inputbuffer.h>
Expand Down Expand Up @@ -46,8 +47,6 @@
#include <regex>
#include <string>
#include <string_view>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

Expand Down Expand Up @@ -289,22 +288,12 @@ FCITX_CONFIGURATION(
_("Use V to trigger quickphrase"), true};
ExternalOption quickphrase{this, "QuickPhrase", _("Quick Phrase"),
"fcitx://config/addon/quickphrase/editor"};
OptionWithAnnotation<std::vector<std::string>, ToolTipAnnotation>
quickphraseTrigger{this,
"QuickPhrase trigger",
_("Strings to trigger quick phrase"),
{"www.", "ftp.", "http:", "mail.", "bbs.", "forum.",
"https:", "ftp:", "telnet:", "mailto:"},
{},
{},
{_("Enter quickphrase mode when current input "
"matches any string from the list.")}};
OptionWithAnnotation<std::vector<std::string>, ToolTipAnnotation>
quickphraseTriggerRegex{
this,
"QuickPhraseTriggerRegex",
_("Regular expression to trigger quick phrase"),
{},
{".(\\.|/|@)$", "^(http|https|ftp|telnet|mailto):"},
{},
{},
{_("Enter quickphrase mode when current input matches any regular "
Expand Down Expand Up @@ -449,8 +438,6 @@ class PinyinEngine final : public InputMethodEngineV3,
PinyinEngineConfig config_;
PinyinEngineConfig pyConfig_;
std::unique_ptr<libime::PinyinIME> ime_;
std::unordered_map<std::string, std::unordered_set<uint32_t>>
quickphraseTriggerDict_;
std::vector<std::regex> quickphraseTriggerRegex_;
KeyList selectionKeys_;
KeyList numpadSelectionKeys_;
Expand Down
61 changes: 60 additions & 1 deletion test/testpinyin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <fcitx-config/rawconfig.h>
#include <fcitx-utils/event.h>
#include <fcitx-utils/eventdispatcher.h>
#include <fcitx-utils/eventloopinterface.h>
#include <fcitx-utils/key.h>
#include <fcitx-utils/keysym.h>
#include <fcitx-utils/log.h>
Expand Down Expand Up @@ -368,6 +369,63 @@ void testPin(Instance *instance) {
});
}

void testQuickPhraseTrigger(Instance *instance) {
instance->eventDispatcher().schedule([instance]() {
auto *testfrontend = instance->addonManager().addon("testfrontend");
auto uuid =
testfrontend->call<ITestFrontend::createInputContext>("testapp");

testfrontend->call<ITestFrontend::keyEvent>(uuid, Key("Control+space"),
false);

testfrontend->call<ITestFrontend::keyEvent>(uuid, Key("w"), false);
testfrontend->call<ITestFrontend::keyEvent>(uuid, Key("w"), false);
testfrontend->call<ITestFrontend::keyEvent>(uuid, Key("w"), false);
testfrontend->call<ITestFrontend::keyEvent>(uuid, Key("."), false);
auto *ic = instance->inputContextManager().findByUUID(uuid);
FCITX_ASSERT(ic);
FCITX_ASSERT(ic->inputPanel().preedit().toString() == "www.");

ic->reset();
testfrontend->call<ITestFrontend::keyEvent>(uuid, Key("a"), false);
testfrontend->call<ITestFrontend::keyEvent>(uuid, Key("."), false);
FCITX_ASSERT(ic->inputPanel().preedit().toString() == "a.");

ic->reset();
testfrontend->call<ITestFrontend::keyEvent>(uuid, Key("u"), false);
testfrontend->call<ITestFrontend::keyEvent>(uuid, Key("s"), false);
testfrontend->call<ITestFrontend::keyEvent>(uuid, Key("e"), false);
testfrontend->call<ITestFrontend::keyEvent>(uuid, Key("r"), false);
testfrontend->call<ITestFrontend::keyEvent>(uuid, Key("@"), false);
FCITX_ASSERT(ic->inputPanel().preedit().toString() == "user@");

ic->reset();
testfrontend->call<ITestFrontend::keyEvent>(uuid, Key("h"), false);
testfrontend->call<ITestFrontend::keyEvent>(uuid, Key("t"), false);
testfrontend->call<ITestFrontend::keyEvent>(uuid, Key("t"), false);
testfrontend->call<ITestFrontend::keyEvent>(uuid, Key("p"), false);
testfrontend->call<ITestFrontend::keyEvent>(uuid, Key(":"), false);
FCITX_ASSERT(ic->inputPanel().preedit().toString() == "http:");

ic->reset();
// htt: shouldn't trigger.
testfrontend->call<ITestFrontend::keyEvent>(uuid, Key("h"), false);
testfrontend->call<ITestFrontend::keyEvent>(uuid, Key("t"), false);
testfrontend->call<ITestFrontend::keyEvent>(uuid, Key("t"), false);

FCITX_ASSERT(ic->inputPanel().candidateList());
FCITX_ASSERT(!ic->inputPanel().candidateList()->empty());
const auto firstCandidate =
ic->inputPanel().candidateList()->candidate(0).text().toString();
testfrontend->call<ITestFrontend::pushCommitExpectation>(
firstCandidate);
testfrontend->call<ITestFrontend::pushCommitExpectation>("");

testfrontend->call<ITestFrontend::keyEvent>(uuid, Key(":"), false);
FCITX_ASSERT(ic->inputPanel().preedit().toString() == "");
});
}

void testPunctuation(Instance *instance) {
instance->eventDispatcher().schedule([instance]() {
auto *testfrontend = instance->addonManager().addon("testfrontend");
Expand Down Expand Up @@ -443,7 +501,7 @@ int main() {
char arg0[] = "testpinyin";
char arg1[] = "--disable=all";
char arg2[] = "--enable=testim,testfrontend,pinyin,punctuation,"
"pinyinhelper,spell";
"pinyinhelper,spell,quickphrase";
char *argv[] = {arg0, arg1, arg2};
fcitx::Log::setLogRule("default=5,pinyin=5");
Instance instance(FCITX_ARRAY_SIZE(argv), argv);
Expand All @@ -454,6 +512,7 @@ int main() {
testForget(&instance);
testActionInStrokeFilter(&instance);
testPin(&instance);
testQuickPhraseTrigger(&instance);
testPunctuation(&instance);
instance.exec();
endTestEvent.reset();
Expand Down

0 comments on commit affd4c1

Please sign in to comment.