aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/subr2.el
blob: 52f9306833367845a21dafc7a8b26c23d1f61983 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
(defvar called-interactively-p-functions nil
  "Special hook called to skip special frames in `called-interactively-p'.
The functions are called with 3 arguments: (I FRAME1 FRAME2),
where FRAME1 is a \"current frame\", FRAME2 is the next frame,
I is the index of the frame after FRAME2.  It should return nil
if those frames don't seem special and otherwise, it should return
the number of frames to skip (minus 1).")

(defconst internal--funcall-interactively
  (symbol-function 'funcall-interactively))

(defun called-interactively-p (&optional kind)
  nil)

;; (defun called-interactively-p (&optional kind)
;;   "Return t if the containing function was called by `call-interactively'.
;; If KIND is `interactive', then only return t if the call was made
;; interactively by the user, i.e. not in `noninteractive' mode nor
;; when `executing-kbd-macro'.
;; If KIND is `any', on the other hand, it will return t for any kind of
;; interactive call, including being called as the binding of a key or
;; from a keyboard macro, even in `noninteractive' mode.

;; This function is very brittle, it may fail to return the intended result when
;; the code is debugged, advised, or instrumented in some form.  Some macros and
;; special forms (such as `condition-case') may also sometimes wrap their bodies
;; in a `lambda', so any call to `called-interactively-p' from those bodies will
;; indicate whether that lambda (rather than the surrounding function) was called
;; interactively.

;; Instead of using this function, it is cleaner and more reliable to give your
;; function an extra optional argument whose `interactive' spec specifies
;; non-nil unconditionally (\"p\" is a good way to do this), or via
;; \(not (or executing-kbd-macro noninteractive)).

;; The only known proper use of `interactive' for KIND is in deciding
;; whether to display a helpful message, or how to display it.  If you're
;; thinking of using it for any other purpose, it is quite likely that
;; you're making a mistake.  Think: what do you want to do when the
;; command is called from a keyboard macro?"
;;   (declare (advertised-calling-convention (kind) "23.1"))
;;   (when (not (and (eq kind 'interactive)
;;                   (or executing-kbd-macro noninteractive)))
;;     (let* ((i 1) ;; 0 is the called-interactively-p frame.
;;            frame nextframe
;;            (get-next-frame
;;             (lambda ()
;;               (setq frame nextframe)
;;               (setq nextframe (backtrace-frame i 'called-interactively-p))
;;               ;; (message "Frame %d = %S" i nextframe)
;;               (setq i (1+ i)))))
;;       (funcall get-next-frame) ;; Get the first frame.
;;       (while
;;           ;; FIXME: The edebug and advice handling should be made modular and
;;           ;; provided directly by edebug.el and nadvice.el.
;;           (progn
;;             ;; frame    =(backtrace-frame i-2)
;;             ;; nextframe=(backtrace-frame i-1)
;;             (funcall get-next-frame)
;;             ;; `pcase' would be a fairly good fit here, but it sometimes moves
;;             ;; branches within local functions, which then messes up the
;;             ;; `backtrace-frame' data we get,
;;             (or
;;              ;; Skip special forms (from non-compiled code).
;;              (and frame (null (car frame)))
;;              ;; Skip also `interactive-p' (because we don't want to know if
;;              ;; interactive-p was called interactively but if it's caller was)
;;              ;; and `byte-code' (idem; this appears in subexpressions of things
;;              ;; like condition-case, which are wrapped in a separate bytecode
;;              ;; chunk).
;;              ;; FIXME: For lexical-binding code, this is much worse,
;;              ;; because the frames look like "byte-code -> funcall -> #[...]",
;;              ;; which is not a reliable signature.
;;              (memq (nth 1 frame) '(interactive-p 'byte-code))
;;              ;; Skip package-specific stack-frames.
;;              (let ((skip (run-hook-with-args-until-success
;;                           'called-interactively-p-functions
;;                           i frame nextframe)))
;;                (pcase skip
;;                  (`nil nil)
;;                  (`0 t)
;;                  (_ (setq i (+ i skip -1)) (funcall get-next-frame)))))))
;;       ;; Now `frame' should be "the function from which we were called".
;;       (pcase (cons frame nextframe)
;;         ;; No subr calls `interactive-p', so we can rule that out.
;;         (`((,_ ,(pred (lambda (f) (subrp (indirect-function f)))) . ,_) . ,_) nil)
;;         ;; In case #<subr funcall-interactively> without going through the
;;         ;; `funcall-interactively' symbol (bug#3984).
;;         (`(,_ . (t ,(pred (lambda (f)
;;                             (eq internal--funcall-interactively
;;                                 (indirect-function f))))
;;                    . ,_))
;;          t)))))

(defun interactive-p ()
  "Return t if the containing function was run directly by user input.
This means that the function was called with `call-interactively'
\(which includes being called as the binding of a key)
and input is currently coming from the keyboard (not a keyboard macro),
and Emacs is not running in batch mode (`noninteractive' is nil).

The only known proper use of `interactive-p' is in deciding whether to
display a helpful message, or how to display it.  If you're thinking
of using it for any other purpose, it is quite likely that you're
making a mistake.  Think: what do you want to do when the command is
called from a keyboard macro or in batch mode?

To test whether your function was called with `call-interactively',
either (i) add an extra optional argument and give it an `interactive'
spec that specifies non-nil unconditionally (such as \"p\"); or (ii)
use `called-interactively-p'."
  (declare (obsolete called-interactively-p "23.2"))
  (called-interactively-p 'interactive))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defvar called-interactively-p-functions nil
  "Special hook called to skip special frames in `called-interactively-p'.
The functions are called with 3 arguments: (I FRAME1 FRAME2),
where FRAME1 is a \"current frame\", FRAME2 is the next frame,
I is the index of the frame after FRAME2.  It should return nil
if those frames don't seem special and otherwise, it should return
the number of frames to skip (minus 1).")

(defun interactive-p ()
  "Return t if the containing function was run directly by user input.
This means that the function was called with `call-interactively'
\(which includes being called as the binding of a key)
and input is currently coming from the keyboard (not a keyboard macro),
and Emacs is not running in batch mode (`noninteractive' is nil).

The only known proper use of `interactive-p' is in deciding whether to
display a helpful message, or how to display it.  If you're thinking
of using it for any other purpose, it is quite likely that you're
making a mistake.  Think: what do you want to do when the command is
called from a keyboard macro or in batch mode?

To test whether your function was called with `call-interactively',
either (i) add an extra optional argument and give it an `interactive'
spec that specifies non-nil unconditionally (such as \"p\"); or (ii)
use `called-interactively-p'."
  (declare (obsolete called-interactively-p "23.2"))
  (called-interactively-p 'interactive))