Sublime Forum

Sublime syntax creation question

#1

Hello, I made a file with these contents and get an error message when loading it:

https://ibb.co/MMgWLq1

I’m creating a syntax file for something that is mostly JavaScript but will allow to write html in it also with HTML syntax highlighting so I used that extends option, is that the best way to do it?

Also are there any other good resources for someone new to creating the syntax files other than the documentation at sublimetext.com/docs/syntax.html?

0 Likes

#2

Btw, you don’t have to upload an image to another website as it can be uploaded on this forum directly. The error msg ask you to add version: 2 to your syntax def as it’s used in JS syntax, which you inherit from.

I used that extends option, is that the best way to do it?

I think it depends on your language specs. How do you know it’s JS now, or it’s HTML now?

0 Likes

#3

The extends keyword works pretty much like class inheritance in C++ or Java. It would be the most appropriate approach to add features to an existing syntax. The downside is, your syntax may break if the extended (JavaScript) syntax is changed by an update.

A syntax, which extends another one (in other words: “is inherited from the other one”) also knows about all its contexts. You can prepend/append patterns to each kontext via meta_prepend or meta_append directive.

You could have a look into ST’s JSX syntax to learn how to extend JavaScript to add additional patterns and/or contexts. JSX extends JS with contexts/patterns to scope XML like react tags. JavaScript is not a simple syntax though.

Unfortunatelly there are no books or tutorials which provide some strategic knowledge about how to start with the more sophisticated parts of writing good syntax definitions.

0 Likes

#4

I used this sublime-syntax to get it to highlight like the image below. How would it be possible to highlight between @# and #@ as HTML?

