22.4 区分交互式调用

有时某个命令应当仅对交互式调用显示额外的视觉反馈(例如 回显区中的提示信息)。实现此需求有三种方式。检测函数是否通过 call-interactively 调用的推荐方式是:为函数添加可选参数 print-message,并通过 interactive 规范使其在交互式 调用时为非 nil 值。示例如下:

(defun foo (&optional print-message)
  (interactive "p")
  (when print-message
    (message "foo")))

我们使用 "p" 是因为数字前缀参数永远不会是 nil。通过这种方式定义的函数,在从键盘宏中调用时也会显示该 消息。

上述使用额外参数的方法通常是最佳选择,因为它允许调用方 明确指定「将本次调用视为交互式调用」。不过你也可以通过检测 called-interactively-p 函数来实现该功能。

Function: called-interactively-p kind

当调用此函数的上层函数是通过 call-interactively 调用时, 该函数返回 t

参数 kind 应是符号 interactive 或符号 any。 若为 interactive,则仅当调用是由用户直接发起时(例如用户 按下绑定到该函数的按键序列),called-interactively-p 才返回 t——但用户运行调用该函数的键盘宏时除外(see 键盘宏)。 若 kindany,则 called-interactively-p 会对任 何类型的交互式调用(包括键盘宏)返回 t

若存在疑问,请使用 any;已知唯一适合使用 interactive 的场景是:需要决定函数运行期间是否显示帮助 信息时。

如果函数是通过 Lisp 求值(或通过 apply / funcall) 调用的,则永远不会被视为交互式调用。

以下是使用 called-interactively-p 的示例:

(defun foo ()
  (interactive)
  (when (called-interactively-p 'any)
    (message "Interactive!")
    'foo-called-interactively))

;; Type M-x foo.
     ⊣ Interactive!

(foo)
     ⇒ nil

以下示例对比了 called-interactively-p 的直接调用与间接调用:

(defun bar ()
  (interactive)
  (message "%s" (list (foo) (called-interactively-p 'any))))

;; Type M-x bar.
     ⊣ (nil t)

emacs

Emacs

org-mode

Orgmode

Donations

打赏

Copyright

© Jasper Hsu

Creative Commons

Creative Commons

Attribute

Attribute

Noncommercial

Noncommercial

Share Alike

Share Alike