求助:如何使得 forward-sexp 可以匹配其他括号(如「」)

image

如图所示,我希望添加新的括号定义,使得可以(在 emacs-lisp-mode 下)通过 forward-sexp 移动。

上图是通过 emacs -Q 启动的,如果使用:

(modify-syntax-entry ?< "(>")
(modify-syntax-entry ?> ")>")

那么是有效果的,但是如果通过:

(modify-syntax-entry ?「 "(」")
(modify-syntax-entry ?」 ")「")

却没有效果。

同时,如果是在 fundamental-mode 下,前两者是都有效果的。

请教论坛的各位前辈,有没有什么知识点是我错过的?望指点一下。

编码问题。用 multibyte string 可破

(modify-syntax-entry ?\「 (string-to-multibyte "(」  "))
(modify-syntax-entry ?\」 (string-to-multibyte ")「  "))

https://www.gnu.org/software/emacs/manual/html_node/elisp/Non_002dASCII-in-Strings.html

2 个赞

前辈那边试过这个代码了吗?

我这边 emacs -Q 也没效果呀 :rofl:

我是 emacs-plus 29.4

试过了才发的,我也 Emacs 29.4,GUI,终端,都试过

好奇怪,我试了好几次,但是确实没有效果 :rofl:

我发现即使是 emacs -Q,也是有括号高亮的,比如下图天蓝色的括号(当然这个时候我使用 forward-sexp 也是有效果的): image

而我按照前辈的代码执行后,光标放在“「”处,没有括号高亮,forward-sexp 也没有预期效果: image

但是前后加上空格后,确实都有效果了: image

请问,前辈是不加空格也有效果吗?

这就是另外一个问题了:syntax 扫描的代码遇到 multibyte buffer 里 UTF-8 的中文字符开头的那个 byte,就会把直到 ASCII 字符之前的内容都认成一整个 token 了。

简单的解决办法是把 buffer 统一设置成 unibyte

我尝试使用 (set-buffer-multibyte t),但是似乎并没有效果;而如果使用 (set-buffer-multibyte nil) 汉字就全变成乱码了。

同时,为什么在 fundamental-mode 模式下,就没有这个问题呢(不需要空格就可以高亮、用 forward-sexp 来移动)

image

  1. 实际上,似乎 buffer 已经是 multibyte 了,之前是我的判断失误。而且只有 multibyte 下才能正常显示中文。

  2. 为什么 fundamental mode 能用,因为 syntax table 不一样 因为 lisp-data-mode 改了 syntax property。这就是为什么我说“简单的解决办法”,因为复杂的解决办法是继续看 lisp-data-mode 改了什么行为。

1 个赞

刚看了下 lisp-data-mode 的代码,确认

(setq-local multibyte-syntax-as-symbol nil) 能解决问题。

Non-nil means ‘scan-sexps’ treats all multibyte characters as symbol.

2 个赞

原来是这个变量 multibyte-syntax-as-symbol 控制的呀,我还以为是 syntax table 的改动导致的呢 :rofl:

非常感谢前辈在我这个疑惑上花费的时间和精力!!!

常理来说我一开始也是这么想的,但实际总要定位到具体代码里的,我看了 lisp data mode 实现才意识到 Emacs 里存在这个变量用来操作 syntax property 的行为。

实际上到这部分为止也都是对的

2 个赞