Discussion:
cc-mode: mark #include <headers> as strings
Mohammed Sadiq
2016-11-14 03:38:55 UTC
Permalink
In the code #include "stdio.h" the points in quotes are marked as string.
But in the code #include <stdio.h> it's not.

Because of this, packages like electric-spacing-mode breaks inside
system header includes (eg: #include <gtk/gtk.h>)

It would be nice if headers like <stdio.h> in #include <stdio.h>
are too marked as strings (That is, set 4th car of syntax-ppss as non-nil)

Thanks.

------------------------------------------------------------------------------
Alan Mackenzie
2016-11-19 12:24:59 UTC
Permalink
Hello, Mohammed.

Thanks for your post to the CC Mode mailing list.
Post by Mohammed Sadiq
In the code #include "stdio.h" the points in quotes are marked as string.
But in the code #include <stdio.h> it's not.
Combining this with the last paragraph in your post, I think you mean
that when you place point inside "stdio.h" and do M-: (syntax-ppss),
element 3 (counting from zero) of the resulting parser state is non-nil,
but when you do the same inside <stdio.h> that element is nil.
Post by Mohammed Sadiq
Because of this, packages like electric-spacing-mode breaks inside
system header includes (eg: #include <gtk/gtk.h>)
OK, I've just had a look at electric-spacing-mode. When I enable it in
a C buffer, then type

#include <gtk/gtk.h>,

I see unwanted spaces being inserted around the "/". However, when I
type, instead,

#include "gtk/gtk.h"

, I also get the unwanted spaces. If this is what you mean when you say
that electric-spacing-mode "breaks", it might well be a problem in
electric-spacing-mode, which you would probably do better to report to
Post by Mohammed Sadiq
It would be nice if headers like <stdio.h> in #include <stdio.h>
are too marked as strings (That is, set 4th car of syntax-ppss as non-nil)
This would be a lot of work. The character "<" is a syntactic horror in
CC Mode, since it has three distinct uses: (i) less than; (ii) A
delimiter in #include <foo.h>; (iii) a template/generic delimiter in
C++/Java. I wouldn't really want to undertake this work unless there
were a clear advantage in doing it, and there weren't a simpler way of
fixing whatever problem it was causing.

I've had a look at the source code for electric-spacing-mode, and it
doesn't seem to test element 3 of a parser state anywhere. Would you
please be more precise about what problem you are seeing that changing
the "syntax" of the contents of <foo.h> to string would solve. Thanks!
--
Alan Mackenzie (Nuremberg, Germany).

------------------------------------------------------------------------------
Alan Mackenzie
2016-11-20 12:13:31 UTC
Permalink
Hello, Mohammed.
Post by Alan Mackenzie
#include "gtk/gtk.h"
, I also get the unwanted spaces. If this is what you mean when you say
that electric-spacing-mode "breaks", it might well be a problem in
electric-spacing-mode, which you would probably do better to report to
I don't know which version of electric-space-mode you are using.
When I try from master (from melpa) #include "gtk/gtk.h" have no issues.
Fair point! Yesterday, I actually had an older version of
electric-spacing-mode.el, dated November 2015, which I got from GNU elpa.
I've just downloaded electric-spacing-20161113.916.el from the melpa
website, and I still see unwanted spaces inserted when I type a "/" after
#include "gtk .

Which version are you using? Maybe the differences we are seeing are
caused by something else, not electric-spacing.el itself.

However, in the following function (from ...-20161113.916.el)

(defun electric-spacing-/ ()
"See `electric-spacing-insert'."
;; *nix shebangs #!
(cond ((and (eq 1 (line-number-at-pos))
(save-excursion
(move-beginning-of-line nil)
(looking-at "#!")))
(insert "/"))
(t
(electric-spacing-insert "/"))))

, it seems clear that the spaces are inserted around a "/" everywhere
except on the first line of a file when that line begins with "#!".
Post by Alan Mackenzie
This would be a lot of work. The character "<" is a syntactic horror in
CC Mode, since it has three distinct uses: (i) less than; (ii) A
delimiter in #include <foo.h>; (iii) a template/generic delimiter in
C++/Java. I wouldn't really want to undertake this work unless there
were a clear advantage in doing it, and there weren't a simpler way of
fixing whatever problem it was causing.
in #include <stdio.h>, <stdio.h> is already having a style like a string.
ie, `face-at-point' returns font-lock-string-face
So would setting syntax-ppss be hard?
It would not be particularly hard (I've done something similar for
template/generic delimiters in C++/Java), but it would be tedious and
take a long time.

The way to do this would be to set "string" syntax-table text properties
on the pertinent "<" and ">". But, consider: these properties cannot be
set on a single "<", they must be set on "<" and ">" in pairs, otherwise
the single "<" in an incomplete "#include <" would make the rest of the
file into one long string (more or less).

Everytime a "<" or a ">" is inserted OR DELETED, the code would have to
analyse whether it's a less/greater-than, a template delimiter, or an
include file delimiter. Assuming it's an include file delimiter, the
code needs to check whether a syntax-table text property needs to be
applied OR REMOVED. More involved checking would be needed to remove the
text properties when "#include" is damaged, say to "#includee".

And anyway, at the time when you would be typing the "/" in
"#include <gtk/", the "<" wouldn't yet have the "string" syntax-table
text property (see two paragraphs back), so I'm not sure what would be
gained by applying these properties to the "<" and ">" later.

And so on..... It could be done, certainly, but it would be a lot of
work.

Question: why can the analysis of this situation not be performed in
electric-spacing-/? All that would be needed would be an extra arm in
the `cond' form which would check for "^[ \t]*#[ \t]*include[ \t]+[<\"]"
at the beginning of the current line. This would be direct, safe, and
much less involved than modifying CC Mode.
--
Alan Mackenzie (Nuremberg, Germany).

------------------------------------------------------------------------------
Alan Mackenzie
2016-11-21 20:44:57 UTC
Permalink
Hello, Mohammed.
Post by Alan Mackenzie
Fair point! Yesterday, I actually had an older version of
electric-spacing-mode.el, dated November 2015, which I got from GNU elpa.
I've just downloaded electric-spacing-20161113.916.el from the melpa
website, and I still see unwanted spaces inserted when I type a "/" after
#include "gtk .
OK. Sorry, I have to explain a bit more. electric-spacing is configured to not
work inside string (see line 143 [or search for 'nth 8']).
So in #include "gtk/
shall give #include "gtk /
While #include "gtk/" shall result no spaces
And I was testing this with electric-pair-mode enabled, which is common.
I don't need complicated rules.
Just as an aside, it probably would have helped if you'd said these
things in your initial bug report.
And so I don't this to be working in #include <gtk
Ie, without closing angle bracket.
You've missed out the verb. I'm guessing you meant "I don't _need_ this
to be working in ..."
But only in #include <gtk..> And it's OK for this to be broken if one
delete the closing angle bracket.
CC Mode needs to work properly for _any_ valid set of personal
preferences. And believe me, as maintainer of CC Mode, for just about
any conceivable set of personal settings, there's somebody who likes it,
no matter how unlikely it may seem to you and me.
I say this because in electric-spacing if one type '<' after #include
'>' is automatically inserted.
This is only a personal preference which not everybody likes. I, for
one, don't like it. What we implement must also work for those who
don't enable electric-pair-mode (or whatever it's called).
I hope I have answered your doubts. Sorry for confusing you.
No problems!

Talking of problems, I think the right way to solve the problem we've
been talking around here (unwanted spaces being inserted on typing a "/"
into the file path introduced by "#include \"" or "#include <") is the
following. I haven't tested it, but think it's likely to work. Feel
free to play around with the idea, or submit it to electic-spacing's
maintainer:



--- electric-spacing-20161113.916.el~ 2016-11-20 10:24:17.000000000 +0000
+++ electric-spacing-20161113.916.el 2016-11-21 20:25:22.000000000 +0000
@@ -409,7 +409,8 @@
(cond ((and (eq 1 (line-number-at-pos))
(save-excursion
(move-beginning-of-line nil)
- (looking-at "#!")))
+ (or (looking-at "#!")
+ (looking-at "[ \t]*#[ \t]*include[ \t]+[<\"]"))))
(insert "/"))
(t
(electric-spacing-insert "/"))))
--
Alan Mackenzie (Nuremberg, Germany).

