Function: define-key

define-key is a function defined in keymap.c.

Signature

(define-key KEYMAP KEY DEF)

Documentation

In KEYMAP, define key sequence KEY as DEF.

KEYMAP is a keymap.

KEY is a string or a vector of symbols and characters, representing a sequence of keystrokes and events. Non-ASCII characters with codes above 127 (such as ISO Latin-1) can be represented by vectors. Two types of vector have special meanings:
 [remap COMMAND] remaps any key binding for COMMAND.
 [t] creates a default definition, which applies to any event with no
    other definition in KEYMAP.

DEF is anything that can be a key's definition:
 nil (means key is undefined in this keymap),
 a command (a Lisp function suitable for interactive calling),
 a string (treated as a keyboard macro),
 a keymap (to define a prefix key),
 a symbol (when the key is looked up, the symbol will stand for its
    function definition, which should at that time be one of the above,
    or another symbol whose function definition is used, etc.),
 a cons (STRING . DEFN), meaning that DEFN is the definition
    (DEFN should be a valid definition in its own right),
 or a cons (MAP . CHAR), meaning use definition of CHAR in keymap MAP,
 or an extended menu item definition.
 (See info node (elisp)Extended Menu Items.)

If KEYMAP is a sparse keymap with a binding for KEY, the existing binding is altered. If there is no binding for KEY, the new pair binding KEY to DEF is added at the front of KEYMAP.

Probably introduced at or before Emacs version 13.

Source Code

// Defined in /usr/src/emacs/src/keymap.c
{
  bool metized = false;

  keymap = get_keymap (keymap, 1, 1);

  ptrdiff_t length = CHECK_VECTOR_OR_STRING (key);
  if (length == 0)
    return Qnil;

  int meta_bit = (VECTORP (key) || (STRINGP (key) && STRING_MULTIBYTE (key))
		  ? meta_modifier : 0x80);

  if (VECTORP (def) && ASIZE (def) > 0 && CONSP (AREF (def, 0)))
    { /* DEF is apparently an XEmacs-style keyboard macro.  */
      Lisp_Object tmp = make_nil_vector (ASIZE (def));
      ptrdiff_t i = ASIZE (def);
      while (--i >= 0)
	{
	  Lisp_Object defi = AREF (def, i);
	  if (CONSP (defi) && lucid_event_type_list_p (defi))
	    defi = Fevent_convert_list (defi);
	  ASET (tmp, i, defi);
	}
      def = tmp;
    }

  ptrdiff_t idx = 0;
  while (1)
    {
      Lisp_Object c = Faref (key, make_fixnum (idx));

      if (CONSP (c))
	{
	  /* C may be a Lucid style event type list or a cons (FROM .
	     TO) specifying a range of characters.  */
	  if (lucid_event_type_list_p (c))
	    c = Fevent_convert_list (c);
	  else if (CHARACTERP (XCAR (c)))
	    CHECK_CHARACTER_CDR (c);
	}

      if (SYMBOLP (c))
	silly_event_symbol_error (c);

      if (FIXNUMP (c)
	  && (XFIXNUM (c) & meta_bit)
	  && !metized)
	{
	  c = meta_prefix_char;
	  metized = true;
	}
      else
	{
	  if (FIXNUMP (c))
	    XSETINT (c, XFIXNUM (c) & ~meta_bit);

	  metized = false;
	  idx++;
	}

      if (!FIXNUMP (c) && !SYMBOLP (c)
	  && (!CONSP (c)
	      /* If C is a range, it must be a leaf.  */
	      || (FIXNUMP (XCAR (c)) && idx != length)))
	message_with_string ("Key sequence contains invalid event %s", c, 1);

      if (idx == length)
	return store_in_keymap (keymap, c, def);

      Lisp_Object cmd = access_keymap (keymap, c, 0, 1, 1);

      /* If this key is undefined, make it a prefix.  */
      if (NILP (cmd))
	cmd = define_as_prefix (keymap, c);

      keymap = get_keymap (cmd, 0, 1);
      if (!CONSP (keymap))
	{
	  const char *trailing_esc = ((EQ (c, meta_prefix_char) && metized)
				      ? (idx == 0 ? "ESC" : " ESC")
				      : "");

	  /* We must use Fkey_description rather than just passing key to
	     error; key might be a vector, not a string.  */
	  error ("Key sequence %s starts with non-prefix key %s%s",
		 SDATA (Fkey_description (key, Qnil)),
		 SDATA (Fkey_description (Fsubstring (key, make_fixnum (0),
						      make_fixnum (idx)),
					  Qnil)),
		 trailing_esc);
	}
    }
}