help-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: parens matching not matching all matching parens


From: Greg Hill
Subject: Re: parens matching not matching all matching parens
Date: Thu, 16 Sep 2004 19:18:45 -0700

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

reply via email to

[Prev in Thread] Current Thread [Next in Thread]