EMACS如何为一个符号设置自定义缩进函数而非符号表达式?

3

CLIPS和JESS是用于人工智能和规则引擎的Lisp语言。它们的EMACS源自lisp-mode。最重要的格式化正确的形式是defrule,这有助于可读性。默认情况下,使用类似于普通lisp-mode的格式:

(defrule any-foo
  "This is a rule for any-foo."
  ?f <- (foo)
  =>
  (do-something-to ?f))

期望的格式如下,可选文档在2个字符内,右箭头在2个字符内,其他所有内容都在6个字符内,如下所示:
(defrule any-foo
  "This is a rule for any-foo."
      ?f <- (foo)
  =>
      (do-something-to ?f))

有很多关于自定义EMACS缩进的资源,但是这个引起了我的注意,因为它让我想知道是否可以拦截匹配右箭头的任何内容的格式化并进行拦截。当我继续阅读时,我更像是理解了您可能会为符号表达式编写自定义格式化函数,但是,右箭头不是那样的。我不想为整个顶层编写格式化函数,也不确定如何做到这一点。

如何以正确的方式获得所需的格式化样式?

1个回答

3

如果您想为以SYMBOL为首元素的Lisp表达式指定缩进,请给SYMBOL赋予lisp-indent-function属性。请参阅Emacs手册中的“Lisp Indent”部分。此属性可以取各种类型的值,这些值在Emacs Lisp手册的“Indenting Macros”部分中有所记录。特别地,如果将该属性设置为一个符号,则:

该符号应该是一个函数名; 该函数被调用来计算此表达式中一行的缩进量。该函数接收两个参数:

state: 当它解析到此行开头时,由 parse-partial-sexp(用于缩进和嵌套计算的Lisp原语)返回的值。

pos: 此行缩进开始的位置。

它应该返回一个数字,即该行的缩进列数,或者其车位为这样一个数字的列表。 返回数字和返回列表之间的区别在于数字表示所有下面的行在相同的嵌套级别上都应该像这个一样缩进; 列表表示以下行可能需要不同的缩进。

(实际上,该函数以另一顺序接收这些参数; 我提交了一个错误报告建议手册进行更正,这在Emacs 24.3中得到了修复.)

因此,您需要编写一个函数来计算defrule形式内一行的适当缩进,可能像这样:

(defun indent-for-defrule (pos state)
  "A lisp-indent-function for defrule.
Indent docstring and => by 2 columns; other lines by 6 columns."
  (save-excursion
    (goto-char pos)
    (let* ((have-string (looking-at "\\s-*\""))
           (have-arrow (looking-at "\\s-*=>"))
           (first-sexp (progn
                         (ignore-errors (backward-sexp))
                         (<= (point) (nth 2 state)))))
      (+ (progn (goto-char (nth 1 state)) (current-column))
         (if (or (and first-sexp have-string) have-arrow) 2 6)))))

然后将该函数分配给defrule符号的lisp-indent-function属性:
(put 'defrule 'lisp-indent-function #'indent-for-defrule)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接