From: Stefan Monnier <monnier@iro.umontreal.ca>
To: Thierry Volpiatto <thierry.volpiatto@gmail.com>
Cc: Michael Heerdegen <michael_heerdegen@web.de>, 17446@debbugs.gnu.org
Subject: bug#17446: 24.4.50; What is the situation around `called-interactively-p'?
Date: Fri, 09 May 2014 17:02:20 -0400 [thread overview]
Message-ID: <jwvr442br96.fsf-monnier+emacsbugs@gnu.org> (raw)
In-Reply-To: <jwvwqdubusd.fsf-monnier+emacsbugs@gnu.org> (Stefan Monnier's message of "Fri, 09 May 2014 15:50:03 -0400")
> 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);
}
next prev parent reply other threads:[~2014-05-09 21:02 UTC|newest]
Thread overview: 37+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-05-09 12:29 bug#17446: 24.4.50; What is the situation around `called-interactively-p'? Thierry Volpiatto
2014-05-09 13:39 ` Drew Adams
2014-05-09 14:11 ` Michael Heerdegen
2014-05-09 14:47 ` Drew Adams
2014-05-09 14:17 ` Drew Adams
2014-05-09 14:15 ` Stefan Monnier
2014-05-09 14:28 ` Drew Adams
2014-05-09 14:50 ` Stefan Monnier
2014-05-09 14:55 ` Drew Adams
2014-05-09 15:15 ` Michael Heerdegen
2014-05-09 17:53 ` Stefan Monnier
2014-05-09 18:47 ` Thierry Volpiatto
2014-05-09 19:50 ` Stefan Monnier
2014-05-09 21:02 ` Stefan Monnier [this message]
2014-05-09 22:39 ` Stefan Monnier
2014-05-09 23:34 ` Drew Adams
2014-05-10 2:13 ` Stefan Monnier
2014-05-10 9:10 ` Thierry Volpiatto
2014-05-10 6:12 ` Thierry Volpiatto
2014-05-10 7:40 ` Michael Heerdegen
2014-05-10 8:41 ` Thierry Volpiatto
2014-05-10 5:51 ` Thierry Volpiatto
2014-05-10 6:45 ` Stefan Monnier
2014-05-10 8:06 ` Thierry Volpiatto
2014-05-10 20:15 ` Stefan Monnier
2014-05-11 4:24 ` Michael Heerdegen
2014-05-11 5:58 ` Michael Heerdegen
2014-05-17 18:01 ` Michael Heerdegen
2014-05-18 1:56 ` Stefan Monnier
2014-05-11 6:02 ` Stefan Monnier
2014-05-11 4:31 ` Thierry Volpiatto
2014-05-10 10:22 ` Andreas Röhler
2014-05-10 20:19 ` Stefan Monnier
2014-05-11 7:47 ` Andreas Röhler
2014-05-10 3:43 ` Thierry Volpiatto
2017-03-25 6:23 ` npostavs
2014-05-09 19:16 ` Drew Adams
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=jwvr442br96.fsf-monnier+emacsbugs@gnu.org \
--to=monnier@iro.umontreal.ca \
--cc=17446@debbugs.gnu.org \
--cc=michael_heerdegen@web.de \
--cc=thierry.volpiatto@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.