------------------------------------------------------------------------------
Mohammed Sadiq
2017-04-21 16:36:36 UTC
Permalink
Hello,
Post by Alan Mackenzie
Hello, Mohammed.
And so I don't this to be working in #include <gtk
Ie, without closing angle bracket.
You've missed out the verb. I'm guessing you meant "I don't _need_ this
to be working in ..."
But only in #include <gtk..> And it's OK for this to be broken if one
delete the closing angle bracket.
CC Mode needs to work properly for _any_ valid set of personal
preferences. And believe me, as maintainer of CC Mode, for just about
any conceivable set of personal settings, there's somebody who likes it,
no matter how unlikely it may seem to you and me.
I say this because in electric-spacing if one type '<' after #include
'>' is automatically inserted.
This is only a personal preference which not everybody likes. I, for
one, don't like it. What we implement must also work for those who
don't enable electric-pair-mode (or whatever it's called).
After a long time, again. I was asking for this feature (That is, to mark
<text> in #include as string) so that it would work fine with
electric-spacing. It is the same electric-spacing package that inserts
closing '>' if one types '<' after #include (not electric-pair-mode or something
else). So no other package is involved here other than electric-spacing.
Post by Alan Mackenzie
I hope I have answered your doubts. Sorry for confusing you.
No problems!
Talking of problems, I think the right way to solve the problem we've
been talking around here (unwanted spaces being inserted on typing a "/"
into the file path introduced by "#include \"" or "#include <") is the
following. I haven't tested it, but think it's likely to work. Feel
free to play around with the idea, or submit it to electic-spacing's
--- electric-spacing-20161113.916.el~ 2016-11-20 10:24:17.000000000 +0000
+++ electric-spacing-20161113.916.el 2016-11-21 20:25:22.000000000 +0000
@@ -409,7 +409,8 @@
(cond ((and (eq 1 (line-number-at-pos))
(save-excursion
(move-beginning-of-line nil)
- (looking-at "#!")))
+ (or (looking-at "#!")
+ (looking-at "[ \t]*#[ \t]*include[ \t]+[<\"]"))))
(insert "/"))
(t
(electric-spacing-insert "/"))))
Any of the following char can be in header file name: +-/~<>...

So checking if the line begins with '#include <' for every char typed
seems pretty much wastage of resource (CPU?) for me. That
was the primary reason I requested for this. Not that it was hard to do
in electric-spacing.

Please just ask me to shut up if this should still better happen in
electric-spacing.

Thanks
Post by Alan Mackenzie
--
Alan Mackenzie (Nuremberg, Germany).
Loading...