Codist icon indicating copy to clipboard operation
Codist copied to clipboard

Is it possible to highlight built-in types by using ClassificationTypes.json and a global Codist.ct.json?

Open wmjordan opened this issue 1 month ago • 16 comments

Discussed in https://github.com/wmjordan/Codist/discussions/379

Originally posted by laicasaane December 2, 2025 I want built-in types to be highlighted in different colors rather than inherit the "keyword" classification. But as stated in the wiki, Codist.ct.json has to be placed in the source folder which I don't want because I want the same behavior for every C# files. Is it possible to do this?

wmjordan avatar Dec 02 '25 08:12 wmjordan

@laicasaane It took me little time to implement a global Codist.ct.json.

I found it cumbersome to edit regular expressions within the json file. I plan to change the file type to another one.

wmjordan avatar Dec 02 '25 11:12 wmjordan

Oh sweet, thank you.

laicasaane avatar Dec 02 '25 11:12 laicasaane

@fitdev @laicasaane What kind of config file is best for this? TOML?

For example,

[
	{
		"file": "<output>",
		"items": [
			{ "match": "([=\\-]{5,})", "tag": "Large", "groupTags": ["Quotation"], "tagLine": "true" },
			{ "match": "\\b(?:[Ee]rror|[Ss]tack [Tt]race|Errno)\\b|[Ee]xception\\b|(?:\\b[1-9]|\\b\\d+\\d) [Ff]ailed\\b|-- FAILED\\b|^Failed\\b", "tag": "Error", "tagLine": "true" },
			{ "match": "\\b(?:[Ww]arning|may not work)\\b", "tag": "Warning", "tagLine": "true" },
			{ "match": "Build: \\d+ succeeded, 0 failed, \\d+ up-to-date, \\d+ skipped", "tag": "Information", "tagLine": "true" },
			{ "match": "\\b\\w[\\w _\\.]* -> ([A-Za-z]:\\\\.+)", "tag": "Information", "groupTags": [ "Underline" ] },
			{ "match": "\\b([A-Z]{1,7}\\d{3,4})(?=:)", "tag": "Bold", "groupTags": ["Underline"] }
		]
	},
	{
		"file": "AssemblyInfo.cs",
		"items": [
			{ "match": "assembly", "tag": "Large" }
		]
	}
]

So terrible to have so many \ characters.

Using TOML:

[[rules]]
file = "<output>"

[[rules.items]]
match = '''([=\-]{5,})'''
tag = "Large"
groupTags = [ "Quotation" ]
tagLine = true

[[rules.items]]
match = '''\b(?:[Ee]rror|[Ss]tack [Tt]race|Errno)\b|[Ee]xception\b|(?:\b[1-9]|\b\d+\d) [Ff]ailed\b|-- FAILED\b|^Failed\b'''
tag = "Error"
tagLine = true

[[rules.items]]
match = '''\b(?:[Ww]arning|may not work)\b'''
tag = "Warning"
tagLine = true

[[rules.items]]
match = '''Build: \d+ succeeded, 0 failed, \d+ up-to-date, \d+ skipped'''
tag = "Information"
tagLine = true

[[rules.items]]
match = '''\b\w[\w _\.]* -> ([A-Za-z]:\\.+)'''
tag = "Information"
groupTags = [ "Underline" ]

[[rules.items]]
match = '''\b([A-Z]{1,7}\d{3,4})(?=:)'''
tag = "Bold"
groupTags = [ "Underline" ]

[[rules]]
file = "AssemblyInfo.cs"

[[rules.items]]
match = '''assembly'''
tag = "Large"

wmjordan avatar Dec 02 '25 11:12 wmjordan

I favor TOML or YAML as human-friendly formats for manual editing.

laicasaane avatar Dec 02 '25 11:12 laicasaane

While I haven't used this feature, I think I agree and also would prefer TOML or YAML, as having so many \ in json is making things harder.

fitdev avatar Dec 03 '25 07:12 fitdev

Well, with Deepseek's help, I settled down to use YAML as the configuration file, since it is neater than TOML and Visual Studio has built-in syntax highlight for it.

The global config file name will be codist.ct.yaml. The content can be the following. The first section is for the output window. The second is for any AssemblyInfo.cs file, which highlights all "assembly" inside.

