本文来自依云's Blog,转载请注明。
自从用上了 fcitx5-android,我便面临一个问题:我有多份 fcitx5 实例在运行,也导致我有多份码表文件。于是时常遇到一个词明明我添加到码表里了,但用的时候却发现它并不在的情况。一开始我只是以电脑上的为准,时不时把手机上的码表文件覆盖一下以保存同步。但情况随着我又买了台式电脑而更加严重起来,盲目地覆盖势必会丢失更多前不久刚添加的新词。是时候弄个新的方案了。
新方案的主旨就是「合并」:如果我在一个实例里添加了某词,那么在其它实例上也添加;删除同理。于是来到了 git 的模型——先指定一个共同的基准,合并的双方都与之比较,多起来的就添加到另一方、少了的就从另一方删除。至于基准的选择也很好决定:指定一个已知同步了的 btrfs 快照里的码表就好了,然后每隔一段时间更新到最近同步过的快照。
接下来就是实现了。fcitx5 的码表格式比较复杂,不过它有提供 libime_tabledict 命令,可以把码表数据转换成纯文本格式。至于对比之后的修改,倒不用再用这个命令转回来,因为我已经有 fcitx5-tabledict 这个编辑工具了。编辑好之后需要重新加载码表。以前我都是先退出 fcitx5,编辑完再启动的。现在 Wayfire 有 bug,重启输入法程序有概率导致它崩溃,查了很久都没能查明原因,就只好想办法绕过了。于是在群里问到了重新加载码表的 D-Bus 接口。Android 那边就用 adb 重启应用吧。
对比的程序也是用 Rust 写的,毕竟效率高、还不容易写出问题来。项目放 GitHub 上了,叫 fcitx5-dictsync。至于最上层完成所有操作的脚本,因为有太多具体环境相关的信息,用 zsh 脚本写就好啦。下边是我两台电脑同步的脚本:
#!/bin/zsh -e base_snap=2024-07-28-11-auto dir=$(mktemp -d -t dictsync.XXXXXX) cleanup () { rm -rf $dir } trap cleanup EXIT INT TERM cd $dir scp lilyforest:.local/share/fcitx5/table/lilywb.'*'.dict . fcitx5-dictsync /run/ssd/snapshots/home-lilydjwg/$base_snap/.local/share/fcitx5/table/lilywb.main.dict ~/.local/share/fcitx5/table/lilywb.main.dict lilywb.main.dict a.change b.change if [[ -s a.change ]]; then fcitx5-tabledict < a.change dbus-send --print-reply=literal --dest=org.fcitx.Fcitx5 /controller org.fcitx.Fcitx.Controller1.SetConfig string:fcitx://config/addon/table/reloaddict variant:string:"" fi if [[ -s b.change ]]; then scp b.change lilyforest:tmpfs ssh -T lilyforest <<SH fcitx5-tabledict < ~/tmpfs/b.change dbus-send --print-reply=literal --dest=org.fcitx.Fcitx5 /controller org.fcitx.Fcitx.Controller1.SetConfig string:fcitx://config/addon/table/reloaddict variant:string:"" rm ~/tmpfs/b.change SH fi
和 fcitx5-android 同步的脚本,长得挺像的。但因为 Android 上经常多出来一些奇奇怪怪的自动造的词,所以添加了编辑操作。听说新版 Android 已经不能访问应用自己的目录了,但我还没用上,所以我先不管啦。
#!/bin/zsh -e base_snap=2024-07-28-11-auto adb connect phone_xz2c:5555 dir=$(mktemp -d -t dictsync.XXXXXX) cleanup () { rm -rf $dir } trap cleanup EXIT INT TERM cd $dir scp phone_xz2c:/sdcard/Android/data/org.fcitx.fcitx5.android/files/data/table/lilywb.'*'.dict . fcitx5-dictsync /run/ssd/snapshots/home-lilydjwg/$base_snap/.local/share/fcitx5/table/lilywb.main.dict ~/.local/share/fcitx5/table/lilywb.main.dict lilywb.main.dict a.change b.change if [[ -s a.change ]]; then vim a.change if [[ -s a.change ]]; then fcitx5-tabledict < a.change dbus-send --print-reply=literal --dest=org.fcitx.Fcitx5 /controller org.fcitx.Fcitx.Controller1.SetConfig string:fcitx://config/addon/table/reloaddict variant:string:"" fi fi if [[ -s b.change ]]; then fcitx5-tabledict lilywb.main.dict lilywb.user.dict < b.change scp lilywb.user.dict phone_xz2c:/sdcard/Android/data/org.fcitx.fcitx5.android/files/data/table/ adb -s phone_xz2c:5555 shell am force-stop org.fcitx.fcitx5.android fi
哦对了,Windows 上虽然还没有 fcitx5,但是托 WubiLex 的福,微软五笔的码表位置和格式都弄清楚了。我还没写生成 .lex 文件的程序啦。先在虚拟机里用 WubiLex 生成了一份自己的码表。虽然词的顺序有很大的问题,但反正我也很少用 Windows,先凑合用着吧,懒得处理了。码表文件要放到 C:\Windows\InputMethod\CHS\ChsWubi.lex
。这个文件只有「TrustedInstaller」用户才有权限修改,不过用管理员权限就可以更改文件的所有者,然后就有权限给自己修改权限,就可以修改它了。Windows 真神奇啊。
Jul 29, 2024 11:41:24 PM
这个能不能直接用syncthing 之类的同步?
Jul 30, 2024 10:08:28 AM
直接同步文件有两个问题:会相互覆盖修改;同步完成时无法通知 fcitx5 重新加载。