Skip to content

Instantly share code, notes, and snippets.

@DogLooksGood
Created February 23, 2020 08:05
Show Gist options
  • Save DogLooksGood/e4ae3f04ab12b023631a373b5b197b2d to your computer and use it in GitHub Desktop.
Save DogLooksGood/e4ae3f04ab12b023631a373b5b197b2d to your computer and use it in GitHub Desktop.
Try to implement a minimal emacs rime input method
(defface rime-preedit-face
'((((class color) (background dark))
(:underline t))
(((class color) (background light))
(:underline t)))
"Face for preedit string"
:group 'rime)
(defvar rime--preedit-overlay nil)
(defvar rime--backspace-fallback nil)
(make-variable-buffer-local 'rime--backspace-fallback)
(defun rime--show-candidates (context)
(let ((candidates (alist-get 'candidates (alist-get 'menu context)))
(idx 1)
(result ""))
(dolist (c candidates)
(setq result
(concat result (format "%d. %s " idx c)))
(setq idx (1+ idx)))
(message result)))
(defun rime--create-preedit (&rest args)
(let ((context (liberime-get-context)))
(when context
(when-let ((preedit (or (alist-get 'commit-text-preview context)
(alist-get 'preedit context))))
(let ((beg (point)))
(insert preedit)
(setq rime--preedit-overlay
(make-overlay beg (point) (current-buffer)))
(overlay-put rime--preedit-overlay 'face 'rime-preedit-face))))))
(defun rime--remove-preedit ()
(when (overlayp rime--preedit-overlay)
(let ((beg (overlay-start rime--preedit-overlay))
(end (overlay-end rime--preedit-overlay)))
(delete-overlay rime--preedit-overlay)
(setq rime--preedit-overlay nil)
(save-mark-and-excursion
(delete-region beg end)))))
(defun rime--backspace ()
(interactive)
(let ((context (liberime-get-context)))
(if (not context)
(call-interactively rime--backspace-fallback)
(liberime-process-key 65288)
(rime--show-candidates (liberime-get-context)))))
(defun rime-input-method (key)
(liberime-process-key key)
(with-silent-modifications
(rime--remove-preedit)
(let ((context (liberime-get-context))
(commit (liberime-get-commit)))
(rime--show-candidates context)
(cond
((and (not context) (not commit))
(liberime-clear-composition)
(list key))
(commit
(mapcar 'identity commit))))))
(defun rime-activate (name)
(interactive)
(setq input-method-function 'rime-input-method
deactivate-current-input-method-function #'rime-deactivate)
(liberime-clear-composition)
(setq-local rime--backspace-fallback (key-binding (kbd "DEL")))
(setq-local rime--space-fallback (key-binding (kbd "SPC")))
(local-set-key (kbd "DEL") 'rime--backspace)
(message "Rime activate"))
(defun rime-deactivate ()
"When quit the input method, we preserve the preedit, remove the overlay."
(when (overlayp rime--preedit-overlay)
(delete-overlay rime--preedit-overlay)
(setq rime--preedit-overlay nil))
(local-unset-key (kbd "DEL")))
(register-input-method "rime" "euc-cn" 'rime-activate "中")
(provide 'the-rime)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment