From e417eaee6402bb87a184946517ec5bff1db32920 Mon Sep 17 00:00:00 2001 From: fanlusky <1730976608@qq.com> Date: Tue, 14 Jul 2026 23:39:34 +0800 Subject: [PATCH] Refactor to prepare for adding the Ziranma scheme. --- server/CMakeLists.txt | 1 + server/MetasequoiaImeEngine | 2 +- server/scripts/config_files/CMakeLists.txt | 1 + server/src/session/engine_input_session.cpp | 31 +++++++++++-------- server/src/session/engine_input_session.h | 4 ++- .../src/session/shuangpin_input_session.cpp | 7 +++-- server/src/session/shuangpin_input_session.h | 5 ++- server/tests/CMakeLists.txt | 1 + server/tests/src/test_shuangpin_scheme.cpp | 25 +++++++++++++++ 9 files changed, 58 insertions(+), 19 deletions(-) diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 11a9308a..18ca45a8 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -105,6 +105,7 @@ set(SRC_FILES_IME_ENGINE "./MetasequoiaImeEngine/schemes/wubi_scheme.cpp" "./MetasequoiaImeEngine/shuangpin/engine.cpp" "./MetasequoiaImeEngine/shuangpin/shuangpin_dictionary.cpp" + "./MetasequoiaImeEngine/shuangpin/shuangpin_profile.cpp" "./MetasequoiaImeEngine/shuangpin/shuangpin_query.cpp" "./MetasequoiaImeEngine/shuangpin/shuangpin_utils.cpp" ) diff --git a/server/MetasequoiaImeEngine b/server/MetasequoiaImeEngine index 50b4507c..620975f0 160000 --- a/server/MetasequoiaImeEngine +++ b/server/MetasequoiaImeEngine @@ -1 +1 @@ -Subproject commit 50b4507c2e780b3024abe6afaf9b7a034a56f129 +Subproject commit 620975f0d37e243f90f7c1c60502135fb4d2ff14 diff --git a/server/scripts/config_files/CMakeLists.txt b/server/scripts/config_files/CMakeLists.txt index f7c7294d..b0759fb1 100644 --- a/server/scripts/config_files/CMakeLists.txt +++ b/server/scripts/config_files/CMakeLists.txt @@ -92,6 +92,7 @@ set(SRC_FILES_IME_ENGINE "./MetasequoiaImeEngine/schemes/shuangpin_scheme.cpp" "./MetasequoiaImeEngine/shuangpin/engine.cpp" "./MetasequoiaImeEngine/shuangpin/shuangpin_dictionary.cpp" + "./MetasequoiaImeEngine/shuangpin/shuangpin_profile.cpp" "./MetasequoiaImeEngine/shuangpin/shuangpin_query.cpp" "./MetasequoiaImeEngine/shuangpin/shuangpin_utils.cpp" ) diff --git a/server/src/session/engine_input_session.cpp b/server/src/session/engine_input_session.cpp index 47ad59a5..a63472ad 100644 --- a/server/src/session/engine_input_session.cpp +++ b/server/src/session/engine_input_session.cpp @@ -47,7 +47,8 @@ struct ShuangpinCompositionBase size_t helpcode_length = 0; }; -ShuangpinCompositionBase ResolveShuangpinCompositionBase(const QueryRequest &request) +ShuangpinCompositionBase ResolveShuangpinCompositionBase(const QueryRequest &request, + const ShuangpinProfile &profile) { ShuangpinCompositionBase base{ request.raw_input, request.raw_input_with_cases.empty() ? request.raw_input : request.raw_input_with_cases}; @@ -59,7 +60,8 @@ ShuangpinCompositionBase ResolveShuangpinCompositionBase(const QueryRequest &req return base; } - if (ShuangpinUtil::IsFullHelpMode(base.effective_raw_input_with_cases) && base.effective_raw_input.size() >= 2) + if (ShuangpinUtil::IsFullHelpMode(base.effective_raw_input_with_cases, profile) && + base.effective_raw_input.size() >= 2) { base.helpcode_length = 2; return base; @@ -68,7 +70,7 @@ ShuangpinCompositionBase ResolveShuangpinCompositionBase(const QueryRequest &req if (base.effective_raw_input.size() % 2 == 1 && base.effective_raw_input.size() > 1) { const std::string pure_raw_input = base.effective_raw_input.substr(0, base.effective_raw_input.size() - 1); - if (shuangpin::is_complete_input(pure_raw_input)) + if (shuangpin::is_complete_input(pure_raw_input, profile)) { base.helpcode_length = 1; } @@ -83,9 +85,9 @@ bool HasActiveQuanpinHelpcode(const QueryRequest &request) quanpin::detect_active_helpcode_length(request.raw_input, request.raw_input_with_cases) > 0; } -std::string ResolveShuangpinCloudCacheKey(const QueryRequest &request) +std::string ResolveShuangpinCloudCacheKey(const QueryRequest &request, const ShuangpinProfile &profile) { - const auto base = ResolveShuangpinCompositionBase(request); + const auto base = ResolveShuangpinCompositionBase(request, profile); if (base.helpcode_length > 0 && base.effective_raw_input.size() >= base.helpcode_length) { return base.raw_input.substr(0, raw_length_for_normalized_prefix( @@ -100,7 +102,9 @@ std::string ResolveQuanpinCloudCacheKey(const QueryRequest &request) } } // namespace -EngineInputSession::EngineInputSession(SchemeType scheme_type) : session_(scheme_type) +EngineInputSession::EngineInputSession(SchemeType scheme_type, const ShuangpinProfile &shuangpin_profile) + : shuangpin_profile_(shuangpin_profile), session_(scheme_type, shuangpin_profile), + shuangpin_dictionary_(shuangpin_profile) { session_.set_shuangpin_helpcode_enabled(GetConfiguredShuangpinHelpcodeEnabled()); session_.set_quanpin_helpcode_enabled(GetConfiguredQuanpinHelpcodeEnabled()); @@ -222,14 +226,15 @@ bool EngineInputSession::is_all_complete_pure_pinyin() const } if (is_shuangpin()) { - const auto base = ResolveShuangpinCompositionBase(request()); + const auto base = ResolveShuangpinCompositionBase(request(), shuangpin_profile_); if (base.helpcode_length > 0 && base.effective_raw_input.size() >= base.helpcode_length) { return shuangpin::is_complete_input( base.raw_input.substr(0, raw_length_for_normalized_prefix( - base.raw_input, base.effective_raw_input.size() - base.helpcode_length))); + base.raw_input, base.effective_raw_input.size() - base.helpcode_length)), + shuangpin_profile_); } - return shuangpin::is_complete_input(base.raw_input); + return shuangpin::is_complete_input(base.raw_input, shuangpin_profile_); } const auto &segmentation = request().normalized_segmentation.empty() ? request().segmentation : request().normalized_segmentation; @@ -283,7 +288,7 @@ IInputSession::SelectionTransition EngineInputSession::advance_composition_after } if (is_shuangpin()) { - const auto base = ResolveShuangpinCompositionBase(request()); + const auto base = ResolveShuangpinCompositionBase(request(), shuangpin_profile_); const size_t word_pinyin_length = HelpcodeUtils::count_han_chars(selected_word) * 2; const size_t total_input_length = base.effective_raw_input.size(); @@ -384,8 +389,8 @@ IInputSession::CloudQueryState EngineInputSession::get_cloud_query_state() const if (is_shuangpin()) { - const auto base = ResolveShuangpinCompositionBase(request()); - state.cache_key = ResolveShuangpinCloudCacheKey(request()); + const auto base = ResolveShuangpinCompositionBase(request(), shuangpin_profile_); + state.cache_key = ResolveShuangpinCloudCacheKey(request(), shuangpin_profile_); state.committed_pinyin = shuangpin::remove_manual_delimiters(state.cache_key); if (base.helpcode_length > 0) @@ -407,7 +412,7 @@ IInputSession::CloudQueryState EngineInputSession::get_cloud_query_state() const if (state.should_query) { - state.query_text = shuangpin::normalize_input_with_delimiters(state.cache_key); + state.query_text = shuangpin::normalize_input_with_delimiters(state.cache_key, shuangpin_profile_); } return state; } diff --git a/server/src/session/engine_input_session.h b/server/src/session/engine_input_session.h index 6898bc9b..f56ef24c 100644 --- a/server/src/session/engine_input_session.h +++ b/server/src/session/engine_input_session.h @@ -7,7 +7,8 @@ class EngineInputSession : public IInputSession { public: - explicit EngineInputSession(SchemeType scheme_type = SchemeType::Shuangpin); + explicit EngineInputSession(SchemeType scheme_type = SchemeType::Shuangpin, + const ShuangpinProfile &shuangpin_profile = GetXiaoheShuangpinProfile()); void handle_key(UINT vk, UINT modifiers_down, WCHAR wch) override; void recompute_candidates() override; @@ -50,6 +51,7 @@ class EngineInputSession : public IInputSession void apply_pending_sequence(); private: + const ShuangpinProfile &shuangpin_profile_; ImeSession session_; DictionaryUlPb shuangpin_dictionary_; QuanpinEngine quanpin_engine_; diff --git a/server/src/session/shuangpin_input_session.cpp b/server/src/session/shuangpin_input_session.cpp index ff022543..9de7cbd7 100644 --- a/server/src/session/shuangpin_input_session.cpp +++ b/server/src/session/shuangpin_input_session.cpp @@ -20,7 +20,7 @@ bool HasActiveShuangpinHelpcode(const ShuangpinInputSession &session) return false; } - if (ShuangpinUtil::IsFullHelpMode(raw_input_with_cases) && raw_input.size() >= 2) + if (ShuangpinUtil::IsFullHelpMode(raw_input_with_cases, session.profile()) && raw_input.size() >= 2) { return true; } @@ -28,7 +28,7 @@ bool HasActiveShuangpinHelpcode(const ShuangpinInputSession &session) if (raw_input.size() % 2 == 1 && raw_input.size() > 1) { const std::string pure_raw_input = raw_input.substr(0, raw_input.size() - 1); - const std::string pure_segmentation = ShuangpinUtil::pinyin_segmentation(pure_raw_input); + const std::string pure_segmentation = ShuangpinUtil::pinyin_segmentation(pure_raw_input, session.profile()); return ShuangpinUtil::is_all_complete_pinyin(pure_raw_input, pure_segmentation); } @@ -36,7 +36,8 @@ bool HasActiveShuangpinHelpcode(const ShuangpinInputSession &session) } } // namespace -ShuangpinInputSession::ShuangpinInputSession() : dictionary_(std::make_unique()) +ShuangpinInputSession::ShuangpinInputSession(const ShuangpinProfile &profile) + : profile_(profile), dictionary_(std::make_unique(profile)) { } diff --git a/server/src/session/shuangpin_input_session.h b/server/src/session/shuangpin_input_session.h index 8877551d..a23aaccc 100644 --- a/server/src/session/shuangpin_input_session.h +++ b/server/src/session/shuangpin_input_session.h @@ -1,12 +1,14 @@ #pragma once #include "input_session.h" +#include "MetasequoiaImeEngine/shuangpin/shuangpin_profile.h" #include class ShuangpinInputSession : public IInputSession { public: - ShuangpinInputSession(); + explicit ShuangpinInputSession(const ShuangpinProfile &profile = GetXiaoheShuangpinProfile()); + const ShuangpinProfile &profile() const { return profile_; } void handle_key(UINT vk, UINT modifiers_down, WCHAR wch) override; void recompute_candidates() override; @@ -42,5 +44,6 @@ class ShuangpinInputSession : public IInputSession const SelectionTransition &selection_transition) const override; private: + const ShuangpinProfile &profile_; std::unique_ptr dictionary_; }; diff --git a/server/tests/CMakeLists.txt b/server/tests/CMakeLists.txt index 8cda47e6..6c3ced02 100644 --- a/server/tests/CMakeLists.txt +++ b/server/tests/CMakeLists.txt @@ -27,6 +27,7 @@ set(TEST_SOURCE_FILES "${CMAKE_SOURCE_DIR}/MetasequoiaImeEngine/quanpin/quanpin_query.cpp" "${CMAKE_SOURCE_DIR}/MetasequoiaImeEngine/shuangpin/engine.cpp" "${CMAKE_SOURCE_DIR}/MetasequoiaImeEngine/shuangpin/shuangpin_dictionary.cpp" + "${CMAKE_SOURCE_DIR}/MetasequoiaImeEngine/shuangpin/shuangpin_profile.cpp" "${CMAKE_SOURCE_DIR}/MetasequoiaImeEngine/shuangpin/shuangpin_query.cpp" "${CMAKE_SOURCE_DIR}/MetasequoiaImeEngine/shuangpin/shuangpin_utils.cpp" "${CMAKE_SOURCE_DIR}/MetasequoiaImeEngine/googlepinyinime-rev/src/share/dictbuilder.cpp" diff --git a/server/tests/src/test_shuangpin_scheme.cpp b/server/tests/src/test_shuangpin_scheme.cpp index 37a0eef6..4c31a814 100644 --- a/server/tests/src/test_shuangpin_scheme.cpp +++ b/server/tests/src/test_shuangpin_scheme.cpp @@ -7,6 +7,18 @@ void InputKey(ShuangpinScheme &scheme, UINT vk, WCHAR wch, UINT modifiers_down = { scheme.handle_key(vk, modifiers_down, wch); } + +const ShuangpinProfile &GetTestShuangpinProfile() +{ + static const ShuangpinProfile profile = [] { + ShuangpinProfile value = GetXiaoheShuangpinProfile(); + value.name = "test"; + value.finals["iang"] = "d"; + value.finals["uang"] = "d"; + return value; + }(); + return profile; +} } TEST_CASE(ShuangpinSchemeBuildRequestPreservesCaseAndNormalizesQuery) @@ -59,3 +71,16 @@ TEST_CASE(ShuangpinSchemeBackspaceRemovesLastInput) REQUIRE_EQ(request.raw_input, std::string("x")); REQUIRE_EQ(request.raw_input_with_cases, std::string("x")); } + +TEST_CASE(ShuangpinSchemeUsesInjectedProfile) +{ + ShuangpinScheme xiaohe; + InputKey(xiaohe, 'X', L'x'); + InputKey(xiaohe, 'L', L'l'); + REQUIRE_EQ(xiaohe.build_request().normalized_segmentation, std::string("xiang")); + + ShuangpinScheme custom(GetTestShuangpinProfile()); + InputKey(custom, 'X', L'x'); + InputKey(custom, 'D', L'd'); + REQUIRE_EQ(custom.build_request().normalized_segmentation, std::string("xiang")); +}