[Top][All Lists]
[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,
- Interactive specs, align.el, Johan Bockgård, 2005/12/09
- Re: Interactive specs, align.el, Juri Linkov, 2005/12/09
- Re: Interactive specs, align.el, Johan Bockgård, 2005/12/09
- Re: Interactive specs, align.el, Juri Linkov, 2005/12/11
- Re: Interactive specs, Juri Linkov, 2005/12/11
- Re: Interactive specs,
Richard M. Stallman <=
- Re: Interactive specs, Stefan Monnier, 2005/12/12
- Re: Interactive specs, Richard M. Stallman, 2005/12/12