At 9:19 PM +0200 9/16/04, Arjan Bos wrote: >Hi all, > >I'm currently developing yet another rich text format writer. And as >you might know, RTF is using curly braces a lot. Alas, every now and >then, a normal parentheses pops up between a set of matching {}. >Both the parens matching colouring and the forward-sexp / >backward-sexp can't handle this. How can I (help to) solve this? > >An rtf snippet is included here: > >{\rtf1\mac\ansicpg10000\uc1 >{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang{\pntxta )}}} > >This is a complete piece of (non-sensical, but correct) rtf. The >first `{' matches the last `}'. Only C-M-f jumps from the first `{' >to the one-to-last `}'. > >I'm wondering if this is a bug or not. > >TIA, > >Arjan Arjan, Personally, I would call it a bug in the 'scan-sexps built-in function, which is called by 'forward-sexp, which is normally bound to "C-M-f". For some reason 'scan-sexps seems to treat a ")" as matching a "{". You might want to submit a bug report, but there is no guanentee the maintainers of Emacs will not call that odd behavior a "feature." On the other hand, if you just want to get on with life, you can try putting something like the following code in your .emacs file. The 'defun defines a function that scans forward for the first '(', '[', '<' or '{' following point, whatever it see first, then scans for a matching closing character, ignoring any other characters. The '(setq forward-sexp-function... effectively replaces the guts of 'forward-sexp with the new function, so you will not have to rebind your keystroke. It works in the backward direction as well ("C-M-b"). (defun forward-pexp (&optional arg) (interactive "p") (or arg (setq arg 1)) (let (open close next notstrc notstro notstre depth) (catch 'done (cond ((> arg 0) (skip-chars-forward "^([{<") (setq open (char-after)) (cond ((eq open ?\() (setq close ?\))) ((eq open ?\[) (setq close ?\])) ((eq open ?\{) (setq close ?\})) ((eq open ?\<) (setq close ?\>)) (t (throw 'done nil) ) ) (setq notstro (concat "^" (char-to-string open)) notstre (concat notstro (char-to-string close)) ) (while (and (> arg 0) (not (eobp))) (skip-chars-forward notstro) (forward-char 1) (setq depth 1) (while (and (> depth 0) (not (eobp))) (skip-chars-forward notstre) (setq next (char-after)) (cond ((eq next open) (setq depth (1+ depth)) ) ((eq next close) (setq depth (1- depth)) ) (t (throw 'done nil) ) ) (forward-char 1) ) (setq arg (1- arg) ) ) ) ((< arg 0) (skip-chars-backward "^)]}>") (setq close (char-before)) (cond ((eq close ?\)) (setq open ?\()) ((eq close ?\]) (setq open ?\[)) ((eq close ?\}) (setq open ?\{)) ((eq close ?\>) (setq open ?\<)) (t (throw 'done nil) ) ) (setq notstrc (concat "^" (char-to-string close)) notstre (concat notstrc (char-to-string open)) ) (while (and (< arg 0) (not (bobp))) (skip-chars-backward notstrc) (forward-char -1) (setq depth 1) (while (and (> depth 0) (not (bobp))) (skip-chars-backward notstre) (setq next (char-before)) (cond ((eq next close) (setq depth (1+ depth)) ) ((eq next open) (setq depth (1- depth)) ) (t (throw 'done nil) ) ) (forward-char -1) ) (setq arg (1+ arg)) ) ) ) ) )) (setq forward-sexp-function 'forward-pexp) I should warn you, by the way, that I just hacked this code together in a few minutes after work tonight, and have not tested it exhuastively. Let me know if you have any questions or problems. --Greg