这个月我花了一些时间与Emacs Lisp斗争,试图获得更好地满足我需求的自动缩进。令人印象深刻的是大多数缩进代码的低级别。我只看到了很少的抽象,比如
我怀疑还有更多有用的抽象,这有助于编写更容易理解和更容易修改的缩进代码。 (即使我引用的抽象也可以改进为“将这个函数重复应用于这些参数,直到函数返回nil或point不在字符串或注释中”。)
我正在使用emacs,但我也用vim标记了这个问题,因为我会从任何地方接受好主意。
如果您想编写干净,设计良好,模块化的自定义缩进函数,您将使用哪些抽象?(我也很高兴看到您认为使用良好抽象的代码指针或者只是设计得很好。)
答案 0 :(得分:4)
听起来你正在寻找更高级别的东西,但是macs 23来了 与SMIE,旨在解决这个问题。但这是主要模式 开发人员,不要修改现有的缩进行为。
编辑:主要抽象似乎是
一个相当弱的运算符优先级解析器,由脏技巧词法分析器补充
每个令牌都有“虚拟缩进”的概念,如果开始一行就会出现
每个标记都有一个'parent',它是封闭语法结构的开头。
进入的费用似乎相当大,该软件附有此免责声明:
在实践中,[默认缩进样式]可能不够好。你会想在许多不同的情况下调整它。
(编辑结束)
你说什么:
通过致电搜索不在字符串或注释
中的正则表达式的第一个实例
syntax-ppss
和re-search-backward
即可轻松完成。
答案 1 :(得分:1)
我知道一些有用的内置基元:
据我所知,有用的原语不是emacs的一部分:
随意填写此列表 - 我没有在emacs缩进上找到很多资源。
答案 2 :(得分:1)
以编程方式在缓冲区周围导航的语言无关的抽象是sexp和语法表:如果模式的语法表格很好,您可以使用forward-sexp
和scan-sexps
移动。我会说只有当这些不能用时才使用regexp,如果你最终确实有re-search-forward
(参见它的BOUND
参数),它甚至会使用它们提供的值。
还可以使用syntax-ppss
轻松识别内部注释或字符串文字,或处理字符转义情况。请参阅Emacs Lisp信息节点Syntax Tables
当然,sexp可能适用于缩进Lisp,因为所有内容都是一个列表,并且可以轻松地向(syntax-ppss)
提出一个问题,例如“多少级别是(point)
?”。使用像Ruby的begin
和end
这样的块分隔符,你会进入疯狂的正则表达式领域。
所以要获得(syntax-ppss)
- 就像其他语言中的善良一样,你只需要为它编写一个解析器。例如ruby-mode
实现了一个解析器,并且还看了nxml-mode
这个令人难以置信的例子。
另请注意,您可以使用with-syntax-table
做很多事情,因为它允许您暂时从不同的角度查看缓冲区。这不是缩进,但考虑http://github.com/capitaomorte/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块。