Skip to content
operational 47.2 KiB
Newer Older
* COMMENT -*- mode: org -*-
#+Date: 2019-10-08
Time-stamp: <2023-08-16>
#+STARTUP: content
* notes                                                               :entry:
** 2019-04-01 zero-el a Chinese IM framework in emacs; FSM              :doc:
title was: how to write a modern im for emacs.
cd ~/lisp/elisp/zero/
- DONE can I implement it as a minor mode? yes.
- DONE can I use panel to show candidates? yes.
- zero minor mode FSM
  implemented in zero.el
  | Imp | state            | action                                              | next state       | trigger action                                                                                          |
  |-----+------------------+-----------------------------------------------------+------------------+---------------------------------------------------------------------------------------------------------|
  | Y   | IM_OFF           | M-x zero-input-on or zero-input-toggle                          | IM_WAITING_INPUT | turn on minor mode                                                                                      |
  | Y   | IM_WAITING_INPUT | type M-x zero-input-off or zero-input-toggle                    | IM_OFF           | turn off minor mode                                                                                     |
  | Y   | IM_WAITING_INPUT | type character that can start a sequence            | IM_PREEDITING    | update preedit str, show candidate list                                                                 |
  | Y   | IM_WAITING_INPUT | type character that can not start a sequence        | IM_WAITING_INPUT | insert character (full-width aware)                                                                     |
  | Y   | IM_WAITING_INPUT | type [,.?!\]                                        | IM_WAITING_INPUT | insert Chinese punctuation character (full-width aware)                                                 |
  | Y   | IM_PREEDITING    | type character (that is not SPC, digit keys)        | IM_PREEDITING    | update preedit str, update and show candidate list                                                      |
  | Y   | IM_PREEDITING    | type RET                                            | IM_WAITING_INPUT | commit preedit str (full-width aware), hide candidate list, reset preedit str                           |
  | Y   | IM_PREEDITING    | type SPC                                            | IM_WAITING_INPUT | commit first candidate or preedit str (full-width aware), reset preedit str                             |
  | Y   | IM_PREEDITING    | type digit keys                                     | IM_WAITING_INPUT | commit nth candidate if it exists, otherwise, append to preedit str                                     |
  |     | IM_PREEDITING    | type C-g                                            | IM_WAITING_INPUT | reset IM (reset preedit str, hide candidate list)                                                       |
  | Y   | IM_PREEDITING    | type M-x zero-input-off or zero-input-toggle                    | IM_OFF           | reset IM, turn off minor mode                                                                           |
  | Y   | IM_PREEDITING    | type <backspace>, when preedit str is longer than 1 | IM_PREEDITING    | update preedit str, update and show candidate list                                                      |
  | Y   | IM_PREEDITING    | type <backspace>, when preedit str is length 1      | IM_WAITING_INPUT | reset IM                                                                                                |
  | Y   | IM_PREEDITING    | focus in                                            | IM_PREEDITING    | show candidat list                                                                                      |
  | Y   | IM_PREEDITING    | focus out                                           | IM_PREEDITING    | hide panel                                                                                              |
  | Y   | IM_PREEDITING    | type [,.?!\]                                        | IM_WAITING_INPUT | commit first candidate or preedit str (full-width aware), insert Chinese punctuation (full-width aware) |
  | Y   | IM_PREEDITING    | type -/=                                            | IM_PREEDITING    | candiate page up/down                                                                                   |
  |     |                  |                                                     |                  |                                                                                                         |

  in IM_OFF state, zero should not do any preedit try nor do punctuation
  translate.

- DONE make zero-input-quickdial IM work in emacs.
  see ~/lisp/elisp/zero/zero-input-quickdial.el
- DONE make zero-input-table IM work in emacs. with zero-input-panel.
  see ~/lisp/elisp/zero/zero-input-table.el
- during development, press F8 to byte-compile and load the current el file.
  this will also look for errors in the file.

  press F9 to run ert tests.
- TODOs
  - whenever a command moves point, IM should probably reset()
    I can't remap every possible key/function.

  - I need hook for buffer/window focus in/out.
    currently, when user switch to another buffer, the panel will still show.

    user can click mouse in another emacs window.
    whenever focus is moved outside current buffer, I need a hook to run
    zero-input-focus-out.

    how to reproduce the problem
    =============================
    open emacs, split, top window show buffer with file t3, bottom window show
    buffer with file t4.

    in t3 buffer, press F1 to toggle zero on. type "a", candidate list will
    show. now press C-x o to switch to t4 buffer. candidate list didn't go
    away. because I can't find a hook for it.

    the mouse case:
    =================
    open emacs, split, top window show buffer with file t3, bottom window show
    buffer with file t4.

    in t3 buffer, press F1 to toggle zero on. type "a", candidate list will
    show. now click mouse on t4 buffer. candidate list didn't go away. because
    I can't find a hook for it.

  - how to check whether string contains character?
    without converting char to string.

    (zero-input-table-can-start-sequence) can use this.
