以编程方式在缓冲区中导航的不错的语言无关抽象是 sexp 和语法表:如果您的模式的语法表构建得很好,您可以使用forward-sexp
and移动scan-sexps
。我会说只在这些不起作用的情况下使用正则表达式,即使你最终确实使用了它们提供的值re-search-forward
(见它的BOUND
论点)。
也可以syntax-ppss
用来轻松辨别是否在注释或字符串文字中,或处理字符转义情况。请参阅 Emacs Lisp 信息节点语法表
诚然,sexp 可能对缩进 Lisp 很有效,因为一切都是一个列表,并且可以很容易地(syntax-ppss)
提出诸如“深度是多少级(point)
?”之类的问题。使用像 Ruby 这样的块分隔符begin
,end
你会进入疯狂的正则表达式领域。
因此,要(syntax-ppss)
在其他语言中获得类似优点,您需要专门为它编写一个解析器。例如ruby-mode
,实现了一个解析器,并查看nxml-mode
了一个令人难以置信的例子。
另请注意,您可以做很多事情,with-syntax-table
因为它允许您暂时从不同的角度查看缓冲区。它不是缩进,但考虑一下http://github.com/joaotavora/autopair中的这个例子,它允许我忽略一些括号类型
(defvar autopair-empty-syntax-table
(let ((empty (make-syntax-table)))
(dotimes (char 256)
(let ((syntax-entry (aref empty char)))
(when (and (consp syntax-entry)
(or (eq (car (string-to-syntax "("))
(car syntax-entry))
(eq (car (string-to-syntax ")"))
(car syntax-entry))))
(modify-syntax-entry char "w" empty))))
empty)
"A syntax table no \"(\" or \")\" syntaxes")
(defun autopair-just-for-delim-syntax-table (delim)
"A syntax table that has \"parenthesis\" syntax just for DELIM."
(let* ((syntax-entry (aref (syntax-table) delim))
(other-syntax-entry (and syntax-entry
(cdr syntax-entry)
(aref (syntax-table) (cdr syntax-entry)))))
(when (consp other-syntax-entry)
(let ((retval (make-syntax-table autopair-empty-syntax-table)))
(aset retval delim syntax-entry)
(aset retval (cdr syntax-entry) other-syntax-entry)
retval))))
现在,在混合[]
,()
和{}
情况的缓冲区中,要求(syntax-ppss)
或(with-syntax-table (autopair-just-for-delim-syntax-table ?{ ) (syntax-ppss))
后者只计算的地方是完全不同的{}
。我不知道您要缩进哪种语言,但这可以帮助您在缩进 C 块方面做合理的工作,例如。