Function: commandp
commandp is a function defined in eval.c.
Signature
(commandp FUNCTION &optional FOR-CALL-INTERACTIVELY)
Documentation
Non-nil if FUNCTION makes provisions for interactive calling.
This means it contains a description for how to read arguments to give it. The value is nil for an invalid function or a symbol with no function definition.
Interactively callable functions include strings and vectors (treated
as keyboard macros), lambda-expressions that contain a top-level call
to interactive, autoload definitions made by autoload with non-nil
fourth argument, and some of the built-in functions of Lisp.
Also, a symbol satisfies commandp if its function definition does so.
If the optional argument FOR-CALL-INTERACTIVELY is non-nil, then strings and vectors are not accepted.
Probably introduced at or before Emacs version 22.1.
Source Code
// Defined in /usr/src/emacs/src/eval.c
{
register Lisp_Object fun;
bool genfun = false; /* If true, we should consult `interactive-form'. */
fun = function;
fun = indirect_function (fun); /* Check cycles. */
if (NILP (fun))
return Qnil;
/* Emacs primitives are interactive if their DEFUN specifies an
interactive spec. */
if (SUBRP (fun))
{
if (XSUBR (fun)->intspec.string)
return Qt;
}
/* Bytecode objects are interactive if they are long enough to
have an element whose index is COMPILED_INTERACTIVE, which is
where the interactive spec is stored. */
else if (COMPILEDP (fun))
{
if (PVSIZE (fun) > COMPILED_INTERACTIVE)
return Qt;
else if (PVSIZE (fun) > COMPILED_DOC_STRING)
{
Lisp_Object doc = AREF (fun, COMPILED_DOC_STRING);
/* An invalid "docstring" is a sign that we have an OClosure. */
genfun = !(NILP (doc) || VALID_DOCSTRING_P (doc));
}
}
#ifdef HAVE_MODULES
/* Module functions are interactive if their `interactive_form'
field is non-nil. */
else if (MODULE_FUNCTIONP (fun))
{
if (!NILP (module_function_interactive_form (XMODULE_FUNCTION (fun))))
return Qt;
}
#endif
/* Strings and vectors are keyboard macros. */
else if (STRINGP (fun) || VECTORP (fun))
return (NILP (for_call_interactively) ? Qt : Qnil);
/* Lists may represent commands. */
else if (!CONSP (fun))
return Qnil;
else
{
Lisp_Object funcar = XCAR (fun);
if (EQ (funcar, Qautoload))
{
if (!NILP (Fcar (Fcdr (Fcdr (XCDR (fun))))))
return Qt;
}
else
{
Lisp_Object body = CDR_SAFE (XCDR (fun));
if (EQ (funcar, Qclosure))
body = CDR_SAFE (body);
else if (!EQ (funcar, Qlambda))
return Qnil;
if (!NILP (Fassq (Qinteractive, body)))
return Qt;
else if (VALID_DOCSTRING_P (CAR_SAFE (body)))
/* A "docstring" is a sign that we may have an OClosure. */
genfun = true;
}
}
/* By now, if it's not a function we already returned nil. */
/* Check an `interactive-form' property if present, analogous to the
function-documentation property. */
fun = function;
while (SYMBOLP (fun))
{
Lisp_Object tmp = Fget (fun, Qinteractive_form);
if (!NILP (tmp))
error ("Found an 'interactive-form' property!");
fun = Fsymbol_function (fun);
}
/* If there's no immediate interactive form but it's an OClosure,
then delegate to the generic-function in case it has
a type-specific interactive-form. */
if (genfun)
{
Lisp_Object iform = call1 (Qinteractive_form, fun);
return NILP (iform) ? Qnil : Qt;
}
else
return Qnil;
}