elisp: Strings of Events

 
 20.7.15 Putting Keyboard Events in Strings
 ------------------------------------------
 
 In most of the places where strings are used, we conceptualize the
 string as containing text characters—the same kind of characters found
 in buffers or files.  Occasionally Lisp programs use strings that
 conceptually contain keyboard characters; for example, they may be key
 sequences or keyboard macro definitions.  However, storing keyboard
 characters in a string is a complex matter, for reasons of historical
 compatibility, and it is not always possible.
 
    We recommend that new programs avoid dealing with these complexities
 by not storing keyboard events in strings.  Here is how to do that:
 
    • Use vectors instead of strings for key sequences, when you plan to
      use them for anything other than as arguments to ‘lookup-key’ and
      ‘define-key’.  For example, you can use ‘read-key-sequence-vector’
      instead of ‘read-key-sequence’, and ‘this-command-keys-vector’
      instead of ‘this-command-keys’.
 
    • Use vectors to write key sequence constants containing meta
      characters, even when passing them directly to ‘define-key’.
 
    • When you have to look at the contents of a key sequence that might
      be a string, use ‘listify-key-sequence’ (SeeEvent Input Misc)
      first, to convert it to a list.
 
    The complexities stem from the modifier bits that keyboard input
 characters can include.  Aside from the Meta modifier, none of these
 modifier bits can be included in a string, and the Meta modifier is
 allowed only in special cases.
 
    The earliest GNU Emacs versions represented meta characters as codes
 in the range of 128 to 255.  At that time, the basic character codes
 ranged from 0 to 127, so all keyboard character codes did fit in a
 string.  Many Lisp programs used ‘\M-’ in string constants to stand for
 meta characters, especially in arguments to ‘define-key’ and similar
 functions, and key sequences and sequences of events were always
 represented as strings.
 
    When we added support for larger basic character codes beyond 127,
 and additional modifier bits, we had to change the representation of
 meta characters.  Now the flag that represents the Meta modifier in a
 character is 2**27 and such numbers cannot be included in a string.
 
    To support programs with ‘\M-’ in string constants, there are special
 rules for including certain meta characters in a string.  Here are the
 rules for interpreting a string as a sequence of input characters:
 
    • If the keyboard character value is in the range of 0 to 127, it can
      go in the string unchanged.
 
    • The meta variants of those characters, with codes in the range of
      2**27 to 2**27+127, can also go in the string, but you must change
      their numeric values.  You must set the 2**7 bit instead of the
      2**27 bit, resulting in a value between 128 and 255.  Only a
      unibyte string can include these codes.
 
    • Non-ASCII characters above 256 can be included in a multibyte
      string.
 
    • Other keyboard character events cannot fit in a string.  This
      includes keyboard events in the range of 128 to 255.
 
    Functions such as ‘read-key-sequence’ that construct strings of
 keyboard input characters follow these rules: they construct vectors
 instead of strings, when the events won’t fit in a string.
 
    When you use the read syntax ‘\M-’ in a string, it produces a code in
 the range of 128 to 255—the same code that you get if you modify the
 corresponding keyboard event to put it in the string.  Thus, meta events
 in strings work consistently regardless of how they get into the
 strings.
 
    However, most programs would do well to avoid these issues by
 following the recommendations at the beginning of this section.