能不能让 liberime 处理选词、翻页,emacs 只做一个显示端

这样 pyim 里面可以留存的就是探针和标点处理了,可以单独添加。

感觉 pyim 里面的 rime 后端处理可能没有必要,导致每次都需要把所有的 key 发给 liberime-process-key 一遍, 还要设置 menu/page_size: 200

下面的代码尝试直接把 key 发给 liberime ,但是 liberime 好像没有获取有效字符的方法。

https://gist.github.com/QiangF/5589c66f75506b338d6e817a232448e8

自己水平太低了,提了个 issue, 希望大师能解决

liberime的维护者最开始提交了一个pr就是使用你提的方式,但集成耦合度太大了,看着难受,现在的方式虽然有点限制,但代码简单。。。

如果你专门开发了一个基于liberime的输入法,那基于event发送的集成方式就是可行的

现在假设用户要输 王七蛋

  1. wangqida
  2. 选“王”
  3. 发现少了个n, 补上
  4. 又要选一次“王”

liberime-get-context 好像选 "王"后,preedit 就只有 qida, 如果用帖子里提的可能会解决这个问题

liberime-get-context 里好像有 cursor position, 我看看原作者最先咋弄的

你搜搜pyim关于 rime的issue, 里面有个链接,不过我感觉你会放弃。。。。

I am trying to create a seperate input buffer to store the user input, the first prototype:

(defface rime-prompt
    '((t (:foreground "#ffff00" :background "gray44")))
    "选词框")
(defvar rime-title "中")

(defvar rime-local-variable-list
'(input-method-function
    deactivate-current-input-method-function
    rime-translating
    rime-output
    rime-context))

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

