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
Loading
Loading
Loading
Loading
+24 −12
Original line number Diff line number Diff line
;; -*- 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)
+12 −2
Original line number Diff line number Diff line
;; -*- 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

zero-pinyin-service.el

0 → 100644
+52 −0
Original line number Diff line number Diff line
;; -*- 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)
+23 −11
Original line number Diff line number Diff line
;; -*- 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)
+1 −0
Original line number Diff line number Diff line
;; -*- lexical-binding: t -*-
;; a simple input method written as an emacs minor mode

(defun zero-quickdial-insert-one ()
Loading