Search code examples
sublime-text-pluginsublime-syntax

Auto-Complete Closing HTML Tags in Extended Syntax


I am currently developing a syntax highlighting plugin for a template engine of my own. The content in the files are based off of the standard HTML syntax highlighting normally seen in Sublime Text.

Accomplishing this was by all means not a problem:

...
contexts:
  main:
    - include: 'scope:text.html.basic'
...

As you can clearly see, the syntax highlighting is written using the (reasonably) new .sublime-syntax YAML. Highlighting the sections in the code I wanted to highlight, as well as highlighting certain sections with other programming languages was not a problem either.

What I cannot seem to figure out, however, is how to make the HTML tags 'auto-complete' the way they do when the syntax is set to regular HTML.

For instance, if the following is entered:

<html>

And then this is entered:

</

It would automatically resolve to the closing </html> tag (granted there is no other tag in between).

Does this go in another file? Perhaps some kind of "plugin definitions file"?

Any pointers in the right direction would be highly appreciated. From the research I have done so far, I cannot seem to find anything on the particular subject.


Solution

  • The command that does this is close_tag and is triggered with the following key binding:

    // HTML, XML close tag
    { "keys": ["/"], "command": "close_tag", "args": { "insert_slash": true }, "context":
        [
            { "key": "selector", "operator": "equal", "operand": "(text.html, text.xml) - string - comment", "match_all": true },
            { "key": "preceding_text", "operator": "regex_match", "operand": ".*<$", "match_all": true },
            { "key": "setting.auto_close_tags" }
        ]
    }
    

    The first context listed here requires the syntax of the file to be text.hml or text.xml but not while inside of a string or comment.

    When you include a scope as you're doing above, the scopes applied to the matched text are taken from the scope you include, but the top level scope is the one defined in your syntax definition.

    As such, if you check the scope by using the Tools > Developer > Show Scope Names command, you will probably see that the top level scope isn't text.html but something else (your syntax definition above doesn't say what that might be).

    If you duplicate the custom binding in your own package with a modified scope, it should do what you want.