tumashu / pyim

一个 emacs 中文输入法,支持全拼,双拼,五笔,仓颉和Rime,pyim 是 GNU elpa 包。
891 stars 93 forks source link

多台机器同步词库想法 #423

Closed lld2001 closed 2 years ago

lld2001 commented 2 years ago

搜了下 issue,多台机器之间同步个人词库没有找到好的方法。有个想法,不知道可不可行,请帮忙看下:

  1. 每次关闭emacs时导出个人词库,把 pyim-export-personal-words 放在 kill-emacs-hook里。
  2. 导出的词库文件位置由git管理,方便多台之间合并词库。
  3. 通过下面方式加载。此处有疑问,由于各台机器之间本身有 cache,并且不同。这样会不会引起重复加载问题?加载优先级问题
    (setq pyim-dicts
      '((:name "dict1" :file "/path/to/pyim-dict1.pyim")
        ))
  4. 有没有更好方法?
tumashu commented 2 years ago

你如果使用五笔,就不必在意个人词库,因为个人词库主要是给拼音输入法用的

tumashu commented 2 years ago

可以试试 pyim-export-words-and-counts ,这个有对应的导入命令,不过只适用于拼音输入法,并且多音字处理有点粗糙

lld2001 commented 2 years ago

我是想要导出词库的。因为在emacs 里用pyim五笔造词太方便了。

导出后,再加载是不是只要设置pyim-dicts就行?cache不用管了吗?

tumashu commented 2 years ago

你这种情况,设置pyim-dicts应该就可以了,记得pyim-restart, pyim-dicts变量一更改,cache相应的也会更新

tumashu commented 2 years ago

我刚刚更新了一下pyim-export-words-and-count, 型码输入法应该也可以使用了

在 2021-12-18 21:39:16,lld2001 @.***> 写道:

我是想要导出词库的。因为在emacs 里用pyim五笔造词太方便了。

导出后,再加载是不是只要设置pyim-dicts就行?cache不用管了吗?

— Reply to this email directly, view it on GitHub, or unsubscribe. Triage notifications on the go with GitHub Mobile for iOS or Android. You are receiving this because you commented.Message ID: @.***>

lld2001 commented 2 years ago

用 pyim-export-words-and-counts 和对应的 import 试了下,似乎没有考虑重码。

tumashu commented 2 years ago

重码是啥意思?

在 2021-12-19 08:38:10,lld2001 @.***> 写道:

用 pyim-export-words-and-counts 和对应的 import 试了下,似乎没有考虑重码。

— Reply to this email directly, view it on GitHub, or unsubscribe. Triage notifications on the go with GitHub Mobile for iOS or Android. You are receiving this because you commented.Message ID: @.***>

lld2001 commented 2 years ago

许是我用法有误?

pyim-import-words-and-counts导入词库:

;;; -*- coding: utf-8-unix -*-
绿春 1
绍砂 1

然后,再用pyim-export-personal-words导出词库:

;;; -*- coding: utf-8-unix -*-
wubi/xvdw 绿春
wubi/xvdi 绍砂
shao-sha 绍砂

问题:包含了 拼音的 导出了

tumashu commented 2 years ago

正常,你个人缓存里面有什么就导出什么,这也是为什么要添加wubi/前缀的原因

在 2021-12-19 08:54:34,lld2001 @.***> 写道:

许是我用法有误?

pyim-export-words-and-counts导入词库:

;;; -- coding: utf-8-unix --

绿春 1

绍砂 1

然后,再用pyim-export-words-and-counts导出词库:

;;; -- coding: utf-8-unix --

wubi/xvdw 绿春

wubi/xvdi 绍砂

shao-sha 绍砂

问题:包含了 拼音的 导出了

— Reply to this email directly, view it on GitHub, or unsubscribe. Triage notifications on the go with GitHub Mobile for iOS or Android. You are receiving this because you commented.Message ID: @.***>

tumashu commented 2 years ago

以前的导入命令默认就是拼音,我今天刚刚将这个限制去掉,所以你以前如果用过这个命令,那么个人词库缓存中就包含拼音了,导出的时候当然也会有

在 2021-12-19 08:54:34,lld2001 @.***> 写道:

许是我用法有误?

pyim-export-words-and-counts导入词库:

;;; -- coding: utf-8-unix --

绿春 1

绍砂 1

然后,再用pyim-export-words-and-counts导出词库:

