* feat(engine): 支持 helpcodes/custom 下的自定义辅助码 custom 目录里的每个 .txt 都是一套方案,方案名为 custom/<文件名>。 文件开头的 "# name:" / "# name_en:" 注释给出中英文显示名,缺省用文件名; 兼容 BOM、CRLF 和全角冒号。方案名不能跳出 custom 目录。 * feat(engine): WebView 契约新增 openHelpcodeDirectory 设置页请求打开自定义辅助码目录,仅允许 settings 页发送。同步 ui-html/webview2/shared。 * feat(server): 设置页列出自定义辅助码并可打开其目录 配置快照带上 helpcode.custom_schemas 与 helpcode.custom_directory,每次都会重新扫描; 方案文件被删除或改名后回退到 lantian。两个设置宿主都会处理 openHelpcodeDirectory。 * feat(ui-html): 辅助码设置显示拼音加加与自定义方案 内置方案“加加”改名为“拼音加加”。自定义方案追加在内置方案之后;新增说明区, 提供“打开目录”和“刷新方案”两个按钮,刷新完成后弹出提示。 * feat(installer): 升级与迁移数据目录时保留自定义辅助码 升级清理时只清掉 helpcodes 里的内置表,保留 custom 子目录;更换数据目录时一并迁移; 安装时建出 helpcodes\custom。
119 lines
4.5 KiB
C++
119 lines
4.5 KiB
C++
#pragma once
|
|
|
|
#include <string>
|
|
#include <filesystem>
|
|
#include <memory>
|
|
#include <unordered_map>
|
|
#include <vector>
|
|
|
|
namespace HelpcodeUtils
|
|
{
|
|
|
|
using Keymap = std::unordered_map<std::string, std::string>;
|
|
using SharedKeymap = std::shared_ptr<const Keymap>;
|
|
SharedKeymap load_helpcode_keymap(const std::filesystem::path &resources, const std::string &schema);
|
|
std::string selected_helpcode_schema();
|
|
const Keymap &helpcode_keymap();
|
|
bool is_supported_helpcode_schema(const std::string &schema);
|
|
bool select_helpcode_schema(const std::string &schema);
|
|
|
|
// User tables dropped into <resources>/helpcodes/custom/*.txt are schemas named
|
|
// "custom/<file stem>". Leading "# name: ..." / "# name_en: ..." comment lines give display names.
|
|
inline constexpr char kCustomHelpcodeSchemaPrefix[] = "custom/";
|
|
struct CustomHelpcodeSchema
|
|
{
|
|
std::string schema;
|
|
std::string name; // Chinese display name; empty when the file does not declare one
|
|
std::string name_en; // English display name; empty when the file does not declare one
|
|
std::string file_stem;
|
|
};
|
|
std::filesystem::path custom_helpcode_directory(const std::filesystem::path &resources);
|
|
std::vector<CustomHelpcodeSchema> list_custom_helpcode_schemas(const std::filesystem::path &resources);
|
|
// Built-in schemas are always available; a custom schema only while its file exists.
|
|
bool is_helpcode_schema_available(const std::filesystem::path &resources, const std::string &schema);
|
|
|
|
std::string get_first_han_char(const std::string &words);
|
|
std::string get_last_han_char(const std::string &words);
|
|
std::string::size_type count_han_chars(const std::string &words);
|
|
std::string::size_type count_utf8_chars(const std::string &text);
|
|
std::string compute_helpcodes(const std::string &words, bool uppercase_all = false, const Keymap *keymap = nullptr);
|
|
|
|
bool is_quanpin_single_help_mode(const std::string &pinyin_with_cases);
|
|
bool is_quanpin_double_help_mode(const std::string &pinyin_with_cases);
|
|
|
|
enum class SingleHelpcodeMatch
|
|
{
|
|
None,
|
|
First,
|
|
Last,
|
|
Both,
|
|
};
|
|
|
|
SingleHelpcodeMatch match_single_helpcode(const std::string &word, const std::string &help_code,
|
|
const Keymap *keymap = nullptr);
|
|
bool matches_double_helpcodes(const std::string &word, const std::string &help_codes, const Keymap *keymap = nullptr);
|
|
|
|
template <typename TWordItem>
|
|
std::vector<TWordItem> reorder_candidates_with_single_helpcode(const std::vector<TWordItem> &candidate_list,
|
|
const std::string &help_code,
|
|
const Keymap *keymap = nullptr)
|
|
{
|
|
if (help_code.size() != 1)
|
|
{
|
|
return candidate_list;
|
|
}
|
|
|
|
std::vector<TWordItem> first_helpcode_matched_list;
|
|
std::vector<TWordItem> last_helpcode_matched_list;
|
|
std::vector<TWordItem> left_helpcode_matched_list;
|
|
std::vector<TWordItem> result_list;
|
|
|
|
for (const auto &cand : candidate_list)
|
|
{
|
|
switch (match_single_helpcode(cand.word, help_code, keymap))
|
|
{
|
|
case SingleHelpcodeMatch::First:
|
|
first_helpcode_matched_list.push_back(cand);
|
|
break;
|
|
case SingleHelpcodeMatch::Last:
|
|
last_helpcode_matched_list.push_back(cand);
|
|
break;
|
|
case SingleHelpcodeMatch::Both:
|
|
first_helpcode_matched_list.push_back(cand);
|
|
break;
|
|
case SingleHelpcodeMatch::None:
|
|
left_helpcode_matched_list.push_back(cand);
|
|
break;
|
|
}
|
|
}
|
|
|
|
result_list.insert(result_list.end(), first_helpcode_matched_list.begin(), first_helpcode_matched_list.end());
|
|
result_list.insert(result_list.end(), last_helpcode_matched_list.begin(), last_helpcode_matched_list.end());
|
|
result_list.insert(result_list.end(), left_helpcode_matched_list.begin(), left_helpcode_matched_list.end());
|
|
return result_list;
|
|
}
|
|
|
|
template <typename TWordItem>
|
|
std::vector<TWordItem> filter_candidates_with_double_helpcodes(const std::vector<TWordItem> &candidate_list,
|
|
const std::string &help_codes,
|
|
const Keymap *keymap = nullptr)
|
|
{
|
|
std::vector<TWordItem> filtered_list;
|
|
if (help_codes.size() != 2)
|
|
{
|
|
return filtered_list;
|
|
}
|
|
|
|
for (const auto &cand : candidate_list)
|
|
{
|
|
if (matches_double_helpcodes(cand.word, help_codes, keymap))
|
|
{
|
|
filtered_list.push_back(cand);
|
|
}
|
|
}
|
|
|
|
return filtered_list;
|
|
}
|
|
|
|
} // namespace HelpcodeUtils
|