From 500fd32347429f174dd40b6a584c47007a379ddb Mon Sep 17 00:00:00 2001 From: Yuanle Song Date: Fri, 5 Apr 2019 16:39:44 +0800 Subject: [PATCH] build-candidates add fetch-size support; - handle fetch more in page down function. - let build-candidates sync version support fetch-size param. - adjusted some debug log - tested zero-pinyin and sync and async mode, both works. I can't feel the difference. --- zero-framework.el | 90 +++++++++++++++++++++++++++++------------------ zero-pinyin.el | 49 +++++++++++++++++++------- zero-table.el | 2 +- 3 files changed, 94 insertions(+), 47 deletions(-) diff --git a/zero-framework.el b/zero-framework.el index f78d65b..f68c315 100644 --- a/zero-framework.el +++ b/zero-framework.el @@ -96,13 +96,13 @@ if item is not in lst, return nil" ;;; concrete input method should define these functions and set them in the ;;; corresponding *-func variable. -(defun zero-build-candidates-default (_preedit-str) nil) +(defun zero-build-candidates-default (_preedit-str _fetch-size) nil) (defun zero-can-start-sequence-default (_ch) nil) (defun zero-get-preedit-str-for-panel-default () zero-preedit-str) (defvar zero-build-candidates-func 'zero-build-candidates-default - "contains a function to build candidates from preedit-str. The function accepts param preedit-str, returns candidate list.") + "contains a function to build candidates from preedit-str. The function accepts param preedit-str, fetch-size, returns candidate list.") (defvar zero-build-candidates-async-func 'zero-build-candidates-async-default - "contains a function to build candidates from preedit-str. The function accepts param preedit-str, and a complete-func that should be called on returned candidate list.") + "contains a function to build candidates from preedit-str. The function accepts param preedit-str, fetch-size, and a complete-func that should be called on returned candidate list.") (defvar zero-can-start-sequence-func 'zero-can-start-sequence-default "contains a function to decide whether a char can start a preedit sequence") (defvar zero-handle-preedit-char-func 'zero-handle-preedit-char-default @@ -152,6 +152,12 @@ otherwise, next single quote insert close quote") "how many candidates to show on each page" :group 'zero) (defvar zero-current-page 0 "current page number. count from 0") +(defvar zero-initial-fetch-size 20 + "how many candidates to fetch for the first call to GetCandidates") +;; zero-fetch-size is reset to 0 when preedit-str changes. +;; zero-fetch-size is set to fetch-size in build-candidates-async complete-func +;; lambda. +(defvar zero-fetch-size 0 "last GetCandidates call's fetch-size") (defvar zero-previous-page-key ?\- "previous page key") (defvar zero-next-page-key ?\= "next page key") @@ -192,23 +198,23 @@ if t, `zero-debug' will output debug msg in *zero-debug* buffer") (destructuring-bind (x y) (zero-get-point-position) (zero-panel-move x y)))) -(defun zero-build-candidates (preedit-str) +(defun zero-build-candidates (preedit-str fetch-size) "build candidates list synchronously" - (zero-debug "build candidates list synchronously") - (if (functionp zero-build-candidates-func) - (funcall zero-build-candidates-func preedit-str) - (error "`zero-build-candidates-func' is not a function"))) + ;; (zero-debug "zero-build-candidates\n") + (unless (functionp zero-build-candidates-func) + (signal 'wrong-type-argument (list 'functionp zero-build-candidates-func))) + (prog1 (funcall zero-build-candidates-func preedit-str fetch-size) + (setq zero-fetch-size fetch-size))) (defun zero-build-candidates-complete (candidates) "called when `zero-build-candidates-async' returns" (setq zero-candidates candidates) - (setq zero-current-page 0) (zero-show-candidates candidates)) -(defun zero-build-candidates-async-default (preedit-str complete-func) +(defun zero-build-candidates-async-default (preedit-str fetch-size complete-func) "build candidate list, when done show it via `zero-show-candidates'" - (zero-debug "building candidate list asynchronously\n") - (let ((candidates (zero-build-candidates preedit-str))) + ;; (zero-debug "zero-build-candidates-async-default\n") + (let ((candidates (zero-build-candidates preedit-str fetch-size))) ;; update cache to make SPC and digit key selection possible. (funcall complete-func candidates))) @@ -278,12 +284,27 @@ return ch's Chinese punctuation if ch is converted. return nil otherwise" (setq zero-current-page (1- zero-current-page)) (zero-show-candidates))) +(defun zero-just-page-down () + "just page down using existing candidates" + (let ((len (length zero-candidates))) + (when (> len (* zero-candidates-per-page (1+ zero-current-page))) + (setq zero-current-page (1+ zero-current-page)) + (zero-show-candidates)))) + (defun zero-page-down () "if there is still candidates to be displayed, show candidates on next page." - (let ((len (length zero-candidates))) - (when (> len (* zero-candidates-per-page (1+ zero-current-page))) - (setq zero-current-page (1+ zero-current-page)) - (zero-show-candidates)))) + (let ((len (length zero-candidates)) + (new-fetch-size (* zero-candidates-per-page (+ 2 zero-current-page)))) + (if (and (< len new-fetch-size) + (< zero-fetch-size new-fetch-size)) + (funcall zero-build-candidates-async-func + zero-preedit-str + new-fetch-size + (lambda (candidates) + (zero-build-candidates-complete candidates) + (setq zero-fetch-size new-fetch-size) + (zero-just-page-down))) + (zero-just-page-down)))) (defun zero-handle-preedit-char-default (ch) "hanlde character insert in `*zero-state-im-preediting*' state" @@ -333,7 +354,9 @@ return ch's Chinese punctuation if ch is converted. return nil otherwise" (defun zero-preedit-str-changed () "called when preedit str is changed and not empty. update and show candidate list" - (funcall zero-build-candidates-async-func zero-preedit-str 'zero-build-candidates-complete)) + (setq zero-fetch-size 0) + (setq zero-current-page 0) + (funcall zero-build-candidates-async-func zero-preedit-str zero-initial-fetch-size 'zero-build-candidates-complete)) (defun zero-backspace-default () "handle backspace key in `*zero-state-im-preediting*' state" @@ -424,23 +447,21 @@ return ch's Chinese punctuation if ch is converted. return nil otherwise" ;; minor mode ;;============ -;; TODO when zero-framework is stable, move default value to defvar. -;; this will allow user to customize the keymap. -(defvar zero-mode-map nil "zero-mode keymap") -(setq zero-mode-map - '(keymap - (escape . zero-reset) - (13 . zero-return) - ;; C-. - (67108910 . zero-cycle-punctuation-level) - (remap keymap - (self-insert-command . zero-self-insert-command) - ;; (forward-char . zero-forward-char) - ;; (backward-char . zero-backward-char) - ;; (forward-word . zero-forward-word) - ;; (backward-word . zero-backward-word) - ;; (delete-char . zero-delete-char) - ))) +(defvar zero-mode-map + '(keymap + (escape . zero-reset) + (13 . zero-return) + ;; C-. + (67108910 . zero-cycle-punctuation-level) + (remap keymap + (self-insert-command . zero-self-insert-command) + ;; (forward-char . zero-forward-char) + ;; (backward-char . zero-backward-char) + ;; (forward-word . zero-forward-word) + ;; (backward-word . zero-backward-word) + ;; (delete-char . zero-delete-char) + )) + "zero-mode keymap") (define-minor-mode zero-mode "a Chinese input method framework written as an emacs minor mode. @@ -466,6 +487,7 @@ return ch's Chinese punctuation if ch is converted. return nil otherwise" (set (make-local-variable 'zero-candidates) nil) (make-local-variable 'zero-candidates-per-page) (make-local-variable 'zero-current-page) + (make-local-variable 'zero-fetch-size) (make-local-variable 'zero-im) (make-local-variable 'zero-build-candidates-func) (make-local-variable 'zero-can-start-sequence-func) diff --git a/zero-pinyin.el b/zero-pinyin.el index 7e3a3b0..889f515 100644 --- a/zero-pinyin.el +++ b/zero-pinyin.el @@ -20,8 +20,6 @@ "accompany `zero-candidates', marks how many preedit-str chars are used for each candidate") (defvar zero-pinyin-pending-str "") (defvar zero-pinyin-pending-preedit-str "") -(defvar zero-pinyin-initial-fetch-size 20 - "how many candidates to fetch for the first call to GetCandidates") ;;===================== ;; key logic functions @@ -40,21 +38,27 @@ (defvar zero-pinyin--build-candidates-use-test-data nil "if t, `zero-pinyin-build-candidates' will use `zero-pinyin-build-candidates-test'") -(defun zero-pinyin-build-candidates (preedit-str) +(defun zero-pinyin-build-candidates (preedit-str fetch-size) + "zero-pinyin-build-candidates synchronous version" (if zero-pinyin--build-candidates-use-test-data - (zero-pinyin-build-candidates-test preedit-str) - (let ((result (zero-pinyin-service-get-candidates preedit-str zero-pinyin-initial-fetch-size))) + (progn + (zero-pinyin-build-candidates-test preedit-str) + (setq zero-fetch-size fetch-size)) + (zero-debug "zero-pinyin building candidate list synchronously\n") + (let ((result (zero-pinyin-service-get-candidates preedit-str fetch-size))) + (setq zero-fetch-size fetch-size) (setq zero-pinyin-used-preedit-str-lengths (second result)) (first result)))) -(defun zero-pinyin-build-candidates-async (preedit-str complete-func) +(defun zero-pinyin-build-candidates-async (preedit-str fetch-size complete-func) "build candidate list, when done call complete-func on it" - (zero-debug "building candidate list async\n") + (zero-debug "zero-pinyin building candidate list asynchronously\n") (zero-pinyin-service-get-candidates-async preedit-str - zero-pinyin-initial-fetch-size + fetch-size (lambda (candidates matched_preedit_str_lengths) (setq zero-pinyin-used-preedit-str-lengths matched_preedit_str_lengths) + (setq zero-fetch-size fetch-size) ;; Note: with dynamic binding, this command result in (void-variable ;; complete-func) error. (funcall complete-func candidates)))) @@ -77,7 +81,9 @@ (should-not (zero-pinyin-can-start-sequence ?v))) (defun zero-pinyin-pending-preedit-str-changed () - (zero-pinyin-build-candidates-async zero-pinyin-pending-preedit-str 'zero-build-candidates-complete)) + (setq zero-fetch-size 0) + (setq zero-current-page 0) + (zero-pinyin-build-candidates-async zero-pinyin-pending-preedit-str zero-initial-fetch-size 'zero-build-candidates-complete)) (defun zero-pinyin-commit-nth-candidate (n) "commit nth candidate and return true if it exists, otherwise, return false" @@ -141,6 +147,23 @@ otherwise, just return nil" t)) (t (error "Unexpected zero-pinyin-state: %s" zero-pinyin-state)))))) +(defun zero-pinyin-page-down () + "handle page down for zero-pinyin. + +This is different from zero-framework because I need to support partial commit" + (let ((len (length zero-candidates)) + (new-fetch-size (* zero-candidates-per-page (+ 2 zero-current-page)))) + (if (and (< len new-fetch-size) + (< zero-fetch-size new-fetch-size)) + (let ((preedit-str (if (eq zero-pinyin-state *zero-pinyin-state-im-partial-commit*) zero-pinyin-pending-preedit-str zero-preedit-str))) + (zero-pinyin-build-candidates-async + preedit-str + new-fetch-size + (lambda (candidates) + (zero-build-candidates-complete candidates) + (zero-just-page-down)))) + (zero-just-page-down)))) + (defun zero-pinyin-handle-preedit-char (ch) "hanlde character insert in `*zero-state-im-preediting*' state. overrides `zero-handle-preedit-char-default'" (cond @@ -154,9 +177,10 @@ otherwise, just return nil" (unless (zero-pinyin-commit-nth-candidate (mod (- (- ch ?0) 1) 10)) (zero-append-char-to-preedit-str ch) (setq zero-pinyin-state nil))) - ((or (= ch zero-previous-page-key) - (= ch zero-next-page-key)) + ((= ch zero-previous-page-key) (zero-handle-preedit-char-default ch)) + ((= ch zero-next-page-key) + (zero-pinyin-page-down)) (t (let ((str (zero-convert-punctuation ch))) (if str (when (zero-pinyin-commit-first-candidate-in-full) @@ -186,7 +210,8 @@ otherwise, just return nil" (zero-register-im 'pinyin '((:build-candidates . zero-pinyin-build-candidates) - (:build-candidates-async . zero-pinyin-build-candidates-async) + ;; comment to use sync version, uncomment to use async version. + ;; (:build-candidates-async . zero-pinyin-build-candidates-async) (:can-start-sequence . zero-pinyin-can-start-sequence) (:handle-preedit-char . zero-pinyin-handle-preedit-char) (:get-preedit-str-for-panel . zero-pinyin-get-preedit-str-for-panel) diff --git a/zero-table.el b/zero-table.el index 3f9d988..c1af9e9 100644 --- a/zero-table.el +++ b/zero-table.el @@ -27,7 +27,7 @@ should sort before rhs." (string< (car lhs) (car rhs))) -(defun zero-table-build-candidates (preedit-str) +(defun zero-table-build-candidates (preedit-str &optional _fetch-size) (mapcar 'cdr (sort (cl-remove-if-not (lambda (pair) (string-prefix-p preedit-str (car pair))) zero-table-table) 'zero-table-sort-key))) (ert-deftest zero-table-build-candidates () -- GitLab