branch: externals/pyim commit 48549c5688f5ae97871631447cc45049c458718f Author: Feng Shu <tuma...@163.com> Commit: Feng Shu <tuma...@163.com>
Simplify pyim-process-select-handle-char --- pyim-outcome.el | 13 +++-- pyim-process.el | 157 +++++++++++++++++++++++++--------------------------- pyim-punctuation.el | 43 +++++++++++--- tests/pyim-tests.el | 4 +- 4 files changed, 120 insertions(+), 97 deletions(-) diff --git a/pyim-outcome.el b/pyim-outcome.el index 80395e413a..1df4c6c1af 100644 --- a/pyim-outcome.el +++ b/pyim-outcome.el @@ -88,7 +88,7 @@ pyim 使用函数 `pyim-process-select-handle-char' 来处理特殊功能触发 方案下,这个快捷键设置是否合理有效,如果不是一个合理的设置,则使 用拼音方案默认的 :prefer-triggers 。 -具体请参考 `pyim-outcome-get-trigger' 。" +具体请参考 `pyim-outcome--get-trigger' 。" :type '(choice (const nil) string)) (defcustom pyim-outcome-trigger-function 'pyim-outcome-trigger-function-default @@ -157,7 +157,11 @@ pyim 使用函数 `pyim-process-select-handle-char' 来处理特殊功能触发 result)) str)) -(defun pyim-outcome-get-trigger () +(defun pyim-outcome-trigger-p (str) + "判断 STR 是否是一个 trigger." + (equal (pyim-outcome--get-trigger) str)) + +(defun pyim-outcome--get-trigger () "检查 `pyim-outcome-trigger' 是否为一个合理的 trigger char 。 pyim 的 translate-trigger-char 要占用一个键位,为了防止用户 @@ -173,10 +177,7 @@ pyim 的 translate-trigger-char 要占用一个键位,为了防止用户 (prefer-triggers (pyim-scheme-prefer-triggers (pyim-scheme-current)))) (if (pyim-string-match-p (regexp-quote user-trigger) first-char) - (progn - ;; (message "注意:pyim-outcome-trigger 设置和当前输入法冲突,使用推荐设置:\"%s\"" - ;; prefer-trigger) - (car prefer-triggers)) + (car prefer-triggers) user-trigger))) (defun pyim-outcome-trigger-function-default (&optional no-space) diff --git a/pyim-process.el b/pyim-process.el index 00eafd834f..2b02d5b1c0 100644 --- a/pyim-process.el +++ b/pyim-process.el @@ -864,105 +864,100 @@ BUG:拼音无法有效地处理多音字。" (declare-function pyim-delete-word-at-point "pyim") (defun pyim-process-select-handle-char (char) - "Pyim 字符转换函数,主要用于处理标点符号. - -pyim 在运行过程中调用这个函数来进行标点符号格式的转换。 - -常用的标点符号数量不多,所以 pyim 没有使用文件而是使用一个变量 -`pyim-punctuation-dict' 来设置标点符号对应表,这个变量是一个 -alist 列表。" - (let* ((str (char-to-string char)) - ;; 注意:`str' 是 *待输入* 的字符对应的字符串。 - (str-before-1 (pyim-char-before-to-string 0)) - (str-before-2 (pyim-char-before-to-string 1)) - (str-before-3 (pyim-char-before-to-string 2)) - ;; 从标点词库中搜索与 `str' 对应的标点列表。 - (punc-list (assoc str pyim-punctuation-dict)) - ;; 从标点词库中搜索与 `str-before-1' 对应的标点列表。 - (punc-list-before-1 - (cl-some (lambda (x) - (when (member str-before-1 x) x)) - pyim-punctuation-dict)) - ;; `str-before-1' 在其对应的标点列表中的位置。 - (punc-posit-before-1 - (cl-position str-before-1 punc-list-before-1 - :test #'equal)) - (trigger (pyim-outcome-get-trigger))) + "Pyim 字符转换函数,CHAR 代表 *待输入* 的字符。" + (let ((str (char-to-string char))) (cond - ;; 空格之前的字符什么也不输入。 - ((< char ? ) "") - - ;; 这个部份与标点符号处理无关,主要用来快速删除用户自定义词条。 - ;; 比如:在一个中文字符串后输入 2-v,可以将光标前两个中文字符 - ;; 组成的字符串,从个人词库删除。 - ((and (eq (char-before) ?-) - (pyim-string-match-p "[0-9]" str-before-2) - (pyim-string-match-p "\\cc" str-before-3) - (equal str trigger)) - (delete-char -2) - (pyim-delete-word-at-point - (string-to-number str-before-2)) + ((pyim-process--invalid-char-p char) "") + + ((pyim-process--trigger-delete-word-p char) + (let ((str-before-2 (pyim-char-before-to-string 1))) + (delete-char -2) + (pyim-delete-word-at-point + (string-to-number str-before-2))) "") - ;; 这个部份与标点符号处理无关,主要用来快速保存用户自定义词条。 - ;; 比如:在一个中文字符串后输入 2v,可以将光标前两个中文字符 - ;; 组成的字符串,保存到个人词库。 - ((and (member (char-before) (number-sequence ?2 ?9)) - (pyim-string-match-p "\\cc" str-before-2) - (equal str trigger)) - (delete-char -1) - (pyim-create-word-at-point - (string-to-number str-before-1)) + + ((pyim-process--trigger-create-word-p char) + (let ((str-before-1 (pyim-char-before-to-string 0))) + (delete-char -1) + (pyim-create-word-at-point + (string-to-number str-before-1))) "") - ;; 光标前面的字符为中文字符时,按 v 清洗当前行的内容。 - ((and (not (numberp punc-posit-before-1)) - (pyim-string-match-p "\\cc" str-before-1) - (equal str trigger) - (functionp pyim-outcome-trigger-function)) + ((pyim-process--call-trigger-function-p char) (funcall pyim-outcome-trigger-function) + (message "PYIM: 运行 `pyim-outcome-trigger-function' 函数。") "") - ;; 关闭标点转换功能时,只插入英文标点。 - ((not (pyim-process--punctuation-full-width-p)) - str) - - ;; 当用户使用 org-mode 以及 markdown 等轻量级标记语言撰写文档时, - ;; 常常需要输入数字列表,比如: - - ;; 1. item1 - ;; 2. item2 - ;; 3. item3 - - ;; 在这种情况下,数字后面输入句号必须是半角句号而不是全角句号。 - ((pyim-punctuation-escape-p (char-before)) + ((pyim-process--punctuation-half-width-p char) str) - ;; 自动切换全角/半角标点符号。 - ((pyim-punctuation-auto-half-width-p char) str) - - ;; 当光标前面为英文标点时, 按 `pyim-outcome-trigger' - ;; 对应的字符后, 自动将其转换为对应的中文标点。 - ((and (numberp punc-posit-before-1) - (= punc-posit-before-1 0) - (equal str trigger)) + ((pyim-process--translate-punctuation-to-full-width-p char) (pyim-punctuation-translate 'full-width) "") - ;; 当光标前面为中文标点时, 按 `pyim-outcome-trigger' - ;; 对应的字符后, 自动将其转换为对应的英文标点。 - ((and (numberp punc-posit-before-1) - (> punc-posit-before-1 0) - (equal str trigger)) + ((pyim-process--translate-punctuation-to-half-width-p char) (pyim-punctuation-translate 'half-width) "") - ;; 正常输入标点符号。 - (punc-list - (pyim-punctuation-return-proper-punct punc-list)) + ((pyim-punctuation-p char) + (pyim-punctuation-return-proper-punct char)) - ;; 当输入的字符不是标点符号时,原样插入。 (t str)))) +(defun pyim-process--invalid-char-p (char) + "当 CHAR 是空格前面的字符时,返回 t." + (< char ? )) + +(defun pyim-process--trigger-delete-word-p (char) + "当光标之前的字符串类似 “[1-9]-<trigger char>”时,比如 “你好-2v” ,返回 t." + (let* ((str (char-to-string char)) + (str-before-2 (pyim-char-before-to-string 1)) + (str-before-3 (pyim-char-before-to-string 2))) + (and (eq (char-before) ?-) + (pyim-string-match-p "[0-9]" str-before-2) + (pyim-string-match-p "\\cc" str-before-3) + (pyim-outcome-trigger-p str)))) + +(defun pyim-process--trigger-create-word-p (char) + "当光标之前的字符串类似“[2-9]<trigger char>”时,比如 “你好2v” ,返回 t." + (let* ((str (char-to-string char)) + (str-before-2 (pyim-char-before-to-string 1))) + (and (member (char-before) (number-sequence ?2 ?9)) + (pyim-string-match-p "\\cc" str-before-2) + (pyim-outcome-trigger-p str)))) + +(defun pyim-process--call-trigger-function-p (char) + "判断是否触发 `pyim-outcome-trigger-function'." + (let* ((str (char-to-string char)) + (str-before-1 (pyim-char-before-to-string 0))) + (and (not (pyim-punctuation-position str-before-1)) + (pyim-string-match-p "\\cc" str-before-1) + (pyim-outcome-trigger-p str) + (functionp pyim-outcome-trigger-function)))) + +(defun pyim-process--translate-punctuation-to-full-width-p (char) + "当光标前面是半角标点时,返回 t." + (let* ((str (char-to-string char)) + (str-before-1 (pyim-char-before-to-string 0)) + (punc-posit-before-1 (pyim-punctuation-position str-before-1))) + (and (numberp punc-posit-before-1) + (= punc-posit-before-1 0) + (pyim-outcome-trigger-p str)))) + +(defun pyim-process--translate-punctuation-to-half-width-p (char) + "当光标前面是全角标点时,返回 t." + (let* ((str (char-to-string char)) + (str-before-1 (pyim-char-before-to-string 0)) + (punc-posit-before-1 (pyim-punctuation-position str-before-1))) + (and (numberp punc-posit-before-1) + (> punc-posit-before-1 0) + (pyim-outcome-trigger-p str)))) + +(defun pyim-process--punctuation-half-width-p (char) + (or (not (pyim-process--punctuation-full-width-p)) + (pyim-punctuation-auto-half-width-p char) + (pyim-punctuation-escape-p (char-before)))) + (defun pyim-process--punctuation-full-width-p () "判断是否需要切换到全角标点输入模式 diff --git a/pyim-punctuation.el b/pyim-punctuation.el index 6e4a806317..9d04c3fd6e 100644 --- a/pyim-punctuation.el +++ b/pyim-punctuation.el @@ -86,9 +86,18 @@ pyim 输入半角标点,函数列表中每个函数都有一个参数:char 3. 当第一个元素为 \\='auto 时,根据中英文环境,自动切换。") (defvar pyim-punctuation-escape-list (number-sequence ?0 ?9) - "Punctuation will not insert after this characters. + "如果某些字符后面必须使用半角字符,可以将这些字符添加到此列表。 -If you don't like this function, set the variable to nil") +比如:当用户使用 org-mode 以及 markdown 等轻量级标记语言撰写文档 +时,常常需要输入数字列表,比如: + +1. item1 +2. item2 +3. item3 + +在这种情况下,数字后面输入句号必须是半角句号而不是全角句号。 + +这个变量设置为 nil 时,取消这个功能。") (defvar pyim-punctuation--pair-status '(("\"" nil) ("'" nil)) @@ -138,6 +147,21 @@ If you don't like this function, set the variable to nil") (pyim-punctuation-translate 'full-width) (pyim-punctuation-translate 'half-width))))) +(defun pyim-punctuation-p (punct) + "判断 PUNCT 是否是包含在 `pyim-punctuation-dict' 中的标点符号。" + (assoc (char-to-string punct) pyim-punctuation-dict)) + +(defun pyim-punctuation-position (punct) + "返回 PUNCT 在 `pyim-punctuation-dict' 某一行中的位置。" + (let* ((punc-list + (cl-some (lambda (x) + (when (member punct x) x)) + pyim-punctuation-dict)) + (punc-position + (cl-position punct punc-list + :test #'equal))) + punc-position)) + (defun pyim-punctuation-translate (&optional punct-style) "将光标前1个或前后连续成对的n个标点符号进行全角/半角转换. @@ -180,7 +204,7 @@ If you don't like this function, set the variable to nil") (cond ((eq punct-style 'full-width) (if (= position 0) - (push (pyim-punctuation-return-proper-punct puncts) result) + (push (pyim-punctuation--return-proper-punct puncts) result) (push punct result))) ((eq punct-style 'half-width) (if (= position 0) @@ -189,7 +213,11 @@ If you don't like this function, set the variable to nil") (insert (string-join (reverse result))) (backward-char rnum))) -(defun pyim-punctuation-return-proper-punct (punc-list &optional before) +(defun pyim-punctuation-return-proper-punct (punct-char) + (let ((punc-list (assoc (char-to-string punct-char) pyim-punctuation-dict))) + (pyim-punctuation--return-proper-punct punc-list))) + +(defun pyim-punctuation--return-proper-punct (punc-list &optional before) "返回合适的标点符号,PUNCT-LIST 为标点符号列表. 这个函数用于处理成对的全角标点符号,简单来说:如果第一次输入的标 @@ -202,7 +230,7 @@ PUNCT-LIST 格式类似: 当 BEFORE 为 t 时,只返回切换之前的结果,这个用来获取切换之前的 标点符号。 -函数 `pyim-punctuation-return-proper-punct' 内部,我们使用变量 +函数 `pyim-punctuation--return-proper-punct' 内部,我们使用变量 `pyim-punctuation--pair-status' 来记录 “成对” 中文标点符号的状态。" (let* ((str (car punc-list)) (punc (cdr punc-list)) @@ -217,9 +245,6 @@ PUNCT-LIST 格式类似: (car punc) (nth 1 punc))))) -(defun pyim-punctuation-escape-p (char) - (member char pyim-punctuation-escape-list)) - (defun pyim-punctuation-auto-half-width-p (char) "测试是否自动切换到半角标点符号。" (cl-some (lambda (x) @@ -228,6 +253,8 @@ PUNCT-LIST 格式类似: nil)) pyim-punctuation-half-width-functions)) +(defun pyim-punctuation-escape-p (char) + (member char pyim-punctuation-escape-list)) ;; * Footer (provide 'pyim-punctuation) diff --git a/tests/pyim-tests.el b/tests/pyim-tests.el index 41124ad7f5..c23bf8a4c4 100644 --- a/tests/pyim-tests.el +++ b/tests/pyim-tests.el @@ -412,8 +412,8 @@ (let ((pyim-punctuation--pair-status '(("\"" nil) ("'" nil)))) - (should (equal (pyim-punctuation-return-proper-punct '("'" "‘" "’")) "‘")) - (should (equal (pyim-punctuation-return-proper-punct '("'" "‘" "’")) "’")))) + (should (equal (pyim-punctuation--return-proper-punct '("'" "‘" "’")) "‘")) + (should (equal (pyim-punctuation--return-proper-punct '("'" "‘" "’")) "’")))) ;; ** pyim-entered 相关单元测试 (ert-deftest pyim-tests-pyim-entered ()