(重新设计)中英文混打:OS输入法管理包 smart-input-source

我才发现,原来之前有人在 Github 提过这个问题:

PS:其实我之前也攒了一些小改进,在本坛存个档,或许有遇到类似问题的坛友:

1、避免在 minibuffer 中激活 inline

(define-advice sis--inline-check-to-activate
    (:around (orig) no-minibuffer)
  (unless (minibufferp)
    (funcall orig)))

否则,至少在我使用 vertico 时,如果激活了 inline,那么增加的 inline overlay 会使得候选项为空。

2、支持 universal-argument 的自动切换英文输入法(就如同这些键被绑定了 sis--prefix-override-handler

(define-advice universal-argument
    (:around (orig) sis)
  (funcall orig)
  (when sis-global-respect-mode
    (setq sis--prefix-handle-stage 'prefix)
    (sis--respect-pre-command-handler)))
(define-advice universal-argument-more
    (:around (orig &rest arg) sis)
  (apply orig arg)
  (when sis-global-respect-mode
    (setq sis--prefix-handle-stage 'prefix)
    (sis--respect-pre-command-handler)))
(define-advice negative-argument
    (:around (orig &rest arg) sis)
  (apply orig arg)
  (when sis-global-respect-mode
    (setq sis--prefix-handle-stage 'prefix)
    (sis--respect-pre-command-handler)))
(define-advice `digit-argument`
    (:around (orig &rest arg) sis)
  (apply orig arg)
  (when sis-global-respect-mode
    (setq sis--prefix-handle-stage 'prefix)
    (sis--respect-pre-command-handler)))

为什么不将这些键加入 sis-prefix-override-keys 呢?因为这些键太多了,比如在 Doom Emacs 下,evil normal state 直接敲击键盘上的数字键,就都是 digit-argument 命令。

3、如果你想手动进入 inline 模式(不想「输入空格」供其检测符合断言才进入、之后再手动删去)

(defun sis-inline-mode-force ()
  (interactive)
  (when (eq sis--for-buffer 'other)
    (setq sis--prefix-handle-stage 'normal)
    (add-transient-hook! 'post-self-insert-hook
      (when (eq last-command 'sis-inline-mode-force)
        (sis--inline-activate 'english (1- (point)))))))

这里的 add-transient-hook! 是 Doom Emacs 中的函数,是为了增加一个只运行一次的 hook/advice。如果不是 Doom 想用的话,得去抄一下这个宏的定义。

4、Doom Emacs 下,不同 evil state 光标颜色不同,让 sis 考虑这一点

(defun my/sis--set-cursor-color-advice (color)
  (pcase sis--current
    ('english
     (cond ((or evil-insert-state-minor-mode evil-normal-state-minor-mode) (list (get 'cursor 'evil-normal-color)))
           (evil-emacs-state-minor-mode (list (get 'cursor 'evil-emacs-color)))
           (t (list sis-default-cursor-color))))
    ('other
     (list sis-other-cursor-color))
    (_
     color)))
(advice-add 'sis--set-cursor-color-advice :override #'my/sis--set-cursor-color-advice)

5、利用 idle 实时切换输入法状态(比如,在 evil insert/emacs state 下,在英文内容和中文内容之间移动光标,就可以自动切换输入法)

(defvar my/idle-command-for-sis-timer nil)
(defun my/idle-command-for-sis ()
  (when (and (or evil-insert-state-minor-mode evil-emacs-state-minor-mode)
             (not (and (boundp 'evil-mc-mode) evil-mc-mode))
             (not (overlayp sis--inline-overlay))
             (not (eq sis--prefix-handle-stage 'sequence))
             (not (memq real-last-command '(sis-inline-mode-force sis--inline-ret-check-to-deactivate)))
             (not (equal last-input-event '(ns-put-working-text))))
    (sis-context)))
(setq my/idle-command-for-sis-timer
      (run-with-idle-timer 0.2 t #'my/idle-command-for-sis))
;; (when my/idle-command-for-sis-timer
;;   (cancel-timer my/idle-command-for-sis-timer))

我给整理一下放到readme上最好,
能够解决更多的用户问题。

其实我在emacs上基本不写中文,
甚至也基本不写代码了。
这个包有很多需要改进的地方,
就一直拖着没动。

1 个赞

请教一下,windows下sis能够自动调用小狼毫的内置中英文切换,mac用鼠须管不行,请问mac上有没有办法实现在鼠须管内部进行中英文切换?

如果不想用 macism(macos)可以用这个 patch 来切换输入法(sis 兼容这个方法,也可以自己设置 F13 绑定到 shift 来切换).emacs.d/patches/ns-mac-input-source.patch at main · LuciusChen/.emacs.d · GitHub

使用坛友 @LuciusChen 制作的补丁,安装Emacs-plus

编辑:原来是切换输入法内部状态,这个确实没找到方法。

因为找不到在鼠须管内部进行中英文切换的方法,我在macos里,英文直接系统自带的,中文用鼠须管。

https://ringawho.github.io/emacs-input-method.html

我是自己 patch 编译鼠须管加了这个功能,不太熟悉 macos 这边,方法可能不是很好,感兴趣可以看看

1 个赞

感谢大佬,不过编译patch对我来说技术难度太大了 :sweat_smile:而且我发现小狼毫的切换也没有我想象中的美好,今天测试了一天,发现SIS在windows上的切换好像只是给小狼毫发送了个切换指令,经常造成中英文状态反转,比如在英文状态下退出insert模式,结果在normal下就变成了中文

你要用小狼毫最新的 Nightly build 版本就不会有问题了。

我也是这样。rime里面带英文输入法没有必要。

应该不是,切换的话,是调用 sis-switch,但是这个命令是提供给用户的,sis内部从未调用过这个命令,都是直接调用 sis-englishsis-other.

另外,建议windows上用自带的’w32 API,肯定要比外挂方案好。

windows上我用的是自带的w32 api,现象是当我在小狼毫配置里patch了emacs程序ascii mode为true时,进入emacs,此时按任意键,输入法会翻转为中文,或者是在输入状态下,当前状态为sis-other,但是进入了小狼毫acsii inline后,此时退出编辑状态,输入法也会翻转为中文

小狼毫也自带ascii inline mode?
难不成和sis的inline mode冲突了?
sis自己有inline mode你知道么?
只用小狼毫的inline mode
或者只用sis的inline mode试试?

sis的inline mode,
在前后空格的处理,
和退出inline mode时的输入法切换,
都是可以定制的。

以前测试的时候发现windows里面对自家的IME api支持最好的就是微软拼音。小狼毫在打开和关闭时,状态栏上的图标不会变。我在windows里中文是用微软拼音输入法的。

sis的inline mode可好用太多了,rime的inline只是单纯的中英文切换,我现在改键把左shift绑在了sis-switch,右shift用来切换rime内部的中英文防止状态反转,这样基本上就解决问题了

请问下,sis 在英文状态下如何输入中文?只能通过sis-switch来切换输入法这种方式吗?是否有像rime中的探针功能通过检测上下文来自动切换输入法?

sis 是有根据上下文自动切换输入法,仔细看一下 readme

1 个赞

这一块功能,
我感觉是所有的想法都实现了。
不过大部分用户没有耐心去了解,
实际用的人不多,有点遗憾

我觉得没关系,毕竟emacs是个小众圈子,受众面太窄,我也是刚开始用,很多好玩的用法还没有去研究。 这就相当于菜刀给了,就看大家怎么用,有些人只能用菜刀切菜,有些人能用菜刀雕花

我是按照readme配置的 image 但是,在编辑文字时总是不能达到预想的效果,比如当前输入法是英文,光标移动到中文下,输入法并不能自动切换为中文。在英文输入法下,只能手动切换到中文输入法,不晓得能不能自动切换到中文,比如双击两下空格。 不晓得是不是我的fcitx设置的有问题。 image

我用的meow,会有模式切换的契机。所以是用的这一行代码。(setq sis-context-hooks '(meow-insert-enter-hook))

原本的定义是 evil 的模式切换的 hook。所以并不是光标一上去就切换的,需要一个契机(hook)。

(defvar sis-context-hooks
  '(evil-insert-state-entry-hook)
  "Hooks trigger the set of input source following context.")

https://imgur.com/a/tSH9UD1