%YAML 1.2
---
# See http://www.sublimetext.com/docs/syntax.html
name: IJS
file_extensions: [ijs]
scope: source.ijs
contexts:
  main:
    - match: ''
      push: Packages/JavaScript/JavaScript.sublime-syntax
      with_prototype:
        - match: (@#)
          push: expr
  expr:
    - match: (#@)
      pop: true

Also I tried using what is below and I didn’t get the error I mentioned earlier anymore but it didn’t seem to highlight the text as JavaScript.

%YAML 1.2
---
# See http://www.sublimetext.com/docs/syntax.html
name: IJS
file_extensions: [ijs]
scope: source.ijs
extends: Packages/JavaScript/JavaScript.sublime-syntax
version: 2
contexts:
  main:
    - match: ''
      scope: 'test.test.test'

I don’t find it possible to learn how to create these from the /docs/syntax.html page alone and there isn’t any other documentation. It would be helpful if there were more examples and possibly visual demonstrations of how each command works, possibly with video tutorials. I was able to stitch together the code at the top of this post that highlights JavaScript from just copy pasting the example code and editing it but I really don’t understand how with_prototype and other commands in it work.

Also if there are any Sublime Text developers reading this would it be possible to use JSON instead of YAML? Because YAML is white space sensitive and also you cannot use tabs, must use spaces that are 2 or 4 which is unnecessary and could make it harder to work with if errors come up when creating things with it. And I was having some issues while using Regex in YAML which I figured out later is because if you don’t put them in quotes it can lead to errors, whereas JSON that could have been avoided. More people already know JSON and it is used in other parts of Sublime Text like the Settings.

0 Likes

#5

If your identifiers are special enough, you can use embed to achieve that. It SIMPLY extracts anything between match and escape and then delegate it to the target syntax.

%YAML 1.2
---
# See http://www.sublimetext.com/docs/syntax.html
name: IJS
file_extensions: 
  - ijs
version: 2
scope: source.ijs
contexts:
  main:
    - match: ''
      push: scope:source.js
      with_prototype:
        - match: "@#"
          scope: punctuation.definition.embedded.begin.ijs
          embed: scope:text.html.basic
          embed_scope: meta.embedded.html.ijs
          escape: "#@"
          escape_captures:
            0: punctuation.definition.embedded.end.ijs

Or, if your identifiers are not that special, you can do it in a maybe safer way. p.s.: embed is preferred whenever possible.

  main:
    - match: ''
      push: scope:source.js
      with_prototype:
        - match: "@#"
          scope: punctuation.definition.embedded.begin.ijs
          push:
            - meta_scope: meta.embedded.html.ijs
            - match: "#@"
              scope: punctuation.definition.embedded.end.ijs
              pop: 1
            - include: scope:text.html.basic

And I was having some issues while using Regex in YAML which I figured out later is because if you don’t put them in quotes it can lead to errors

https://packagecontrol.io/packages/PackageDev is your friend.

Also, maybe both of

Also if there are any Sublime Text developers reading this would it be possible to use JSON instead of YAML?

I don’t think it will happen. If it will, it should happen back to before Jon invented .sublime-syntax. And… I don’t won’t to count how many \ there are in JSON.

0 Likes

#6

That worked, thanks. I was thinking of some way to make the documentation better so that I could learn how to write the sublime-syntax files and other types of things in the documentation. It would be helpful if the creators of Sublime Text could have people who know how it works write an article in their words and possibly with screenshots visually how it works / parts of it work and it could be linked in the documentation. At the top of the article there could be a notice with when it was written and for what version and it may not be fully compatible in the future but would still help a lot to teach people the different concepts of how they work in different words and styles. It would be like user generated content articles where the purpose is to explain how parts of the documentation work in different ways that helped them learn how it worked and they think maybe other people learn in a similar way.

Also in the documentation possibly there could be a link to where you can ask questions about this specific topic where there is an archive of forum questions like these organized in one place, like at the top of /docs/syntax.html you can hit a link to create a forum post and it will be in Plugin Development but also have a tag so it know it is a question related to developing syntax definitions and /docs/syntax.html and they are organized in one place for people learning how to create them to read the forum post questions / answers to learn more about the topic.

I think with these 2 techniques it could improve the documentation a lot.

0 Likes

#8

I’m making something for Node.js that allows it to work like PHP. Is there anything I can do to make it highlight if the file starts with HTML like this one and also for the first <? tag to display like the others?

%YAML 1.2
---
# See http://www.sublimetext.com/docs/syntax.html
name: 'IJS'
version: 2
file_extensions: ['ijs']
scope: 'source.ijs'
contexts:
  main:
    - match: ''
      push: 'scope:source.js'
      with_prototype:
        - match: '\?>'
          scope: 'punctuation.definition.embedded.begin.ijs markup.bold'
          embed: 'scope:text.html.basic'
          embed_scope: 'meta.embedded.html.ijs'
          escape: '<\?'
          escape_captures:
            0: 'punctuation.definition.embedded.end.ijs markup.bold'

I was thinking of flipping it around so it is embedding JS in HTML but then this happens, in that case is there a way to make it so it doesn’t highlight the ([{}]) brackets as errors?

<?

var fs = require('fs')
var util = require('util')
var http = require('http')
var url = require('url')

http.createServer(function(req, res){
	req.parsed_url = url.parse(req.url, true)
	req.pathname = req.parsed_url.pathname
	req.query = req.parsed_url.query
	req.ip = req.socket.remoteAddress
	// req.method contains request method

	res.writeHead(200, {
		'Content-Type': 'text/html'
	})

	// include './header.ijs'
	if (req.pathname == '/') {
		// include './index.ijs'
?>
<div>
<?
	}
	if (req.pathname == '/products') {
		// include './products.ijs'
	}
	// include './footer.ijs'

	res.end()
}).listen(80)

?>

<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<style>
body {
	font: 10pt Arial;
}
a {
	color: blue;
}

</style>
<script type='text/javascript'>
</script>
</head>
<body>

<div style='background-color: lightblue;'>Header</div>

<div>
<span>
<a href='/'>Home</a>
<a href='/products'>Products</a>
</div>

<?

function test1 () {
	function test2 () {
	}
	test2()
}
test1()

?>
0 Likes