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.

View in manual

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;
}