Commit f4a20631 authored by Yuanle Song's avatar Yuanle Song
Browse files

add zero-pinyin-service.el

dbus based sync and async api both works.
- added error handler for dbus client in emacs lisp.
- use lexical-binding for all files
- added M-x zero-reload-all this will byte compile and reload file files.
parent 8941891c
;; -*- 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)
......
;; -*- 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
......
;; -*- 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)
;; -*- 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)
......
;; -*- lexical-binding: t -*-
;; a simple input method written as an emacs minor mode
(defun zero-quickdial-insert-one ()
......
;; -*- 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)))
;; -*- 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")
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment