新人报到,写了个中文词性高亮的小功能,请各位前辈批评

楼上说了我再补充几句可能涉及一些“高级Elisp技巧的东西”

  1. Emacs 27 用 json-parse-string 性能更好,这是基于 libjansson C 库的 JSON 解析,json-read-from-string 是用 Lisp 实现的 JSON 解析。另外 JSON array 我建议直接按默认变成 vector,然后用 (aref array index) 来访问元素,因为转成链表之后虽然方便了,但是访问比较靠后的元素是没有 vector 的下标访问快的

  2. 用 comint 确实不太优雅,但是用 start-process 应该没法直接发送 Python expression 去给 Python eval。我的建议是学习一下 Emacs 的异步进程机制。先写一个 Python wrapper,从 stdin 接受字符串,然后把分词结果发送到 stdout。

  3. cnhl-last-sentence 是一个很耗时的函数,放在 after-change-functions 里面,每次变更都要运行,浪费时间。我的建议是加入 debounce – 每次触发时,放到一个 timer 里面,延迟 100ms 左右再执行,如果 timer 正在计时中,那就删除掉原来的 timer 重新计时,可以有效减少这种耗费时间的操作的执行。

  4. 上面提到 (second item) 是一个 pattern, 这时候可以引入 struct 来抽象化访问,比如用 cl-defstruct 定义一个结构,然后写一个函数把 JSON 解析成这个结构,就可以通过 结构的 accessor 访问,更清晰。

  5. chnl 里面有一个 cond, 里面有很多 (member (second item) '("n" "ns" "ni" "nz" "r" "j") 这样的结构,这里可以使用 pcase 模式匹配,让程序更易读。如

(cond
  ((member (second item) '("n" "ns" "ni" "nz" "r" "j" "np")) 'cnhl-shades-n-r-j)
  ((member (second item) '("u" "y" "h" "k" "e" "o")) 'cnhl-shades-u-y-h-k-e-o)
  ((member (second item) '("v" "id" "i")) 'cnhl-shades-v-i-id)
  ((member (second item) '("d" "c" "p")) 'cnhl-shades-d-c-p)
  ((member (second item) '("a" "f" "s" "t" "m" "q" "mq")) 'cnhl-shades-a-f-s-t-m-q-mq)
  (t 'cnhl-shades-g-w-x))

重构为

(pcase (second item)
  ((or "n" "ns" "ni" "nz" "r" "j" "np")
   'cnhl-shades-n-r-j)
  ((or "u" "y" "h" "k" "e" "o")
   'cnhl-shades-u-y-h-k-e-o)
  ((or "v" "id" "i")
   'cnhl-shades-v-i-id)
  ((or "d" "c" "p")
   'cnhl-shades-d-c-p)
  ((or "a" "f" "s" "t" "m" "q" "mq")
   'cnhl-shades-a-f-s-t-m-q-mq)
  (_
   'cnhl-shades-g-w-x))

关于 pcase, 论坛里有一个帖子

  1. 正则表达式用 rx 宏来写,更易懂

参见

那串正则可以改成

(rx
(or (group ",")
    (group "。")
    (group "?")
    (group ";")
    (group ":")
    (group "、")
    (group "‘")
    (group "’")
    (group "“")
    (group "”")
    (group "…")
    (group "!")
    (group "(")
    (group ")")
    (seq
     (group "~")
     "|"
     (group "*"))))
10 个赞