Specifically, I want to add Vulkan highlighting to the Boxy Theme. What file do I need to edit? I’m running Sublime Text 3 on Ubuntu 16.04.
How do I add syntax highlighting to a theme
Themes, color schemes and syntax highlighters are all decoupled from each other. This is the core of ST that is indeed very powerful. So, to highlight a new language you only need to grab a “syntax definition” and the color scheme you’re using will automatically highlight it.
That said, Vulkan is a C library, and C is part of the default languages that have a syntax definition shipped with ST, so I’m not sure exactly what you want to accomplish.
Vulkan has pre-defined types which begin with ‘Vk’, e.g. VkShaderModule, and I want to highlight these.
OK, this means you want to “override” the default C syntax by providing rules that match an identifier starting with “Vk” and give them a special scope.
Unfortunately, it is currently impossible to “override” parts of an existing syntax definition. However, there are attempts to address this with a plugin called YAML Macros. See also this thread.
At last, a customer!
- Install “YAMLMacros” via package control.
- Create a new “Vulkan” directory in your Packages directory.
- Get a copy of the default C syntax. Put this in your new “Vulkan” package.
- Create a new file in your Vulkan package named “Vulkan.sublime-syntax.yaml-macros”.
Then, in that file, we want to include and extend the C syntax. We start out thus:
%YAML 1.2
%TAG ! tag:yaml-macros:YAMLMacros.lib.extend:
---
!extend
_base: C.sublime-syntax
name: Vulkan
If you build this using the “YAML Macros” build system, it will produce “Vulkan.sublime-syntax”, which will be an exact functional copy of the C syntax but named “Vulkan”.
Now, we want to add new functionality. Looking at the C syntax, we can see where we should inject our new rules:
early-expressions:
- include: preprocessor-expressions
- include: comments
- include: case-default
- include: access
- include: typedef
- include: keywords-parens
- include: keywords
- include: numbers
- include: operators
- include: strings
- include: parens
- include: brackets
- include: block
- include: variables
- include: constants
- match: ','
scope: punctuation.separator.c
- match: '\)|\}'
scope: invalid.illegal.stray-bracket-end.c
We want to add the Vulkan types to the front of this list:
%YAML 1.2
%TAG ! tag:yaml-macros:YAMLMacros.lib.extend:
---
!extend
_base: C.sublime-syntax
name: Vulkan
contexts: !merge
early-expressions: !prepend
- include: vulkan-expressions
vulkan-expressions:
- match: '\b(?=Vk){{identifier}}\b'
scope: support.type.vulkan.c
Build the file again, then open up a new window and test out your new syntax. Type VkShaderModule x;
and the Vulkan type will be marked and highlighted as support.type.vulkan.c
.
As an aside, the default C syntax looks like a bit of a mess. Perhaps someone who uses C more often than I do could clean it up a bit.
C is a disaster to try and highlight properly, which is (IMO) a large part of why it is a mess. The C preprocessor makes it very difficult to get things right since you are effectively tracking two contexts at the same time. Also, the fact that you don’t know if you have a variable definition or a function until you hit a (
makes it a pain also.
That said, I’m sure someone with some time could make plenty of improvements.
Yeah, perfect C highlighting is impossible without actually running the macros. Perfect-except-for-macros highlighting is possible in principle, but not in Sublime because Sublime only parses deterministic CFGs and has lookahead limitations. Within those limitations, some distinctions can be made only via lookaheads and guesswork.
But in addition to that, we also have stuff like the following:
variables:
- match: '\bg[A-Z]\w*\b'
scope: variable.other.readwrite.global.mac-classic.c
- match: '\bs[A-Z]\w*\b'
scope: variable.other.readwrite.static.mac-classic.c
In my opinion, the core syntax should be more conservative, eschewing vendor-specific extensions and conventions. That’s actually one of the main motivations for YAML Macros – it lets the end user and package authors more easily build upon and customize a simpler base.