请试用:全新出炉的rime.el

liberime 老王有安装教程。

  1. 所有按键全部发送给rime,选词翻页都交给rime
  2. 智能中英切换
  3. 智能标点符号
  4. 成对标点连输入2次切换 参考:

https://github.com/merrickluo/liberime https://github.com/tumashu/pyim/ https://github.com/d5884/mozc-im/blob/master/mozc-im.el https://github.com/google/mozc/blob/master/src/unix/emacs/mozc.el https://github.com/jwiegley/emacs-release/blob/master/lisp/international/quail.el

 ;; Questions
;; 1. How to send Shift+Delete with liberime-process-key
;; 2. with liberime, there is no way to retrieve user input when liberime-get-context returns nil, eg. after typing "u"
;; how to set rime to treat u and i as legitimate input
;; how to enable rime to suport partial matching
;; eg "idegc ℃ 1" is in custom_phrase.txt, I have to type the whole code idegc to get the symbol 
;; 3. can liberime do reverse search: get pinyin for phrase?

(require 'cl-lib)

(defvar rime-probe-list
'(evil-normal-state-p
    rime-probe-program-mode
    rime-probe-english-context))

(defvar rime-local-variable-list
'(input-method-function
    deactivate-current-input-method-function
    rime-last-punctuation))

(dolist (var rime-local-variable-list)
(defvar var nil)
(make-variable-buffer-local var)
(put var 'permanent-local t))

(defvar rime-menu-keys `(;; Next PageDown
                        ("M-n" . 65366)
                        ;; Prior PageUp
                        ("M-p" . 65365)
                        ;; C-n Down
                        ("C-n" . 65364)
                        ;; Up
                        ("C-p" . 65362)
                        ;; Space
                        ("SPC" . 32)
                        ("RET" . 65293)
                        ("C-m" . 65293)
                        ;; exwm-mode buffer
                        ("<return>" . 65293)
                        ,@(mapcar (lambda (x)
                                    `(,(char-to-string x) . ,x))
                                (number-sequence ?1 ?9))))

(defvar rime-composition-keys '(("C-d" . 65535)
                                ("<deletechar>" . 65535)
                                ;; Shift+Delete
                                ("C-k" . (65505 65535))
                                ("C-h" . 65288)
                                ;; BackSpace
                                ("DEL" . 65288)
                                ("<backspace>" . 65288)
                                ("<delete>" . 65288)
                                ;; Left
                                ("C-b" . 65361)
                                ;; Right
                                ("C-f" . 65363)
                                ;; Home
                                ("C-a" . 65360)
                                ;; End
                                ("C-e" . 65367)))

(defvar rime-aux-map
(let ((map (make-sparse-keymap)))
    (define-key map "\C-h" 'delete-backward-char)
    (define-key map [delete] 'delete-backward-char)
    (define-key map (kbd "DEL") 'delete-backward-char)
    (define-key map [backspace] 'delete-backward-char)
    map))

(defvar rime-map
(let ((map (make-sparse-keymap)))
    (dolist (i (number-sequence ?\  127))
    (define-key map (char-to-string i) 'rime-translate-key))
    (dolist (i (append rime-menu-keys rime-composition-keys))
    (define-key map (kbd (car i)) 'rime-translate-key))
    map))

(defun rime-probe-program-mode ()
"中文输入限制在字符串和 comment 中"
(interactive)
(when (derived-mode-p 'prog-mode)
    (let* ((ppss (syntax-ppss (point))))
    (not
    (or (car (setq ppss (nthcdr 3 ppss)))
        (car (setq ppss (cdr ppss)))
        (nth 3 ppss))))))

(defun rime-probe-english-context ()
(or
;; 中文后面紧接1个空格切换到英文输入
;; \cC represents any character of category “C”, and according to “M-x describe-categories”
(looking-back "\\cc " (max (line-beginning-position) (- (point) 2)))
;; 英文,数字后保持英文输入
(looking-back "[a-zA-Z0-9]" (max (line-beginning-position) (1- (point))))))

(defun rime-english-mode-p ()
(unless (string-match " *temp*" (buffer-name))
    (cl-some #'(lambda (x)
                (if (functionp x) (funcall x) nil))
            rime-probe-list)))

;; todo: type v to toggle the previously inserted punctuation 
(defun rime-fullwidth-mode-p ()
(not
(looking-back "[0-9]\\| " (max (line-beginning-position) (1- (point))))))

(defun rime-activate (name)
(interactive)
(setq input-method-function 'rime-input-method
        deactivate-current-input-method-function #'rime-deactivate)
(when (eq (selected-window)
            (minibuffer-window))
    (add-hook 'minibuffer-exit-hook 'rime-exit-from-minibuffer)))

(defun rime-deactivate ()
(mapc 'kill-local-variable rime-local-variable-list))

(defun rime-exit-from-minibuffer ()
(deactivate-input-method)
(when (<= (minibuffer-depth) 1)
    (remove-hook 'minibuffer-exit-hook 'rime-exit-from-minibuffer)))

(defun rime-input-method (key)
(if (or buffer-read-only
        (not enable-multibyte-characters)
        overriding-terminal-local-map
        overriding-local-map)
    (list key)
    (with-silent-modifications
        (unwind-protect
            (let* ((echo-keystrokes 0)
                    (help-char nil)
                    (overriding-terminal-local-map rime-map)
                    ;; bind input-method-function to nil to prevent recursion.
                    (input-method-function nil)
                    (input-method-exit-on-first-char nil)
                    ;; Hide the original `buffer-undo-list'.
                    (buffer-undo-list t)
                    ;; preview string in buffer, see quail.el
                    (input-method-use-echo-area nil)
                    (inhibit-modification-hooks t)
                    (inhibit-quit t)
                    (modified-p (buffer-modified-p))
                    ;; rime local variables
                    (rime-input-buffer
                    (get-buffer-create " *rime-input*"))
                    (rime-translating t)
                    result)
            (with-current-buffer rime-input-buffer
                (erase-buffer))
            (liberime-clear-composition)
            ;; Push back the last event on the event queue.
            (and key (push key unread-command-events))
            (rime-start-translation)
            (if (stringp result)
                (mapcar 'identity result)
                ;; if result are vectors, convert to a list, maybe unecessary
                (append result nil)))))))

(defun rime-start-translation ()
(while rime-translating
    (let ((keyseq (read-key-sequence-vector nil nil nil t)))
    (rime-translate-key keyseq))
    ;; continuation check
    ;; liberime-get-commit returns the result only after all being translated
    (if (or result
            (setq result (liberime-get-commit)))
        (progn
        (setq rime-translating nil))
        (let ((context (liberime-get-context)))
        ;; update prompt and continue
        (rime-prompt--refresh))))
result)

(defun rime-translate-key (keyseq)
(let* ((keyseq-name (key-description keyseq))
        (key (aref keyseq (1- (length keyseq))))
        keysym-num)
    ;; key processing based on key type
    (cond
    ;; 1. alphabet
    ((and (= (length keyseq-name) 1)
            (string-match "[[:alpha:]]" keyseq-name)
            (not (rime-english-mode-p)))
    (liberime-process-key key)
    (with-current-buffer rime-input-buffer
        (insert key))
    (setq rime-last-punctuation nil))
    ;; 2. same punctuation press twice to go to the next candidate
    ((and (= (length keyseq-name) 1)
            (rime-fullwidth-mode-p)
            (string-match "[[:punct:]]" keyseq-name))
    (liberime-process-key key)
    (if (eq rime-last-punctuation key)
        (progn
            (liberime-select-candidate 1)
            ;; delete the last char
            (push 127 unread-post-input-method-events)
            ;; insert the replacement
            (push (string-to-char (liberime-get-commit)) unread-command-events))
        (liberime-select-candidate 0))
    (setq rime-translating nil)
    (setq rime-last-punctuation key))
    ;; 3. menu key
    ((and (setq keysym-num
                (cdr (assoc keyseq-name rime-menu-keys))))
    ;; numeric and space char
    (if (and (or (= (length keyseq-name) 1)
                    (string-equal "SPC" keyseq-name))
                (rime-input-empty-p))
        (setq result (char-to-string key))
        (liberime-process-key keysym-num)))
    ;; 4. composition key
    ((and (setq keysym-num
                (cdr (assoc keyseq-name rime-composition-keys))))
    (liberime-process-key keysym-num)
    (with-current-buffer rime-input-buffer
        (let* ((overriding-terminal-local-map rime-aux-map)
                (bind (key-binding keyseq t)))
        (if bind
            (ignore-errors
                (call-interactively bind nil keyseq))
            (let (message-log-max)
                (message "%s is undefined" (key-description keys))
                (undefined))))))
    (t (setq result (this-command-keys))))))

(defun rime-prompt--format-prompt ()
(if (not context)
    (with-current-buffer rime-input-buffer
        (concat (buffer-substring-no-properties 1 (point)) "|"
                (buffer-substring-no-properties (point) (point-max))))
    (let* ((composition (alist-get 'composition context))
            (composition-length (alist-get 'length composition))
            (cursor-pos (alist-get 'cursor-pos composition))
            (preedit (alist-get 'preedit composition))
            (menu (alist-get 'menu context))
            (highlighted-candidate-index (alist-get 'highlighted-candidate-index menu))
            (last-page-p (alist-get 'last-page-p menu))
            (num-candidates (alist-get 'num-candidates menu))
            (page-no (alist-get 'page-no menu))
            (candidates (alist-get 'candidates menu))
            (cursor-distance-to-end (- composition-length cursor-pos)))
        (with-current-buffer rime-input-buffer
        (erase-buffer)
        (insert preedit)
        (backward-char cursor-distance-to-end))
        (concat
        (with-current-buffer rime-input-buffer
        (concat (buffer-substring-no-properties 1 (point)) "|"
                (buffer-substring-no-properties (point) (point-max))))
        ":"
        ;; candidates
        (let (result)
        (dolist (i (number-sequence 0 (1- num-candidates)))
            ;; 高亮当前选择的词条
            (push (if (= i highlighted-candidate-index)
                    (format "[%d.%s]" (1+ i) (nth i candidates))
                    (format "%d.%s" (1+ i) (nth i candidates)))
                result))
        (concat
            (mapconcat #'identity (reverse result) " ")
            ;; current page number
            (if last-page-p
                (format "(%s<)" (1+ page-no))
                (format "(%s)" (1+ page-no)))))))))

(defun rime-prompt--refresh ()
(when (and (null unread-command-events)
            (null unread-post-input-method-events))
    (let ((prompt-str (rime-prompt--format-prompt)))
    (if (eq (selected-window)
            (minibuffer-window))
        ;; minibuffer 使用下一行显示候选词
        (rime-prompt--minibuffer-message (concat "\n" prompt-str))
        ;; 普通 buffer 
        (message prompt-str)))))

(defun rime-prompt--minibuffer-message (string)
"minibuffer 中需要将原来显示的信息和选词框整合在一起显示"
(message nil)
(let ((inhibit-quit t)
        point-1)
    (save-excursion
    (insert string)
    (setq point-1 (point)))
    (sit-for 1000000)
    (delete-region (point) point-1)
    (when quit-flag
    (setq quit-flag nil
            unread-command-events '(7)))))

(defun rime-input-empty-p ()
(= (buffer-size rime-input-buffer) 0))

;; add word to ~/.emacs.d/rime/my_phrase.dict.yaml and sort
(defun rime-add-to-user-dict ())

;; add word to ~/.emacs.d/rime/custom_phrase.txt and sort:
;; auto add pinyin code, prompt for confirmation 
(defun rime-add-to-custom-phrase ())

(defun rime-register-input-method ()
(register-input-method "rime" "euc-cn" 'rime-activate "中"))

(add-hook 'emacs-startup-hook 'rime-register-input-method)
(rime-register-input-method)
(provide 'rime)
11赞

好好整理一下,做个 melpa package吧,这样发展更好

也许会出现magit方式的发展,成为emacs中文社区重要的一个package

感谢大师鼓励,希望能加到liberime包里,修复一个小问题。帖子已经更新

不知道为啥,exwm mode里面 backspace无法使用

啊 重启后正常了

加到liberime中也是一个好主意

这里还弄了一个有 output 缓存功能的,这个缓存还可以单独编辑,类似于 exwmx-sendstring,但是不通过剪切板,今天没时间弄了

(require 'cl-lib)

(defvar rime-probe-list
'(evil-normal-state-p
    rime-probe-program-mode
    rime-probe-english-context))

(defvar rime-local-variable-list
'(input-method-function
    deactivate-current-input-method-function
    rime-last-punctuation))

(defun rime-cache-p ()
;; exwm-xim use " *temp*"
(string= (buffer-name) " *temp*"))

(dolist (var rime-local-variable-list)
(defvar var nil)
(make-variable-buffer-local var)
(put var 'permanent-local t))

(defvar rime-punctuation-pair-start
(mapcar (lambda (x) (aref `,x 0)) '("'" "\"" "(" "[" "{")))

(defvar rime-menu-keys `(;; Next PageDown
                        ("M-n" . 65366)
                        ;; Prior PageUp
                        ("M-p" . 65365)
                        ;; C-n Down
                        ("C-n" . 65364)
                        ;; Up
                        ("C-p" . 65362)
                        ;; Space
                        ("SPC" . 32)
                        ("RET" . 65293)
                        ,@(mapcar (lambda (x)
                                    `(,(char-to-string x) . ,x))
                                (number-sequence ?1 ?9))))

(defvar rime-composition-keys '(("C-d" . 65535)
                                ("<deletechar>" . 65535)
                                ;; Shift+Delete
                                ("C-k" . (65505 65535))
                                ("C-h" . 65288)
                                ;; BackSpace
                                ("DEL" . 65288)
                                ;; Left
                                ("C-b" . 65361)
                                ;; Right
                                ("C-f" . 65363)
                                ;; Home
                                ("C-a" . 65360)
                                ;; End
                                ("C-e" . 65367)))

(defvar rime-map
(let ((map (rime-make-self-insert-map 'rime-self-insert-command)))
    (dolist (i (number-sequence ?\  127))
    (define-key map (char-to-string i) 'rime-translate-key))
    (dolist (i (append rime-menu-keys rime-composition-keys))
    (define-key map (kbd (car i)) 'rime-translate-key))
    map))

(defun rime-probe-program-mode ()
"中文输入限制在字符串和 comment 中"
(interactive)
(when (derived-mode-p 'prog-mode)
    (let* ((ppss (syntax-ppss (point))))
    (not
    (or (car (setq ppss (nthcdr 3 ppss)))
        (car (setq ppss (cdr ppss)))
        (nth 3 ppss))))))

(defun rime-probe-english-context ()
(or
;; 中文后面紧接1个空格切换到英文输入
;; \cC represents any character of category “C”, and according to “M-x describe-categories”
(looking-back "\\cc " (max (line-beginning-position) (- (point) 2)))
;; 英文,数字后保持英文输入
(looking-back "[a-zA-Z0-9]" (max (line-beginning-position) (1- (point))))))

(defun rime-chinese-mode-p ()
(not (cl-some #'(lambda (x)
                    (if (functionp x) (funcall x) nil))
                rime-probe-list)))

(defun rime-fullwidth-mode-p ()
(not
(looking-back "[0-9]\\| " (max (line-beginning-position) (1- (point))))))

(defun rime-deactivate ()
(mapc 'kill-local-variable rime-local-variable-list)
;; rime-cache can be edited seperately, don't kill it
;; (when (rime-cache-p)
;;   (and rime-output-buffer
;;        (kill-buffer rime-output-buffer)))
(and rime-input-buffer
    (kill-buffer rime-input-buffer)))

(defun rime-activate (name)
(interactive)
(setq input-method-function 'rime-input-method
        deactivate-current-input-method-function #'rime-deactivate)
(when (eq (selected-window)
            (minibuffer-window))
    (add-hook 'minibuffer-exit-hook 'rime-exit-from-minibuffer)))

(defun rime-exit-from-minibuffer ()
(deactivate-input-method)
(when (<= (minibuffer-depth) 1)
    (remove-hook 'minibuffer-exit-hook 'rime-exit-from-minibuffer)))

(defun rime-input-method (key)
(if (or buffer-read-only
        (not enable-multibyte-characters)
        overriding-terminal-local-map
        overriding-local-map)
    (list key)
        (unwind-protect
            (with-silent-modifications
    (let* ((echo-keystrokes 0)
            (help-char nil)
            ;; to avoid exwm-input mess with key event during a translation
            (exwm-input--skip-buffer-list-update t)
            (overriding-terminal-local-map rime-map)
            ;; bind input-method-function to nil to prevent recursion.
            (input-method-function nil)
            (input-method-exit-on-first-char nil)
            ;; Hide the original `buffer-undo-list'.
            (buffer-undo-list t)
            ;; preview string in buffer, see quail.el
            (input-method-use-echo-area nil)
            (inhibit-modification-hooks t)
            (inhibit-quit t)
            (modified-p (buffer-modified-p))
            ;; rime local variables
            (rime-translating t)
            ;; with liberime, there is no way to retrieve user input when liberime-get-context returns nil
            ;; so create a buffer to save user input
            (rime-input-buffer
            (get-buffer-create " *rime-input*"))
            (rime-cache (if (rime-cache-p)
                            (get-buffer-create " *rime-cache*")))
            (rime-output-buffer (or rime-cache (current-buffer)))
            result)
        (liberime-clear-composition)
        ;; Push back the last event on the event queue.
        (push key unread-command-events)
        (rime-start-translation)
        (if (stringp result)
            (mapcar 'identity result)
            ;; if result are vectors, convert to a list, maybe unecessary
            (append result nil)))))))

(defun rime-start-translation ()
(while rime-translating
    (let* ((keyseq (read-key-sequence-vector nil nil nil t))
        context
        commit-cache)
    (rime-translate-key keyseq)
    ;; process commit
    (let ((commit (liberime-get-commit)))
        (when commit
        (if rime-cache
            ;; when using rime-cache, put commit into cache
            (rime-with-output
                (insert commit))
            ;; else put it into result
            (setq result commit))))
    ;; continuation check
    ;; liberime-get-commit returns the result only after all being translated
    ;; (message "result %s commit %s" result (or result
    ;;         (setq result (liberime-get-commit))))
    (cond
        ;; 1. there's unprocessed keys, exit to process these keys
        ;; 2. not using rime-cache, exit to send commit to the buffer
        (result
        (setq rime-translating nil))
        ;; no result, using rime-cache and last key is return
        (commit-cache (rime-with-output
                        (let ((buffer-string (buffer-string)))
                        (if (< (length buffer-string) 0)
                            ;; no cache, just return the key
                            (setq result keyseq)
                            (setq result buffer-string)
                            (erase-buffer))))
                    (setq rime-translating nil))
        ;; update prompt and continue
        (t (when (setq context (liberime-get-context))
            (let* ((composition (alist-get 'composition context))
                    (composition-length (alist-get 'length composition))
                    (cursor-pos (alist-get 'cursor-pos composition))
                    (preedit (alist-get 'preedit composition))
                    (menu (alist-get 'menu context))
                    (highlighted-candidate-index (alist-get 'highlighted-candidate-index menu))
                    (last-page-p (alist-get 'last-page-p menu))
                    (num-candidates (alist-get 'num-candidates menu))
                    (page-no (alist-get 'page-no menu))
                    (candidates (alist-get 'candidates menu)))
            ;; fix point position in input buffer
            ;; rime moves cursor back in unit of pinyin combo, moving distance is not fixed
            ))
        (rime-prompt--refresh)))))
result)

(defun rime-translate-key (keyseq)
(let* ((keyseq-name (key-description keyseq))
        (key (aref keyseq (1- (length keyseq))))
        keysym-num)
    ;; key processing based on key type
    (cond 
        ;; 1. alphabet
        ((and (= (length key-name) 1)
            (string-match "[[:alpha:]]" key-name)
            (rime-with-output (rime-chinese-mode-p)))
        (liberime-process-key key)
        (with-current-buffer rime-input-buffer
        (insert key))
        (setq rime-last-punctuation nil))
        ;; 2. punctuation
        ((and (= (length key-name) 1)
            (string-match "[[:punct:]]" key-name)
            (rime-with-output (rime-fullwidth-mode-p)))
        (liberime-commit-composition)
        (setq result (liberime-get-commit))
        ;; no conversion for two consecutive puctuations
        (if rime-last-punctuation
            (progn
            ;; prvious is a pair, need to remove the matching char
            (when (member rime-last-punctuation rime-punctuation-pair-start)
                ;; delete the auto inserted pair end
                ;; 1. use delete-char (we are using a cache anyway)
                ;; 2. push backe delete, previous and current event?
                ;; 3. send deletchar and two puctuations?
                (delete-char 1))
            (delete-char -1)
            (insert rime-last-punctuation)
            (insert key))
            (liberime-process-key key)
            (liberime-select-candidate 0)))

        (setq rime-last-punctuation key))
        ;; 3. menu key
        ((setq keysym-num
            (cdr (assoc key-name rime-menu-keys)))
        (if (liberime-get-context)
            (liberime-process-key keysym-num)
            (setq result keyseq)))
        ;; 4. return: set commit-cache flag
        ((string-equal key-name "RET")
        (when rime-cache
        (setq commit-cache t))
        ;; Return C-m, 字母上屏
        ;; ("RET" . 65293)
        (liberime-process-key 65293))
        ;; 5. composition key
        ((setq keysym-num
            (cdr (assoc key-name rime-composition-keys)))
        (if (rime-input-empty-p)
            (rime-interactive-call rime-output-buffer)
            (liberime-process-key keysym-num)
            (rime-interactive-call rime-input-buffer)))
        ;; 6. other key, just return the keyseq string
        (t (setq result keyseq)
        (setq rime-translating nil)))))

(defun rime-prompt--format-prompt ()
(concat
;; cache
(and rime-cache
        (concat
        (rime-create-buffer-view rime-output-buffer)
        "\n"))
(if (not context)
    (rime-create-buffer-view rime-input-buffer)
    (concat
        (with-temp-buffer
        (insert preedit)
        (backward-char (- composition-length cursor-pos))
        (insert "|")
        (buffer-string))
        ":"
        ;; candidates
        (let (result)
        (dolist (i (number-sequence 0 (1- num-candidates)))
            ;; 高亮当前选择的词条
            (push (if (= i highlighted-candidate-index)
                    (format "[%d.%s]" (1+ i) (nth i candidates))
                    (format "%d.%s" (1+ i) (nth i candidates)))
                result))
        (concat
        (mapconcat #'identity (reverse result) " ")
        ;; current page number
        (if last-page-p
            (format "(%s<)" (1+ page-no))
            (format "(%s)" (1+ page-no)))))))))

(defun rime-create-buffer-view (buf-name)
;; | 显示光标位置的字符
(with-current-buffer (get-buffer buf-name)
    (concat (buffer-substring-no-properties 1 (point)) "|"
            (buffer-substring-no-properties (point) (point-max)))))

(defun rime-prompt--refresh ()
(when (and (null unread-command-events)
            (null unread-post-input-method-events))
    (let ((prompt-str (rime-prompt--format-prompt)))
    (if (eq (selected-window)
            (minibuffer-window))
        ;; minibuffer 使用下一行显示候选词
        (rime-prompt--minibuffer-message (concat "\n" prompt-str))
        ;; 普通 buffer 
        (let ((message-log-max nil))
            (cond (t (message prompt-str))))))))

(defun rime-input-empty-p ()
(= (buffer-size rime-input-buffer) 0))

(defmacro rime-with-output (&rest forms)
(declare (indent 0) (debug t))
`(with-current-buffer ,rime-output-buffer
    ,@forms))

(defun rime-interactive-call (buf)
(with-current-buffer buf
    (let* ((overriding-terminal-local-map nil)
        (bind (key-binding keyseq t)))
    (if bind
        (call-interactively bind nil keyseq)
        (let (message-log-max)
            (message "%s is undefined" (key-description keys))
            (undefined))))))

(defun rime-prompt--minibuffer-message (string)
"minibuffer 中需要将原来显示的信息和选词框整合在一起显示"
(message nil)
(let ((inhibit-quit t)
        point-1)
    (save-excursion
    (insert string)
    (setq point-1 (point)))
    (sit-for 1000000)
    (delete-region (point) point-1)
    (when quit-flag
    (setq quit-flag nil
            unread-command-events '(7)))))

;; add word to ~/.emacs.d/rime/my_phrase.dict.yaml and sort
(defun rime-add-to-user-dict ())

;; add word to ~/.emacs.d/rime/custom_phrase.txt and sort:
;; auto add pinyin code, prompt for confirmation 
(defun rime-add-to-custom-phrase ())

(defun rime-register-input-method ()
(register-input-method "rime" "euc-cn" 'rime-activate "中"))

(add-hook 'emacs-startup-hook 'rime-register-input-method)
(rime-register-input-method)
(provide 'rime)

因为自己不用evil,所以集成成本挺高的,想了解一下这个能不能支持自动上屏的功能。

这个和evil没关系,可以简单改一下,只有1个candidate自动上屏

这个是rime专用客户端,我个人感觉,librime有的功能,它都支持😁

手动点个赞,不错不错,等稳定以后,切换到你的这个专用客户端上。

试了一下,有点小问题。 顶屏上去以后,编码统一清空了,逻辑上是可以有剩余编码的。

比如编码abcd的时候,e把abcd的字顶上去了,这个时候编码应该还有个e。

我只会全拼呢,既然abcd就commit了,后面的e应该是另一个翻译循环了,两个循环不应该有干扰吧

如果e是专门顶的,你可以自己改一下后面把它加到input里面吗

目前还没发现问题,就是两次输入 " 删除前面“输入”这个小功能不太完美,在 exwm-mode buffer 里面没法删除前面字符,127这个 event 被 exwm-xim 给忽略了

   (if (eq rime-last-punctuation key)
       (progn
         (liberime-select-candidate 1)
         ;; delete the last char
         (push 127 unread-post-input-method-events)
         ;; insert the replacement
         (push (string-to-char (liberime-get-commit)) unread-command-events))
       (liberime-select-candidate 0))

不是专门项,是通用的项。

  1. 把按键发给 librime
  2. 从librime获取要展示的编码
  3. 从librime获取要展示的候选
  4. 从librime获取要上屏的内容

这四个里面是有实现不了的吗?

好像backspace就是不能用啊。

如果没有候选,用户输入liberime是不能返回的,我单独创建了 rime-input-buffer 跟踪用户输入,你看看哪个地方漏了,全拼没发现问题

我觉得你早点创建一个rime-el项目,添加到melpa比较好,这样大家就可以提交issue,而不是在群里跟帖

1赞