Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Combining Syntax Definitions in SublimeText2

I want to write a syntax definition file for Sublime Text 2 for the Find Results that respects the file extensions for each place it finds the searched for term. The documentation mentions that "Syntax definitions from separate files can be combined" but does not mention how.

Does anyone have any examples of how that works? An answer to this question: Sublime Text 2: Setting file syntax inside the file itself (as Vim modelines) would work also.

EDIT

Ok, so tip one from a friend: http://manual.macromates.com/en/language_grammars

That uses the 'include' tag with a name to reference another language. That would work for me, but unfortunately I'd need to write a plugin to re-compile the file every time Sublime Text opened and re-write it with the various language extensions...Any chance y'all have a better idea?

like image 682
Chris Pfohl Avatar asked Sep 21 '12 15:09

Chris Pfohl


1 Answers

Recently, I obsessively tricked out my ST2 CSS syntax highlighting. My understanding of these *.tmLanguage files is based on trial and error--mostly error. I mention this to note my grasp is spotty, at best.

I think the file you want to modify is ~/Library/Application Support/Sublime Text 2/Packages/Default/Find Results.hidden-tmLanguage

Long story short, I think you want to set it up like this gist (which has liberal commenting):

https://gist.github.com/4333623#file-find-results-hidden-tmlanguage

A typical Find in files results will look something like this:

Searching 11 files for "feedback-assistance-form" (regex)

/_projects/___/group_reg.js:
   60       });
   61  
   62:      $asstForm = $help.find('#feedback-assistance-form');
   63  
   64       if (!$asstForm.length) {
   65:          console.log('WARN: Feedback assistance: #feedback-assistance-form not found');
   66           return;
   67       }

/_projects/___/group_register_help_tmpl.html:
    6  <div id="group-reg-help">
    7  
    8:  <form id="feedback-assistance-form" class="js-popover help-content hide" action="{% url info.views.assistance_request %}" method="post">
    9       
   10       <legend>Need Assistance?</legend>

3 matches across 2 files

The Find Results.hidden-tmLanguage parses the results into 3 relevant parts:

  • The line with the filename
  • An excerpted line without a match
  • An excerpted line with a match

The rules for this are in the <patterns> section:

<key>patterns</key>
<array>
    <dict>
        <key>match</key>
        <string>^([^ ].*):$</string>
        <key>captures</key>
        <dict>
            <key>1</key>
            <dict>
                <key>name</key>
                <string>entity.name.filename.find-in-files</string>
            </dict>
        </dict>
    </dict>
    <dict>
        <key>match</key>
        <string>^ +([0-9]+) </string>
        <key>captures</key>
        <dict>
            <key>1</key>
            <dict>
                <key>name</key>
                <string>constant.numeric.line-number.find-in-files</string>
            </dict>
        </dict>
    </dict>
    <dict>
        <key>match</key>
        <string>^ +([0-9]+):</string>
        <key>captures</key>
        <dict>
            <key>1</key> <!-- capture group 1 -->
            <dict>
                <key>name</key>  <!-- name it so it can be colored -->
                <string>constant.numeric.line-number.match.find-in-files</string>
            </dict>
        </dict>
    </dict>
</array>

These just go through the file, line-by-line, and look for a match. If a match is found, one or more <key>name</key> definitions are applied to the capturing group(s) of the match, if there are any. These name definitions are referenced in the theme definition file (for instance, Monokai) and the color is applied to the characters matched by the named capturing group.

The patterns above are just matches with capturing groups. I think a limitation of this is the match (or it's capturing groups) can't be further processed.

What's applied in the gist are patterns of the format:

<key>patterns</key>
<array>
    <dict>
        <key>begin</key>

<!-- add the filetype extensions, here -->
<!-- these are XML formatted files: -->

        <string>^([^ ].*\.(?:xml|tmLanguage|hidden-tmLanguage|tmTheme):)$</string>
        <key>beginCaptures</key>
        <dict>
            <key>1</key>
            <dict>
                <key>name</key>
                <string>entity.name.filename.find-in-files</string>
            </dict>
        </dict>
        <key>end</key>
        <string>^[^ ]</string>
        <key>patterns</key>
        <array>
            <dict>
                <key>include</key>
                <string>#line-numbers</string>
            </dict>
            <dict>
                <key>include</key>


<!-- which syntax should match up to the filetype extensions listed above: -->
<!-- to find out what the "scopeName" is, refer to the corresponding *.tmLanguage file -->
<!-- for XML, this is ~/Library/Application Support/Sublime Text 2/Packages/XML/XSL.tmLanguage -->

                <string>text.xml</string>
            </dict>
        </array>
    </dict>
    <!-- ... can have many more -->
</array>

The main thing with this type of pattern is it has a <begin> and an <end>, then it has it's own <pattern> section. When the <begin> regex is matched, the contents of <patterns> are applied until (this is where I get really spotty) an unmatched token is encountered, at which point the <end> is tested. I think.

In any event, the gist defines several of these begin-end-patterns blocks, one for each XML, HTML, JavaScript and CSS file types and syntaxes. The <being> regex matches the line with the filename and a particular file extension. This is used to create the start of the "context" for a given syntax. The context ends when elements in the subsequent <patterns> block stop matching and the <end> regex matches. I think you will basically just want to flesh this out for whichever syntaxes you want to highlight in find results...

Here is a screenshot of the syntax-highlighted find results I am getting using that gist:

Blingwear

I should note, a big issue I encountered is when a block-comment starts in an excerpt but the excerpt doesn't include the characters that end the block-comment. The block-comment just continues until the terminating token is encountered somewhere else in the find results. This extends into subsequent searches, as well.

Update:

I meant to add that you shouldn't need to recompile anything on startup. Although, it's worth mentioning that you have to restart sublime for the changes in Find Results.hidden-tmLanguage to take effect. If you make this a plugin of some sort, seems like changes would primarily consist of adding new languages, which could just be an infrequent plugin-update.

like image 79
tiffon Avatar answered Oct 22 '22 08:10

tiffon