;;; -- coding: utf-8-unix --

wubi/xvdw 绿春

wubi/xvdi 绍砂

shao-sha 绍砂

问题:包含了 拼音的 导出了

— Reply to this email directly, view it on GitHub, or unsubscribe. Triage notifications on the go with GitHub Mobile for iOS or Android. You are receiving this because you commented.Message ID: @.***>

lld2001 commented 2 years ago

好的,那我只用:pyim-export-words-and-counts.

现在可以了,经过几次导入导出,我上面的想法实现了。以后在各台机器间可以同步词库了。

lld2001 commented 2 years ago

最后没有用设置 pyim-dicts 的方法,用了以下配对的导入导出:

(pyim-import-words-and-counts (concat (borg-worktree "z-init") "etc/dict.pyim") nil t)
(pyim-export-words-and-counts (concat (borg-worktree "z-init") "etc/dict.pyim"))
lld2001 commented 2 years ago

经过在多台机器实测,已经正常,谢谢帮助。

lld2001 commented 2 years ago

请教默认词库的词频数值是多少?

我在用上述方法管理词库及词频时,词频更新过快,导致 dict.pyim 文件更新太频繁。现在解决办法是直接将词频设置为2 (用:(lambda (num1 num2) 2)),可以减少导出的 dict.pyim 更新频率。

故请教下默认词频。

(pyim-import-words-and-counts   "etc/dict.pyim"   (lambda (num1 num2) 2)  t)
lld2001 commented 2 years ago

五笔重码低,我的想法是词频大于默认就行。

(defun pyim-dhashcache-export-words-and-counts (file &optional confirm)
  (with-temp-buffer
    (insert ";;; -*- coding: utf-8-unix -*-\n")
    (maphash
     (lambda (key value)
       (insert (format "%s %s\n" key value)))
     pyim-dhashcache-iword2count)
    ;; 在默认情况下,用户选择过的词生成的缓存中存在的词条,
    ;; `pyim-dhashcache-iword2count' 中也一定存在,但如果用户
    ;; 使用了特殊的方式给用户选择过的词生成的缓存中添加了
    ;; 词条,那么就需要将这些词条也导出,且设置词频为 0
    (maphash
     (lambda (_ words)
       (dolist (word words)
         (unless (gethash word pyim-dhashcache-iword2count)
           (insert (format "%s %s\n" word 0)))))
     pyim-dhashcache-icode2word)
    (pyim-dcache-write-file file confirm)))

我查看了导出函数,下面这段能不能像导入一样暴露个计算词频的函数出来,这样形码就直接按词优先顺序递减来计算词频。

(maphash
     (lambda (key value)
       (insert (format "%s %s\n" key value)))
     pyim-dhashcache-iword2count)
tumashu commented 2 years ago

导出的时候,你缓存里面保存的是多少,就导出多少,导入的时候因为有两个词频数据,所以我提供了一个函数用来合并词频

tumashu commented 2 years ago

默认词频就是0

lld2001 commented 2 years ago

那可能拼音跟五笔不一样。五笔我觉得有个优先顺序就行了。还有就是词频统计时,如果词就在第一个,能不能就不要加词频?

lld2001 commented 2 years ago

我能不能改下这个函数签名, export-words-and-counts改成一个参数,不要写死,这样可以自定义下导出词频的处理方式

(defun pyim-dcache-export-words-and-counts (file &optional confirm)
  "将个人词条以及词条对应的词频信息导出到文件 FILE.

如果 FILE 为 nil, 提示用户指定导出文件位置, 如果 CONFIRM 为
non-nil,文件存在时将会提示用户是否覆盖,默认为覆盖模式"
  (interactive "F将词条和词频信息导出到文件: ")
  (pyim-dcache-init-variables)
  (pyim-dcache-call-api 'export-words-and-counts file confirm)
  (message "PYIM: 词条和词频信息导出完成。"))
tumashu commented 2 years ago

我建议你自定义一个导出函数吧,更灵活。

(defun my_export (file)
  (with-temp-buffer
    (insert ";;; -*- coding: utf-8-unix -*-\n")
    (maphash
     (lambda (key _)
       (insert (format "%s\n" key)))
     pyim-dhashcache-iword2count)
    (pyim-dcache-write-file file)))

如果不导出词频,功能和命令名称就不对应了,不合理。

lld2001 commented 2 years ago

好的,我试试。我产意思不是不导出词频,而是把词频 再排序。以1为基准重新排下。这样可能降低词库文件更新频率。

tumashu commented 2 years ago

我添加了一个 ignore-counts 参数,估计可以满足你的需求

lld2001 commented 2 years ago

我的想法是像这样,导出时重新从1开始排列下词频:

(defun pyim-dhashcache-export-words-and-reorder-counts (file &optional confirm ignore-counts)
  (with-temp-buffer
    (insert ";;; -*- coding: utf-8-unix -*-\n")
    (maphash
     (lambda (key value)
       (if ignore-counts
           (insert (format "%s\n" key))
         (let ((i 1))
           (dolist (word (reverse value))
             (insert (format "%s %s\n" word i))
             (setq i (1+ i))))))
     pyim-dhashcache-icode2word)
    ;; 在默认情况下,用户选择过的词生成的缓存中存在的词条,
    ;; `pyim-dhashcache-iword2count' 中也一定存在,但如果用户
    ;; 使用了特殊的方式给用户选择过的词生成的缓存中添加了
    ;; 词条,那么就需要将这些词条也导出,且设置词频为 0
    (maphash
     (lambda (_ words)
       (dolist (word words)
         (unless (gethash word pyim-dhashcache-iword2count)
           (insert
            (if ignore-counts
                (format "%s\n" word)
              (format "%s %s\n" word 0))))))
     pyim-dhashcache-icode2word)
    (pyim-dcache-write-file file confirm)))

