将自定义函数写入自动代码有什么好*抽象*?

时间:2012-07-07 11:20:26

标签: emacs elisp indentation vim

这个月我花了一些时间与Emacs Lisp斗争,试图获得更好地满足我需求的自动缩进。令人印象深刻的是大多数缩进代码的低级别。我只看到了很少的抽象,比如

  • 搜索不在字符串或注释中的正则表达式的第一个实例

我怀疑还有更多有用的抽象,这有助于编写更容易理解和更容易修改的缩进代码。 (即使我引用的抽象也可以改进为“将这个函数重复应用于这些参数,直到函数返回nil或point不在字符串或注释中”。)

我正在使用emacs,但我也用vim标记了这个问题,因为我会从任何地方接受好主意。

如果您想编写干净,设计良好,模块化的自定义缩进函数,您将使用哪些抽象?(我也很高兴看到您认为使用良好抽象的代码指针或者只是设计得很好。)

3 个答案:

答案 0 :(得分:4)

听起来你正在寻找更高级别的东西,但是macs 23来了 与SMIE,旨在解决这个问题。但这是主要模式 开发人员,不要修改现有的缩进行为。

编辑:主要抽象似乎是

  • 一个相当弱的运算符优先级解析器,由脏技巧词法分析器补充

  • 每个令牌都有“虚拟缩进”的概念,如果开始一行就会出现

  • 每个标记都有一个'parent',它是封闭语法结构的开头。

进入的费用似乎相当大,该软件附有此免责声明:

  

在实践中,[默认缩进样式]可能不够好。你会想在许多不同的情况下调整它。

(编辑结束)


你说什么:

  

搜索不在字符串或注释

中的正则表达式的第一个实例
通过致电syntax-ppssre-search-backward即可轻松完成

答案 1 :(得分:1)

我知道一些有用的内置基元:

  • 缩进线对
  • 电流压痕

据我所知,有用的原语不是emacs的一部分:

  • 后藤先前非空白行
  • line-matches-p(regex)
  • inside-p(开启字符串结束字符串)

随意填写此列表 - 我没有在emacs缩进上找到很多资源。

答案 2 :(得分:1)

以编程方式在缓冲区周围导航的语言无关的抽象是sexp和语法表:如果模式的语法表格很好,您可以使用forward-sexpscan-sexps移动。我会说只有当这些不能用时才使用regexp,如果你最终确实有re-search-forward(参见它的BOUND参数),它甚至会使用它们提供的值。

还可以使用syntax-ppss轻松识别内部注释或字符串文字,或处理字符转义情况。请参阅Emacs Lisp信息节点Syntax Tables

当然,sexp可能适用于缩进Lisp,因为所有内容都是一个列表,并且可以轻松地向(syntax-ppss)提出一个问题,例如“多少级别是(point)?”。使用像Ruby的beginend这样的块分隔符,你会进入疯狂的正则表达式领域。

所以要获得(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块。