Commit | Line | Data |
---|---|---|
33813370 RT |
1 | (defvar called-interactively-p-functions nil |
2 | "Special hook called to skip special frames in `called-interactively-p'. | |
3 | The functions are called with 3 arguments: (I FRAME1 FRAME2), | |
4 | where FRAME1 is a \"current frame\", FRAME2 is the next frame, | |
5 | I is the index of the frame after FRAME2. It should return nil | |
6 | if those frames don't seem special and otherwise, it should return | |
7 | the number of frames to skip (minus 1).") | |
8 | ||
9 | (defconst internal--funcall-interactively | |
10 | (symbol-function 'funcall-interactively)) | |
11 | ||
12 | (defun called-interactively-p (&optional kind) | |
13 | nil) | |
14 | ||
15 | ;; (defun called-interactively-p (&optional kind) | |
16 | ;; "Return t if the containing function was called by `call-interactively'. | |
17 | ;; If KIND is `interactive', then only return t if the call was made | |
18 | ;; interactively by the user, i.e. not in `noninteractive' mode nor | |
19 | ;; when `executing-kbd-macro'. | |
20 | ;; If KIND is `any', on the other hand, it will return t for any kind of | |
21 | ;; interactive call, including being called as the binding of a key or | |
22 | ;; from a keyboard macro, even in `noninteractive' mode. | |
23 | ||
24 | ;; This function is very brittle, it may fail to return the intended result when | |
25 | ;; the code is debugged, advised, or instrumented in some form. Some macros and | |
26 | ;; special forms (such as `condition-case') may also sometimes wrap their bodies | |
27 | ;; in a `lambda', so any call to `called-interactively-p' from those bodies will | |
28 | ;; indicate whether that lambda (rather than the surrounding function) was called | |
29 | ;; interactively. | |
30 | ||
31 | ;; Instead of using this function, it is cleaner and more reliable to give your | |
32 | ;; function an extra optional argument whose `interactive' spec specifies | |
33 | ;; non-nil unconditionally (\"p\" is a good way to do this), or via | |
34 | ;; \(not (or executing-kbd-macro noninteractive)). | |
35 | ||
36 | ;; The only known proper use of `interactive' for KIND is in deciding | |
37 | ;; whether to display a helpful message, or how to display it. If you're | |
38 | ;; thinking of using it for any other purpose, it is quite likely that | |
39 | ;; you're making a mistake. Think: what do you want to do when the | |
40 | ;; command is called from a keyboard macro?" | |
41 | ;; (declare (advertised-calling-convention (kind) "23.1")) | |
42 | ;; (when (not (and (eq kind 'interactive) | |
43 | ;; (or executing-kbd-macro noninteractive))) | |
44 | ;; (let* ((i 1) ;; 0 is the called-interactively-p frame. | |
45 | ;; frame nextframe | |
46 | ;; (get-next-frame | |
47 | ;; (lambda () | |
48 | ;; (setq frame nextframe) | |
49 | ;; (setq nextframe (backtrace-frame i 'called-interactively-p)) | |
50 | ;; ;; (message "Frame %d = %S" i nextframe) | |
51 | ;; (setq i (1+ i))))) | |
52 | ;; (funcall get-next-frame) ;; Get the first frame. | |
53 | ;; (while | |
54 | ;; ;; FIXME: The edebug and advice handling should be made modular and | |
55 | ;; ;; provided directly by edebug.el and nadvice.el. | |
56 | ;; (progn | |
57 | ;; ;; frame =(backtrace-frame i-2) | |
58 | ;; ;; nextframe=(backtrace-frame i-1) | |
59 | ;; (funcall get-next-frame) | |
60 | ;; ;; `pcase' would be a fairly good fit here, but it sometimes moves | |
61 | ;; ;; branches within local functions, which then messes up the | |
62 | ;; ;; `backtrace-frame' data we get, | |
63 | ;; (or | |
64 | ;; ;; Skip special forms (from non-compiled code). | |
65 | ;; (and frame (null (car frame))) | |
66 | ;; ;; Skip also `interactive-p' (because we don't want to know if | |
67 | ;; ;; interactive-p was called interactively but if it's caller was) | |
68 | ;; ;; and `byte-code' (idem; this appears in subexpressions of things | |
69 | ;; ;; like condition-case, which are wrapped in a separate bytecode | |
70 | ;; ;; chunk). | |
71 | ;; ;; FIXME: For lexical-binding code, this is much worse, | |
72 | ;; ;; because the frames look like "byte-code -> funcall -> #[...]", | |
73 | ;; ;; which is not a reliable signature. | |
74 | ;; (memq (nth 1 frame) '(interactive-p 'byte-code)) | |
75 | ;; ;; Skip package-specific stack-frames. | |
76 | ;; (let ((skip (run-hook-with-args-until-success | |
77 | ;; 'called-interactively-p-functions | |
78 | ;; i frame nextframe))) | |
79 | ;; (pcase skip | |
80 | ;; (`nil nil) | |
81 | ;; (`0 t) | |
82 | ;; (_ (setq i (+ i skip -1)) (funcall get-next-frame))))))) | |
83 | ;; ;; Now `frame' should be "the function from which we were called". | |
84 | ;; (pcase (cons frame nextframe) | |
85 | ;; ;; No subr calls `interactive-p', so we can rule that out. | |
86 | ;; (`((,_ ,(pred (lambda (f) (subrp (indirect-function f)))) . ,_) . ,_) nil) | |
87 | ;; ;; In case #<subr funcall-interactively> without going through the | |
88 | ;; ;; `funcall-interactively' symbol (bug#3984). | |
89 | ;; (`(,_ . (t ,(pred (lambda (f) | |
90 | ;; (eq internal--funcall-interactively | |
91 | ;; (indirect-function f)))) | |
92 | ;; . ,_)) | |
93 | ;; t))))) | |
94 | ||
95 | (defun interactive-p () | |
96 | "Return t if the containing function was run directly by user input. | |
97 | This means that the function was called with `call-interactively' | |
98 | \(which includes being called as the binding of a key) | |
99 | and input is currently coming from the keyboard (not a keyboard macro), | |
100 | and Emacs is not running in batch mode (`noninteractive' is nil). | |
101 | ||
102 | The only known proper use of `interactive-p' is in deciding whether to | |
103 | display a helpful message, or how to display it. If you're thinking | |
104 | of using it for any other purpose, it is quite likely that you're | |
105 | making a mistake. Think: what do you want to do when the command is | |
106 | called from a keyboard macro or in batch mode? | |
107 | ||
108 | To test whether your function was called with `call-interactively', | |
109 | either (i) add an extra optional argument and give it an `interactive' | |
110 | spec that specifies non-nil unconditionally (such as \"p\"); or (ii) | |
111 | use `called-interactively-p'." | |
112 | (declare (obsolete called-interactively-p "23.2")) | |
113 | (called-interactively-p 'interactive)) | |
114 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
115 | ||
116 | (defvar called-interactively-p-functions nil | |
117 | "Special hook called to skip special frames in `called-interactively-p'. | |
118 | The functions are called with 3 arguments: (I FRAME1 FRAME2), | |
119 | where FRAME1 is a \"current frame\", FRAME2 is the next frame, | |
120 | I is the index of the frame after FRAME2. It should return nil | |
121 | if those frames don't seem special and otherwise, it should return | |
122 | the number of frames to skip (minus 1).") | |
123 | ||
124 | (defun interactive-p () | |
125 | "Return t if the containing function was run directly by user input. | |
126 | This means that the function was called with `call-interactively' | |
127 | \(which includes being called as the binding of a key) | |
128 | and input is currently coming from the keyboard (not a keyboard macro), | |
129 | and Emacs is not running in batch mode (`noninteractive' is nil). | |
130 | ||
131 | The only known proper use of `interactive-p' is in deciding whether to | |
132 | display a helpful message, or how to display it. If you're thinking | |
133 | of using it for any other purpose, it is quite likely that you're | |
134 | making a mistake. Think: what do you want to do when the command is | |
135 | called from a keyboard macro or in batch mode? | |
136 | ||
137 | To test whether your function was called with `call-interactively', | |
138 | either (i) add an extra optional argument and give it an `interactive' | |
139 | spec that specifies non-nil unconditionally (such as \"p\"); or (ii) | |
140 | use `called-interactively-p'." | |
141 | (declare (obsolete called-interactively-p "23.2")) | |
142 | (called-interactively-p 'interactive)) |