declare smobs in alloc.c
[bpt/emacs.git] / lisp / subr2.el
CommitLineData
33813370
RT
1(defvar called-interactively-p-functions nil
2 "Special hook called to skip special frames in `called-interactively-p'.
3The functions are called with 3 arguments: (I FRAME1 FRAME2),
4where FRAME1 is a \"current frame\", FRAME2 is the next frame,
5I is the index of the frame after FRAME2. It should return nil
6if those frames don't seem special and otherwise, it should return
7the 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.
97This means that the function was called with `call-interactively'
98\(which includes being called as the binding of a key)
99and input is currently coming from the keyboard (not a keyboard macro),
100and Emacs is not running in batch mode (`noninteractive' is nil).
101
102The only known proper use of `interactive-p' is in deciding whether to
103display a helpful message, or how to display it. If you're thinking
104of using it for any other purpose, it is quite likely that you're
105making a mistake. Think: what do you want to do when the command is
106called from a keyboard macro or in batch mode?
107
108To test whether your function was called with `call-interactively',
109either (i) add an extra optional argument and give it an `interactive'
110spec that specifies non-nil unconditionally (such as \"p\"); or (ii)
111use `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'.
118The functions are called with 3 arguments: (I FRAME1 FRAME2),
119where FRAME1 is a \"current frame\", FRAME2 is the next frame,
120I is the index of the frame after FRAME2. It should return nil
121if those frames don't seem special and otherwise, it should return
122the 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.
126This means that the function was called with `call-interactively'
127\(which includes being called as the binding of a key)
128and input is currently coming from the keyboard (not a keyboard macro),
129and Emacs is not running in batch mode (`noninteractive' is nil).
130
131The only known proper use of `interactive-p' is in deciding whether to
132display a helpful message, or how to display it. If you're thinking
133of using it for any other purpose, it is quite likely that you're
134making a mistake. Think: what do you want to do when the command is
135called from a keyboard macro or in batch mode?
136
137To test whether your function was called with `call-interactively',
138either (i) add an extra optional argument and give it an `interactive'
139spec that specifies non-nil unconditionally (such as \"p\"); or (ii)
140use `called-interactively-p'."
141 (declare (obsolete called-interactively-p "23.2"))
142 (called-interactively-p 'interactive))