(list 'function-put (list 'quote f)
''command-modes (list 'quote val))))
+(defalias 'byte-run--set-interactive-args
+ #'(lambda (f args &rest val)
+ (setq args (remove '&optional (remove '&rest args)))
+ (list 'function-put (list 'quote f)
+ ''interactive-args
+ (list
+ 'quote
+ (mapcar
+ (lambda (elem)
+ (cons
+ (seq-position args (car elem))
+ (cadr elem)))
+ val)))))
+
;; Add any new entries to info node `(elisp)Declare Form'.
(defvar defun-declarations-alist
(list
(list 'indent #'byte-run--set-indent)
(list 'speed #'byte-run--set-speed)
(list 'completion #'byte-run--set-completion)
- (list 'modes #'byte-run--set-modes))
+ (list 'modes #'byte-run--set-modes)
+ (list 'interactive-args #'byte-run--set-interactive-args))
"List associating function properties to their macro expansion.
Each element of the list takes the form (PROP FUN) where FUN is
a function. For each (PROP . VALUES) in a function's declaration,
xsignal0 (Qmark_inactive);
}
-/* If the list of args INPUT was produced with an explicit call to
- `list', look for elements that were computed with
- (region-beginning) or (region-end), and put those expressions into
- VALUES instead of the present values.
+/* If FUNCTION has an `interactive-args' spec, replace relevant
+ elements in VALUES with those forms instead.
This function doesn't return a value because it modifies elements
of VALUES to do its job. */
static void
fix_command (Lisp_Object input, Lisp_Object function, Lisp_Object values)
{
- /* FIXME: Instead of this ugly hack, we should provide a way for an
- interactive spec to return an expression/function that will re-build the
- args without user intervention. */
- if (CONSP (input))
+ /* Quick exit if there's no values to alter. */
+ if (!CONSP (values))
+ return;
+
+ Lisp_Object reps = Fget (function, Qinteractive_args);
+
+ if (!NILP (reps) && CONSP (reps))
{
- Lisp_Object car;
+ int i = 0;
+ Lisp_Object vals = values;
- car = XCAR (input);
- /* Skip through certain special forms. */
- while (EQ (car, Qlet) || EQ (car, Qletx)
- || EQ (car, Qsave_excursion)
- || EQ (car, Qprogn))
+ while (!NILP (vals))
{
- while (CONSP (XCDR (input)))
- input = XCDR (input);
- input = XCAR (input);
- if (!CONSP (input))
- break;
- car = XCAR (input);
- }
- if (EQ (car, Qlist))
- {
- Lisp_Object intail, valtail;
- for (intail = Fcdr (input), valtail = values;
- CONSP (valtail);
- intail = Fcdr (intail), valtail = XCDR (valtail))
- {
- Lisp_Object elt;
- elt = Fcar (intail);
- if (CONSP (elt))
- {
- Lisp_Object presflag, carelt;
- carelt = XCAR (elt);
- /* If it is (if X Y), look at Y. */
- if (EQ (carelt, Qif)
- && NILP (Fnthcdr (make_fixnum (3), elt)))
- elt = Fnth (make_fixnum (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));
- }
- }
- }
+ Lisp_Object rep = Fassq (make_fixnum (i), reps);
+ if (!NILP (rep))
+ Fsetcar (vals, XCDR (rep));
+ vals = XCDR (vals);
+ ++i;
}
}
optional, remove them from the list. This makes navigating the
history less confusing, since it doesn't contain a lot of
parameters that aren't used. */
- if (CONSP (values))
+ Lisp_Object arity = Ffunc_arity (function);
+ /* We don't want to do this simplification if we have an &rest
+ function, because (cl-defun foo (a &optional (b 'zot)) ..)
+ etc. */
+ if (FIXNUMP (XCAR (arity)) && FIXNUMP (XCDR (arity)))
{
- Lisp_Object arity = Ffunc_arity (function);
- /* We don't want to do this simplification if we have an &rest
- function, because (cl-defun foo (a &optional (b 'zot)) ..)
- etc. */
- if (FIXNUMP (XCAR (arity)) && FIXNUMP (XCDR (arity)))
+ Lisp_Object final = Qnil;
+ ptrdiff_t final_i = 0, i = 0;
+ for (Lisp_Object tail = values;
+ CONSP (tail);
+ tail = XCDR (tail), ++i)
{
- Lisp_Object final = Qnil;
- ptrdiff_t final_i = 0, i = 0;
- for (Lisp_Object tail = values;
- CONSP (tail);
- tail = XCDR (tail), ++i)
+ if (!NILP (XCAR (tail)))
{
- if (!NILP (XCAR (tail)))
- {
- final = tail;
- final_i = i;
- }
+ final = tail;
+ final_i = i;
}
-
- /* Chop the trailing optional values. */
- if (final_i > 0 && final_i >= XFIXNUM (XCAR (arity)) - 1)
- XSETCDR (final, Qnil);
}
+
+ /* Chop the trailing optional values. */
+ if (final_i > 0 && final_i >= XFIXNUM (XCAR (arity)) - 1)
+ XSETCDR (final, Qnil);
}
}
defsubr (&Scall_interactively);
defsubr (&Sfuncall_interactively);
defsubr (&Sprefix_numeric_value);
+
+ DEFSYM (Qinteractive_args, "interactive-args");
}