emacs-devel
[Top][All Lists]
Advanced

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

Re: CC Mode and electric-pair "problem".


From: João Távora
Subject: Re: CC Mode and electric-pair "problem".
Date: Thu, 31 May 2018 17:07:43 +0100
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/27.0.50 (gnu/linux)

Hi again, Alan

Alan Mackenzie <address@hidden> writes:

>     " (
>
>       ) "
>
> .  With point just after the (, type a ).  The expected result is that
> everything up to and including the existing ) gets "chomped", leaving
> the buffer looking like:
>
>     " () "
>
> .  This no longer happens in C++ mode, and it is not clear that it
> should.  In the original buffer, ( and ) are not in the same string,
> since the opening string ends at EOL, there being no backslash to
> continue it.
>
> If there were escaped newlines in the buffer, I don't think the "chomp"
> would work, because elec-pair.el doesn't recognise escaped newlines as
> whitespace.
>
> Comments?

I can reproduce this, even without turning "chomping" on: 26.1 skips to
the closing parens, master doesn't.

But it's tricky. From elec-pair.el's perspective, skipping whitespace
means skipping whitespace characters *and* not crossing string/comment
boundaries.  To analyse a test case very similar to yours I wrote a
simple function (attached after my sig) to analyse just 5 characters and
an end-of-file.

   ( " \n " ) EOF

In Emacs 26.1 I get

  ((:character 34 :formatted "\"" :syntax
               (7)
               :depth 0 :string nil :last-open-parens nil)
   (:character 40 :formatted "(" :syntax
               (4 . 41)
               :depth 0 :string 34 :last-open-parens 1)
   (:character 10 :formatted "\n" :syntax
               (0)
               :depth 0 :string 34 :last-open-parens 1)
   (:character 41 :formatted ")" :syntax
               (5 . 40)
               :depth 0 :string 34 :last-open-parens 1)
   (:character 34 :formatted "\"" :syntax
               (7)
               :depth 0 :string 34 :last-open-parens 1)
   (:character nil :formatted "EOF" :syntax nil :depth 0 :string nil
               :last-open-parens nil))
               

In Emacs master, I get

  ((:character 34 :formatted "\"" :syntax
               (15)
               :depth 0 :string nil :last-open-parens nil)
   (:character 40 :formatted "(" :syntax
               (4 . 41)
               :depth 0 :string t :last-open-parens 1)
   (:character 10 :formatted "\n" :syntax
               (15)
               :depth 0 :string t :last-open-parens 1)
   (:character 41 :formatted ")" :syntax
               (5 . 40)
               :depth 0 :string nil :last-open-parens nil)
   (:character 34 :formatted "\"" :syntax
               (15)
               :depth -1 :string nil :last-open-parens nil)
   (:character nil :formatted "EOF" :syntax nil :depth -1 :string t
               :last-open-parens 5))

Note that the newline character changed its syntax from (0), which is
whitespace, to (15) which is generic string. But more importantly, the
closing paren after it no longer declares to be inside a string
according to syntax-ppss.

Is this what you and (the majority of) cc-mode users expect? If it is,
then this test (and probably many other ones) must be changed to reflect
that.

As a data-point, as an occasional c++- mode user, I'd much rather have
Emacs 26's behaviour.  When faced with such admittedly invalid C, I at
most expect M-x compile or Flymake to tell me about it, but would like
Emacs to treat it as whitespace so electric-pair keeps functioning
correctly.  That is, I expect Emacs to not choke my editing tools
because I've temporarily produced syntactically incorrect code while
editing, particularly tools designed to correct such situations.

I've also noted that whitespace-fixing tools aren't tripped by your
change. But that's because they don't care about comment and string
boundaries, although they could/should.  This suggests we could make
elec-pair.el also not care about them in c++ mode, but it would only
take us so far, because I fear worse problems would come in more basic
elec-pair.el funtionality.

In general, I think you should review the recent c++-mode changes. To
illustrate, here's a new bug report without any newlines.

1. emacs-master/src/emacs -Q
2. M-x erase-buffer RET !
3. M-x c++-mode
4. M-x electric-pair-mode
5. insert a double quote (this inserts a closer)
6. insert an opening parens (this inserts a closer)
7. insert a double quote (this inserts a closer, but...)

... it additionally popups up an error:

   c-append-to-state-cache: Scan error: "Unbalanced parentheses", 5, 1

The last quote becomes red. If I erase the buffer again and do the whole
thing again, no error happens and no red quote, which is what I expect
it to do (and Emacs 26 behaviour).

Actually, electric-pair-mode doesn't even need to be on:

1. emacs-master/src/emacs -Q
2. M-x erase-buffer RET !
3. M-x c++-mode
5a. insert a double quote
5b. insert the closer quote
5.c go back one char
6a. insert an opening parens
6b. insert the closer, go back one char
7a. insert a double quote
7b. try to insert the closer quote

You get the same c-append-to-state-cache error

João


(defun joaot/analyse (&optional int)
  (interactive "p")
  (cl-loop for p = (point-min)
           then (1+ p)
           while (<= p (point-max))
           for (depth _ _ string comment _ _ _ open-parens _) = (syntax-ppss p)
           for char = (char-after p)
           collect (list :character char
                         :formatted (if char (format "%c" char) "EOF")
                         :syntax (syntax-after p)
                         :depth depth :string string
                         :last-open-parens open-parens)
           into retval
           finally (when int (message "%s" (pp-to-string retval)))
           (cl-return retval)))



reply via email to

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