Sublime Forum

Help with integration of an ad-hoc keyword highlighter (Synethesia plugin) with an existing color scheme (Tomorrow)

#1

Looking for assistance in integrating the ad-hoc keyword highlighting plugin Synethesia with an existing color scheme (Tomorrow-Blue). I’m using SublimeText for writing prose and it’s difficult to follow the author’s help file since I don’t understand most of the underlying framework.

I tried using package resource viewer to access Tomorrow’s code, copying and pasting it into the file compiled by Synethesia but it didn’t work.

I also tried a hail mary by writing “include:”[/tomorrow theme file path] within the file created by synethesia but no joy.

Here is relevant information from the github plugin page (https://github.com/dariusf/synesthesia)

Inner Workings
Compiling a highlighting scheme generates three files:
Language definition (.tmLanguage)
Colour theme (.tmTheme)
Settings (.sublime-settings)
The first two work in tandem, specifying a mini-language consisting of the user's keywords, along with a colour theme designed specifically for that mini-language. The settings file glues them together, causing Sublime Text to associate the theme with the mini-language. All this is done via Sublime Text's built-in mechanisms for syntax highlighting, so it's robust and stable.
Other plugins for highlighting arbitrary words do so either via named regions or by mutating the current colour theme.
The first method doesn't interact well with live editing and is limited to only changing the background colour of text.
The second provides a slightly higher level of flexibility (for example, there may be no need to switch to a different language) but is much more complex implementation-wise. It also may not play nice with all language definitions and colour schemes.
The method used in this plugin, while static, is great for live editing and is much simpler to manage. Interactions with other language definitions are also made explicit. I see it as the middle ground between these approaches.
0 Likes

#2

That’s an interesting idea for a package; I’ve not run across that one before. Probably the best solution would be to have the package author update it to perhaps blend the generated theme together with your current theme, especially since it’s generating tmLanguage files and Sublime now supports sublime-syntax, which is easier to understand.

However that’s probably more of a long term kind of goal, so in the interim it’s probably still a good idea to manually integrate things together.

For a little background on what’s happening here, syntax highlighting in Sublime works with a couple of files taken together.

The first file is a syntax definition that allows Sublime to recognize key parts of the text so that it can highlight them as appropriate. The syntax definition is essentially an ordered list of regular expressions that match text and apply to them one or more scopes that classify what that text means.

The assigned scopes are used by a second file, the color scheme, which matches the scopes of text against rules that tell Sublime what color items with that scope should be rendered as, along with other instructions such as if it should be bold, italicized, etc.

The color scheme also includes a lot of other information, such as the normal background color, what color the selected text should be, and so on.

The following uses the results of choosing Synesthesia: New Highlighting Scheme from the command palette, saving it as Hello World.json and then compiling it with synesthesia. The original file gets saved in your User package and three other files are created.

The first is Hello World.tmLanguage which contains the rules that match text. This file is XML formatted and the interesting parts of it are the contents of the patterns key. Since the input file has two items it’s looking for, there are two items in the patterns array:

<dict>
    <key>match</key>
    <string>\broses\b</string>
    <key>name</key>
    <string>roses_0</string>
</dict>

<dict>
    <key>match</key>
    <string>\bviolets\b</string>
    <key>name</key>
    <string>violets_1</string>
</dict>

There is one <dict> for each of the rules in the input file, associating a regular expression (e.g. \broses\b) with a scope name (roses_0).

The second file is Hello World.tmTheme, which is the color scheme file that applies your custom colors. Like the language file, this is also an XML formatted file. The first parts of the file give the overall settings for the scheme in general (background color, selected text color, etc).

Following those settings are a series of items that say what color rules apply to each scope:

<dict>
    <key>name</key>
    <string>roses_0</string>
    <key>scope</key>
    <string>roses_0</string>
    <key>settings</key>
    <dict>

        <key>foreground</key>
        <string>#ff0000</string>

    </dict>
</dict>

<dict>
    <key>name</key>
    <string>violets_1</string>
    <key>scope</key>
    <string>violets_1</string>
    <key>settings</key>
    <dict>

        <key>foreground</key>
        <string>#0000ff</string>

    </dict>
</dict>

These rules match the scope from the language (roses_0) to a color specification (#ff0000), so there will be one for each of the matches in the syntax file.

The last file is a settings file, Hello World.sublime-settings. Unlike the other two files, this file is JSON:

{
    "color_scheme": "Packages/User/Hello World.tmTheme",
    "extensions": ["txt", "md"]
}

This file is some “glue” that ties everything together. It’s saying that any files with the extension txt or md should use a different color scheme than the usual one, so that when you open one of those files the custom color scheme is used.

With all of that said, to do what you want one of two things has to happen:

  • Copy the overall settings from your normal tmTheme and replace the overall settings in the generated theme. Overall settings are the section at the top that spell out what the background color and so on should be. For example, for the Sixteen theme that ships with Sublime, that would look like this:
<dict>
    <key>settings</key>
    <dict>
        <key>background</key>
        <string>#000000</string>
        <key>caret</key>
        <string>#9F9F9F</string>
        <key>foreground</key>
        <string>#DEDEDE</string>
        <key>invisibles</key>
        <string>#343434</string>
        <key>lineHighlight</key>
        <string>#2A2A2A</string>
        <key>selection</key>
        <string>#424242</string>
    </dict>
</dict>

If you do this, the theme that Syntesthesia generates will still be used, but now everything about it will appear to be identical to other files, except that now it has the ability to apply your custom highlighting rules (but only your custom rules, although that’s not a big deal).

  • Copy all of the match rules from the generated tmTheme file and add them to your normal theme. That would be the parts that look like this:
<dict>
    <key>name</key>
    <string>roses_0</string>
    <key>scope</key>
    <string>roses_0</string>
    <key>settings</key>
    <dict>

        <key>foreground</key>
        <string>#ff0000</string>

    </dict>
</dict>

If you do this, you need to open that sublime-setting file that Synesthesia generated and remove the color_scheme line, because now your normal theme knows how to highlight your new rules automatically (along with all the others).

Of the two, I would recommend the first one. Partially that’s because there is far less to copy and paste, and partially because modifying your usual theme is not necessarily a good idea. Although it will work, if the original theme author ever updates the theme, at worst your changes might get clobbered away and at best you won’t see any changes. Depending on the frequency of updates that may or may not be a problem.

Whichever way you go, every time you modify the input json file and rebuild the language, you will need to perform the same steps again as you did the first time. That may or may not be a recommendation for doing it the way that seems like less work. :wink:

2 Likes

#3

This is an excellent answer. Thank you. Especially for taking the time to explain at the level of a basic user. I’m going to give it a try and report back.

0 Likes