3

CLIPS 和 JESS 是用于 AI 和规则引擎的 lispy 语言。他们的 EMACS 源自 lisp-mode。正确格式化最重要的形式是 defrule,它有助于提高可读性。默认情况下,正常的 lisp 模式格式是这样使用的:

(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 中的自定义缩进的资源,但是这个跳出来了,因为它让我想知道我是否可以截取任何匹配右箭头的格式并截取它。当我进一步阅读时,我的理解更像是您可以为符号表达式编写自定义格式化函数,但是,右箭头不是那样的。我不想为整个顶层编写格式化函数,也不确定如何。

获得这种所需格式样式的正确方法是什么?

4

1 回答 1

3

你可以通过给 SYMBOL 一个lisp-indent-function属性来为第一个元素是 SYMBOL 的 Lisp 表单指定缩进。请参阅 Emacs 手册中的“ Lisp 缩进”部分。此属性可以采用各种类型的值,这些值在 Emacs Lisp 手册的“缩进宏”部分中有说明。特别是,如果您将属性设置为符号,则:

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

stateparse-partial-sexp(缩进和嵌套计算的 Lisp 原语)在解析到此行开头时 返回的值。

pos缩进行开始的位置。

它应该返回一个数字,即该行的缩进列数,或者一个列表,其 car 是这样的数字。返回数字和返回列表的区别在于,数字表示同一嵌套级别的所有后续行都应该像这个一样缩进;一个列表说以下几行可能需要不同的缩进。

(该函数实际上以其他顺序接收这些参数;我提交了一个错误报告,建议对手册进行更正,这已在 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)))))

然后将该函数分配给符号的lisp-indent-function属性:defrule

(put 'defrule 'lisp-indent-function #'indent-for-defrule)
于 2013-01-15T13:42:56.173 回答