Subject: bug#283: scan-error for keyboard macro

From: Stefan Monnier <[email-masked]>
Date: Tue, 20 May 2008 09:06:28 -0400

> The following piece of code was generated with insert-kbd-macro
> (fset 'foo
>    [?\C-[ ?f ?\C-[ ?  ?\C-[ ?b ?\C-[ ?w ?\C-x ?o ?\C-x ?\C-v left left ?\C-@ ?\C-r ?/ ?\C-m ?\C-w ?/ ?\C-y ?\C-[ ?y ?\C-m ?\C-x ?o])

> If you put it into a file and load the file, the macro is available.
> If you put point at the end of the macro definition and execute
> C-x C-e (eval-last-sexp) this does not allow you to load the macro
> (though eval-last-sexp doesn't throw an error, in the end the
> macro foo is not available). If you put point inside the macro
> definition and type C-M-x (eval-defun) it throws the error

> (scan-error "Unbalanced parentheses" 1 145)

The problem is a known one: the emacs-lisp-mode and its syntax-table
does not properly recognize all the escaping going on in
character constants.  E.g. in ?\C-[, the mode thinks this opens a square
bracket expression.  If you add \ in front of the [ the problem
will disappear.

So we could fix it either by improving the Elisp code (i.e. either
improve syntax.c to be able to understand it, or add
a font-lock-syntactic-keywords), or by changing the printer code to
escape those chars with a \.  Can you confirm that the patch below
fixes it?

        Stefan

=== modified file 'lisp/macros.el'
--- lisp/macros.el	2008-05-06 14:18:59 +0000
+++ lisp/macros.el	2008-05-20 13:05:47 +0000
@@ -86,45 +86,7 @@
 	  (setq end (point-marker))
 	  (goto-char beg)
 	  (while (< (point) end)
-	    (let ((char (following-char)))
-	      (cond ((= char 0)
-		     (delete-region (point) (1+ (point)))
-		     (insert "\\C-@"))
-		    ((< char 27)
-		     (delete-region (point) (1+ (point)))
-		     (insert "\\C-" (+ 96 char)))
-		    ((= char ?\C-\\)
-		     (delete-region (point) (1+ (point)))
-		     (insert "\\C-\\\\"))
-		    ((< char 32)
-		     (delete-region (point) (1+ (point)))
-		     (insert "\\C-" (+ 64 char)))
-		    ((< char 127)
-		     (forward-char 1))
-		    ((= char 127)
-		     (delete-region (point) (1+ (point)))
-		     (insert "\\C-?"))
-		    ((= char 128)
-		     (delete-region (point) (1+ (point)))
-		     (insert "\\M-\\C-@"))
-		    ((= char (aref "\M-\C-\\" 0))
-		     (delete-region (point) (1+ (point)))
-		     (insert "\\M-\\C-\\\\"))
-		    ((< char 155)
-		     (delete-region (point) (1+ (point)))
-		     (insert "\\M-\\C-" (- char 32)))
-		    ((< char 160)
-		     (delete-region (point) (1+ (point)))
-		     (insert "\\M-\\C-" (- char 64)))
-		    ((= char (aref "\M-\\" 0))
-		     (delete-region (point) (1+ (point)))
-		     (insert "\\M-\\\\"))
-		    ((< char 255)
-		     (delete-region (point) (1+ (point)))
-		     (insert "\\M-" (- char 128)))
-		    ((= char 255)
-		     (delete-region (point) (1+ (point)))
-		     (insert "\\M-\\C-?"))))))
+            (prin1-char (following-char))))
       (if (vectorp definition)
 	  (let ((len (length definition)) (i 0) char mods)
 	    (while (< i len)