然后调用时换成:

(defun pyim-dcache-export-words-and-counts (file &optional confirm ignore-counts)
  "将个人词条以及词条对应的词频信息导出到文件 FILE.

如果 FILE 为 nil, 提示用户指定导出文件位置, 如果 CONFIRM 为
non-nil,文件存在时将会提示用户是否覆盖,默认为覆盖模式"
  (interactive "F将词条和词频信息导出到文件: ")
  (pyim-dcache-init-variables)
  (pyim-dcache-call-api 'export-words-and-reorder-counts file confirm ignore-counts)
  (message "PYIM: 词条和词频信息导出完成。"))
lld2001 commented 2 years ago

这样导出的文件变更不会太频繁,只是不知道这样改有没有什么副作用。

还有就是如果是第一个候选项,应该就不要增加词频。

tumashu commented 2 years ago

pyim 里面的词频就是某个词被选择的次数,我倾向于不做转换。

tumashu commented 2 years ago
这样导出的文件变更不会太频繁

文件变更频繁不频繁好像没什么影响吧, 你又不需要通过文本来merge词库,你把所有的文件统统导入,然后再导出,不就是合并了吗?

lld2001 commented 2 years ago

文件变更频繁不频繁好像没什么影响吧, 你又不需要通过文本来merge词库

我是在两台机器上使用,导出词库文件 dict.pyim 由git管理。因两台机器都有可能改变词频,经常发生冲突(词频数字不一),需要手动 merge。

请教你是怎么在不同机器之间同步词库、词频的?

tumashu commented 2 years ago

你可以将两台机器上的文件导出为两个文件,然后写个循环把两个文件都导入,不就不需要解决冲突了吗?

lld2001 commented 2 years ago

这样就变手动了。我现在将词库纳入 git, 可以自动合并。

词频更新时,如果词就在第一个,就不要加词频,对五笔较好,请教这要怎么hack下?

tumashu commented 2 years ago

为什么变手动了?

lld2001 commented 2 years ago

比如工作时,一台工作电脑,使用 pyim 后,个性化一堆词语和词频。回家后,一台家里电脑,使用 pyim 后,也是个性化一堆词语和词频。

现在我的方式是,退出工作电脑,生产新 dict,第二天git提交。家里电脑也一样。两边提交时 git 自动合并。

lld2001 commented 2 years ago

如果两边都要导出,就得先集中两个词库文件。

tumashu commented 2 years ago
如果两边都要导出,就得先集中两个词库文件。

不需要,你把两个文件都导入,他们自动会在pyim缓存中集中。

tumashu commented 2 years ago

这也是用 count 的好处,因为 pyim 中词频表示你输入某个词的次数,所以无论在哪里,按照这个词频排序都是合理的。

lld2001 commented 2 years ago

工作和家不在一处,集中两个文件不方便。

lld2001 commented 2 years ago

pyim-dhashcache-icode2word和pyim-dhashcache-iword2count两者中的词是不是一致的?

tumashu commented 2 years ago
工作和家不在一处,集中两个文件不方便。

你不是用 git 管理文件么, 一个文件和两个文件有区别吗?

lld2001 commented 2 years ago

哈,那我其实还有一台机器,还会生成词库。我先按reorder的方式用用看。

tumashu commented 2 years ago

我说的合并是指:

(dolist (file '(file1 file2 file3))
  (pyim-import-words-and-counts file nil t))
lld2001 commented 2 years ago

嗯,理解了。这个导入是要放 pyim-restart-1 之前还是之后。用得 daemon。

tumashu commented 2 years ago

试试 pyim-load-hook

tumashu commented 2 years ago

你放到 pyim-restart-1 之后也可以,我感觉

lld2001 commented 2 years ago

多谢啦。

词频更新时,如果词就在第一个,就不要加词频,对五笔较好,请教这要怎么hack下?

这个我这样解决了,在第一个时,不更新词频:

(defun pyim-select-word:xingma ()
  "从选词框中选择当前词条,然后删除该词条对应编码。"
  (interactive)
  (pyim-process-outcome-handle 'candidate)
  (if (pyim-process-with-entered-buffer
        (and (> (point) 1)
             (< (point) (point-max))))
      (progn
        (pyim-process-with-entered-buffer
          ;; 把本次已经选择的词条对应的子 entered, 从 entered
          ;; 字符串里面剪掉。
          (delete-region (point-min) (point)))
        (pyim-process-run))
    ;; 型码输入法,只考虑将词条保存到个人词库,用于调整词频,单字不保存。
    (unless (pyim-process-select-subword-p) ;NOTE: 以词定字的时候,到底应不应该保存词条呢,需要进一步研究。
      (let ((outcome (pyim-process-get-outcome))
            (candidates (pyim-process-get-candidates)))
        (unless (or (= (length outcome) 1)
                    (equal outcome (car candidates)))
          (if (member outcome candidates)
              (pyim-process-create-word outcome t)
            (pyim-process-create-word outcome)))))
    (pyim-process-terminate)
    ;; pyim 使用这个 hook 来处理联想词。
    (run-hooks 'pyim-select-finish-hook)))

只是不知道是不是只有这个函数要改

tumashu commented 2 years ago
词频更新时,如果词就在第一个,就不要加词频

目的是什么?

lld2001 commented 2 years ago

就五笔说下我的理解,看上面的注释:

;; 型码输入法,只考虑将词条保存到个人词库,用于调整词频,单字不保存。

由于五笔重码低,也没有自动造词。如果要输入的词是 候选词 中第一个,直接按 SPC 输入即可,没必要增加词频。

因为,增加它的词频也没有改变词的顺序。反而这样会额外导致调用 (pyim-process-create-word outcome t),重复生成已经存在的词,导致导出的 dict.pyim 文件也会有大量冗余的词。

tumashu commented 2 years ago
    ;; 型码输入法,只考虑将词条保存到个人词库,用于调整词频,单字不保存。
    (unless (pyim-process-select-subword-p) ;NOTE: 以词定字的时候,到底应不应该保存词条呢,需要进一步研究。
      (when (> (length (pyim-process-get-outcome)) 1)
        (if (member (pyim-process-get-outcome) (pyim-process-get-candidates))
            (pyim-process-create-word (pyim-process-get-outcome) t)
          (pyim-process-create-word (pyim-process-get-outcome)))))

要不把这段代码删除得了, 是不是型码输入法大多数不需要动态调整词频。

lld2001 commented 2 years ago

我觉得还是需要的,比如:khyy这个编码,目前对应:“中文、中方、遗言”三个候选词,按照最近输入过的还会再次输入原则,输入“中方”后,我觉得还是有必要把它提前,这样下次直接按 空格 就能输入。

至于如果输入的是“中文”,我就不希望再更新词频,保持原样就好。

tumashu commented 2 years ago

如果这样考虑,我觉得逻辑就没问题, 无论你按数字还是按空格,都是输入过某个词,那这个词的 count 理所当然要加1,这个逻辑上我感觉没问题。

tumashu commented 2 years ago
导致导出的 dict.pyim 文件也会有大量冗余的词。

这个正常,这是你输入过的词,应该导出。

tumashu commented 2 years ago
增加它的词频也没有改变词的顺序。

这个只不顾没实现而已,因为以前有人反映过,不希望词的位置频繁变动。