`vendor/MetasequoiaImeEngine` submodule 改为 `engine/` 目录,导入的是 product-lock.json 原本钉住的提交 c810d201,逐文件核对过 blob,因此这是一次 搬迁而不是引擎升级。引擎自己的嵌套 submodule(googlepinyinime-rev、utfcpp、 miniaudio)按各自 gitlink 一并展开,来源与提交见 engine/UPSTREAM.md。 Windows 专门化裁掉了不属于本产品的部分:whisper.cpp 与本地推理 provider、 macOS 示例宿主、整个 dictionary/ 建库流水线、上游 CI 与 release-please 配置。 词库仍按 product-lock.json 在构建时取发布产物。 引擎不再进 product-lock.json:没有 gitlink 就没有可比对的东西,锁里写一个上游 commit 等于宣称这棵树仍等于上游,而第一个 Windows 专门化改动落地时这句话就假了。 verify-contracts / verify-checkout 随之移除,verify-published 保留。 CI 与工具链:引擎源码并入根 scripts/format.sh(删掉引擎自己的那份,避免两套排除 列表分叉);引擎 voice.yml 里的 silero_vad.onnx 摘要校验移到本仓 lock job; engine-bump-triage 工作流与其测试删除;gitsubmodule 的 dependabot 频率由 daily 改为 monthly。 README、README.en、AGENTS.md、CONTRIBUTING、docs/product-release.md 及各子目录 文档同步说明新的位置与边界。
252 lines
12 KiB
C++
252 lines
12 KiB
C++
#pragma once
|
||
|
||
#include "ime_session.h"
|
||
#include "input_session_types.h"
|
||
#include "candidate_queries.h"
|
||
#include "punctuation_policy.h"
|
||
#include "online_request_guard.h"
|
||
#include "../local_modes/date_time_query.h"
|
||
#include "../english/english_dictionary.h"
|
||
#include "word_item.h"
|
||
#include "../quanpin/engine.h"
|
||
|
||
#include <cstddef>
|
||
#include <cstdint>
|
||
#include <functional>
|
||
#include <memory>
|
||
#include <optional>
|
||
#include <string>
|
||
#include <vector>
|
||
|
||
namespace metasequoia
|
||
{
|
||
// Platform-neutral composition session shared by the native frontends. It owns an ImeSession and
|
||
// applies the key-handling and commit policy that each frontend would otherwise reimplement, so a
|
||
// frontend only has to translate platform key events into these calls.
|
||
class InputSession
|
||
{
|
||
public:
|
||
// Frontends pass their persisted options at session creation so every platform uses the same
|
||
// engine configuration and commit policy.
|
||
explicit InputSession(SchemeType scheme_type = SchemeType::Quanpin, unsigned quanpin_autocorrect_types = 0,
|
||
bool helpcode_enabled = true, bool chinese_punctuation_enabled = true,
|
||
bool candidate_learning_enabled = true, RuntimePaths paths = RuntimePaths::legacy());
|
||
InputSession(SchemeType scheme_type, const ShuangpinProfile &shuangpin_profile,
|
||
RuntimePaths paths = RuntimePaths::legacy());
|
||
|
||
// Feeds one lowercase ASCII letter or an in-composition apostrophe. Other input is rejected as
|
||
// unhandled so the frontend can pass it through to the client application.
|
||
KeyResult handle_character(char character, bool shift_only = false);
|
||
// Applies a command. Every command is unhandled while no composition is active, which keeps
|
||
// Backspace and Escape working normally in the client application.
|
||
KeyResult handle_command(Command command);
|
||
// Maps the visible 1-9 candidate keys and Chinese punctuation independently of platform UI.
|
||
KeyResult handle_candidate_key(char character);
|
||
KeyResult handle_punctuation(char character);
|
||
// Commit the selected prefix and retain any unconsumed pinyin. Hosts insert
|
||
// KeyResult::commit and then render the remaining preedit from this session.
|
||
KeyResult select_candidate(std::size_t index);
|
||
// Flush all remaining input for punctuation, scheme changes and host passthrough.
|
||
KeyResult finish_composition(std::size_t first_index = 0);
|
||
KeyResult select_candidate(const std::string &candidate);
|
||
KeyResult select_candidate_edge(std::size_t index, CandidateEdge edge);
|
||
KeyResult pin_candidate(std::size_t index);
|
||
KeyResult remove_candidate(std::size_t index);
|
||
KeyResult set_candidate_position(std::size_t index, int position);
|
||
void enable_fixed_positions();
|
||
void set_shuangpin_helpcode_enabled(bool enabled);
|
||
void set_quanpin_helpcode_enabled(bool enabled);
|
||
static bool is_supported_helpcode_schema(const std::string &schema);
|
||
bool set_helpcode_schema(const std::string &schema);
|
||
// Compatibility default for subsequently created sessions.
|
||
static bool select_helpcode_schema(const std::string &schema);
|
||
bool set_frequency_adjustment(FrequencyAdjustmentOptions options);
|
||
const FrequencyAdjustmentOptions &frequency_adjustment() const;
|
||
void set_local_mode_options(LocalModeOptions options);
|
||
const LocalModeOptions &local_mode_options() const;
|
||
bool set_english_input_options(EnglishInputOptions options);
|
||
const EnglishInputOptions &english_input_options() const;
|
||
void set_mixed_expressive_options(MixedExpressiveOptions options);
|
||
void set_wubi_input_options(metasequoia::WubiInputOptions options);
|
||
const MixedExpressiveOptions &mixed_expressive_options() const;
|
||
void set_dedicated_english_mode(bool enabled);
|
||
bool dedicated_english_mode() const;
|
||
LocalInputMode local_input_mode() const;
|
||
void set_local_date_time_provider(std::function<local_modes::LocalDateTime()> provider);
|
||
std::optional<OnlineQuery> online_query() const;
|
||
bool apply_online_candidate(const OnlineQuery &query, std::string candidate, CandidateSource source);
|
||
|
||
SchemeType scheme_type() const;
|
||
unsigned quanpin_autocorrect_types() const;
|
||
bool helpcode_enabled() const;
|
||
bool chinese_punctuation_enabled() const;
|
||
bool candidate_learning_enabled() const;
|
||
// Switching schemes discards the current composition. A frontend that promises to preserve
|
||
// typed text must commit it before calling this method.
|
||
void switch_scheme(SchemeType scheme_type);
|
||
SchemeType scheme() const;
|
||
|
||
bool has_composition() const;
|
||
const std::string &preedit() const;
|
||
std::string editing_text() const;
|
||
std::size_t caret_position() const;
|
||
const std::string &raw_segmentation() const;
|
||
const std::string &normalized_segmentation() const;
|
||
const std::vector<WordItem> &candidates() const;
|
||
// True while the current composition is answered by the wubi mixed-pinyin fallback.
|
||
bool answered_by_pinyin_fallback() const;
|
||
|
||
// Advanced composition operations for hosts with their own asynchronous text insertion.
|
||
// They share the same engine/configuration as the portable character/command API.
|
||
struct SelectionTransition
|
||
{
|
||
bool continues_composition = false;
|
||
std::string full_pure_pinyin;
|
||
std::string current_segmentation;
|
||
std::string current_segmentation_with_cases;
|
||
std::string selected_canonical_pinyin;
|
||
};
|
||
|
||
struct CloudQueryState
|
||
{
|
||
bool should_query = false;
|
||
std::string query_text;
|
||
std::string cache_key;
|
||
std::string committed_pinyin;
|
||
};
|
||
|
||
struct CreatingWordProgress
|
||
{
|
||
std::string pinyin;
|
||
std::string word;
|
||
std::string preedit;
|
||
bool completed = false;
|
||
bool can_store = false;
|
||
};
|
||
|
||
void handle_engine_key(ImeKeyCode vk, ImeModifierMask modifiers_down, ImeCharacter wch);
|
||
void recompute_candidates();
|
||
SchemeType current_scheme_type() const;
|
||
|
||
void reset_state();
|
||
void reset_cache();
|
||
|
||
const std::vector<WordItem> &get_candidates() const;
|
||
bool expand_initial_candidates();
|
||
std::optional<WordItem> find_candidate(const std::string &key, const std::string &value);
|
||
|
||
const std::string &get_pinyin_sequence() const;
|
||
const std::string &get_pinyin_sequence_with_cases() const;
|
||
const std::string &get_pure_pinyin_sequence() const;
|
||
const std::string &get_pinyin_segmentation() const;
|
||
std::string get_pinyin_segmentation_with_cases() const;
|
||
std::string get_quanpin() const;
|
||
bool is_all_complete_pure_pinyin() const;
|
||
bool has_active_helpcode() const;
|
||
|
||
void set_pinyin_sequence(const std::string &pinyin_sequence);
|
||
void set_pinyin_sequence_with_cases(const std::string &pinyin_sequence);
|
||
|
||
int store_user_phrase(std::string pinyin, std::string word);
|
||
int store_user_phrase_from_canonical_pinyin(std::string pinyin, std::string word);
|
||
int pin_candidate(std::string pinyin, std::string word);
|
||
int remove_candidate(std::string pinyin, std::string word);
|
||
int cache_dynamic_candidate(const std::string &pinyin, const std::string &word, CandidateSource source);
|
||
SelectionTransition advance_composition_after_selection(const std::string &selected_pinyin,
|
||
const std::string &selected_word,
|
||
const std::string &selected_canonical_pinyin);
|
||
CloudQueryState get_cloud_query_state() const;
|
||
CreatingWordProgress update_creating_word_progress(const std::string ¤t_pinyin,
|
||
const std::string ¤t_word,
|
||
const std::string &selected_word,
|
||
const SelectionTransition &selection_transition) const;
|
||
|
||
void set_quanpin_autocorrect_types(unsigned autocorrect_types);
|
||
void set_fuzzy_pinyin_options(metasequoia::FuzzyPinyinOptions options)
|
||
{
|
||
engine_.set_fuzzy_pinyin_options(options);
|
||
}
|
||
void set_chinese_punctuation_enabled(bool enabled)
|
||
{
|
||
chinese_punctuation_enabled_ = enabled;
|
||
}
|
||
void set_candidate_learning_enabled(bool enabled)
|
||
{
|
||
candidate_learning_enabled_ = enabled;
|
||
}
|
||
void set_shuangpin_preedit_uses_raw(bool enabled)
|
||
{
|
||
shuangpin_preedit_uses_raw_ = enabled;
|
||
}
|
||
|
||
private:
|
||
const QueryRequest &request() const;
|
||
bool is_shuangpin() const;
|
||
bool is_wubi() const;
|
||
// Wubi whose candidates came from the wubi table. A code answered by the quanpin
|
||
// fallback carries pinyin words, so ranking, fixed positions and removal have to key
|
||
// off the pinyin rather than off the code that produced them.
|
||
bool wubi_candidates_are_native() const;
|
||
// The candidates on offer behave like pinyin: quanpin, shuangpin, or a wubi code the
|
||
// table could not answer. Committing one of these commits a spelling out of a longer
|
||
// one, so the rest of the composition has to survive the selection.
|
||
bool candidates_follow_pinyin() const;
|
||
bool is_japanese() const;
|
||
void clear_pending_sequence();
|
||
void apply_pending_sequence();
|
||
|
||
KeyResult commit(std::size_t index);
|
||
KeyResult handle_local_character(char character);
|
||
KeyResult insert_at_caret(char character);
|
||
KeyResult edit_at_caret(Command command);
|
||
KeyResult replace_editing_text(std::string text, std::size_t caret);
|
||
std::optional<std::size_t> caret_;
|
||
std::optional<std::string> update_local_candidates();
|
||
void update_mixed_candidates();
|
||
void apply_candidate_positions(std::vector<WordItem> &items);
|
||
std::string position_context(bool english) const;
|
||
bool fixed_positions_enabled_ = false;
|
||
void update_dedicated_english_candidates();
|
||
void reset_composition();
|
||
void discard_abandoned_phrase_progress();
|
||
std::optional<std::string> learn_candidate(std::size_t index);
|
||
std::optional<std::string> adjust_candidate_frequency(std::size_t index, FrequencyAdjustmentOptions options,
|
||
bool force_top);
|
||
|
||
CreatingWordProgress immediate_phrase_progress_;
|
||
bool shuangpin_preedit_uses_raw_ = true;
|
||
std::unique_ptr<QuanpinEngine> canonical_phrase_engine_;
|
||
std::string pending_pinyin_sequence_;
|
||
std::string pending_pinyin_sequence_with_cases_;
|
||
bool has_pending_pinyin_sequence_ = false;
|
||
bool has_pending_pinyin_sequence_with_cases_ = false;
|
||
|
||
RuntimePaths paths_;
|
||
CandidateQueries candidate_queries_;
|
||
ImeSession engine_;
|
||
// 位掩码(quanpin::kAutocorrect* 位),不是 bool:bool 会把邻键位截断丢失。
|
||
unsigned quanpin_autocorrect_types_ = 0;
|
||
bool quanpin_helpcode_enabled_ = true;
|
||
bool shuangpin_helpcode_enabled_ = true;
|
||
bool chinese_punctuation_enabled_ = true;
|
||
bool candidate_learning_enabled_ = true;
|
||
PunctuationPolicy punctuation_;
|
||
const ShuangpinProfile shuangpin_profile_;
|
||
FrequencyAdjustmentOptions frequency_adjustment_;
|
||
bool frequency_adjustment_configured_ = false;
|
||
LocalModeOptions local_mode_options_;
|
||
EnglishInputOptions english_input_options_;
|
||
MixedExpressiveOptions mixed_expressive_options_;
|
||
bool dedicated_english_mode_ = false;
|
||
std::string dedicated_english_preedit_;
|
||
std::vector<WordItem> dedicated_english_candidates_;
|
||
std::vector<WordItem> mixed_candidates_;
|
||
LocalInputMode local_input_mode_ = LocalInputMode::None;
|
||
std::optional<SchemeType> temporary_original_scheme_;
|
||
std::string local_preedit_;
|
||
std::vector<WordItem> local_candidates_;
|
||
std::function<local_modes::LocalDateTime()> local_date_time_provider_;
|
||
OnlineRequestGuard online_requests_;
|
||
};
|
||
} // namespace metasequoia
|