** 2020-02-04 how to make a release?					:doc:
- update version number in zero-input-framework.el
Yuanle Song's avatar
Yuanle Song committed
- update ./ChangeLog, add user visible changes
Yuanle Song's avatar
Yuanle Song committed
  M-x add-change-log-entry or C-x 4 a.
- run tests
  make check
- build a release .el file
  make dist
- check & fix styling issues
  open zero-input.el file
  M-x checkdoc
  M-x package-lint-current-buffer
Yuanle Song's avatar
Yuanle Song committed
- test zero-input.el in a fresh emacs -Q window.

  (load-file "~/.emacs.d/elpa/s-1.11.0/s.elc")
  (byte-compile-file "~/lisp/elisp/zero/zero-input.el" t)
  (global-set-key (kbd "<f1>") 'zero-input-mode)
  (zero-input-set-default-im "pinyin")
Yuanle Song's avatar
Yuanle Song committed

  now in some buffer,
  press F1 and start typing.

- make a git commit in master branch.
- copy zero-input.el over to pkg branch.
Yuanle Song's avatar
Yuanle Song committed
  cp zero-input.el ../zero-pkg/

Yuanle Song's avatar
Yuanle Song committed
  make a git commit in pkg branch.
  tag it if it is a stable release.

- push commits.
  push tags if it is a stable release.

** 2019-10-10 documents
- Using of D-Bus
  https://www.gnu.org/software/emacs/manual/html_mono/dbus.html
Yuanle Song's avatar
Yuanle Song committed
- Travis CI
  The Ubuntu 18.04 Build Environment - Travis CI
  https://docs.travis-ci.com/user/reference/bionic/
  Installing Dependencies - Travis CI
  https://docs.travis-ci.com/user/installing-dependencies
  Customizing the Build - Travis CI
  https://docs.travis-ci.com/user/customizing-the-build#build-matrix
Yuanle Song's avatar
Yuanle Song committed
  Testing Your Project on Multiple Operating Systems - Travis CI
  https://docs.travis-ci.com/user/multi-os/
** 2023-08-16 architecture                                         :arch:doc:
see https://blog.emacsos.com/zero-el.html#org8e45833

#+BEGIN_SRC text
	   emacs zero-input-mode
		   |
		   |
	     zero-input-pinyin
		  /\
		 /  \
		/    \
	       /      \
	 dbus /        \ dbus
	     /          \                         
	    /            \ 
	   /              \ 
	  /                \
  zero-pinyin-service     zero-panel
#+END_SRC

* later                                                               :entry:
* current                                                             :entry:
** 
** 2023-08-16 create a panel using emacs facility.
make it work in terminal emacs.

- yasnippet when select snippet can show a dropdown list.
- check the arch. how is dbus message sent to different component?
  zero-input call zero-panel service directly from emacs lisp code.

  so I only need to register a new service and select which service to publish
  message to. this is not as flexible.

  try this instead:
  still use the same service name and spec.

  in emacs lisp, allow user to stop (kill) existing service and choose which
  panel service to start.

  worry about this later. first make it work in terminal emacs.
- create a zero-panel service in raw emacs.

  ~/.emacs.d/site-lisp/yasnippet/dropdown-list.el

  According to Jaeyoun Chung, "overlay code stolen from company-mode.el."

  search: emacs lisp which overlay drop down menu to use?

  which one does pyim use?

  GitHub - tumashu/pyim: 一个 emacs 中文输入法,支持全拼,双拼,五笔,仓颉和Rime,pyim 是 GNU elpa 包。
  https://github.com/tumashu/pyim
  GNU ELPA - pyim
  https://elpa.gnu.org/packages/pyim.html

  让选词框跟随光标
  https://github.com/tumashu/pyim#%E8%AE%A9%E9%80%89%E8%AF%8D%E6%A1%86%E8%B7%9F%E9%9A%8F%E5%85%89%E6%A0%87
  overlay solutions to show candidates

  - popup
    (require 'popup)

    GitHub - auto-complete/popup-el: Visual Popup Interface Library for Emacs
    https://github.com/auto-complete/popup-el

    popup is in melpa.
    last release is 20221231.1634

  - popon
    (require 'popon)

    akib/emacs-popon: "Pop" floating text "on" a window - emacs-popon - Codeberg.org
    https://codeberg.org/akib/emacs-popon

    It is not on GNU elpa or melpa. out.

  - posframe
    (require 'posframe)

    GitHub - tumashu/posframe: Pop a posframe (just a child-frame) at point, posframe is a **GNU ELPA** package!
    https://github.com/tumashu/posframe
    GNU ELPA - posframe
    https://elpa.gnu.org/packages/posframe.html

    posframe is both in GNU elpa and melpa.

  none is included in emacs.

- evaluate which overlay solution has best performance and is easy to use.

  I will try both popup and posframe.

  just show the same thing as zero-panel-client-demo.

  see test code in ./test-popup.el

Yuanle Song's avatar
Yuanle Song committed
** 2021-08-08 create a panel for wayland display server.
currently zero-panel doesn't position itself correctly in wayland on debian 11
bullseye.

- 2023-08-16 panel flash on GNOME 40 Wayland in RHEL 9.
  see ~/projects/zero-panel/operational

  There are two problems of zero-panel on Wayland.
  1. zero-panel window keeps getting focus and unfocused. e.g. flashing.
  2. zero-panel window is not positioned at emacs (point) location.

** 2020-02-23 support typing ±, ≥, ≤ easier.
when user type +-, it is converted to ±.
use a flag to control conversion.
zero-input-auto-symbol-p default value is 'FULL, means only enable when
punctuation mode is 'FULL. if set to t, always convert char to symbol. if set
to nil, never convert char to symbol.

Non-nil means auto convert some consective character to related symbol.

#+BEGIN_SRC elisp
  (defcustom zero-input-auto-symbol-alist
    '(((?+ ?-) "±")
      ((?> ?=) "≥")
      ((?< ?=) "≤")
      ((?* ?x) "×")
      ((?< ?>) "≠")
      ((?! ?=) "≠"))
    "When user type chars in key, convert it to symbol in the value."
    :group 'zero-input
    :type 'TODO)
#+END_SRC
((?* ?x) "×") this one is different. x will be preedit str.
it's better if this is wrapped in a new mode.
like v mode used in some IM.
type v > = will show ≥ in candidate list.

- rethink about it later.

Yuanle Song's avatar
Yuanle Song committed
** 2020-02-21 zero-pinyin-service and zero-panel should recommend or suggest dbus pkg.
I don't know it should recommend or suggest.
** 2019-10-23 checkdoc and package-lint can't ignore some non-issues.
I can't run them in git pre-commit hook.
* done                                                                :entry:
Yuanle Song's avatar
Yuanle Song committed
** 2020-02-21 org-mode, click badge should link to the pkg. not the image file.
need to drop ?branch=master
it works.
Yuanle Song's avatar
Yuanle Song committed
** 2020-02-20 integrate travis CI support.
just run "make dist-check".

- problems
  - how to run on both debian 9, 10 and ubuntu 18.04?

    The Ubuntu 18.04 Build Environment - Travis CI
    https://docs.travis-ci.com/user/reference/bionic/
    There is no debian image on Travis CI.

  - how to install s pkg when run on travis CI?
    if ~/.emacs.d/elpa/s-1.11.0/s.el doesn't exist, install s and load it first.

    how to use package-install with package-desc?

    (package-install "s")
    (package-install "s-1.12.0")

    search: (error "Package `s-' is unavailable")

    Package 's-' is unavailable · Issue #373 · cask/cask
    https://github.com/cask/cask/issues/373

    elisp - Emacs's package-install inserts an extra dash at the end of the package - Stack Overflow
    https://stackoverflow.com/questions/36338528/emacss-package-install-inserts-an-extra-dash-at-the-end-of-the-package
    wat?
    I don't think this is the problem. In my setup, melpa is not the first element.

    I will cheat. Just download the file from github when run on travis CI.
    https://github.com/magnars/s.el

  - how to run it on emacs24, emacs25, emacs26?
    emacs24-nox is on xenial 16.04
    emacs25-nox is on bionic 18.04
    emacs26 is not in ubuntu yet.

    How to Install GNU Emacs 26.1 in Ubuntu 18.04, 16.04, 18.10 | UbuntuHandbook
    http://ubuntuhandbook.org/index.php/2019/02/install-gnu-emacs-26-1-ubuntu-18-04-16-04-18-10/
    https://launchpad.net/~kelleyk/+archive/ubuntu/emacs
    sudo add-apt-repository ppa:kelleyk/emacs
    sudo apt update
    sudo apt install emacs26
    I will ignore emacs26 for now.

  - travis forces venv, doesn't allow install to user site-packages.

    https://docs.travis-ci.com/user/languages/python/
    to use --user you just need to not use "language: python".
    I will use language: python and fix the command.

  - DONE elisp tests need access to GetCandidatesV2 dbus method.
    zero-input-pinyin-service-get-candidates
    why?

    this is good. I can install the deb in travis container.

  - DONE emacs run ert test doesn't exit with non-zero code when there are errors.
    it needs a wrapper function.

    ert-run-tests-batch
    Returns the stats object.
    ert-run-tests-batch-and-exit
    nice.

  - travis: no access to session bus.
    how to start dbus session bus when x is not running?
    search: travis start dbus session bus

    Testing with PulseAudio server in Travis · Issue #20 · favonia/pulse
    https://github.com/favonia/pulse/issues/20

  - MOVED zero-pinyin-service and zero-panel should recommend or suggest dbus pkg.
    I don't know it should recommend or suggest.

  - travis CI test works. great. integrate to master branch.

Yuanle Song's avatar
Yuanle Song committed
** 2020-02-20 add github issue system support.
- create issue templates online. then merge into master.
  git remote add github git@github.com:sylecn/zero-el.git
  git fetch github sylecn-patch-1
  gco github/sylecn-patch-1 .github/

  drop the feature branch on github
  git push github :sylecn-patch-1
  git push github :pkg
  git push github :multi-file-pkg

Yuanle Song's avatar
Yuanle Song committed
- update README, add bug report doc.
- 
** 2019-11-03 add completion support for zero-input-set-im
complete registered im symbols.

- 2020-02-16
  Function: completing-read prompt collection &optional predicate

  make sure non-interactively usage still works.
  (zero-input-set-im 'pinyin)

- DONE allow input method name to be string.
  to add backward compatibility, symbol is also supported.
  symbol is auto converted to lower case string.

  string is a better fit for names. it can include unicode strings easier.

- problems
  - how to call completing-read when call interactively?

    search: use completing-read with interactive function

    just call the function when &optional arg is nil.

  - (zero-input-set-im 'pinyin)
    this doesn't allow input pinyin after switching to table and back。

    if then else issue.
    fixed.

  - DONE when im name is string, alist eq comparison won't work.
    change to string-equal based compare.

    search: assq-delete-all but with string-equal

    emacs - Elisp: How to delete an element from an association list with string key - Stack Overflow
    https://stackoverflow.com/questions/9812393/elisp-how-to-delete-an-element-from-an-association-list-with-string-key

  - (zero-input-set-im 'pinyin)
    method not registered.

    (assq im-name zero-input-ims)
    (assoc im-name zero-input-ims)

  - try switch to empty and back.

    (zero-input-set-im 'pinyin)
    (zero-input-set-im 'empty)

    it works.

** 2020-02-16 declare zero-input-punctuation-level, zero-input-full-width-p using defcustom
use set-default to set the value.

set-default is the default setter. no problem.

- also for
  zero-input-pinyin-fuzzy-flag
  INVALID zero-input-auto-fix-dot-between-numbers, already via defcustom.

- problems
  - search: defvar-local vs defcustom

    just add
    (make-variable-buffer-local 'zero-input-punctuation-level)

  - DONE zero-input-pinyin-fuzzy-flag, why links in doctstring doesn't work?
    use raw string there.
    80 width can be avoided by using \ escape at line end.

** 2020-02-15 zero-el:中文标点full模式下,无法输入 fan'gai 翻盖
因为'会自动变成左引号。
而'在zps里面还有分词字符的含义。

- 建议取消 preedit 状态下'的自动 commit 1st candidate 并插入引号的功能。

  zero-input-pinyin-handle-preedit-char

** 2020-02-14 zero-el: H。265 > H.265
除了数字+小数点+数字,大写英文+小数点+数字也可以自动转换。

** 2020-02-02 zero-el: 如果输入“。”之前和之后输入的是数字,则自动将"。"转换为小数点"."。
(setq zero-input-auto-fix-dot-between-numbers t)
enabled by default.

- is it easy to implement in elisp?

  try it in self-insert-command hook.
  post-self-insert-hook

  (add-hook 'post-self-insert-hook #'t1-replace-chinese-dot-maybe nil t)

  see ~/lisp/elisp/testing-only/auto-fix-typing-via-self-insert-command-hook.el

  it works.
  when I type 1a3 it will insert 1.3.

- I think this can probably work outside zero-input.
  nope. zero doesn't use self-insert-command for inserting Chinese dot.

  what does it use?
  zero-input-pinyin-handle-preedit-char

  it should be easy to implement the same thing there.
  - when commit digit, just also add digit in a ring buffer. and check whether
    there is a Chinese dot to be replaced.
  - when commit Chinese dot, add Chinese dot in a ring buffer.

  // These digits and Chinese dot is not part of key IM logic.
  // zero-input-can-start-sequence will return false for them.
  // I don't even need to change zero-input-commit-text.

- put the feature under a flag.
  zero-input-auto-fix-dot-between-numbers

- problems
  - how to get last insert char?
  - how to get last 3 char from a string?
    (equal (substring "abcde" -3) "cde")
    (equal (substring "abc" -3) "abc")
    (equal (substring "ab" -3) "ab")

    how to loop characters over a string?
    (mapcar (lambda (ch) ch) "abc")
  - in elisp, use #'(lambda (x) x) or (lambda (x) x)?
    Anonymous Functions - GNU Emacs Lisp Reference Manual
    https://www.gnu.org/software/emacs/manual/html_node/elisp/Anonymous-Functions.html
    use #' is better. it is short for (function (lambda (x) ...)).
  - DONE return key should also insert ?\n to ring buffer.
    bug reproduce:
    type
    25。<ret>
    6
    it is converted to
    25。.6

    where is return key handled when not in preedit mode?

    debug log:
    user typed: .
    cannot start sequence, state=IM_WAITING_INPUT
    press <ret> doesn't get any debug output.

    ret is handled here:
    (define-key zero-input-mode-map (kbd "RET") 'zero-input-return)
    (define-key zero-input-mode-map (kbd "RET") nil)

    When not in preedit-mode, I use system default self-insert-command binding
    for RET key. So I still need the hook.

    (add-hook 'post-self-insert-hook #'zero-input-post-self-insert nil t)

    - when I do this, digit key press will insert twice into ring.
      fixed. only use post-self-insert-hook, drop my explicit call.
    - when type 。 it is not added to ring buf.
      // it is added, just doesn't have debug log. because it uses mapc to add ch
      // to ring.

      The hook function should handle auto fix Chinese dot in digits.
      now it works.

  - WONTFIX backspace should update ring buffer. Oh, I can't restore old char.
    just remove the newest item in the ring buffer.

    e.g. 1<backspace>。6 should not be converted to ".6".

    (define-key zero-input-mode-map (kbd "<backspace>") 'zero-input-backspace)
    // I don't do anything here. auto fix doesn't work with preedit mode.

    (define-key zero-input-mode-map (kbd "<backspace>") nil)

    backspace doesn't run self-insert-command in many major modes.
    There is nothing I can do.
    Is there a hook I can use?
    delete-char

  - DONE only do auto fix when zero-input-mode is on.

  - DONE when zero is off, clear the ring buffer.
    do it in zero-input-reset.

** 2020-02-04 zero-input-pinyin, allow switch between sync and async mode in runtime.
title was: zero-input-pinyin.el why sometimes it uses sync call and sometimes
it uses async call?

- debug log.

  #+BEGIN_SRC sh
    zero-input-pinyin building candidate list synchronously
    zero-input-pinyin building candidate list asynchronously
  #+END_SRC

  zero-input-pinyin.el why sometimes it uses sync call and sometimes it
  uses async call? I think every async call should chain back to sync
  call.

  I think when a call is triggered from zero-framework.el, it will always
  be sync call. when a call is triggered from zero-pinyin.el, it MAY used
  async call directly.

  who calls zero-input-pinyin-build-candidates-async

  - zero-input-pinyin-preedit-str-changed
    calls framework's version. which use default async call. and chains to
    zero-pinyin sync call.
  - zero-input-pinyin-pending-preedit-str-changed
    uses async call.
  - zero-input-pinyin-page-down
    uses async call.

  No wonder zero-pinyin sync and async performance is on par. Because sync
  call is not used much.
- How to use sync or async call in all places? I don't want to mix it.
  just enable async in IM register code? confirmed enable async will only
  use async version.

  how to switch to sync version only?
- implementation
  - added zero-input-pinyin-use-async-fetch flag variable.
  - added zero-input-pinyin-build-candidates-unified, it will call sync or
    async version based on the flag.
- problems
  - how to be able to switch between sync and async version in runtime?
    now I can switch it in build time, but how to switch it in runtime?

    It's mainly about the im register code.

    I have to provide a method to do it. a variable is not enough.
    Because I need to update the IM class method slot value.

    M-x zero-input-pinyin-enable-async
    M-x zero-input-pinyin-disable-async
  - 

** 2020-02-03 部分词组,打字时只出现词组,不能选单字。
zhiyuan 支援
zhishi 知识
weishi 微湿
weiyi 卫衣

- zhiyuan,zhishi 已修复。
  首次取词 21 个即可。
  // 不过这是假修复。没有解决词不够时,没有继续获取新词的问题。
- weishi,weiyi 还是有问题。
- all problems fixed.
- problems
  - added some debug log.
    zero-input-fetch-size is just wrong.
    "already fetched size" is wrong. which result in zero not trying to fetch
    more candidate when there is not enough to show in panel.
  - weiyi 卫衣
    50

    debug log
    #+BEGIN_SRC sh
      user typed: y
      still preediting
      appended y, preedit str is: weiy
      zero-input-pinyin building candidate list synchronously
      set zero-input-fetch-size to (max 21 (卫衣 味业 唯一 尾页 位于 未有 为已 委员 伪影 为一 惟一 唯有 卫浴 惟有 位於 违约 伟业 为由 为宜 喂养 位元 为有 威严 未央 位移 维亚 未用 胃炎 为与 为以 胃液 尾翼 为友 微一 尾牙 为用 委以 微雨 未予 为要 为伊 未遇 为盈 为业 为也 为云 威远 为月 微有 威仪)) = 50
      candidates: 卫衣, 味业, 唯一, 尾页, 位于, 未有, 为已, 委员, 伪影, 为一
      user typed: i
      still preediting
      appended i, preedit str is: weiyi
      zero-input-pinyin building candidate list synchronously
      set zero-input-fetch-size to (max 21 (卫衣 唯一 为已 为一 惟一 为宜 位移 为以 尾翼 微一 委以 为伊 威仪 偎依 逶迤 为意 维一 唯以 维以 伟易 唯壹 苇一)) = 22
      candidates: 卫衣, 唯一, 为已, 为一, 惟一, 为宜, 位移, 为以, 尾翼, 微一
      candidates: 卫衣, 唯一, 为已, 为一, 惟一, 为宜, 位移, 为以, 尾翼, 微一
      zero-input-enable-preediting-map
      user typed: =
      still preediting
      decide whether to fetch more candidates, on page 0, has 22 candidates, already fetched 50, new-fetch-size=21
      showing candidates on page 1
      candidates: 委以, 为伊, 威仪, 偎依, 逶迤, 为意, 维一, 唯以, 维以, 伟易
      candidates: 委以, 为伊, 威仪, 偎依, 逶迤, 为意, 维一, 唯以, 维以, 伟易
      zero-input-enable-preediting-map
      candidates: 委以, 为伊, 威仪, 偎依, 逶迤, 为意, 维一, 唯以, 维以, 伟易
      zero-input-enable-preediting-map
    #+END_SRC
    also, why show candidates are called twice?
  - can I trace zero-input-fetch-size variable in emacs lisp?

    replace byte-compiled version with non-byte-compiled version.

    Command: debug-on-entry function-name
    Command: cancel-debug-on-entry &optional function-name
  - I have a feeling of what's wrong.
    since the value is last time's fetch size.
    max of something, that something is not set properly.
    not zero-input-fetch-size itself.

    length of candidates. the candidates list is not updated in time or in
    correct order.

    yes. zero-input-pinyin-build-candidates doesn't set zero-input-candidates
    variable in time.

    who/when sets zero-input-candidates after fetching new candidates?

    in zero-input-framework.el, zero-input-build-candidates.

    it's override in zero-input-pinyin.el zero-input-pinyin-build-candidates.

    why zero-input-pinyin-build-candidates return the candidates as result. I
    think the return value is discarded. the return value is used by async
    complete function, used in default async implementation.

    how to distinguish between async and sync fetch?
    in async fetch, should update zero-input-candidates when fetch finished.
    in sync fetch, should update zero-input-candidates right away.
    I don't need to distinguish them, if zero-input-pinyin-build-candidates is
    called, it is using sync fetch. There is no time delay or async io.
  - DONE when is sync version used, when is async version used?
    // sync version is always called via async-func.

    zero-input-pinyin-page-down always call async verison.
    it relies on zero-input-build-candidates-complete to set
    zero-input-candidates variable.

    - when preedit-str changes.
      zero-input-preedit-str-changed
      calls zero-input-build-candidates-async-func

    - when user press = goto next page.
      zero-input-page-down
      calls zero-input-build-candidates-async-func

    - so sync version is always called via async-func.

    - zero-input-build-candidates-complete is not used properly in
      zero-input-page-down. do not reuse zero-input-build-candidates-complete
      function, just inline what should be called.

      #+BEGIN_SRC emacs-lisp
        (defun zero-input-build-candidates-complete (candidates)
          "Called when `zero-input-build-candidates-async' return.

        CANDIDATES is returned candidates list from async call."
          (setq zero-input-candidates candidates)
          (zero-input-show-candidates candidates))
      #+END_SRC
      this is where two show-candidates calls are made.
      now fixed.

    - double check zero-input-pinyin-build-candidates-async doesn't do the
      same thing that the callback function already did.

      it has done it twice.
      fixed.

    - zero-input-framework.el sync/async version is not quite right.
      zero-input-pinyin.el async version is not being used? It's okay.
      does sync version work as expected?

      the two "external" use case always call async version, so sync version
      is only used to build candidates, and I confirm it doesn't need to
      update metadata.

      zero pinyin:
      #+BEGIN_SRC emacs-lisp
        (zero-input-register-im
         'pinyin
         '((:build-candidates . zero-input-pinyin-build-candidates)
           ;; comment to use sync version, uncomment to use async version.
           ;; (:build-candidates-async . zero-input-pinyin-build-candidates-async)
      #+END_SRC

** 2019-11-10 space doesn't work in full-width mode.
全角和半角 - 维基百科,自由的百科全书
https://zh.wikipedia.org/wiki/%E5%85%A8%E5%BD%A2%E5%92%8C%E5%8D%8A%E5%BD%A2

ascii   full-width unicode codepoint.
0x20 	" " 	U+3000

- add a failing unit test.

** 2019-11-07 full width mode no longer works. why?
C-c , . enabled full-width mode.
but modeline is not changed.
type digit just insert half-width char.

zero-input-full-width-p

it's always nil.
check zero-input-toggle-full-width

- defvar-local and setq problem.
  (defvar-local zero-input-full-width-p nil)
  (setq zero-input-full-width-p (not zero-input-full-width-p))

  maybe setq doesn't set buffer local variable when it is defined as
  defvar-local.

  eval (zero-input-toggle-full-width) inside zero buffer does work.
  but press C-c ,. doesn't change the variable in zero buffer.

  C-c ,, zero-input-cycle-punctuation-level does work.

- read buffer-local variables.
  Info: (elisp) Buffer-Local Variables

  A variable can have buffer-local bindings in some buffers but not in other
  buffers.  The default binding is shared by all the buffers that don’t have
  their own bindings for the variable.

- check how it is done in old code. before defvar-local.
  git show a8e2341f978d64d6068bb564ad15e896e810e21b -- zero-input-framework.el

  (make-local-variable 'zero-input-full-width-mode)
  I think I need this back.
  defvar-local only make variable buffer local when it is set for the first
  time. maybe that's not enough.

  first call to C-c,. should be "enabled full-width mode"

- 2019-11-10 it's said 2.0.0 also have problem.

  add (make-local-variable 'zero-input-full-width-mode) in minor mode init
  works.

  are there other similar problems for local variables?

  defvar-local is not the same as make-local-variable.
  because if you only read the variable, it will get a global value.

  defvar-local is similar to make-variable-buffer-local. both only create a
  buffer local binding on first set.

  use setq-local is equivalent to make-local-variable and setq.

** 2019-11-03 review advice from riscy.
riscy, thanks for the review. Some quite good advice there.

Here are changes I have made.

- dropped Package-Version metadata. Version was there from the start.
- zero-input-full-width-mode renamed to zero-input-full-width-p.
- zero-input-toggle is now an obsolete alias for zero-input-mode.
  updated docstring to suggest user bind key to zero-input-mode.
- use defvar-local when variable is always buffer local.
  git grep make-local-variable
- moved test data to debug/test files.
- Comments on keeping just one `provide' call for zero-input.el

  It's easy to fix in build script. But I have kept multiple provide calls for
  the following reasons:

  - All features provided are in fact independent modules. They can be
    optionally loaded, they could have alternative implementations, and some
    can be reused in other emacs lisp projects.
  - Test file for each feature only require that feature, not all of
    zero-input.el. If only one provide is used, test file have to require the
    whole thing, or I will need different require call for development code
    and released code.
  - The one file zero-input.el is only created for easier distribution. I
    would like to switch to multi-file distribution when package-lint supports
    multi-file packages.

  If possible, I would like to keep the multiple provide calls.
- fixed typo. zero-input-pinin-service > `zero-input-pinyin-service'.

- implementation
  - test zero-input-mode function works fine when bind to a key.
- problems
  - when use one `provide' call. tests (require 'zero-input-panel) won't work.
  - test in emacs -Q. press f5 zero-input-mode, type anything result in
    English text. M-x zero-on does work.

    zero-input-on and zero-input-off have more to do than just set the minor
    mode on and off.

    Can I do those via hooks?

    - zero-input-on, can just do it at minor mode definition.
    - zero-input-off, it calls reset and set-state.
    - all fixed. just use emacs generated zero-input-mode function.  always
      reset when minor mode is enabled. there is no need to reset when minor
      mode is turned off.

** 2019-10-15 make package-lint happy on all el files.
- package-lint doesn't support multi-file package.

  Need to add headers to make it happy.

  Because it doesn't have concept on multi-file package, it insists all
  functions in file start with file name prefix. I can't have zero-input-* utility
  function in zero-input-panel.el

- M-x package-lint-current-buffer fail on zero.el file
  this line:
  (eval-when-compile (require 'cl-macs))

  M-x package-lint-current-buffer fails on a fresh .el file with just that
  line.

  #+BEGIN_SRC sh
    Debugger entered--Lisp error: (wrong-type-argument integer-or-marker-p nil)
      package-lint--map-symbol-match("(\\s-*?require\\s-*?'cl-\\(?:macs\\|seq\\)\\_>" #f(compiled-function (_) #<bytecode 0x15e4cd9>))
      package-lint--check-no-use-of-cl-lib-sublibraries()
      package-lint--check-all()
      package-lint-buffer()
      package-lint-current-buffer()
      funcall-interactively(package-lint-current-buffer)
      call-interactively(package-lint-current-buffer record nil)
      command-execute(package-lint-current-buffer record)
      execute-extended-command(nil "package-lint-current-buffer" nil)
      funcall-interactively(execute-extended-command nil "package-lint-current-buffer" nil)
      call-interactively(execute-extended-command nil nil)
      command-execute(execute-extended-command)
  #+END_SRC

  package-lint--check-no-use-of-cl-lib-sublibraries
  'warning
  "This file is not in the `cl-lib' ELPA compatibility package: require `cl-lib' instead."

  says you should use cl-lib instead. may as well try that.
  yes. that works.

- create a single file for distribution.
  package-lint doesn't support multiple file pkg yet.

  - create a single zero.el file for distribution.
    rename current zero.el to zero-input-framework.el
    create zero.el.in
  - make build
    should generate zero.el and run checks on it.
  - insert content to zero.el.in
    ;;; Code:
    ;;; .*\.el ends here
  - now package-lint should be fine.
  - I should I put zero.el in a branch or a separate git repo?
    separate git repo is better.
    how to auto build and commit on source repo push?
    use gocd CI, I can trigger a build. just run git add and git push there?
    if run in the same repo, two branch is required.
  - maybe just add zero.el in master branch and commit it anyway.
  - 

** 2019-10-11 move tests to separated files.
otherwise (require 'zero-input-pinyin) will fail because (require 'ert) is not in
** 2019-10-09 release zero-el on melpa
melpa/CONTRIBUTING.org at master · melpa/melpa · GitHub
https://github.com/melpa/melpa/blob/master/CONTRIBUTING.org

Making your package ready for inclusion
https://github.com/melpa/melpa/blob/master/CONTRIBUTING.org#making-your-package-ready-for-inclusion

Packaging Basics - GNU Emacs Lisp Reference Manual
https://www.gnu.org/software/emacs/manual/html_node/elisp/Packaging-Basics.html#Packaging-Basics

name: zero
version: 1.2.2
brief: a Chinese input method framework
long: zero is a Chinese input method framework for Emacs, implemented
as an Emacs minor mode. A zero-pinyin input method is included with zero
distribution.
dependencies: s

progress:
Preparing a pull request to MELPA
https://github.com/melpa/melpa/blob/master/CONTRIBUTING.org#preparing-a-pull-request-to-melpa

- problems
  - should I create two pkg, one for zero-framework and one for zero-pinyin?
    does melpa require two repo for this?
  - minimum s version?
    I only use s-contains-p s-join.
    checked github
    tag 1.2.0 already include these functions.
    https://github.com/magnars/s.el/blob/1.2.0/s.el
  - Note that there is no way to control the order in which files are
    byte-compiled.

    // seems my pkg compile just fine.
  - how to add autoload magic comments?

    https://www.gnu.org/software/emacs/manual/html_node/elisp/Autoload.html

    A magic autoload comment (often called an autoload cookie) consists of
    ‘;;;###autoload’, on a line by itself, just before the real definition of
    the function in its autoloadable source file.

    add this for some user commands.
    zero-set-im
    zero-set-default-im
    zero-on
    zero-toggle
  - run package-lint
  - Prefix function names with #’ (i.e., the special form function) instead of
    just ’ (i.e., the special form quote) to tell the compiler this is a
    function reference. E.g., (seq-filter #'evenp list).

    I don't think this is necessary in my code.
  - do I need to fix all checkdoc problems for my pkg to be accepted by melpa?
    search: melpa checkdoc one liner functions docstring

    yes. they require all checkdoc problem be fixed.
    Add recipe for a.el by dotemacs · Pull Request #4830 · melpa/melpa
    https://github.com/melpa/melpa/pull/4830

    how to specify minimum emacs version?
    ;; Package-Requires: ((emacs "24"))
  - DONE fix all checkdoc problems.
    // except for zero-mode, which I don't know how to fix. all other problems
    fixed.
    - Disambiguate zero-mode by preceding w/ function,command,variable,option
      or symbol. (C-h,f,e,n,p,q) [4 times]

      this one is really confusing.
      org-mode-map doesn't do this.
      magit-mode-map doesn't do this.
  - TODO how to add dbus as dependencies?
    some emacs build may not have dbus.
    (require 'dbus)

    also how to only allow install on linux? when I test it dbus only worked
    in linux.

    what's the correct syntax for specifying dbus as dependency?
    (dbus "1.0")
    didn't work.
  - search: package-install-file package--description-file: Wrong type argument: stringp, nil
    search: emacs package-install-file install tar package--description-file: Wrong type argument: stringp, nil

    install from dir is okay.
    install from tar is not. Not sure what's wrong.
** 2019-10-08 support full-width characters and symbols.
全角 半角

- feature requests
  - when zero-mode is on, and in full-width mode
    - commit English character and symbol should commit full-width character
      if there is a full-width character. This should happen before checking
      punctuation mapping. if a map is found, punctuation mapping is ignored.
    - type letters should still go into preedit str, only commit full-width
      char when user press RET.
  - when zero-mode is on, and in half-width mode (the default)
    - do what it does now. punctuation mapping is checked.

- implementation
  - Block Halfwidth and Fullwidth Forms – Codepoints
    https://codepoints.net/halfwidth_and_fullwidth_forms
  - how to support full width character and symbol in zero?
    update fsm table.