all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
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);
 }






  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.