如何将参数传递给Elisp函数?

时间:2019-03-07 06:36:43

标签: emacs

我有这个键盘映射来刷新空行,如下所示:

(global-set-key (kbd "M-T") (lambda () (interactive) (flush-lines "^[[:space:]]*$")))

但这不适用于某个地区。区域之外无关的行将被合并。但是,当我选择一个区域并手动尝试使用M-x刷新线RET ^ [[:space:]] * $ RET时,它会按预期工作。 我在做什么错了?

1 个答案:

答案 0 :(得分:5)

可以交互或非交互地调用一个函数(实际上稍微复杂一点,但这足够好了)。交互式调用模式用于绑定当前环境中的某些函数自变量或与用户进行交互。当您使用Emacs Lisp编写时,非交互模式是正常的调用模式。

通常,交互行为是在文档字符串后使用(interactive ...)形式声明的,但是在flush-lines的特定情况下,该行为部分由interactive规范自动完成,部分由硬编码(用于区域部分)。您可以通过调用called-interactively-p来询问Emacs是否以交互方式执行当前代码,但是正如文档所说,建议使用另一个可选参数来指示该调用是否是交互式的。

函数签名为:

(flush-lines REGEXP &optional RSTART REND INTERACTIVE)

RSTARTREND是当前区域的开始和结束位置,以整数表示。它们也可以是nil。最后一个参数指示呼叫是否是交互式的。

当您从匿名函数调用flush-lines时,您是在非交互方式下调用它,这意味着您需要将参数显式传递给函数。

对于此功能,您可以简单地按如下方式调用它:

(flush-lines "^[[:space:]]*$" nil nil t)

这使该函数的行为与交互调用时一样,在这种情况下,由于start和end参数为nil,因此会自动计算区域。

在一般情况下,您要做的是拥有自己的(interactive "r")声明,并向匿名函数添加两个参数。例如,在*scratch*缓冲区中,您可以对以下表达式求值:

(call-interactively
  (lambda (beg end)
    (interactive "r")
    (list beg end)))

然后,结果是一个代表您所在地区的光标位置列表。 例如,您会打(flush-lines "^[[:space:]]*$" beg end)