* 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 , when preedit str is longer than 1 | IM_PREEDITING | update preedit str, update and show candidate list | | Y | IM_PREEDITING | type , 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 - update ./ChangeLog, add user visible changes 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 - 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 "") 'zero-input-mode) (zero-input-set-default-im "pinyin") now in some buffer, press F1 and start typing. - make a git commit in master branch. - copy zero-input.el over to pkg branch. cp zero-input.el ../zero-pkg/ 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 - 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 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 ** 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. ** 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: ** 2020-02-21 org-mode, click badge should link to the pkg. not the image file. need to drop ?branch=master it works. ** 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. ** 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 - 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。 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 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。6 should not be converted to ".6". (define-key zero-input-mode-map (kbd "") 'zero-input-backspace) // I don't do anything here. auto fix doesn't work with preedit mode. (define-key zero-input-mode-map (kbd "") 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 (_) #)) 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 source code. ** 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. add a zero-full-width-mode variable add default binding shift+space, M-x zero-toggle-full-width-mode use modeline LIGHTER to show full/half width mode. when in full-width mode, show ZeroF. FSM table: move from gtk-im-module-zero operational file. - updated FSM. so it's only a few changes. - when insert character that can't start a sequence, insert char should be full-width aware. zero-self-insert-command DONE zero-commit-preedit-str DONE zero-convert-punctuation - when commit preedit str, insert should be full-width aware. - when insert Chinese punctuation character, insert should be full-width aware. - problems - where is the GB standard file? - docs GB/T 15834―2011 标点符号用法 电子版 http://people.ubuntu.com/~happyaron/l10n/GB(T)15834-2011.html doesn't have much about full width vs half width. - indeed double quotation mark is different from fullwidth quotation mark. LEFT DOUBLE QUOTATION MARK “” FULLWIDTH QUOTATION MARK "" - search U+FF02 U+FF02 FULLWIDTH QUOTATION MARK – Codepoints https://codepoints.net/U+FF02 Block Halfwidth and Fullwidth Forms – Codepoints https://codepoints.net/halfwidth_and_fullwidth_forms - why bind S-SPC key in zero-mode-map didn't work. global-set-key does work. shift-space is always translated to space in minor mode? shift is not registered as key prefix. I will just use another key binding for this command. try M-space. nope. https://www.gnu.org/software/emacs/manual/html_node/elisp/Keymaps-and-Minor-Modes.html#Keymaps-and-Minor-Modes Minor modes may bind commands to key sequences consisting of C-c followed by a punctuation character. However, sequences consisting of C-c followed by one of {}<>:;, or a control character or digit, are reserved for major modes. Also, C-c letter is reserved for users. See Key Binding Conventions. try use C-c , , and C-c , . how to add C-c , as prefix key and add binding for those two commands? it works. - elisp how to convert unicode hex to char? 1. Non-ASCII Characters https://ftp.gnu.org/old-gnu/Manuals/elisp-manual-21-2.8/html_chapter/elisp_33.html#SEC541 FF01 to FF65 only 65 chars. I will just type it. "\uff01" ! char to code point: (split-char ?\)(unicode 0 255 1) # FF01 (split-char ?\!)(unicode 0 255 1) (insert (make-char 'unicode 0 255 1)) (split-char ?\!)(ascii 33) # FF5A (split-char ?\z)(unicode 0 255 90) (insert (make-char 'unicode 0 255 90)) (split-char ?\z)(ascii 122) # FF65 (split-char ?\・)(unicode 0 255 101) (insert (make-char 'unicode 0 255 101)) ascii [33, 122] map to unicode 0 255 [1, 101]. then pick a few others if they are of importance. - commit preedit str in full-width mode didn't work. it still commit half-width str. is zero-commit-preedit-str called at all? there is no debug message. that is for commit preedit-str when there is no candidate. when I press RET, the code is in zero-return. - type = will insert both full-width char and half-width char. fixed. * wontfix :entry: ** 2020-02-20 gitlab doesn't render README as org-mode file. github does render it. should I name it README.org? - does gitlab newer version support parsing mode line? search: gitlab parse mode line from README file search: gitlab render README file without suffix gitlab only support markdown, ascii doc and rst. org-mode is not supported. add .org suffix won't help gitlab. Either keep it or rewrite it as markdown or rst. I will keep it. ** 2020-02-04 zero-input-pinyin-pending-preedit-str="erduo" not correct? - zero-input-pinyin-pending-preedit-str="erduo" zero-input-pinyin-pending-preedit-str this variable may not be cleared at proper place. #+BEGIN_SRC sh synchronously candidates: 摩尔, 莫尔, 末儿, 模, 默, 麽, 莫, 摸, 末, 磨 user typed: d still preediting appended d, preedit str is: moerd zero-input-pinyin building candidate list synchronously candidates: 摸耳朵, 莫尔德, 摩尔, 莫尔, 末儿, 模, 默, 麽, 莫, 摸 user typed: u still preediting appended u, preedit str is: moerdu zero-input-pinyin building candidate list synchronously candidates: 摩尔, 莫尔, 末儿, 模, 默, 麽, 莫, 摸, 末, 磨 user typed: o still preediting appended o, preedit str is: moerduo zero-input-pinyin building candidate list synchronously candidates: 摸耳朵, 摩尔, 莫尔, 末儿, 模, 默, 麽, 莫, 摸, 末 user typed: still preediting zero-input-pinyin-commit-nth-candidate n=0 candidate=摸耳朵 used-len=7 zero-input-pinyin-pending-preedit-str="erduo" commit in full set state to IM-WAITING-INPUT zero-input-disable-preediting-map commit text: 摸耳朵 hide candidate list user typed: d can start sequence, state=IM_PREEDITING set state to IM-PREEDITING zero-input-enable-preediting-map appended d, preedit str is: d zero-input-pinyin building candidate list synchronously candidates: 的, 都, 到, 等, 第, 带, 大, 对, 当, 低 user typed: u still preediting appended u, preedit str is: du zero-input-pinyin building candidate list synchronously candidates: 度, 赌, 读, 独, 毒, 都, 肚, 督, 渡, 杜 user typed: i still preediting appended i, preedit str is: dui zero-input-pinyin building candidate list synchronously candidates: 对, 队, 堆, 對, 兑, 隊, 怼, 碓, 桘, 憝 user typed: b still preediting appended b, preedit str is: duib zero-input-pinyin building candidate list synchronously candidates: 对比, 对白, 对本, 对不, 对吧, 对被, 对表, 对半, 对把, 对边 user typed: u still preediting appended u, preedit str is: duibu zero-input-pinyin building candidate list synchronously candidates: 对不, 队部, 对, 队, 堆, 對, 兑, 隊, 怼, 碓 user typed: q still preediting appended q, preedit str is: duibuq zero-input-pinyin building candidate list synchronously candidates: 对不起, 对不, 队部, 对, 队, 堆, 對, 兑, 隊, 怼 user typed: i still preediting appended i, preedit str is: duibuqi zero-input-pinyin building candidate list synchronously candidates: 对不起, 对不, 队部, 对, 队, 堆, 對, 兑, 隊, 怼 user typed: still preediting zero-input-pinyin-commit-nth-candidate n=0 candidate=对不起 used-len=7 zero-input-pinyin-pending-preedit-str="erduo" commit in full set state to IM-WAITING-INPUT zero-input-disable-preediting-map commit text: 对不起 hide candidate list #+END_SRC I can redproduce it. just delete the user phrase, then type it again. #+BEGIN_SRC sh user typed: o still preediting appended o, preedit str is: moerduo zero-input-pinyin building candidate list synchronously candidates: 摸耳朵, 摩尔, 莫尔, 末儿, 模, 默, 麽, 莫, 摸, 末 zero-input-pinyin building candidate list synchronously candidates: 摩尔, 莫尔, 末儿, 模, 默, 麽, 莫, 摸, 末, 磨 user typed: 8 still preediting zero-input-pinyin-commit-nth-candidate n=7 candidate=摸 used-len=2 zero-input-pinyin-pending-preedit-str="" partial commit, in partial commit mode now. zero-input-pinyin building candidate list synchronously candidates: 耳朵, 尔多, 而多, 尔, 耳, 而, 儿, 二, 兒, 爾 user typed: still preediting zero-input-pinyin-commit-nth-candidate n=0 candidate=耳朵 used-len=5 zero-input-pinyin-pending-preedit-str="erduo" finishes partial commit set state to IM-WAITING-INPUT zero-input-disable-preediting-map commit text: 摸耳朵 hide candidate list #+END_SRC This is not a bug. zero-input-pinyin-pending-preedit-str is not used when IM has not go to partial commit mode. it will always be set to correct value when it does go to partial commit mode.