[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
bug#17446: 24.4.50; What is the situation around `called-interactively-p
From: |
Stefan Monnier |
Subject: |
bug#17446: 24.4.50; What is the situation around `called-interactively-p'? |
Date: |
Fri, 09 May 2014 17:02:20 -0400 |
User-agent: |
Gnus/5.13 (Gnus v5.13) Emacs/24.4.50 (gnu/linux) |
> Right, I'm thinking of introducing a new `funcall-interactively' which
> is just like `funcall' except that the called function will see its
> `called-interactively-p' returning non-nil.
How 'bout the patch below,
Stefan
=== modified file 'lisp/simple.el'
--- lisp/simple.el 2014-05-01 23:25:28 +0000
+++ lisp/simple.el 2014-05-09 20:42:04 +0000
@@ -1503,24 +1503,13 @@
;; add it to the history.
(or (equal newcmd (car command-history))
(setq command-history (cons newcmd command-history)))
- (unwind-protect
- (progn
- ;; Trick called-interactively-p into thinking that `newcmd' is
- ;; an interactive call (bug#14136).
- (add-hook 'called-interactively-p-functions
- #'repeat-complex-command--called-interactively-skip)
- (eval newcmd))
- (remove-hook 'called-interactively-p-functions
- #'repeat-complex-command--called-interactively-skip)))
+ (apply #'funcall-interactively
+ (car newcmd)
+ (mapcar (lambda (e) (eval e t)) (cdr newcmd))))
(if command-history
(error "Argument %d is beyond length of command history" arg)
(error "There are no previous complex commands to repeat")))))
-(defun repeat-complex-command--called-interactively-skip (i _frame1 frame2)
- (and (eq 'eval (cadr frame2))
- (eq 'repeat-complex-command
- (cadr (backtrace-frame i #'called-interactively-p)))
- 1))
(defvar extended-command-history nil)
=== modified file 'lisp/subr.el'
--- lisp/subr.el 2014-04-09 01:48:07 +0000
+++ lisp/subr.el 2014-05-09 20:24:34 +0000
@@ -3832,7 +3832,8 @@
(byte-compile-log-warning msg))
(run-with-timer 0 nil
(lambda (msg)
- (message "%s" msg)) msg))))
+ (message "%s" msg))
+ msg))))
;; Finally, run any other hook.
(run-hook-with-args 'after-load-functions abs-file))
@@ -4149,7 +4150,8 @@
if those frames don't seem special and otherwise, it should return
the number of frames to skip (minus 1).")
-(defconst internal--call-interactively (symbol-function 'call-interactively))
+(defconst internal--funcall-interactively
+ (symbol-function 'funcall-interactively))
(defun called-interactively-p (&optional kind)
"Return t if the containing function was called by `call-interactively'.
@@ -4225,8 +4227,8 @@
(`((,_ ,(pred (lambda (f) (subrp (indirect-function f)))) . ,_) . ,_)
nil)
;; In case #<subr call-interactively> without going through the
;; `call-interactively' symbol (bug#3984).
- (`(,_ . (t ,(pred (eq internal--call-interactively)) . ,_)) t)
- (`(,_ . (t call-interactively . ,_)) t)))))
+ (`(,_ . (t ,(pred (eq internal--funcall-interactively)) . ,_)) t)
+ (`(,_ . (t funcall-interactively . ,_)) t)))))
(defun interactive-p ()
"Return t if the containing function was run directly by user input.
=== modified file 'src/callint.c'
--- src/callint.c 2014-04-22 07:04:34 +0000
+++ src/callint.c 2014-05-09 20:47:17 +0000
@@ -29,7 +29,7 @@
#include "keymap.h"
Lisp_Object Qminus, Qplus;
-static Lisp_Object Qcall_interactively;
+static Lisp_Object Qfuncall_interactively;
static Lisp_Object Qcommand_debug_status;
static Lisp_Object Qenable_recursive_minibuffers;
@@ -233,6 +233,22 @@
}
}
+/* BEWARE: Calling this directly from C would defeat the purpose! */
+DEFUN ("funcall-interactively", Ffuncall_interactively, Sfuncall_interactively,
+ 1, MANY, 0, doc: /* Like `funcall' but marks the call as interactive.
+I.e. arrange that within the called function `called-interactively-p' will
+return non-nil. */)
+ (ptrdiff_t nargs, Lisp_Object *args)
+{
+ ptrdiff_t speccount = SPECPDL_INDEX ();
+ temporarily_switch_to_single_kboard (NULL);
+
+ /* Nothing special to do here, all the work is inside
+ `called-interactively-p'. Which will look for us as a marker in the
+ backtrace. */
+ return unbind_to (speccount, Ffuncall (nargs, args));
+}
+
DEFUN ("call-interactively", Fcall_interactively, Scall_interactively, 1, 3, 0,
doc: /* Call FUNCTION, providing args according to its interactive
calling specs.
Return the value FUNCTION returns.
@@ -374,8 +390,13 @@
Vreal_this_command = save_real_this_command;
kset_last_command (current_kboard, save_last_command);
- temporarily_switch_to_single_kboard (NULL);
- return unbind_to (speccount, apply1 (function, specs));
+ {
+ Lisp_Object args[3];
+ args[0] = Qfuncall_interactively;
+ args[1] = function;
+ args[2] = specs;
+ return unbind_to (speccount, Fapply (3, args));
+ }
}
/* Here if function specifies a string to control parsing the defaults. */
@@ -446,10 +467,11 @@
else break;
}
- /* Count the number of arguments, which is one plus the number of arguments
- the interactive spec would have us give to the function. */
+ /* Count the number of arguments, which is two (the function itself and
+ `funcall-interactively') plus the number of arguments the interactive spec
+ would have us give to the function. */
tem = string;
- for (nargs = 1; *tem; )
+ for (nargs = 2; *tem; )
{
/* 'r' specifications ("point and mark as 2 numeric args")
produce *two* arguments. */
@@ -488,13 +510,13 @@
specbind (Qenable_recursive_minibuffers, Qt);
tem = string;
- for (i = 1; *tem; i++)
+ for (i = 2; *tem; i++)
{
- visargs[0] = make_string (tem + 1, strcspn (tem + 1, "\n"));
- if (strchr (SSDATA (visargs[0]), '%'))
+ visargs[1] = make_string (tem + 1, strcspn (tem + 1, "\n"));
+ if (strchr (SSDATA (visargs[1]), '%'))
callint_message = Fformat (i, visargs);
else
- callint_message = visargs[0];
+ callint_message = visargs[1];
switch (*tem)
{
@@ -789,21 +811,22 @@
QUIT;
- args[0] = function;
+ args[0] = Qfuncall_interactively;
+ args[1] = function;
if (arg_from_tty || !NILP (record_flag))
{
/* We don't need `visargs' any more, so let's recycle it since we need
an array of just the same size. */
- visargs[0] = function;
- for (i = 1; i < nargs; i++)
+ visargs[1] = function;
+ for (i = 2; i < nargs; i++)
{
if (varies[i] > 0)
visargs[i] = list1 (intern (callint_argfuns[varies[i]]));
else
visargs[i] = quotify_arg (args[i]);
}
- Vcommand_history = Fcons (Flist (nargs, visargs),
+ Vcommand_history = Fcons (Flist (nargs - 1, visargs + 1),
Vcommand_history);
/* Don't keep command history around forever. */
if (INTEGERP (Vhistory_length) && XINT (Vhistory_length) > 0)
@@ -816,7 +839,7 @@
/* If we used a marker to hold point, mark, or an end of the region,
temporarily, convert it to an integer now. */
- for (i = 1; i < nargs; i++)
+ for (i = 2; i < nargs; i++)
if (varies[i] >= 1 && varies[i] <= 4)
XSETINT (args[i], marker_position (args[i]));
@@ -829,11 +852,7 @@
kset_last_command (current_kboard, save_last_command);
{
- Lisp_Object val;
- specbind (Qcommand_debug_status, Qnil);
-
- temporarily_switch_to_single_kboard (NULL);
- val = Ffuncall (nargs, args);
+ Lisp_Object val = Ffuncall (nargs, args);
UNGCPRO;
return unbind_to (speccount, val);
}
@@ -888,7 +907,7 @@
DEFSYM (Qplus, "+");
DEFSYM (Qhandle_shift_selection, "handle-shift-selection");
DEFSYM (Qread_number, "read-number");
- DEFSYM (Qcall_interactively, "call-interactively");
+ DEFSYM (Qfuncall_interactively, "funcall-interactively");
DEFSYM (Qcommand_debug_status, "command-debug-status");
DEFSYM (Qenable_recursive_minibuffers, "enable-recursive-minibuffers");
DEFSYM (Qmouse_leave_buffer_hook, "mouse-leave-buffer-hook");
@@ -946,5 +965,6 @@
defsubr (&Sinteractive);
defsubr (&Scall_interactively);
+ defsubr (&Sfuncall_interactively);
defsubr (&Sprefix_numeric_value);
}
- bug#17446: 24.4.50; What is the situation around `called-interactively-p'?, (continued)
- bug#17446: 24.4.50; What is the situation around `called-interactively-p'?, Stefan Monnier, 2014/05/09
- bug#17446: 24.4.50; What is the situation around `called-interactively-p'?, Drew Adams, 2014/05/09
- bug#17446: 24.4.50; What is the situation around `called-interactively-p'?, Stefan Monnier, 2014/05/09
- bug#17446: 24.4.50; What is the situation around `called-interactively-p'?, Drew Adams, 2014/05/09
- bug#17446: 24.4.50; What is the situation around `called-interactively-p'?, Michael Heerdegen, 2014/05/09
- bug#17446: 24.4.50; What is the situation around `called-interactively-p'?, Stefan Monnier, 2014/05/09
- bug#17446: 24.4.50; What is the situation around `called-interactively-p'?, Thierry Volpiatto, 2014/05/09
- bug#17446: 24.4.50; What is the situation around `called-interactively-p'?, Stefan Monnier, 2014/05/09
- bug#17446: 24.4.50; What is the situation around `called-interactively-p'?,
Stefan Monnier <=
- bug#17446: 24.4.50; What is the situation around `called-interactively-p'?, Stefan Monnier, 2014/05/09
- bug#17446: 24.4.50; What is the situation around `called-interactively-p'?, Drew Adams, 2014/05/09
- bug#17446: 24.4.50; What is the situation around `called-interactively-p'?, Stefan Monnier, 2014/05/09
- bug#17446: 24.4.50; What is the situation around `called-interactively-p'?, Thierry Volpiatto, 2014/05/10
- bug#17446: 24.4.50; What is the situation around `called-interactively-p'?, Thierry Volpiatto, 2014/05/10
- bug#17446: 24.4.50; What is the situation around `called-interactively-p'?, Michael Heerdegen, 2014/05/10
- bug#17446: 24.4.50; What is the situation around `called-interactively-p'?, Thierry Volpiatto, 2014/05/10
- bug#17446: 24.4.50; What is the situation around `called-interactively-p'?, Thierry Volpiatto, 2014/05/10
- bug#17446: 24.4.50; What is the situation around `called-interactively-p'?, Stefan Monnier, 2014/05/10
- bug#17446: 24.4.50; What is the situation around `called-interactively-p'?, Thierry Volpiatto, 2014/05/10