- file: "<output>"
  items:
    - match: ([=\-]{5,})
      tag: "Large"
      groupTags: ["Quotation"]
      tagLine: true
    - match: \b(?:[Ee]rror|[Ss]tack [Tt]race|Errno)\b|[Ee]xception\b|(?:\b[1-9]|\b\d+\d) [Ff]ailed\b|-- FAILED\b|^Failed\b
      tag: "Error"
      tagLine: true
    - match: \b(?:[Ww]arning|may not work)\b
      tag: "Warning"
      tagLine: true
    - match: 'Build: \d+ succeeded, 0 failed, \d+ up-to-date, \d+ skipped'
      tag: "Information"
      tagLine: true
    - match: \b\w[\w _\.]* -> ([A-Za-z]:\\.+)
      tag: "Information"
      groupTags: ["Underline"]
    - match: \b([A-Z]{1,7}\d{3,4})(?=:)
      tag: "Bold"
      groupTags: ["Underline"]
- file: 'AssemblyInfo\.cs'
  items:
    - match: assembly
      tag: "Information"

wmjordan avatar Dec 03 '25 08:12 wmjordan

@laicasaane Please download the new beta and test it.

When a codist.ct.yaml is found in the configuration folder, it will be parsed. Otherwise, codist.ct.json will be attempted to load, if it presents. When any of the aforementioned configuration file is loaded, it will be monitored and subsequent changes to it will be applied to the syntax highlight.

If codist.ct.json has been loaded and codist.ct.yaml is created afterwards. The latter will not be loaded unless VS is restarted.

wmjordan avatar Dec 03 '25 08:12 wmjordan

@wmjordan Thank you. It works well for my needs.

Image Image

laicasaane avatar Dec 03 '25 15:12 laicasaane

The new beta will keep monitoring the global configuration directory. The "codist.ct.yaml" file will be loaded after VS's startup, even if it is created afterwards.

wmjordan avatar Dec 04 '25 03:12 wmjordan

@wmjordan Will it impact the performance?

laicasaane avatar Dec 04 '25 03:12 laicasaane

I don't think it will impact the performance, thus I have the Codist config folder monitored. It is implemented via the FileSystemWatcher, which barely adds burden to the system if no file changes within the Codist folder at usual.

wmjordan avatar Dec 04 '25 06:12 wmjordan

@wmjordan I see that using regex to add another classification to keywords can also highlight them at wrong places, like within a string or comment:

Image Image Image

This is my naive codist.ct.yaml:

- file: '\.cs'
  items:
    - match: \b(bool|byte|sbyte|char|decimal|double|float|int|uint|nint|nuint|long|ulong|short|ushort)\b
      tag: "Built-in Value Types"
    - match: \b(object|string|delegate|dynamic)\b
      tag: "Built-in Reference Types"
    - match: \b(true|false)\b
      tag: "Built-in Value Keywords"
    - match: \b(null)\b
      tag: "Built-in Reference Keywords"

How do you think about this?

laicasaane avatar Dec 06 '25 09:12 laicasaane

The customized syntax highlight has no idea about the syntax.

We have to modify the existing advanced syntax highlighter for the C# language to add new styles for your requirement, as the resource, abstraction, control flow keywords that we already have nowadays.

@fitdev How do you think about that?

wmjordan avatar Dec 07 '25 02:12 wmjordan

I am mostly fine with the existing way. I mean I understand the value in customizing the highlights for such cases, but I probably won't be using them since I already have too many colors/styles used for other purposes.

Though making null standout is perhaps more useful than than the others. And perhaps also the other reference keyword types as well, but as for value types and value keywords - this seems like too much. If anything, I might want a special syntax for nint and nuint to draw attention to the fact that they have dynamic size, but even then it may be too much. Plus not sure about performance implications.

So overall I guess I am in favor of adding styles for reference type keywords and null, but not for the value types.

fitdev avatar Dec 07 '25 05:12 fitdev

Thank you for your precious opinions. I have similar considerations as well. Maybe further refactor the current C# highlighter could mitigate the performance hit.

wmjordan avatar Dec 07 '25 11:12 wmjordan

Thank you for your precious opinions. I have thought of adding more categories to C# keywords for several times, but having the same considerations as yours.

Maybe further refactoring the current C# highlighter can mitigate the performance hit from the newly added keyword categories. A way of refactoring might be using a factory pattern to create an array of sub-highlighter to request the semantic information and do the concrete highlighting jobs, then using those sub-highlighters to compute needed semantic information on demand, according to the highlight configurations that a user has set. For instance, if a user has set some styles of a certain C# keywords, then the highlighter will take care of the keywords. If a user does not set any style of keywords, the highlighter will just ignore the keywords.

wmjordan avatar Dec 07 '25 11:12 wmjordan