emacs-pretest-bug
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Interactive specs


From: Richard M. Stallman
Subject: Re: Interactive specs
Date: Sun, 11 Dec 2005 17:57:18 -0500

    I think a simpler and better change is to relax this restriction in
    `fix_command' to allow `if' with else-forms, and keep region-beginning
    in the history only if it is presented in then-form.

This is not correct.  Specifically, it gives wrong results
in the case of

  (if FOO (region-beginning) (my-function))

It will "preserve" this argument even if (my-function) should
not be treated that way.

It would be ok to change fix_command to check _both_ arms of the if.
I wrote a patch for that; see below.  Could you try it?


After the release, I think it calls for a different approach.  For
instance, we could write

   (interactive
     (list (recompute-arg EXPRESSION) (recompute-arg EXPRESSION) ...))

When evaluated, recompute-arg would return its arg, but when
fix_command sees it, it would save EXPRESSION as the value.


*** callint.c   07 Aug 2005 13:30:36 -0400      1.140
--- callint.c   11 Dec 2005 17:40:40 -0500      
***************
*** 64,69 ****
--- 64,71 ----
  /* Allocated length of that buffer.  */
  static int callint_message_size;
  
+ static int recomputable_arg_p P_ ((Lisp_Object));
+ 
  /* ARGSUSED */
  DEFUN ("interactive", Finteractive, Sinteractive, 0, UNEVALLED, 0,
         doc: /* Specify a way of parsing arguments for interactive use of a 
function.
***************
*** 189,210 ****
  fix_command (input, values)
       Lisp_Object input, values;
  {
!   if (CONSP (input))
      {
        Lisp_Object car;
  
        car = XCAR (input);
        /* Skip through certain special forms.  */
!       while (EQ (car, Qlet) || EQ (car, Qletx)
!            || EQ (car, Qsave_excursion)
!            || EQ (car, Qprogn))
        {
!         while (CONSP (XCDR (input)))
!           input = XCDR (input);
!         input = XCAR (input);
!         if (!CONSP (input))
            break;
-         car = XCAR (input);
        }
        if (EQ (car, Qlist))
        {
--- 191,226 ----
  fix_command (input, values)
       Lisp_Object input, values;
  {
!   if (CONSP (input) && CONSP (values))
      {
        Lisp_Object car;
  
        car = XCAR (input);
        /* Skip through certain special forms.  */
!       while (1)
        {
!         if (EQ (car, Qlet) || EQ (car, Qletx)
!             || EQ (car, Qsave_excursion)
!             || EQ (car, Qprogn)
!             || EQ (car, Qwhen))
!           {
!             while (CONSP (XCDR (input)))
!               input = XCDR (input);
!             input = XCAR (input);
!             if (!CONSP (input))
!               break;
!             car = XCAR (input);
!           }
!         else if (EQ (car, Qif)
!                  && EQ (Fnthcdr (make_number (3), input), Qnil))
!           {
!             input = Fnth (make_number (2), input);
!             if (!CONSP (input))
!               break;
!             car = XCAR (input);
!           }
!         else
            break;
        }
        if (EQ (car, Qlist))
        {
***************
*** 215,249 ****
            {
              Lisp_Object elt;
              elt = Fcar (intail);
!             if (CONSP (elt))
!               {
!                 Lisp_Object presflag, carelt;
!                 carelt = Fcar (elt);
!                 /* If it is (if X Y), look at Y.  */
!                 if (EQ (carelt, Qif)
!                     && EQ (Fnthcdr (make_number (3), elt), Qnil))
!                   elt = Fnth (make_number (2), elt);
!                 /* If it is (when ... Y), look at Y.  */
!                 else if (EQ (carelt, Qwhen))
!                   {
!                     while (CONSP (XCDR (elt)))
!                       elt = XCDR (elt);
!                     elt = Fcar (elt);
!                   }
! 
!                 /* If the function call we're looking at
!                    is a special preserved one, copy the
!                    whole expression for this argument.  */
!                 if (CONSP (elt))
!                   {
!                     presflag = Fmemq (Fcar (elt), preserved_fns);
!                     if (!NILP (presflag))
!                       Fsetcar (valtail, Fcar (intail));
!                   }
!               }
            }
        }
      }
  }
  
  DEFUN ("call-interactively", Fcall_interactively, Scall_interactively, 1, 3, 
0,
--- 231,286 ----
            {
              Lisp_Object elt;
              elt = Fcar (intail);
! 
!             if (recomputable_arg_p (elt))
!               Fsetcar (valtail, elt);
            }
        }
      }
+ }
+ 
+ /* Return 1 if EXP, when used in (interactive (list ...))
+    to compute one of the arguments, should be recorded and
+    recomputed if we repeat the command.  */
+ 
+ static int
+ recomputable_arg_p (exp)
+      Lisp_Object exp;
+ {
+   Lisp_Object presflag, carelt;
+ 
+   if (!CONSP (exp))
+     return 0;
+ 
+   carelt = Fcar (exp);
+   /* If it is (if X Y), look at Y.
+      If it is (if X Y Z), look at Y and Z.  */
+   if (EQ (carelt, Qif))
+     {
+       /* Test the then-clause.  */
+       if (! recomputable_arg_p (Fnth (make_number (2), exp)))
+       return 0;
+       /* More than one else-clause means we fail.  */
+       if (! NILP (Fnthcdr (make_number (4), exp)))
+       return 0;
+       /* Test the else-clause.  */
+       return recomputable_arg_p (Fnth (make_number (3), exp));
+     }
+   
+   /* If it is (when X Y), look at Y.  */
+   if (EQ (carelt, Qwhen))
+     {
+       /* More than one then-clause means we fail.  */
+       if (! NILP (Fnthcdr (make_number (4), exp)))
+       return 0;
+       /* Test Y.  */
+       return recomputable_arg_p (Fnth (make_number (2), exp));
+     }
+ 
+   /* If the function call we're looking at
+      is a special preserved one, it is ok.  */
+   presflag = Fmemq (carelt, preserved_fns);
+   return !NILP (presflag);
  }
  
  DEFUN ("call-interactively", Fcall_interactively, Scall_interactively, 1, 3, 
0,




reply via email to

[Prev in Thread] Current Thread [Next in Thread]