diff --git a/zero-framework.el b/zero-framework.el index 3a02df06a4b2ed20dd5c9b4fa0fe401ecad3fc60..6e2cf992a06931f5f6fd943942cfaf914f05c894 100644 --- a/zero-framework.el +++ b/zero-framework.el @@ -1,3 +1,4 @@ +;; -*- lexical-binding: t -*- ;; the zero Chinese input method framework for emacs. ;; implemented as a minor mode. ;; (load-file "~/lisp/elisp/zero/zero-panel.elc") @@ -95,11 +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-can-start-sequence-default (ch) nil) +(defun zero-build-candidates-default (_preedit-str) 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") + "contains a function to build candidates from preedit-str. The function accepts param preedit-str, 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.") (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 @@ -189,18 +192,23 @@ if t, `zero-debug' will output debug msg in *zero-debug* buffer") (defun zero-build-candidates (preedit-str) "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"))) -(defun zero-build-candidates-async (preedit-str) +(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) "build candidate list, when done show it via `zero-show-candidates'" - (zero-debug "building candidate list\n") + (zero-debug "building candidate list asynchronously\n") (let ((candidates (zero-build-candidates preedit-str))) ;; update cache to make SPC and digit key selection possible. - (setq zero-candidates candidates) - (setq zero-current-page 0) - (zero-show-candidates candidates))) + (funcall complete-func candidates))) (defun zero-convert-punctuation-basic (ch) "convert punctuation for *zero-punctuation-level-basic* @@ -323,7 +331,7 @@ 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" - (zero-build-candidates-async zero-preedit-str)) + (funcall zero-build-candidates-async-func zero-preedit-str 'zero-build-candidates-complete)) (defun zero-backspace-default () "handle backspace key in `*zero-state-im-preediting*' state" @@ -488,7 +496,7 @@ registered input method is saved in `zero-ims'" (if (not (member level (list *zero-punctuation-level-basic* *zero-punctuation-level-full* *zero-punctuation-level-none*))) - (error "level not supported: %s" level) + (error "Level not supported: %s" level) (setq zero-punctuation-level level))) (defun zero-set-punctuation-levels (levels) @@ -497,7 +505,7 @@ registered input method is saved in `zero-ims'" (if (not (member level (list *zero-punctuation-level-basic* *zero-punctuation-level-full* *zero-punctuation-level-none*))) - (error "level not supported: %s" level))) + (error "Level not supported: %s" level))) (setq zero-punctuation-levels levels)) (defun zero-cycle-punctuation-level () @@ -521,6 +529,9 @@ if im-name is nil, use default empty input method" (setq zero-build-candidates-func (or (cdr (assq :build-candidates im-functions)) 'zero-build-candidates-default)) + (setq zero-build-candidates-async-func + (or (cdr (assq :build-candidates-async im-functions)) + 'zero-build-candidates-async-default)) (setq zero-can-start-sequence-func (or (cdr (assq :can-start-sequence im-functions)) 'zero-can-start-sequence-default)) @@ -537,9 +548,10 @@ if im-name is nil, use default empty input method" (if (functionp init-func) (funcall init-func))) (set (make-local-variable 'zero-im) im-name)) - (error "input method %s not registered in zero" im-name))) + (error "Input method %s not registered in zero" im-name))) (zero-debug "using default empty input method") (setq zero-build-candidates-func 'zero-build-candidates-default) + (setq zero-build-candidates-async-func 'zero-build-candidates-async-default) (setq zero-can-start-sequence-func 'zero-can-start-sequence-default) (setq zero-handle-preedit-char-func 'zero-handle-preedit-char-default) (setq zero-get-preedit-str-for-panel-func 'zero-get-preedit-str-for-panel-default) diff --git a/zero-panel.el b/zero-panel.el index bb59298b243b2d2313a346d729371d4864cf0438..741e060a92fe7cf7dc6116524b2f7f1f364ecfdf 100644 --- a/zero-panel.el +++ b/zero-panel.el @@ -1,3 +1,4 @@ +;; -*- lexical-binding: t -*- ;; provide emacs interface for zero-panel dbus service. ;;================ @@ -6,13 +7,22 @@ (require 'dbus) -(defun zero-panel-async-call (method handler &rest args) +(defun zero-panel-error-handler (event error) + "handle dbus errors" + (when (or (string-equal "com.emacsos.zero.Panel" + (dbus-event-interface-name event)) + (s-contains-p "com.emacsos.zero.Panel" (cadr error))) + (error "zero-panel dbus failed: %S" (cadr error)))) + +(add-hook 'dbus-event-error-functions 'zero-panel-error-handler) + +(defun zero-panel-async-call (method _handler &rest args) "call Method on zero-panel service asynchronously. This is a wrapper around `dbus-call-method-asynchronously'" (apply 'dbus-call-method-asynchronously :session "com.emacsos.zero.Panel" "/com/emacsos/zero/Panel" "com.emacsos.zero.Panel" - method nil args)) + method nil :timeout 500 args)) ;;============ ;; public API diff --git a/zero-pinyin-service.el b/zero-pinyin-service.el new file mode 100644 index 0000000000000000000000000000000000000000..ee63b8898c6680898bae90e5511bed7e8533268f --- /dev/null +++ b/zero-pinyin-service.el @@ -0,0 +1,52 @@ +;; -*- lexical-binding: t -*- +;; provide emacs interface for zero-pinyin-service dbus service. + +;;================ +;; implementation +;;================ + +(require 'dbus) + +(defun zero-pinyin-service-error-handler (event error) + "handle dbus errors" + (when (or (string-equal "com.emacsos.zero.ZeroPinyinService" + (dbus-event-interface-name event)) + (s-contains-p "com.emacsos.zero.ZeroPinyinService" (cadr error))) + (error "zero-pinyin-service dbus failed: %S" (cadr error)))) + +(add-hook 'dbus-event-error-functions 'zero-pinyin-service-error-handler) + +(defun zero-pinyin-service-async-call (method handler &rest args) + "call Method on zero-pinin-service asynchronously. This is a wrapper around `dbus-call-method-asynchronously'" + (apply 'dbus-call-method-asynchronously + :session "com.emacsos.zero.ZeroPinyinService" + "/com/emacsos/zero/ZeroPinyinService" + "com.emacsos.zero.ZeroPinyinService" + method handler :timeout 1000 args)) + +(defun zero-pinyin-service-call (method &rest args) + "call Method on zero-pinin-service synchronously. This is a wrapper around `dbus-call-method'" + (apply 'dbus-call-method + :session "com.emacsos.zero.ZeroPinyinService" + "/com/emacsos/zero/ZeroPinyinService" + "com.emacsos.zero.ZeroPinyinService" + method :timeout 1000 args)) + +;;============ +;; public API +;;============ + +(defun zero-pinyin-service-get-candidates (preedit-str) + "get candidates for pinyin in preedit-str synchronously" + (zero-pinyin-service-call "GetCandidates" :string preedit-str)) + +(defun zero-pinyin-service-get-candidates-async (preedit-str get-candidates-complete) + "get candidates for pinyin in preedit-str asynchronously" + (zero-pinyin-service-async-call + "GetCandidates" get-candidates-complete :string preedit-str)) + +(defun zero-panel-quit () + "quit panel application" + (zero-pinyin-service-async-call "Quit" nil)) + +(provide 'zero-panel) diff --git a/zero-pinyin.el b/zero-pinyin.el index db7a663615040e70dab67a2597baf6ce0324f243..7da9809a196d2a20e3e6359362368674b40193ea 100644 --- a/zero-pinyin.el +++ b/zero-pinyin.el @@ -1,3 +1,4 @@ +;; -*- lexical-binding: t -*- ;; a pinyin input method for zero-framework ;;============== @@ -33,16 +34,26 @@ (make-local-variable 'zero-pinyin-state) (zero-pinyin-reset)) -(defun zero-pinyin-build-candidates (preedit-str) - (zero-pinyin-build-candidates-test preedit-str)) +(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-async (preedit-str) -;; "build candidate list, when done show it via `zero-pinyin-show-candidates'" -;; (zero-pinyin-debug "building candidate list\n") -;; (let ((candidates (zero-pinyin-build-candidates preedit-str))) -;; ;; update cache to make SPC and digit key selection possible. -;; (setq zero-pinyin-candidates candidates) -;; (zero-pinyin-show-candidates candidates))) +(defun zero-pinyin-build-candidates (preedit-str) + (if zero-pinyin--build-candidates-use-test-data + (zero-pinyin-build-candidates-test preedit-str) + (let ((result (zero-pinyin-service-get-candidates preedit-str))) + (setq zero-pinyin-used-preedit-str-lengths (second result)) + (first result)))) + +(defun zero-pinyin-build-candidates-async (preedit-str complete-func) + "build candidate list, when done call complete-func on it" + (zero-debug "building candidate list async\n") + (zero-pinyin-service-get-candidates-async + preedit-str + (lambda (candidates matched_preedit_str_lengths) + (setq zero-pinyin-used-preedit-str-lengths matched_preedit_str_lengths) + ;; Note: with dynamic binding, this command result in (void-variable + ;; complete-func) error. + (funcall complete-func candidates)))) (defun zero-pinyin-can-start-sequence (ch) "return t if char ch can start a preedit sequence." @@ -100,7 +111,7 @@ (setq zero-pinyin-pending-preedit-str (substring zero-pinyin-pending-preedit-str used-len)) (zero-pinyin-pending-preedit-str-changed) t)) - (t (error "unexpected zero-pinyin-state: %s" zero-pinyin-state)))))) + (t (error "Unexpected zero-pinyin-state: %s" zero-pinyin-state)))))) (defun zero-pinyin-commit-first-candidate-or-preedit-str () (unless (zero-pinyin-commit-nth-candidate 0) @@ -124,7 +135,7 @@ otherwise, just return nil" (zero-set-state *zero-state-im-waiting-input*) (zero-commit-text (concat zero-pinyin-pending-str candidate)) t)) - (t (error "unexpected zero-pinyin-state: %s" zero-pinyin-state)))))) + (t (error "Unexpected zero-pinyin-state: %s" zero-pinyin-state)))))) (defun zero-pinyin-handle-preedit-char (ch) "hanlde character insert in `*zero-state-im-preediting*' state. overrides `zero-handle-preedit-char-default'" @@ -171,6 +182,7 @@ otherwise, just return nil" (zero-register-im 'pinyin '((:build-candidates . zero-pinyin-build-candidates) + (: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-quickdial.el b/zero-quickdial.el index fab7bb3f15c4ddca64cbaa2ec9b5f8ccfa302fd4..5e416dbe19028ebc3df48917f2e2cb00f06d18da 100644 --- a/zero-quickdial.el +++ b/zero-quickdial.el @@ -1,3 +1,4 @@ +;; -*- lexical-binding: t -*- ;; a simple input method written as an emacs minor mode (defun zero-quickdial-insert-one () diff --git a/zero-reload-all.el b/zero-reload-all.el new file mode 100644 index 0000000000000000000000000000000000000000..6412776549812a8366b199a22cd0c46f98cd2f8e --- /dev/null +++ b/zero-reload-all.el @@ -0,0 +1,11 @@ +;; -*- no-byte-compile: t; -*- +(defun zero-reload-all () + (interactive) + (byte-recompile-directory "~/lisp/elisp/zero/" 0) + (dolist (f '("zero-quickdial.elc" + "zero-panel.elc" + "zero-framework.elc" + "zero-table.elc" + "zero-pinyin-service.elc" + "zero-pinyin.elc")) + (load-file f))) diff --git a/zero-table.el b/zero-table.el index 3dcf354ed68c484583f40067b9c6ad52febc4c7f..3f9d9888d8827bd7019bd73b4968cb2df31365d8 100644 --- a/zero-table.el +++ b/zero-table.el @@ -1,3 +1,4 @@ +;; -*- lexical-binding: t -*- ;; a simple input method written as an emacs minor mode ;; (load-file "~/lisp/elisp/zero/zero-panel.elc") ;; (load-file "~/lisp/elisp/zero/zero-framework.elc")