Emacs Lisp 和非确定性正则表达式

Dan*_*ood 5 regex emacs elisp

我最近花了太多时间尝试调试 Emacs 中的一些自动完成模式功能,这个功能似乎是不确定的,让我完全困惑。

 (re-search-backward "\\(\\sw\\|\\s_\\|\\s\\.\\|\\s\\\\|[#@|]\\)\\=")
Run Code Online (Sandbox Code Playgroud)

该命令在 while 循环中调用,从当前点向后搜索以找到应该自动完成的完整“单词”。供参考,实际代码

一些背景和我的调查

我一直在尝试为 Javascript 设置自动完成,使用 slime 连接到 Node.js 后端。

在连接到 Node.js 后端的 Slime REPL 中自动完成是完美的,

在此处输入图片说明

连接到 Slime 的 js2 模式缓冲区内的自动完成无法从 Slime 中查找完成。在此图像中,您可以看到它回退到缓冲区中已有的单词。

在此处输入图片说明

我已经将其追溯到 Slime 的 Slime -beginning-of-symbol函数。

假设我试图在需要的fs.ch地方完成并且fs已经在范围内,该点位于h角色之后。

在 slime repl 缓冲区中,开始函数将点一直向后移动,直到遇到空格并匹配fs.ch

在 js2 模式缓冲区中,开始函数仅将点移动到点字符并仅匹配ch.

重现问题

我一直在通过在各种缓冲区中重复evaling 来测试这一点(re-search-backward "\\(\\sw\\|\\s_\\|\\s\\.\\|\\s\\\\|[#@|]\\)\\=")。对于所有示例,该点从行尾开始并向后移动,直到搜索失败。

  • 在暂存缓冲区中fs.ch,点结束于c.
  • 在 Slime repl 中fs.ch,点结束于f.
  • 在 js2 模式缓冲区中,fs.ch该点以c.
  • 在 emacs-lisp-mode 缓冲区中fs.ch,点结束于f.

我不知道为什么会这样

我将假设在这些模式中有一些设置或取消设置全局正则表达式变量然后具有这种效果的东西,但到目前为止我一直无法找到或暗示任何东西。

我什至将其追溯到emacs c 代码,但那时我意识到我完全不知所措并决定寻求帮助。

帮助?

Dan*_*ood 0

我通过重新定义添加到自动完成的ac-sources.

我仍在学习 elisp 的方法,所以这可能是实现我需要的最像黑客的方法,但它有效。

我将正则表达式更改为:

\\(\\sw\\|\\s_\\|\\s\\.\\|\\s\\\\|[#@|]\\)\\=
Run Code Online (Sandbox Code Playgroud)

\\(\\sw\\|\\s_\\|\\s.\\|\\s\\\\|[#@|]\\)\\=
Run Code Online (Sandbox Code Playgroud)

\\s\\.\\(注意到的更改\\s.\\)。

然后覆盖我的 init.el 中的自动完成设置。(当我真正了解 elisp 时,我可能会找到一百种方法来改进它)。

(defun js-slime-beginning-of-symbol ()
  "Move to the beginning of the CL-style symbol at point."
  (while (re-search-backward "\\(\\sw\\|\\s_\\|\\s.\\|\\s\\\\|[#@|]\\)\\="
                             (when (> (point) 2000) (- (point) 2000))
                             t))
  (re-search-forward "\\=#[-+.<|]" nil t)
  (when (and (looking-at "@") (eq (char-before) ?\,))
    (forward-char)))

(defun js-slime-symbol-start-pos ()
  "Return the starting position of the symbol under point.
The result is unspecified if there isn't a symbol under the point."
  (save-excursion (js-slime-beginning-of-symbol) (point)))

(defvar ac-js-source-slime-simple
  '((init . ac-slime-init)
    (candidates . ac-source-slime-simple-candidates)
    (candidate-face . ac-slime-menu-face)
    (selection-face . ac-slime-selection-face)
    (prefix . js-slime-symbol-start-pos)
    (symbol . "l")
    (document . ac-slime-documentation)
    (match . ac-source-slime-case-correcting-completions))
  "Source for slime completion.")

(defun set-up-slime-js-ac (&optional fuzzy)
  "Add an optionally-fuzzy slime completion source to `ac-sources'."
  (interactive)
  (add-to-list 'ac-sources ac-js-source-slime-simple))
Run Code Online (Sandbox Code Playgroud)

回答我自己关于正则表达式全局状态的问题。有很多。

Emacs 正则表达式使用主模式中定义的语法表来确定要匹配的字符。我在 lisp 模式下看到点匹配但在 js 模式下看不到的原因是因为定义不同。在 lisp 模式下 '.' 被定义为符号,在 js2 模式“.”中 被定义为标点符号。

因此,解决该问题的另一种方法是在 js2 模式下重新定义 . 的语法。我尝试了一下并重新定义了。作为一个词(modify-syntax-entry ?. "w")。然而我决定不坚持这个结果,因为它可能会破坏一些东西。

另外,我必须感谢 #emacs 中的人们,他们在这方面确实帮助了我,教我有关语法表和 elisp 正则表达式全局变量的可怕之处。