进阶专题

制作定制版

用 data_custom 目录把清风改造成自己的发行版:换默认方案、改默认配置、删掉不需要的内置内容,主程序升级零冲突

v0.120.1
0.120 新增

这一页是给二次定制的作者看的:你想把清风改造成「虎码版」「小鹤音形版」再分发给自己的用户,而不是自己一个人换套方案用。终端用户不需要读这一页——个人调整走设置界面就够了。

定制层要解决的问题

以前做定制只能直接改发布包里的 data\ 目录:删掉不要的方案、换掉 config.toml、塞进自己的词库。主程序一发新版,data\ 整个被覆盖,你得把上一版的改动逐个文件 diff 回来——每次发版都重来一遍。

定制层的目标只有一句:把你的全部定制内容放进 data_custom\,一个字节都不碰 data\,主程序升级时你的定制毫发无伤。

三层,各管一段

位置谁维护装什么
出厂层安装目录 data\主程序,升级时整个覆盖内置方案、主题、词库、默认配置
定制层安装目录 data_custom\,程序只读不写你这个发行版的方案、主题、默认配置
用户层%APPDATA%\WindInput\终端用户用户自己的个人设置

优先级 出厂 < 定制 < 用户。也就是说:

  • 你能盖掉任何出厂值;
  • 但你永远盖不过终端用户自己的设置。定制版是「换一套出厂配置」,不是「替用户做决定」。用户改过的项,装了你的包也仍然是他改的那个值。

data_custom\data\ 必须同级

第一步:放一个 custom.toml

程序判定「这是定制版」的依据是 data_custom\custom.toml 在场且能解析,不是目录存在。文件内容:

[custom]
id = "huma-edition"        # 稳定标识,日志、关于页、用户报障时用
name = "虎码定制版"          # 显示名
version = "1.2"            # 你这个定制包自己的版本
base_version = "0.119.0"   # 基于哪个主程序版本定制的

[schemas]
hide = ["wubi86", "wubi86_pinyin"]

[themes]
hide = ["msime"]

清单只负责两件事:身份[custom])与减法hide)。加东西、换东西都不用在这里声明。

清单读不出来,整层就当不存在

custom.toml 缺失、语法错、或者用记事本存成了 GBK,后果不是「少了 hide 清单」,而是你的方案、主题、配置全部回落到原版——而程序一切正常,日志里连一条警告都没有。这是最难自查的一种故障,所以打包前请务必跑一次体检

段名 [schemas] / [themes] 都是复数。写成 [schema] 能解析通过,但一个字都不起作用。

你能做的三件事

加 / 换:把文件放进对应位置

data_custom\data\ 目录结构同构。把文件放到对应位置就生效,不需要在清单里声明任何东西。

你放什么覆盖粒度
config.toml按键深合并——你只写想改的键,其余仍取出厂值
schemas\<id>.schema.tomlschemas\<id>\ 下的词库等逐文件覆盖;出厂没有的 id 就是新增方案
themes\<名>\opencc\*.octrie按名逐文件覆盖,同名的用你的,没放的用出厂的
compat.toml按进程名条目合并
pinyin_map.txtsystem.*.tomlschemas\common_chars.txt整表替换:放了就完全替代出厂那份

config.toml 只写差异键

机制上你可以整份复制出厂 config.toml 再改几处,但别这么做。与出厂值相同的键现在看不出区别,可将来主程序调整那个默认值时,你这份旧值会把新默认顶住——本该跟着升级改善的行为,在你的用户那里被冻结了。差异越小,跨版本存活率越高。

删:写进 hide

删掉不需要的内置方案或主题,只能靠清单里的 hide——你没法「删掉」出厂目录里的文件。

[schemas]
hide = ["wubi86", "wubi86_pinyin"]

[themes]
hide = ["msime"]

hide 是绝对的:被 hide 的 id 在任何层都不存在,包括终端用户自己在 %APPDATA%\WindInput\schemas\ 里放的同名文件。所以只 hide 你确实想从这个发行版里移除的内置 id。

如果你只是想让某个方案不出现在切换列表里、但仍然可用(比如英文方案、快符表),那是方案文件里的 hidden,两者不是一回事。

hide 掉的东西不能还被引用着

wubi86 hide 了,却在 config.toml 里让 schema.active = "wubi86"、或者混输成员、特殊模式里还引用着它,程序起来就没有可用方案。体检会把这类引用当错误报出来。

打包前跑一次体检

wind_input config check --custom D:\build\data_custom --data D:\build\data

--data 省略时会自动找 --custom 同级的 data\。这条命令全程离线:不连服务、不读用户配置、一个字节都不写盘,你把安装包解开就能跑,不必先把输入法装起来。

它会替你查出来:

  • 清单本身——缺失、语法错、段名/键名拼错、身份字段没填、base_version 与当前主程序差了几个版本
  • 配置键——已经被移除或从来不存在的键、类型不符、值超出合法范围、把一整段写成了标量
  • 真加载一遍——按运行时同样的方式把你的定制层加载一次,光看配置表看不出来的坏值(映射表里的值、越界的整数)在这里现形
  • 引用面——hide 掉的 id 是否还被别处引用着、hide 的目标在盘上是否真的存在
  • 几个不会报错的静默陷阱——见下

退出码:0 没问题、1 查出了错误、2 命令用法不对。警告不影响退出码,可以直接接进打包脚本。

三个不报错但会坑到用户的写法

这几条的共同点是:程序照常工作、不报错、日志里也没有,但你的用户会遇到怪事。体检都会替你查出来,这里说清楚为什么。

  1. 定制层里不要声明 [keys] key_actionsinput.temp_pinyin.trigger_keysinput.temp_english.trigger_keys 同理)。首次启动时程序会把按键绑定一次性物化进终端用户的个人配置并打上完成标记。此后你在定制包里再改这些绑定,对已经装过旧版包的用户永远不生效——只有全新安装的用户才拿得到新绑定。

  2. data_custom\opencc\ 里的文件名必须与出厂目录逐字相同,含大小写。 简繁转换按文件名跨层取,只放一两本是正常用法(没放的自动用出厂的)。但名字完全对不上MyDict.octrie)的那本在任何平台上都永远取不到;只差大小写stphrases.octrie)在 Windows 和 macOS 上现在能取到,可那是在赌文件系统大小写不敏感,换到区分大小写的环境就失效。届时的现象是「同一个包在这台机器上换了词表、在那台上一个字都没变」。

  3. 映射表的值是数组,不是单个值。 [input.punct.custom_mappings] 要写 "," = [","] 而不是 "," = ","[ui.font.scripts] 同理(latin = ["Consolas"])。写错的后果是那一整段配置在加载时被丢掉换成出厂默认,每个用户、每次启动都会踩到。

分发与升级

data_custom\ 不在官方安装包里,官方安装包也不会删它。所以:

  • 分发——由你自己把 data_custom\ 放进安装目录:可以让用户装完官方包后解压一个压缩包进去,也可以做你自己的安装脚本。
  • 升级——用户装新版官方包时,data\ 被整个覆盖,data_custom\ 原样保留,你的定制立即在新版上继续生效。这正是这套机制存在的意义。
  • 改定制内容——只需要重新分发 data_custom\,不用重打整个安装包。

装好之后确认一下清单真被读到了

在装了你的定制版的机器上,不带参数跑一次 wind_input config check。它会自动找本机的定制层——如果回你「本机不是定制版」,说明清单没被读到,此刻整个定制层是没生效的。

启动日志里也会有对应的一行:定制版 huma-edition「虎码定制版」1.2(基于 0.119.0)

本页目录