现在已经在 emacs 里使用 pyim 或 emacs-rime 等内置输入法输入中文,用内置输入法最大的优点是可以编写探针函数,从而根据不同状态自动切换中英文输入。同理,也可以在不同的 buffer 里主动激活或关闭输入法,达到接近完美的自动切换功能。

因此在之前给 telega 写了个 advice ,把需要指定中英文的 chatbuf 写在配置文件中,可以做到进不同的频道切换自动切换中英文。但这样做有一个缺点,就是如果中英文频道信息有变化(包括群组名称变化),则需要修改配置文件后重新加载才能生效。

嗯,用群友的话说,这很不优雅。

于是今天抽空把配置里的中英文 chatbuf 列表进行持久化保存,并且改为保存 chatid ,避免修改名称引起的切换失效。

代码如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
;;; cnsunyour/telega/+telega-auto-input-method.el -*- lexical-binding: t; -*-


(defcustom +telega--chat-cn-list nil
  "`telega' 里中文对话列表,用于自动切换到中文输入。"
  :type 'list
  :group 'telega)

(defcustom +telega--chat-en-list nil
  "`telega' 里英文对话列表,用于自动切换到英文输入。"
  :type 'list
  :group 'telega)

(defun +telega--save-encn-list ()
  "保存中英文对话列表。"
  (customize-save-variable '+telega--chat-cn-list +telega--chat-cn-list)
  (customize-save-variable '+telega--chat-en-list +telega--chat-en-list))

(defun +telega--add-cn-list (chat)
  "将当前聊天对话加入到中文列表中,以自动激活中文输入法。"
  (interactive (list (or telega-chatbuf--chat
                         telega--chat
                         (telega-chat-at (point)))))
  (let ((chatid (plist-get chat :id)))
    (cl-pushnew chatid +telega--chat-cn-list)
    (setq +telega--chat-en-list (cl-remove chatid +telega--chat-en-list))
    (+telega--save-encn-list)
    (message (concat "telega.el: Chat [\""
                     (telega-chat-title chat)
                     "\"] is added to CN chat list."))))

(defun +telega--add-en-list (chat)
  "将当前聊天对话加入到英文列表中,以自动关闭中文输入法。"
  (interactive (list (or telega-chatbuf--chat
                         telega--chat
                         (telega-chat-at (point)))))
  (let ((chatid (plist-get chat :id)))
    (cl-pushnew chatid +telega--chat-en-list)
    (setq +telega--chat-cn-list (cl-remove chatid +telega--chat-cn-list))
    (+telega--save-encn-list)
    (message (concat "telega.el: Chat [\""
                     (telega-chat-title chat)
                     "\"] is added to EN chat list."))))

(defun +telega--remove-from-list (chat)
  "将当前聊天对话从中英文列表中删除,将根据对话名称自动切换中英文输入法。"
  (interactive (list (or telega-chatbuf--chat
                         telega--chat
                         (telega-chat-at (point)))))
  (let ((chatid (plist-get chat :id)))
    (setq +telega--chat-en-list (cl-remove chatid +telega--chat-en-list))
    (setq +telega--chat-cn-list (cl-remove chatid +telega--chat-cn-list))
    (+telega--save-encn-list)
    (message (concat "telega.el: Chat [\""
                     (telega-chat-title chat)
                     "\"] is removed from EN/CN chat list."))))

(defun +telega--active-input-method ()
  "Active input method."
  (activate-input-method default-input-method))

(defun +telega--deactive-input-method ()
  "Deactive input method"
  (deactivate-input-method))

(defadvice! +toggle-input-method--telega-chat-mode-a (chat &optional no-history-load)
  "在 telega-chat-mode 里根据 chat 名称切换输入法,如果名称包含
中文,则激活中文输入法,否则关闭中文输入法"
  :after #'telega-chat--pop-to-buffer
  (let ((title (telega-chat-title chat))
        (chatid (plist-get chat :id)))
    (cond ((member chatid +telega--chat-cn-list) (+telega--active-input-method))
          ((member chatid +telega--chat-en-list) (+telega--deactive-input-method))
          ((string-match "\\cc" title) (+telega--active-input-method))
          ((telega-chat-bot-p chat) (+telega--deactive-input-method))
          ((telega-chat-private-p chat) (+telega--active-input-method))
          (t (+telega--deactive-input-method)))))