(defvar rime-auxiliary-map
(let ((map (make-sparse-keymap)))
    (dolist (i (number-sequence 32 255))
    (define-key map (char-to-string i) 'rime-self-insert-command))
    (define-key map "\C-d" 'rime-input-delete-forward)
    (define-key map "\C-h" 'rime-input-delete-backward)
    (define-key map "\C-f" 'rime-input-forward-point)
    (define-key map "\C-b" 'rime-input-backward-point)
    (define-key map "\C-e" 'rime-input-end-of-line)
    (define-key map "\C-a" 'rime-input-beginning-of-line)
    (define-key map "\C-n" 'rime-prompt--next-word)
    (define-key map "\C-p" 'rime-prompt--previous-word)
    (define-key map "\M-n" 'rime-prompt--next-page)
    (define-key map "\M-p" 'rime-prompt--previous-page)
    map)
"serves as a lookup table, not used as a mode map")

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

(defun rime-activate (name)
(interactive)
(mapc 'make-local-variable rime-local-variable-list)
(setq input-method-function 'rime-input-method)
(setq 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 ((input-string (rime-start-translation key)))
            (when (and (stringp input-string)
                        (> (length input-string) 0))
                (mapcar 'identity input-string)))))))

(defun rime-start-translation (key)
(let* ((echo-keystrokes 0)
        (help-char nil)
        (overriding-terminal-local-map rime-auxiliary-map)
        (input-method-function nil)
        (input-method-exit-on-first-char nil)
        (buffer-undo-list t)
        (input-method-use-echo-area nil)
        (modified-p (buffer-modified-p))
        (inhibit-modification-hooks t)
        (inhibit-quit t)
        last-command-event last-command this-command result)
    (setq rime-translating t)
    (rime-clear-input)
    ;; Push back the last event on the event queue.
    (and key (push key unread-command-events))
    (while rime-translating
    (let* ((keyseq (read-key-sequence-vector nil nil nil t))
            (rime-cmd (lookup-key rime-auxiliary-map keyseq)))
        (if (if (= 0 (length (rime-input-get)))
                ;; ignore command other than self-insert when composition is empty
                (eq rime-cmd 'rime-self-insert-command)
                (commandp rime-cmd))
            (progn
            (set-buffer-modified-p modified-p)
            (setq current-input-method-title rime-title)
            (setq last-command-event (aref keyseq (1- (length keyseq)))
                    last-command this-command
                    this-command rime-cmd)
            (condition-case-unless-debug err
                (progn
                    (call-interactively rime-cmd)
                    (rime-prompt--refresh))
                (error (message "Input method error: %S" err)
                    (beep)))
            (setq result rime-output))
            ; keyseq doen't have any meaning in the context of the input method
            ;; option 1: just return the keyseq string
            (message "keyseq: %s rime-cmd: %s rime-context: %s"
                    keyseq rime-cmd rime-context)
            (setq result (this-command-keys)))))
    (setq rime-output nil)
    result))

(defun rime-self-insert-command ()
(interactive "*")
(let ((char-str (char-to-string last-command-event)))
    (liberime-process-key last-command-event)
    (lv-message "%s" last-command-event)
(if (string-equal " " char-str)
    (progn (liberime-commit-composition)
            (setq rime-output (liberime-get-commit))
            (message "rime-output 1: %s" rime-output)
            (rime-terminate))
    (rime-with-input (insert char-str)))))

(defun rime-terminate ()
(setq rime-translating nil)
(setq rime-output nil)
(setq rime-context nil)
(rime-clear-input))

(defun rime-prompt--refresh ()
;; Show page.
(when (and (null unread-command-events)
            (null unread-post-input-method-events))
    ;; update context
    (setq rime-context (liberime-get-context))
    (message "context 1: %s" (liberime-get-context))
    (message "rime-context: %s" rime-context)
    (if (eq (selected-window) (minibuffer-window))
        ;; minibuffer 中输入中文时,使用当前输入的下一行来显示候选词。
        (rime-prompt--minibuffer-message
        (concat "\n" (rime-prompt--format-prompt)))
        ;; 普通 buffer 
        (let ((message-log-max nil))
        (message (rime-prompt--format-prompt))))))

(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-prompt--create-candidate-list (candidates index)
"这个函数用于创建在 page 中显示的备选词条菜单。"
(let ((i 0)
        result)
    (dolist (candidate candidates)
    (when (> i 0)
        (push " " result))
    ;; 高亮当前选择的词条
    (push (if (= i index)
                (propertize (format "[%d.%s]" (1+ i) candidate)
                            'face 'rime-prompt)
                (format "%d.%s" (1+ i) candidate))
            result)
    (setq i (1+ i)))
(mapconcat #'identity (reverse result) "")))

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

(defun rime-prompt--format-prompt ()
(concat (rime-prompt--create-input-view) 
        (if rime-context
            (let* ((composition (alist-get 'composition rime-context))
                    (menu (alist-get 'menu rime-context))
                    (page-no (alist-get 'page-no menu))
                    (index (alist-get 'highlighted-candidate-index menu))
                    (candidates (alist-get 'candidates menu)))
                (format "%s\n%s"
                        (alist-get 'preedit composition)
                        (rime-prompt--create-candidate-list candidates index)))
            "")))

(defmacro rime-with-input (&rest forms)
(declare (indent 0) (debug t))
`(let ((exwm-input--skip-buffer-list-update t))
    (with-current-buffer
        (get-buffer-create " *rime-input*")
    ,@forms)))

(defun rime-input-get ()
(rime-with-input
    (buffer-string)))

(defun rime-clear-input ()
(rime-with-input (erase-buffer))
(liberime-clear-composition))

(defun rime-input-forward-point ()
(interactive)
(rime-with-input
    (ignore-errors
    (forward-char)))
;; send right
(liberime-process-key 39))

(defun rime-input-backward-point ()
(interactive)
(rime-with-input
    (ignore-errors
    (backward-char)))
;; send left
(liberime-process-key 37))

(defun rime-input-beginning-of-line ()
(interactive)
(rime-with-input
    (beginning-of-line))
;; send home
(liberime-process-key 36))

(defun rime-input-end-of-line ()
(interactive)
(rime-with-input
    (end-of-line))
;; send end
(liberime-process-key 35))

(defun rime-input-delete-backward-1 (&optional n)
(interactive)
(rime-with-input
    (ignore-errors
    (delete-char (- 0 (or n 1))))))

(defun rime-input-delete-backward ()
(interactive)
(rime-input-delete-backward-1 1)
(liberime-process-key 65288))
;; send backspace
;; (liberime-process-key 8))

(defun rime-input-delete-forward ()
"在rime-input中向前删除1个字符"
(interactive)
(rime-input-delete-backward -1)
;; send delete
(liberime-process-key 127))

(defun rime-prompt--next-page (arg)
(interactive)
(liberime-process-key (string-to-char "=")))

(defun rime-prompt--previous-page (arg)
(interactive)
(liberime-process-key (string-to-char "-")))

(defun rime-prompt--next-word (arg)
(interactive)
;; send down
(liberime-process-key 40))

(defun rime-prompt--previous-word (arg)
(interactive)
;; send up
(liberime-process-key 38))

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

还差一点就成功了,求助: 1, 2, 3, 4, 5是不是也有1个和ascii code不同的 keysym

like this https://anzeljg.github.io/rin2/book2/2405/docs/tkinter/key-names.html I can’t find it?