▼ 本文更新于 [2026-05-15 周五 15:35]

emacs-在windows上使用emacs内的rimel进行中文输入


本文全程使用emacs内置的rimel输入法+rime-frost方案写作

Emacs的中文输入一直以来都是一个问题。虽然我们已经有了珠玉在前的sis,可以在Emacs内流畅切换外部输入法,但是在Windows和MacOS上,外部输入法的表现总有一些美中不足:

在Windows上,获取输入法状态的API好像有点问题。根据我个人使用小狼毫的经验来看,当小狼毫在其他程序中切换中英文输入状态时,又或者当你的rime重载后,Emacs往往记住的是先前的状态,导致不得不手动切换一次小狼毫的中英文状态以匹配Emacs内的sis状态。

在MacOS上,问题更加麻烦,广泛使用的Emacs-plus并没有内置的切换输入法API,相反的是GUI Emacs Mac Port有,导致我一直用坛友Lucius的编译脚本为Emacs-plus 打上输入法切换功能的补丁,以适配sis。

而 sis 本身也有一些美中不足。因为它无法判断用户的按键输入是为了在可输入区域内输入文本,还是为了触发一个按键功能,所以在一些时候比较麻烦。比如在 org-agenda 的界面,就可能会出现按下 t 键弹出拼音输入框的问题。但内置的输入法就没有这个困扰,只会在可输入文本的场景出现。

幸好,Emacs内部也能调用动态模组,因此涌现了pyimliberimeemacs-rimerimel等充分利用Emacs内置输入功能以及librime的中文输入模组。其中liberime仅用于提供一个动态模组,将Emacs和外部的librime.dll结合起来,因此暂且不将其列入对比。至于剩下的三者,可以在这里查看比较。

我选用 rimel 的原因其实也很简单,单纯是它比较轻量,安装理论上来说相对更容易。我曾经尝试过在Windows 的 Emacs 上安装 emacs-rime ,最终还是被编译动态模块所劝退了。

1. 安装配置 liberime 和 rimel

因为这两者都上了 melpa 且 rimel 依赖着 liberime ,因此我们在写 use-package 的时候仅需要指明 rimel 即可:

(use-package rimel :ensure t

然后我们参考 rimel 和 liberime 给出的说明,进行一番配置。

首先配置 liberime 的 dll 位置以及相关文件夹。
我把 liberime-core.dll 放在了 ~/.emacs.d/bin/ 路径下,以便在多设备下同步。相关的依赖 DLL ,也在同一个位置,我们后面详解有哪些需要复制过来。

  :custom
  (liberime-module-file "~/.emacs.d/bin/liberime-core.dll")

然后我们设置两个关键的文件夹路径: shared-data-dir 决定了共享的基础 rime 配置文件,每次我们启动 rimel 的时候,都会从这个文件夹和 user-data-dir 读取配置文件,并在 user-data-dir 生成一个直接使用的最终build文件夹。出于一次配置所有设备共享的考虑,我们可以将输入方案放在 shared-data-dir 里面,并将 shared-data-dir 设置到一个跟随 Emacs 配置文件同步的路径中,以便在不同设备中快捷共享配置方案。 user-data-dir 仅用于存储用户个人定制方案和输入数据,我们需要把它放到不同步的路径中(我放在 ~/emacs-local/ 文件夹)。

前者可以先从 liberime 的 release 路径里 /share/rime-data 中复制来。

  (liberime-shared-data-dir "~/.emacs.d/bin/rime-data")
  (liberime-user-data-dir "~/emacs-local/rimel")

这里记得配置一下默认输入法为 rimel

  (default-input-method "rimel")

下面这个变量决定了在什么区域自动关闭输入法进入英文模式。

  ;; 推荐配置:代码区 + 字母后 + 大写字母
  (rimel-disable-predicates
      '(rimel-predicate-prog-in-code-p
        rimel-predicate-after-alphabet-char-p
        rimel-predicate-current-uppercase-letter-p))

这里其实也可以再添加一个 rimel-predicate-org-in-src-block-p ,以便在代码块内自动切换成英文。但是需要注意,它用到的函数 org-in-src-block-p 文档中明确指出:所有在 end 之后的空行都会被计算进 src-block 之内。

Note that affiliated keywords and blank lines after are considered a part of a source block.

所以根据实际情况考虑使用吧。

在 GUI 下使用悬浮框展示候选词

