Skip to content

Commit 88d42da

Browse files
committed
feat: support chorded input
1 parent 1b70d9c commit 88d42da

File tree

1 file changed

+82
-1
lines changed

1 file changed

+82
-1
lines changed

rime.el

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,9 @@ By default the input-method will not handle DEL, so we need this command."
799799
"If ascii-mode is enabled."
800800
(rime-lib-get-option "ascii_mode"))
801801

802+
(defconst rime-release-modifier 1073741824
803+
"Key release modifier (1 << 30).")
804+
802805
(defun rime--inline-ascii ()
803806
"Toggle inline ascii."
804807
(let ((key-code
@@ -810,7 +813,7 @@ By default the input-method will not handle DEL, so we need this command."
810813
(alt-l 65513)
811814
(alt-r 65514))))
812815
(rime-lib-process-key key-code 0)
813-
(rime-lib-process-key key-code 1073741824)))
816+
(rime-lib-process-key key-code rime-release-modifier)))
814817

815818
(defun rime-inline-ascii ()
816819
"Toggle inline ascii and redisplay."
@@ -825,6 +828,80 @@ By default the input-method will not handle DEL, so we need this command."
825828
(not (or inhibit-read-only
826829
(get-pos-property (point) 'inhibit-read-only)))))
827830

831+
(defun rime--chord-typing-p ()
832+
"Return t if the rime input session supports chord typing."
833+
(rime-lib-get-option "_chord_typing"))
834+
835+
(defvar rime-chord-duration 0.2
836+
"The duration of a key chord.
837+
838+
User should press and release all keys in the chord within the defined duration.
839+
The default value works for an average chord typist using Combo Pinyin. Tune the
840+
value if the user's stroke rate is higher or lower.")
841+
842+
(defun rime--chording-key-p (key)
843+
"Return t if KEY is used for chorded input."
844+
(cond
845+
((= key 32) t) ; space
846+
((= key 39) t) ; [']
847+
((and (>= key 44) (<= key 57)) t) ; [-,./0-9]
848+
((= key 59) t) ; [;]
849+
((= key 61) t) ; [=]
850+
((and (>= key 91) (<= key 93)) t) ; [\[\\\]]
851+
((and (>= key 96) (<= key 122)) t) ; [`a-z]
852+
(t nil)))
853+
854+
(defvar rime--chording-keys nil
855+
"The list of keys being pressed at the same time.")
856+
857+
(defun rime--release-chording-keys ()
858+
"Simulate key release events for the pressed keys in the chord."
859+
(dolist (key rime--chording-keys)
860+
(rime-lib-process-key key rime-release-modifier)))
861+
862+
(defvar rime--chord-timer nil
863+
"The timer which, when triggered, concludes the chord.")
864+
865+
(defun rime--on-chord-timer ()
866+
"The callback function invoked when a key chord is time up.
867+
868+
Assume all pressed keys are released and process the chord as input."
869+
(if (and rime--chording-keys rime-active-mode)
870+
(progn
871+
(rime--release-chording-keys)
872+
(rime--update-chorded-input-result)))
873+
(rime--clear-chord))
874+
875+
(defun rime--update-chorded-input-result ()
876+
"Update candidates, status and commit text after processing chorded input."
877+
(let ((commit (rime-lib-get-commit)))
878+
(unwind-protect
879+
(cond
880+
(commit
881+
(rime--clear-overlay)
882+
(insert commit))
883+
(t
884+
(rime--redisplay)))
885+
(rime--refresh-mode-state))))
886+
887+
(defun rime--update-chord (key)
888+
"Add KEY to the chord.
889+
890+
Absent are key up events in Emacs input method, a timer is used to conclude a
891+
chord after `rime-chord-duration' seconds. When the timer is triggered, key up
892+
events of the recorded keys are sent to librime."
893+
(add-to-list 'rime--chording-keys key)
894+
(unless rime--chord-timer
895+
(setq rime--chord-timer
896+
(run-with-timer rime-chord-duration nil #'rime--on-chord-timer))))
897+
898+
(defun rime--clear-chord ()
899+
"Clears the key chord."
900+
(if rime--chord-timer
901+
(cancel-timer rime--chord-timer))
902+
(setq rime--chording-keys nil
903+
rime--chord-timer nil))
904+
828905
(defun rime-input-method (key)
829906
"Process KEY with input method."
830907
(setq rime--current-input-key key)
@@ -848,6 +925,10 @@ By default the input-method will not handle DEL, so we need this command."
848925
(rime--inline-ascii)
849926
(setq inline-ascii-prefix t))
850927
(let ((handled (rime-lib-process-key key 0)))
928+
(if (and handled (rime--chord-typing-p))
929+
(if (rime--chording-key-p key)
930+
(rime--update-chord key)
931+
(rime--clear-chord)))
851932
(with-silent-modifications
852933
(let* ((context (rime-lib-get-context))
853934
(commit-text-preview (alist-get 'commit-text-preview context))

0 commit comments

Comments
 (0)