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

From: Stefan Monnier <[email-masked]>
Date: Tue, 20 May 2008 10:39:45 -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?

I wasn't very awak when I wrote that patch.  The patch below seems to
actually work.  Of course, it only fixes the printing part, so if you
already have the above fest in your .emacs, that won't directly help you.

        Stefan

--- macros.el.~1.54.~	2008-05-11 17:49:20.000000000 -0400
+++ macros.el	2008-05-20 10:37:31.000000000 -0400
@@ -131,41 +131,9 @@
 	      (insert (if (zerop i) ?\[ ?\s))
 	      (setq char (aref definition i)
 		    i (1+ i))
-	      (cond ((not (numberp char))
-		     (prin1 char (current-buffer)))
-		    (t
-		     (insert "?")
-		     (setq mods (event-modifiers char)
-			   char (event-basic-type char))
-		     (while mods
-		       (cond ((eq (car mods) 'control)
-			      (insert "\\C-"))
-			     ((eq (car mods) 'meta)
-			      (insert "\\M-"))
-			     ((eq (car mods) 'hyper)
-			      (insert "\\H-"))
-			     ((eq (car mods) 'super)
-			      (insert "\\s-"))
-			     ((eq (car mods) 'alt)
-			      (insert "\\A-"))
-			     ((and (eq (car mods) 'shift)
-				   (>= char ?a)
-				   (<= char ?z))
-			      (setq char (upcase char)))
-			     ((eq (car mods) 'shift)
-			      (insert "\\S-")))
-		       (setq mods (cdr mods)))
-		     (cond ((= char ?\\)
-			    (insert "\\\\"))
-                           ((= char ?\")
-                            (insert "\\\""))
-			   ((= char ?\;)
-			    (insert "\\;"))
-			   ((= char 127)
-			    (insert "\\C-?"))
-			   ((< char 127)
-			    (insert char))
-			   (t (insert "\\" (format "%o" char)))))))
+	      (if (not (numberp char))
+                  (prin1 char (current-buffer))
+                (princ (prin1-char char) (current-buffer))))
 	    (insert ?\]))
 	(prin1 definition (current-buffer))))
     (insert ")\n")