DogLooksGood / emacs-rime

RIME ㄓ in Emacs
GNU General Public License v3.0
473 stars 68 forks source link
emacs input-method rime

+TITLE: Emacs Rime

[[https://melpa.org/#/rime][file:https://melpa.org/packages/rime-badge.svg]] [[https://stable.melpa.org/#/rime][file:https://stable.melpa.org/packages/rime-badge.svg]]

[[file:README_EN.org][Document in English]]

[[file:https://i.imgur.com/jHpk7BT.gif]]

+BEGIN_SRC emacs-lisp

;; 默认值 (setq rime-translate-keybindings '("C-f" "C-b" "C-n" "C-p" "C-g" "" "" "" "" "" "" ""))

+END_SRC

** 指定 Rime 共享目录和用户目录

共享目录即 ~rime-share-data-dir~ 是 Rime 安装后放置配置(包括输入方案)的目录, 例如 Linux 上默认为 =/usr/share/rime-data= ,通常使用默认值即可。 如果使用其它的位置,可以配置该值。 例如对于 fcitx5-rime 可能要使用 =~/.local/share/fcitx5/rime= 。

用户目录即 ~rime-user-data-dir~ 为 emacs-rime 布署的位置(包括词频等)。 默认为 =~/.emacs.d/rime= ,如果需要其它位置,可以配置该值。

不建议 ~emacs-rime~ 与 ~fcitx-rime~ 共用用户数据目录 。 以地球拼音方案在 fcitx-rime 与 emacs-rime 中使用为例,若设置

+BEGIN_SRC emacs-lisp

(setq rime-user-data-dir "~/.config/fcitx/rime/")

+END_SRC

,则在 ~emacs-rime~ 初次部署后,将会生成新的 ~terra_pinyin.userdb/~ 文件夹,原有 ~fcitx-rime~ 使用记录将会被移动到 ~terra_pinyin.userdb.old/~ ,此时新的 ~terra_pinyin.userdb.txt~ 中词频为空。

** 打开 Rime 的配置文件

使用 ~rime-open-configuration~ 打开自定义配置文件。

使用 ~rime-open-schema~ 打开一个方案的自定义配置文件。

** 重新部署

+html:

+html: 切换折叠

~emacs-rime~ 的配置文件更新之后,与 RIME 一样,都需要重新部署才可生效。

以添加 ~地球拼音(terra_pinyin)~ 为例。

找到 ~emacs-rime~ 配置所在路径,或使用 ~M-x rime-open-configuration~ 打开文件 ~default.custom.yaml~ ,在 ~patch:schema_list~ 中添加 ~- schema: terra_pinyin~ ,需要 ~M-x rime-deploy~ 重新部署才可启用地球拼音方案,重新部署成功后按 ~C-`~ 选择输入方案。

示例如下:

+BEGIN_SRC yaml

patch: schema_list:

*** 重新部署后原有个人词库丢失?

这很可能是 ~emacs-rime~ 与 ~fcitx-rime~ 共用用户数据文件夹导致的。

如何找回:(依然以地球拼音为例)设置 ~emacs-rime~ 用户数据目录到其他文件夹,删除 ~terra_pinyin.userdb/~ 并将 ~terra_pinyin.userdb.old/~ 重命名为前者,再次同步或部署, ~terra_pinyin.userdb.txt~ 亦将恢复。

+html:

** 同步词库

+html:

+html: 切换折叠

~M-x rime-sync~ 可对 RIME 输入方案和词库进行同步与备份,每次同步双向进行,词库生成的备份文件为 ~sync/ins_id/schema.userdb.txt~ ,其本身是文件夹 ~schema.userdb/~ 中词库与词频使用记录的纯文本形式,方便用户跨平台、多设备使用。

所谓双向同步,即当前设备中的词频或用户自造词( ~schema.userdb/~ 中)与备份文件( ~sync/ins_id/schema.userdb.txt~ 中)所记录的词库会被 RIME 合并,其 并集 将会继续记录在 ~schema.userdb/~ 中,同时生成一份新的备份文件,仍名为 ~sync/ins_id/schema.userdb.txt~ ,并(在不询问用户的情况下)将旧的覆盖。

上述路径中 ~sync~ 文件夹与配置文件 ~default.custom.yaml~ 在同一目录, ~ins_id~ 对应的是 ~installation.yaml~ 文件中 ~installation_id~ 的值,默认值为随机生成,可自定义为其他字符串。

以添加 ~地球拼音(terra_pinyin)~ 后同步为例。启用该方案后,在 RIME 数据目录下会产生名为 ~terra_pinyin.userdb~ 的文件夹,其中为使用频率与自造词的记录,不可随意修改。同步前先修改 ~installation.yaml~ 中内容为自定义的 ~installation_id: "hesperus"~ ,之后 ~M-x rime-sync~ ,将会在 ~sync/hesperus/~ 生成文件 ~terra_pinyin.userdb.txt~ (词库)与 ~terra_pinyin.schema.yaml~ (输入方案)。

若在其他设备或系统中有个人积累的词库,想继续使用。则先在旧系统中进行同步,将生成的 ~terra_pinyin.userdb.txt~ 复制到当前系统的 ~sync/hesperus/~ 下,再进行同步或部署,此时旧系统中备份的词库将会被合并到当前系统的 ~terra_pinyin.userdb/~ ,新的并集也将会被同时导出,并覆盖 ~terra_pinyin.userdb.txt~ 。

+html:

*** 词库同步失败?

+html:

+html: 切换折叠

(以地球拼音方案使用为例。)

建议将不同设备或系统中的 ~installation_id~ 设为同一值 。若其不同,则可能同步失败,即从旧系统同步并复制的 ~terra_pinyin.userdb.txt~ 中的词频记录不会被纳入到当前的 ~terra_pinyin.userdb/~ 。 此时该文件中词频不为空,但其中 ~user_id~ 等不同,修改此值后再次同步仍可能不生效。

+html:

+html:

设置 ~rime-show-candidate~ 。

| 可选值 | 说明 | |------------+--------------------------------------------------------| | ~nil~ | 不展示 | | ~minibuffer~ | 在 minibuffer 中展示, 推荐使用的方式 | | ~message~ | 直接使用 ~message~ 输出,兼容控制 ~minibuffer~ 内容的插件 | | ~popup~ | 使用 ~popup.el~ 展示跟随的候选 | | ~posframe~ | 使用 ~posframe~ 展示跟随的候选,在不可用的时候会用 ~popup~ | | ~sidewindow~ | 使用 ~sidewindow~ 展示跟随的候选 |

** 候选样式

| Face | 说明 | |-------------------------+------------------------------------| | ~rime-default-face~ | 默认的前景色和背景色(仅 posframe) | | ~rime-code-face~ | 编码的颜色 | | ~rime-candidate-num-face~ | 候选序号颜色 | | ~rime-comment-face~ | 编码提示颜色 |

** posframe/popup/sidewindow 候选版式

设置 ~rime-posframe-style~ , ~rime-popup-style~ 或者 ~rime-sidewindow-style~ 可选值有

| 可选值 | 说明 | |------------+------------| | ~simple~ | 单行 | | ~horizontal~ | 水平,默认 | | ~vertical~ | 垂直 |

** posframe 的其它属性

设置 ~rime-posframe-properties~, 其中颜色的设置使用 ~rime-default-face~.

+begin_src emacs-lisp

(setq rime-posframe-properties (list :font "sarasa ui sc" :internal-border-width 10))

+end_src

支持的内容参照 [[https://github.com/tumashu/posframe/blob/master/posframe.el#L212][posframe]] 。

** sidewindow 的其它屬性

设置 ~rime-sidewindow-style~ ,可选值有 ~top~, ~bottom~, ~left~, ~right~ ,分别指 sidewindow 出现的位置位于上下左右。

设置 ~rime-sidewindow-keep-window~ ,为 ~t~ 时可保持 sidewindow 为开启状态。

** 彩色指示标志

可用 ~(rime-lighter)~ 得到彩色指示标志 ~ㄓ~. 可将其放在 modeline 等任意地方。

可用 ~rime-title~ 、 ~rime-indicator-face~ 和 ~rime-indicator-dim-face~ 来自定义。 ** 设置软光标的样式

默认使用 ~|~ 字符做为软光标,可以通过如下方式修改。

+BEGIN_SRC emacs-lisp

(setq rime-cursor "˰")

+END_SRC

颜色可通过 ~rime-cursor-face~ 设置。

** 设置嵌入文本的样式

可通过 ~rime-preedit-face~ 设置。

** 编码的展示形式

设置 ~rime-show-preedit~, 可选值有 | 可选值 | 说明 | |--------+--------------| | ~t~ | 展示在菜单中 | | ~inline~ | 替换上屏预览 | | ~nil~ | 不展示 |

注意:使用 ~inline~ 或 ~nil~ 将不再展示软光标。

+html:

一个在 ~evil-normal-state~ 中、在英文字母后面以及代码中自动使用英文的例子。

+BEGIN_SRC emacs-lisp

(setq rime-disable-predicates '(rime-predicate-evil-mode-p rime-predicate-after-alphabet-char-p rime-predicate-prog-in-code-p))

+END_SRC

*** 目前可用的断言函数

+html:

+html: 切换折叠

+html:

*** 可提示临时英文状态的提示符

使用函数 ~(rime-lighter)~ 返回一个用于展示的 ~ㄓ~ 符号。 可以通过 ~rime-indicator-face~ 和 ~rime-indicator-dim-face~ 设置样式。

如下设置可替换输入法的符号,使其用颜色提示当前的临时英文状态。

+begin_src emacs-lisp

;;; 具体参考 mode-line-mule-info 默认值,其中可能有其它有用信息 (setq mode-line-mule-info '((:eval (rime-lighter))))

+end_src

*** 基于 Rime inline ascii 模式的临时英文

设置 ~rime-inline-predicates~ ,结构与 ~rime-disable-predicates~ 相同,具有较低优先级。

这个功能主要用来实现输入带空格的临时英文的场景。

由于当前实现限制,如果 Rime 配置中没有使用默认的 ~Shift_L~ 切换 inline ascii 模式,需要在 emacs-rime 中指定。 两边配置相同才能正常激活。

+begin_src emacs-lisp

;;; support shift-l, shift-r, control-l, control-r (setq rime-inline-ascii-trigger 'shift-l)

+end_src

在有编码的状态下使用 ~rime-inline-ascii~ 命令可以切换状态。

+begin_src emacs-lisp

(define-key rime-active-mode-map (kbd "M-j") 'rime-inline-ascii)

+end_src

*** 临时英文中阻止标点直接上屏

+begin_src emacs-lisp

(setq rime-inline-ascii-holder ?x) ; Any single character that not trigger auto commit

+end_src

** 断言成立时的强制中文模式 使用 ~rime-force-enable~ 来临时强制使用强制中文模式(即无视 ~rime-disable-predicates~ 中的规则), 在 一次输入行为取消输入* 之后会自动关闭强制中文模式。

你可能需要给这个命令绑定一个按键来使用。

+begin_src emacs-lisp

(define-key rime-mode-map (kbd "M-j") 'rime-force-enable)

+end_src

+html:

** Commit1 自动上屏 emacs-rime 内置了 =rime-commit1= 函数,其作用是在输入状态下将候选框中的首项自动上屏。

这对于不注重(或几乎不需要)选重、且码长可不固定(即简码)的输入方案,如纯形码、音形码等(尤其是顶功类方案)而言,非常有用。

此函数不是针对单独使用的,而主要是为了配合自定义其它函数,以适应个人的各种使用场景。 *** 实例:在切换输入法时首项自动上屏 在切换输入法时首项自动上屏,这是 fcitx5-rime 等所支持的功能。 这里就以在 emacs-rime 中实现相同功能为例,说明如何使用 =rime-commit1= 函数。

基本思路是,先自定义一个函数,功能是先使得首项自动上屏,再切换输入法; 再将这个函数绑定到某个按键组合上,来替代原本 ~toggle-input-method~ 的功能。

示例配置如下:

+begin_src elisp

(defun rime-commit1-and-toggle-input-method () "Commit the 1st item if exists, then toggle input method." (interactive) (ignore-errors (rime-commit1)) (toggle-input-method))

(global-set-key (kbd "C-;") #'rime-commit1-and-toggle-input-method)

+end_src

这里使用了 =ignore-errors= 来防止在初次切换输入法时 =rime-commit1= 未被加载而报错。 在此配置生效后,按 =C-;= 即可使首项自动上屏并切换输入法。 *** 对任意无关函数首项自动上屏 若你有很多函数需要在其执行前首项自动上屏,而又不想对它们一个个进行自定义函数与绑定的配置,你可以设置对任意与 emacs-rime 无关函数的首项自动上屏。

机制:

示例配置如下:

+begin_src elisp

(setq rime-commit1-forall t)

+end_src

*** 按 ESC 时首项自动上屏 上述全局设置,不能使得在输入时按 ESC 时首项也自动上屏,这里给出针对性的配置方法。

机制:在 emacs-rime 的输入状态下,ESC 被绑定到了 =rime--escape= 函数上,此函数显然不是“与 emacs-rime 无关的函数”。

实例:以 evil 插件为例,若要使得 ESC 能自动上屏并切换到 evil 的 normal state,可以先自定义函数,并将此函数绑定到 ESC 上。 (注:至少对于 evil 插件而言, =C-[= 和 =ESC= 被 emacs 当作同一按键,所以不需要对 =C-[= 另行绑键。)

示例配置如下:

+begin_src elisp

(defun rime-commit1-and-evil-normal () "Commit the 1st item if exists, then go to evil normal state." (interactive) (rime-commit1) (evil-normal-state)) (define-key rime-active-mode-map (kbd "") 'rime-commit1-and-evil-normal)

+end_src

** 在 minibuffer 使用后自动关闭输入法

默认行为为自动关闭,设置 ~rime-deactivate-when-exit-minibuffer~ 为 nil 取消该行为。

** 结合 evil-escape 一起使用

+html:

+html: 切换折叠

以下代码可能有性能问题

在你的配置中添加如下内容,即可在当前没有输入内容(没有 preedit overlay)的情况 下,用[[https://github.com/syl20bnr/evil-escape][evil-escape]]的按键回到 normal 模式。

+BEGIN_SRC emacs-lisp

(defun rime-evil-escape-advice (orig-fun key) "advice for rime-input-method' to make it work together withevil-escape'. Mainly modified from evil-escape-pre-command-hook'" (if rime--preedit-overlay ;; ifrime--preedit-overlay' is non-nil, then we are editing something, do not abort (apply orig-fun (list key)) (when (featurep 'evil-escape) (let ( (fkey (elt evil-escape-key-sequence 0)) (skey (elt evil-escape-key-sequence 1)) ) (if (or (char-equal key fkey) (and evil-escape-unordered-key-sequence (char-equal key skey))) (let ((evt (read-event nil nil evil-escape-delay))) (cond ((and (characterp evt) (or (and (char-equal key fkey) (char-equal evt skey)) (and evil-escape-unordered-key-sequence (char-equal key skey) (char-equal evt fkey)))) (evil-repeat-stop) (evil-normal-state)) ((null evt) (apply orig-fun (list key))) (t (apply orig-fun (list key)) (if (numberp evt) (apply orig-fun (list evt)) (setq unread-command-events (append unread-command-events (list evt)))))) ) (apply orig-fun (list key)))))))

(advice-add 'rime-input-method :around #'rime-evil-escape-advice)

+END_SRC

+html:

+html:

假设你为菜单使用 ~C-~~ 。

+begin_src yaml

switcher: caption: 〔方案選單〕 hotkeys:

你可用函数 ~rime-send-keybinding~ 将此按键绑定到 ~rime-mode-map~ 。

+begin_src emacs-lisp

(use-package ...

:bind
(:map rime-mode-map
      ("C-`" . 'rime-send-keybinding))
...
)

+end_src

+html:

目前在 isearch 中不能正常工作,但是可以使用 [[https://github.com/zk-phi/phi-search][phi-search]].

** 候选框最后一项不显示?

+html:

+html: 切换折叠

极少数用户下会偶尔出现最后一个候选词不显示的情况,可以确定跟 posframe 有关,但 目前尚未找到原因,有一个暂时的解决办法,就是给候选词列表最后附加一个全角空格,这 样即使出现“吃字”的情况也只是把末尾的全角空格“吃”掉,不会影响候选词的显示。 代码如下:

+BEGIN_SRC emacs-lisp

(defun +rime--posframe-display-content-a (args) "给 rime--posframe-display-content' 传入的字符串加一个全角空 格,以解决posframe' 偶尔吃字的问题。" (cl-destructuring-bind (content) args (let ((newresult (if (string-blank-p content) content (concat content " ")))) (list newresult))))

(if (fboundp 'rime--posframe-display-content) (advice-add 'rime--posframe-display-content :filter-args

'+rime--posframe-display-content-a)

(error "Function `rime--posframe-display-content' is not available."))

+END_SRC

+html:

** 无需 librime 纯 Emacs 实现的输入法?

你可能需要 [[https://github.com/tumashu/pyim][pyim]].

+html: