有时某个命令应当仅对交互式调用显示额外的视觉反馈(例如
回显区中的提示信息)。实现此需求有三种方式。检测函数是否通过
call-interactively 调用的推荐方式是:为函数添加可选参数
print-message,并通过 interactive 规范使其在交互式
调用时为非 nil 值。示例如下:
(defun foo (&optional print-message)
(interactive "p")
(when print-message
(message "foo")))
我们使用 "p" 是因为数字前缀参数永远不会是
nil。通过这种方式定义的函数,在从键盘宏中调用时也会显示该
消息。
上述使用额外参数的方法通常是最佳选择,因为它允许调用方
明确指定「将本次调用视为交互式调用」。不过你也可以通过检测
called-interactively-p 函数来实现该功能。
当调用此函数的上层函数是通过 call-interactively 调用时,
该函数返回 t。
参数 kind 应是符号 interactive 或符号 any。
若为 interactive,则仅当调用是由用户直接发起时(例如用户
按下绑定到该函数的按键序列),called-interactively-p 才返回
t——但用户运行调用该函数的键盘宏时除外(see 键盘宏)。
若 kind 为 any,则 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)