Skip to content

syntax/c: highlight the header name in #include as a string, not a type - #4236

Open
Londopy wants to merge 4 commits into
micro-editor:masterfrom
Londopy:fix-c-include-highlight
Open

Londopy wants to merge 4 commits into
micro-editor:masterfrom
Londopy:fix-c-include-highlight

Conversation

@Londopy

@Londopy Londopy commented Sep 20, 2026

Copy link
Copy Markdown
Contributor

#include <float.h> highlighted float as a type (and <, ., > as operators) because the #include line was only matched by a pattern rule, so the other top-level patterns still ran over the header name.

This makes #include lines a preproc region (like scad.yaml does), which stops the type/identifier patterns from matching inside it. The region's inner rules highlight <...> and "..." as constant.string — matching how #include "float.h" was already rendered — and keep trailing // and /* */ comments as comments. Inner rules are patterns rather than nested regions, since nested regions get top-level patterns leaked into them by highlightRegion.

Checked with pkg/highlight directly:

input result
#include <float.h> #include:preproc, <float.h>:constant.string
#include "float.h" unchanged from before
# include <stdint.h> // TODO: drop <stdint.h>:constant.string, // TODO: drop:comment
#include <bool.h> /* int */ /* int */:comment (int no longer a type)
#include MY_HEADER all preproc
float x = 1.0f; / int y = a < b > c; unchanged
#include <float.h> followed by float z; second line still highlights float as type (region closes at EOL)

Closes #3930

@Andriamanitra Andriamanitra left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a nice little improvement, works as expected.

You could remove "include" from the preproc rule on line 17 since it's now handled by the region.

@Londopy

Londopy commented Sep 20, 2026

Copy link
Copy Markdown
Contributor Author

Done! Dropped include from the pattern. While retesting I noticed that left #include_next unhighlighted (the old pattern was partially matching it), so the region start now also accepts _next.

@JoeKar

JoeKar commented Sep 21, 2026

Copy link
Copy Markdown
Member

The same is valid for the cpp.yaml (maybe even more like objc.yaml), right?

@Andriamanitra

Copy link
Copy Markdown
Collaborator

The same is valid for the cpp.yaml (maybe even more like objc.yaml), right?

Good point! We have syntaxes for 6 different variants of C:

  • arduino
  • c
  • cpp
  • cuda
  • hc
  • objc

It would probably make sense to use include: "c" in at least some of these to inherit from the C syntax, but I'm not sure which ones are true supersets of C. But for this PR simply copying the rule to all of them would be fine too.

Grepping for #.*include also found three others that are not C but I guess can use a similar preprocessor (I don't think we need to touch these):

  • ats
  • fortran
  • zscript

arduino, cpp, cuda, hc and objc had the same issue as c: the header name in an
#include line was matched by the type/identifier rules (e.g. float in <float.h>).

Each file keeps the group it already used for the directive (statement for arduino,
special for objc) so the only visual change is the header name becoming a string.
In objc the whole-line special rule for import/include is superseded by the region
and has been removed.
Comment thread runtime/syntax/objc.yaml
- preproc: "^[[:space:]]*#[[:space:]]*(define|(un|ifn?)def|endif|el(if|se)|if|warning|error|pragma).*$"
- preproc: "__[A-Z0-9_]*__"

- special: "^[[:space:]]*[#|@][[:space:]]*(import|include)[[:space:]]*[\"|<].*\\/?[>|\"][[:space:]]*$"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You accidentally removed highlighting for @import here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Restored it verbatim in 555409f. @import Foundation; was never affected (the @(...) statement rule covers it), but @import <Foundation/Foundation.h> and @import "X.h" lost highlighting since the region only matches #. The region supersedes that rule for # lines, so it still does its job for @.

I also diffed every touched syntax file before/after over a corpus: the only lines that change now are #include/#import directives.

… identifiers

Restores the whole-line special rule in objc.yaml verbatim: the region only
matches the # form, so removing it dropped highlighting for @import <...> and
@import "...". The region supersedes it for # lines.

Also adds each file's own identifier rule inside the region, ordered before the
string rule, so a macro-form include (#include MY_HEADER) keeps the identifier
highlighting it had before while <...> and "..." still win.
@dmaluka

dmaluka commented Sep 21, 2026

Copy link
Copy Markdown
Collaborator

works as expected.

I don't think so.

image

@Londopy

Londopy commented Sep 21, 2026

Copy link
Copy Markdown
Contributor Author

You're right, thanks for catching it — I reproduced it with your file.

The cause turned out not to be this PR though. In highlightRegion, the region's end is located inside the region's own slice of the line, but that line-relative index is compared against the region's absolute start offset:

if start == endLoc[0] {
    searchNesting = false
}

When the two happen to be equal, every rule inside the region is skipped. #include "irq.h" hits it because start is 8 and the remaining slice "irq.h" is also 8 long — which is why the short header names in your screenshot fail and the longer ones don't.

It's pre-existing. On current master, with no changes at all, in a C file:

int a;// TODO: x    → TODO not highlighted
int ab;// TODO: x   → TODO highlighted

I've opened #4240 with the one-line fix (endLoc[0] == 0) and a regression test. With that applied, your kvm file highlights every include correctly:

#include <linux/kvm_host.h>   "#include":preproc | "<linux/kvm_host.h>":constant.string
#include "irq.h"              "#include":preproc | "\"irq.h\"":constant.string
#include "mmu.h"              "#include":preproc | "\"mmu.h\"":constant.string
...

So this PR depends on #4240 — happy to reorder them, or to hold this one until that lands.

@dmaluka

dmaluka commented Sep 21, 2026

Copy link
Copy Markdown
Collaborator

@JoeKar does this problem remind your of something?

@Andriamanitra

Copy link
Copy Markdown
Collaborator

works as expected.

I don't think so.

My bad, I didn't think to test with a file where the #include lines are exactly 16 characters long! I guess this is one of the bugs fixed by #4022...

@Londopy Londopy mentioned this pull request Sep 22, 2026
@Londopy

Londopy commented Sep 22, 2026

Copy link
Copy Markdown
Contributor Author

Correction to my comment above: the fix already exists as #4022 (tracked by #4018) — I missed it and opened a duplicate, which I've now closed. #4022 has the same one-line change plus nested-region fixes.

So this PR depends on #4022 rather than anything of mine. I've offered my regression test over there since that PR has no tests and the open question was whether it breaks anything else.

This one is fine to hold until #4022 lands — no rush from my side.

@JoeKar

JoeKar commented Sep 22, 2026

Copy link
Copy Markdown
Member

@JoeKar does this problem remind your of something?

At the very least, we should merge #4022 (go from my side) as a temporary solution, and I need to continue working on #3127 to remove this weird (somehow self-inflicted) highlighter loop.

Yes, I know...this line was my fault and turned out to be just half of the truth. 😞

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

C syntax highlighting.

4 participants