Subject: Re: bug#5560: 23.1.92; parens matching in c-mode broken

From: Alan Mackenzie <[email-masked]>
Date: Sat, 20 Feb 2016 22:57:23 +0000

Hello, David and Andrew.

On Tue, Feb 16, 2016 at 10:56:34PM -0500, Andrew Hyatt wrote:

> I can confirm this still doesn't work right in Emacs 25.  However, I get
> a slightly different experience, with clicking on all 3 left parens
> highlighting until the first right paren only.  Similarly, that right
> paren seems to be the matching paren for all 3 left parens.

What is (now) happening is this: the C Preprocessor construct ends at the
end of the second line (due to the space after the \ there).  The first
two open parentheses on that line are unmatched.  In such circumstances,
CC Mode splats the syntax of such characters by setting syntax-table text
properties on them.  This is to prevent them spuriously matching parens
outside the CPP construct.

When you double click on one of the non-matching parens, the critical
piece of code reached is in `mouse-start-end'.  Instead of checking the
syntax of the character in its context (i.e. respecting syntax-table text
properties), it simply checks the syntax of the bare character '(', and
finds it's an open paren.  It then does (forward-sexp) to try and find the
matching ')'.  This ignores the two "dummy" parens and then scans over
the real paren pair remaining.

One solution would be to replace the (obsolete) form in mouse.el:

    (char-syntax (char-after start))

with the modern (and correct) form

    (syntax-after start)

.  A small problem with this is that `syntax-after' returns a cons of raw
numbers rather than the more picturesque character descriptors like ?\(.
A bigger problem is that there are still approximately 164 uses of
`char-syntax' in our sources, all (or most) of which need superseding by
`syntax-after'.

If this were to be done, double clicking on one of these unmatched parens
would attempt to match the "word it is in".  I don't know exactly what
would happen.  Probably not very much.  In fact, I'm going to try it.  (A
bit later): Double clicking on a "dummy paren" would mark the sequence of
three parens.  I think this is better than marking up to the single close
paren, but not by much.

> David Reitter <[email-masked]> writes:

> > Parens matching in C mode is sometimes surprising. In the example
> > below, double-clicking on either of the first two opening parentheses 
> > will mark the text until the "     hyper_modifier : 0)", but that is correct
> > only for the second paren, while the first one is unmatched due to a space
> > following the backslash.

> > #define EV_MODIFIERS(e)                               \
> >     ((([e modifierFlags] & NSHelpKeyMask) ?           \ 
> >            hyper_modifier : 0)                        \    
> >     ...

> > It would be more useful if an "unmatched parentheses" was shown, or
> > if the region up to the end of the scan process (i.e. the
> > space+newline) was marked.

Giving a decent error message here would be difficult.  We're down in the
depths of the mouse code, but the strategem of giving syntax-table text
properties to parentheses is a pure CC Mode one.  Signaling an error if
a paren has other than paren syntax is liable to have unforseen side
effects somewhere, somehow, some time.

Do you (plural) think it is worth while fixing the mouse code, as
detailed above, or do you have any other ideas for a fix?

> > In GNU Emacs 23.1.92.86 (x86_64-apple-darwin10.2.0, NS apple-appkit-1038.25)
> >  of 2010-02-08 on scarlett.local - Aquamacs Distribution 2.0dev
> > Windowing system distributor `Apple', version 10.3.1038
> > configured using `configure  '--with-ns' 'CFLAGS=-O0 -g''

> > Major mode: ObjC/l

-- 
Alan Mackenzie (Nuremberg, Germany).