Sublime Forum

Creating a syntax definition for an embedded language

#1

I’d like to write a syntax definition for a JS template compiler I wrote. It emulates Razor syntax, and is called Vash. It’s available: https://github.com/kirbysayshi/vash

As an example, this is what a snippet of Vash (Razor code in JS) would look like:

<table>
@model.blank_order_items.forEach(function(item){
	<tr>
		<td class="item-color">@item.color[0].long_value</td>
		<td class="item-size">@item.size[0].long_value</td>
		<td class="item-type">@item.type[0].long_value</td>
		<td class="item-quantity">
			@if( item.status !== 'consumed' ){
				<input name="item-quantity-@item.id" type="text" value="@item.quantity" maxlength="5" size="6" />	
			} else {
				@item.quantity
			}
		</td>
		<td class="item-price">$@item.unit_price</td>
		<td class="item-status">@(item.status === 'consumed' ? 'In Inventory' : 'Outstanding')</td>
	</tr>
})
</table>

As you can see, it’s main trigger character is the @ symbol, and then is just a combination of HTML and JS.

I’d like to make a syntax definition for it to enable syntax highlighting, but have never done so for Sublime or Textmate. Typically JS templates are separate files, but often they are included inside of HTML source, contained within script tags, like so:

<script type="text/tpl-vash">
	<input type="hidden" name="order-id" value="@model.id" />

	<div class="row-fluid">
		<div class="span4">
			<h3 class="order-id">ORDER #: @model.id</h3>
		</div>
	</div>
</script>

So the question is, how do you create a syntax file that can be active on a buffer, but only for a portion? I wouldn’t want to have to make several syntax files, one for each language you could have this embedded in… for example: HTML (Vash), PHP (Vash), etc. Would this be handled by something like the ‘include’ directive as explained here: http://sublimetext.info/docs/en/extensibility/syntaxdefs.html?

Is this something that can be done, or will the user have to explicitely set their buffer syntax to HTML (Vash) etc?

0 Likes

#2

I think the easiest way to handle all cases would be to edit the default HTML.tmLanguage file by adding syntax definitions for Vash.

You could also create a new HTML (Vash).tmLanguage file based on the default HTML.tmLanguage file. In this case the user would only have to change the buffer’s syntax once as Sublime will remember the selection.

0 Likes

#3

Do it like the HTML language does. Create a separate syntax file with all of your Vash tmLanguage stuff in it, and simply use the #include key like is done for javascript and other languages. You will have to modify the HTML tmLanguage, but only to add an embedded code entry for Vash.

0 Likes

#4

You can also do what @facelessuser suggests but I think it’s better to include the text.html.basic in your own definition so you won’t have to edit the HTML.tmLanguage file which will get over-written when users update Sublime.

0 Likes

#5

There’s one other tricky bit, and that is that Vash is really just a combination of javascript + html with a few special characters to tell between the two. I was hoping to be able to use the JavaScript and HTML tmLanguages to handle that, so I wouldn’t have to reimplement.

Ideally, I would want the user to not have to worry about switching buffer syntaxes, and thus Vash would be an include referenced from HTML.tmLanguage. But I assume that it’s pretty difficult to get something like that added into the trunk code. I would still want snippets and everything else to function properly, which might not if the main buffer is set to Vash (a lot more things to handle?).

I’m really new at this, so my assumptions might be totally off. Maybe a better place to start is to just get syntax highlighting working for Vash, and then worry about where to put it.

0 Likes

#6

[quote=“kirbysayshi”]There’s one other tricky bit, and that is that Vash is really just a combination of javascript + html with a few special characters to tell between the two. I was hoping to be able to use the JavaScript and HTML tmLanguages to handle that, so I wouldn’t have to reimplement.

Ideally, I would want the user to not have to worry about switching buffer syntaxes, and thus Vash would be an include referenced from HTML.tmLanguage. But I assume that it’s pretty difficult to get something like that added into the trunk code. I would still want snippets and everything else to function properly, which might not if the main buffer is set to Vash (a lot more things to handle?).

I’m really new at this, so my assumptions might be totally off. Maybe a better place to start is to just get syntax highlighting working for Vash, and then worry about where to put it.[/quote]

HTML and JS Completions use the current scope regardless if it’s embedded. If you would rather users not have to switch grammar you will need to add the syntax to the HTML.tmLanguage file if VASH uses the html file extension. I’m not familiar with VASH enough but I would still suggest you create a new grammar file since once you change the syntax for the current file Sublime will remember the setting. So it would only have to be changed once and this prevents you from having to change the default HTML.tmLanguage file that could get over-written during an update.

Something like this HTML (Vash).tmLanguage

header stuff filetype html etc...
...

<key>begin</key>
<string>(vash regex start js string)</string>
<key>end</key>
<string>(vash regex end js string)</string>
... use beginCaptures endCaptures for scoping here
<key>patterns</key>
<array>
<dict>
<key>include</key>
<string>source.js</string>
</dict>
<dict>
<key>include</key>
<string>text.html.basic</string>
</dict>
</array>
...
<key>include</key>
</string>text.html.basic</string>

I’m pretty sure if you play with the tmLanguage file a while you’ll get it working just as you like. GL HTH

0 Likes

Python syntax - import/from
#7

Thanks, atomi!

I’ll start playing…

0 Likes