EMACS自定义函数用于符号而不是符号表达式?

时间:2013-01-13 06:04:52

标签: emacs lisp elisp indentation

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

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

所需的格式将是这样的,可选文档2个字符和右箭头两个字符和其他所有6个字符,如下所示:

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

在EMACS中有很多关于自定义缩进的资源,但是this一个跳出来因为它让我想知道我是否可以截取与右箭头匹配的任何格式并拦截它。当我进一步阅读时,我更了解你可能会为符号表达式编写自定义格式化函数,但右箭头不是这样。我不想为整个顶级写一个格式化函数,我不知道怎么回事。

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

1 个答案:

答案 0 :(得分:3)

您可以通过为SYMBOL提供lisp-indent-function属性来为其第一个元素为SYMBOL的Lisp表单指定缩进。请参阅Emacs手册中的“Lisp Indent”部分。此属性可以采用各种值,这些值记录在Emacs Lisp手册的“Indenting Macros”部分中。特别是,如果将属性设置为符号,则:

  

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

     

<强>状态   parse-partial-sexp(缩进和嵌套计算的Lisp原语)在解析此行的开头时返回的值。

     

pos 缩进行开始的位置。

     

它应该返回一个数字,即该行的缩进列数,或者一个汽车就是这样一个数字的列表。返回一个数字和返回一个列表之间的区别在于,一个数字表示同一嵌套级别的所有后续行应该像这一行一样缩进;列表表示以下行可能会调用不同的缩进。

(该函数实际上以其他顺序接收这些参数;我submitted a bug report建议更正手册,并在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)