;; 可选:使用 posframe 展示候选(如果安装了 posframe,默认会使用 posframe)
  (rimel-show-candidate 'posframe))

2. 安装配置 DLL

注意,由于我用的 UCRT 版本的 Windows Emacs ,因此后续均以次为参考,请读者自行根据 Emacs 版本选择对应 DLL 。

书接上文,如果我们从 liberime 的 release 中直接下载预编译打包好的 DLL 文件,放到前面指明的 liberime-module-file 路径中,会发现根本没办法启动。

根据尝试,这是因为预编译好的文件中仅在 /bin 里有 liberime.dlllibrime-1.dll ,还缺少这两个 DLL 的依赖文件。

具体依赖文件如下:

libgflags.dll
libglog-2.dll
libleveldb.dll
libmarisa-0.dll
libopencc-1.2.dll
libunwind.dll
libyaml-cpp.dll

最简单的方式就是下载一个msys2,然后安装-配置镜像源-更新,安装一个librime,最后在对应的 版本/bin (比如我是 /ucrt/bin )中找到DLL并拷贝即可。

第二简单的获取方式就是找到 msys2 的 package 界面,搜索需要的文件名,然后点击 「File:」 后面跟随的链接,下载解压,并在 /bin 下找到对应 DLL ,复制出来放到前面指明的 liberime-module-file 路径中即可。

3. 调整 rime 配置方案

假如你以上两步均胜利完成,那么重启 Emacs 之后,轻按 C-\ ,随便按几下键盘,应该就能看见候选词出现在 minibuffer 或者 posframe 中了。但细心的你同样发现,怎么打出来的是繁体字啊?这是因为前面复制的默认使用明月拼音,初始输出就是繁体。幸好,我们可以充分利用 rime 的自定义功能,换成我们想用的方案。

但是在你兴高采烈准备使用各种花里胡哨的方案前,不得不提醒一句:由于我们的 liberime 仅使用了 librime ,因此在许多方案中被广泛使用的 LUA 脚本插件、语言模型插件(octagram)均无法在 liberime 中生效使用,需要我们手动调整方案。

至于使用什么方案,可以参考 rime-frost 的作者搞的 rime-schema 评测,并着重查看其中没有「_with_gram」的结果。根据 2026 年 5 月 12 日的评测结果,rime_frost 句子正确率: 46.88% 、文字正确率: 86.25% 、文字正确率(逐句平均): 84.87% ,排名前列。所以我后续以 rime-frost 方案为例讲解。

我们从 rime-frost 的 release 下载最新方案压缩包,解压之后将里面内容全部复制替换 shared-data-dir 内文件,并直接修改 shared-data-dir 内对应文件。

3.1. 修改默认输入方案

虽然 rimel 提示我们可以通过修改 rimel-schema 变量来修改输入方案,但实践证明没有这个必要,直接修改 default.yaml 就好了。由于我只用小鹤双拼,因此我改为了:

# 方案列表
schema_list:
  # 可以直接删除或注释不需要的方案,对应的 *.schema.yaml 方案文件也可以直接删除
  - schema: rime_frost_double_pinyin_flypy    # 小鹤双拼

然后,进入你选择的方案配置文件中,我这里是 rime_frost_double_pinyin_flypy.schema.yaml ,删除掉其中涉及到 lua 的部分,比如 engine 下,所有以 lua_ 开头的行,都必须删掉。我删除后的结果如下:

# 输入引擎
engine:
  processors:
    - ascii_composer
    - recognizer
    - key_binder
    - speller
    - punctuator
    - selector
    - navigator
    - express_editor
  segmentors:
    - ascii_segmentor
    - matcher
    - abc_segmentor
    - affix_segmentor@radical_lookup  # 部件拆字自定义 tag
    - punct_segmentor
    - fallback_segmentor
  translators:
    - punct_translator
    - table_translator@frost_aux       # ` single-char aux lookup
    - script_translator
    - table_translator@custom_phrase    # 自定义短语 custom_phrase.txt
    - table_translator@melt_eng         # 英文输入
    - table_translator@cn_en            # 中英混合词汇
    - table_translator@radical_lookup   # 部件拆字反查
  filters:
    - reverse_lookup_filter@radical_reverse_lookup  # 部件拆字滤镜
    - simplifier@emoji                              # Emoji
    - simplifier@chaifen
    - simplifier@chaifen_all
    - simplifier@chinese_english
    - simplifier@traditionalize                     # 简繁切换
    - simplifier@mars                               #火星文
    - uniquifier                                    # 去重

3.2. 配置同步

因为同步功能只看用户文件夹,所以我们需要进入 user-data-dir 里,修改 installation.yaml ,添加一行 sync_dir: ,才可以利用 rime 的同步功能。

具体方式与小狼毫或者鼠须管一致,这里不详细展开。

3.3. 一些个人偏好的优化

由于 Emacs 的内部界面寸土寸金,我关闭了候选词备注拼音功能,仅需将 translator:comment_format: 设置为 - xform/.*// 即可。

: 下述内容已于这个 commit 里修复,不再需要。

rimel在启动的时候似乎会错误将 rimel-schema(liberime-current-schema) 进行字符串比较,但后者根本不是一个可行的函数。我们需要手动修改 rimel-active 函数,将

(defun rimel-activate (_name)
  "Activate rimel input method.
Called by Emacs when user selects the \"rimel\" input method.
_NAME is the input method name (unused)."
  (unless (liberime-workable-p)
    (liberime-load))
  (when (and rimel-schema
             (liberime-workable-p)
             (not (string= rimel-schema (liberime-current-schema))))
    (liberime-try-select-schema rimel-schema))
  (setq-local input-method-function #'rimel-input-method)
  (setq-local deactivate-current-input-method-function #'rimel-deactivate))

替换为

(defun rimel-activate (_name)
  "Activate rimel input method.
Called by Emacs when user selects the \"rimel\" input method.
_NAME is the input method name (unused)."
  (unless (liberime-workable-p)
    (liberime-load))
  (when (and rimel-schema
             (liberime-workable-p)
             (not (string= rimel-schema liberime-current-schema)))
    (liberime-try-select-schema rimel-schema))
  (setq-local input-method-function #'rimel-input-method)
  (setq-local deactivate-current-input-method-function #'rimel-deactivate))

内置的 rimel-predicate-org-in-src-block-p 因为直接调用 org-in-src-block-p ,导致代码块换行后难以输入中文。我们直接修改一个自己的判断函数,删去跳过换行、空格功能:

(defun my/rimel-predicate-org-in-src-block-p ()
  "Return non-nil when point is inside an Org source block."
  (and (derived-mode-p 'org-mode)
       (fboundp 'org-in-src-block-p)
       (let ((element (org-element-at-point)))
         (when (org-element-type-p element 'src-block)
           (not (or (<= (line-beginning-position)
                        (org-element-post-affiliated element))
                    (>= (line-end-position)
                        (org-with-point-at (org-element-end element)
                          (point)))))))))

;; 添加进去
(add-to-list 'rimel-disable-predicates 'my/rimel-predicate-org-in-src-block-p)

如果你使用的系统输入法是小狼毫或者鼠须管,可以在对应的 weasel.custom.yaml 或者 squirrel.custom.yaml 中,明确在 Emacs 里切换到英文模式:

下面是weasel

patch:
  app_options:
    emacs.exe:               # 带 .exe 的进程名:Weasel 15.0 及之前版本须小写; PR #1049 合并后释出的版本大小写不敏感
      ascii_mode: true     # 英文模式

下面是squirrel

patch:
  app_options:
    org.gnu.Emacs:
      ascii_mode: true
      no_inline: true

4. 补充说明

4.1. 关于启动报错

如果你一切都配置就绪了,但是发现执行 liberime-load 的时候报错,可能是加载路径的问题,可以考虑将 liberime-module-file 所在路径添加到 Windows 的用户环境变量里,然后重启电脑以重新读取用户环境变量,再启动 Emacs 试试。

4.2. 关于macOS

我也在 macOS 配置了 rimel 。总体和 Windows 上大差不差,仅需从 liberime 的 release 里面下载对应架构的 liberime-core.dylib ,放在路径中,然后 brew install librime 即可。记得配置里分别明确 windows 和 macOS 下的 liberime-module-file 路径。

需要注意一点,我之前设置的 emoji 为 Twitter Emoji ,在按下 e 键的时候报错,取消恢复到 Apple 默认 emoji 之后就正常了。

5. 配置文件

(files--ensure-directory my/desktop-path)
(let ((file "rimel-config.txt"))
  (org-babel-tangle-file (buffer-file-name) (concat my/desktop-path file) "elisp")
  (format "[[https://blog.prayhand13013.top/%s][一键查看上述配置代码汇总]]" file))

一键查看上述配置代码汇总

© Published by Emacs 31.0.50 (Org mode 10.0-pre) | RSS Comment