0

I am the author and maintainer of WoW Bundle for Visual Studio Code.

In Blizzard's World of Warcraft API, many constants like events names, widgets scripts handlers or certain function parameters are strings. Those strings can be single- or double-quoted and some (not all) of them are case-insensitive. For example:

local myFrame = CreateFrame('Button', nil, UIParent)
myFrame:SetPoint('CENTER', 0, 0)
MyFrame:RegisterEvent('PLAYER_ENTERING_WORLD')
myFrame:SetScript('OnEvent', myEventHandler)

To scope those special strings in my tmLanguage file, I declare them in a repository:

<!-- This is only an excerpt, there are many more of these :) -->
<key>repository</key>
<dict>
    <key>string-parameters</key>
    <dict>
        <key>match</key>
        <string>(?i)(Button|Frame|Slider|StatusBar|TOP|LEFT|BOTTOM|RIGHT|BACKGROUND|ARTWORK|LOW|MEDIUM|HIGH)</string>
        <key>name</key>
        <string>support.constant.wow.parameter.lua</string>
    </dict>
    <key>event-names</key>
    <dict>
        <key>match</key>
        <string>(PLAYER_ENTERING_WORLD|ADDON_LOADED)</string>
        <key>name</key>
        <string>support.constant.wow.event.lua</string>
    </dict>
    <key>script-handlers</key>
    <dict>
        <key>match</key>
        <string>(OnLoad|OnShow|OnEvent)</string>
        <key>name</key>
        <string>support.constant.wow.hander.lua</string>
    </dict>
</dict>

and I include them inside a surrounding scope:

<dict>
    <key>name</key>
    <string>support.constant.wow.quoted.single.lua</string>
    <key>begin</key>
    <string>'</string>
    <key>beginCaptures</key>
    <dict>
        <key>0</key>
        <dict>
            <key>name</key>
            <string>punctuation.definition.constant.begin.lua</string>
        </dict>
    </dict>
    <key>end</key>
    <string>'</string>
    <key>endCaptures</key>
    <dict>
        <key>0</key>
        <dict>
            <key>name</key>
            <string>punctuation.definition.constant.end.lua</string>
        </dict>
    </dict>
    <key>patterns</key>
    <array>
        <dict>
            <key>include</key>
            <string>#string-parameters</string>
        </dict>
        <dict>
            <key>include</key>
            <string>#event-names</string>
        </dict>
        <dict>
            <key>include</key>
            <string>#script-handlers</string>
        </dict>
    </array>
</dict>

Of course, I have two of these blocks (one for single quotes, one for double quotes) and they are declared before the regular strings blocks to make sure they take precedence.

So, this works... almost.

In declarations like:

local myFrame = CreateFrame(' Frame ', nil, UIParent)  -- Notice the spaces around Frame

or, worse:

local myFrame = CreateFrame('Frame Type That Does Not Exist', nil, UIParent)

the whole string is still parsed as valid (as it contains the word Frame from the #string-parameters repo) when it should obviously not.

How do I make sure that only one word, without spaces around, from the repositories is matched? I tried modifying the regexes in many ways but to no avail.

  • Due to the lack of answers :) I finally took an other path and managed to properly colorized my string. I'll leave the question open for any one to eventually provide an answer. – Stephan Schreiber Oct 15 '16 at 15:20

1 Answers1

0

I believe there is a mistunderstanding here. Rules are matched in the order they are defined, with later rules overriding the exiting style if they match the same string (part) as an earlier rule. Hence, try to reorder your rules such that the more general comes first (the string rule) and after that the colorization of your keyword rules.

Btw, did you know you can also use JSON to define your rules, which is much easier to read than XML? For instance see my syntax file here.

Mike Lischke
  • 48,925
  • 16
  • 119
  • 181