83

Is there a way to extend the supported languages/grammars in Visual Studio Code? I'd like to add a custom language syntax, but I've not been able to find any information on how language services are provided.

Can anybody point to any references or even examples of existing language implementations?

Gama11
  • 31,714
  • 9
  • 78
  • 100
Rick Strahl
  • 17,302
  • 14
  • 89
  • 134

5 Answers5

100

It's possible with the new version 0.9.0. There's an official documentation on how to add a custom language: https://github.com/microsoft/vscode-docs/blob/main/release-notes/v0_9_0.md

You need a .tmLanguage file for the language you want to add. You can find existing files e.g. on GitHub or you can define your own language file. Look here to get an idea of how to create one: http://manual.macromates.com/en/language_grammars

After finding a .tmLanguage file you have two ways to create an extension based on it.

Option 1: Using a Yeoman generator

  • Install node.js (if you haven't already done)
  • Install yo (if you haven't already done) by executing npm install -g yo
  • Install the Yo generator for code: npm install -g generator-code
  • Run yo code and select New language support
  • Follow the instructions (define the .tmLangauge file, define the plugin name, file extensions etc.)
  • The generator creates a directory for your extension with the name of the plugin in your current working directory.

Option 2: Create the directory on your own

  • Create a directory with the name of your plugin (only lowercase letters). Let's say we call it mylang.

  • Add a subfolder syntaxes and place the .tmlanguage file inside of it

  • Create a file package.json inside the root of the extension folder with content like this

     {
         "name": "mylang",
         "version": "0.0.1",
         "engines": {
             "vscode": ">=0.9.0-pre.1"
         },
         "publisher": "me",
         "contributes": {
             "languages": [{
                 "id": "mylang",
                 "aliases": ["MyLang", "mylang"],
                 "extensions": [".mylang",".myl"]
             }],
             "grammars": [{
                 "language": "mylang",
                 "scopeName": "source.mylang",
                 "path": "./syntaxes/mylang.tmLanguage"
             }]
         }
     }
    

Finally add your extension to Visual Studio Code

Copy the extension folder to the extension directory. This is:

  • on Windows %USERPROFILE%\.vscode\extensions

  • on Mac/Linux $HOME/.vscode/extensions

Restart Code. Now your extension will run automatically everytime you open a file with the specified file extension. You can see the name of the used plugin in the down right corner. You can change it by clicking on the name of the extension. If your extension is not the only one registered for a specific file extension then Code may chooses the wrong one.

kjhughes
  • 106,133
  • 27
  • 181
  • 240
Wosi
  • 41,986
  • 17
  • 75
  • 82
  • 1
    I'm getting a languageFileName is not defined error. Ever seen that one? – SC_Chupacabra Feb 05 '16 at 16:51
  • 4
    It could be noted, that the `scopeName` has to be the same as in the `.tmLanguage`-file – BadAtLaTeX May 01 '17 at 15:19
  • 3
    If I write a language support for an already supported language, what should I do to make sure Code uses my extension and disables *the feature only* of the other? – joulev Sep 15 '19 at 14:56
  • How can we define a new extension (e.g. `.mylang`) which is based on an already existent syntax (let's say HTML files), but has some differences? E.g. I would like to define a custom syntax for HTML template files, for this I want to create a new `.mylang` extension for my files. These files would contain HTML + some constructs added by this template language (`.mylang`, e.g. keywords for loops, interpolations, etc...). How can we achieve this? Thank you! – tonix Oct 03 '20 at 22:05
  • 1
    Where and how do we change the colors for the syntax highlighters? All I've found was information on editor.tokenColorCustomizations but this is apparently not allowed in settings.json for individual languages "This setting does not support per-language configuration." – MaxRocket Jan 06 '22 at 22:34
13

To extend Wosi's .tmLanguage answer, using a .tmLanguage file is optional. Using a regular .json is a perfectly valid and—in my opinion—better readable alternative.

For an example, see VSCode_SQF: sqf.json

Inside the package.json, you would only need to change the path from ./syntaxes/mylang.tmLanguage to ./syntaxes/mylang.json.

Michael
  • 8,362
  • 6
  • 61
  • 88
Armitxes
  • 183
  • 1
  • 10
  • 6
    You might also see the file extension as `.tmLanguage.json`. I'm not sure about more readable, but you can include this schema to get intellisense when writing your language json: ```{ "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json", "name": "mylang", ...``` – aamarks Jun 23 '19 at 15:42
7

Using reverse engineering you can add a new language to VSCode. You can take a look on how typescript is implemented as a JavaScript plugin and how it communicates with node.exe via pipe. But it's a hard thing since it's coming all without documentation I'll provide a really short documentation here:

You can define a new plugin in the plugins folder C:\Users\USER\AppData\Local\Code\app-0.3.0\resources\app\plugins.

Copy the typescript plugin folder and rename mentioned file extensions and language names in all files to your new language, so that your new plugin is going to be used when a .mylang file is opened.

In typescriptServiceClient.js you see that a child process is being forked and that its stdout is coupled to a new WireProtocol.Reader. Bind your own mylanguage.exe (you'll probably need to write that exe on your own). VSCode asks that binary to get more language specific information.

In typescriptMain.js you find the feature registration for the language. Delete every call to monaco.Modes.XXXXXXSupport.register except monaco.Modes.DeclarationSupport.register.

Now open a directory in VSCode that contains .mylang files and open one of them via CTRL+P + FileName. Right click on an identifier and select Go to Definition. VSCode sends now a request like this via StdIn to your exe

{"seq":1,"type":"request","command":"definition","arguments":{"file":"d:/Projects/MyProj/Source/MyFile.mylang","line":45,"offset":9}}

VSCode expects an answer like this:

Content-Length: 251
[LINE BREAK]
{ "seq" : 1, "type" : "response", "command" : "definition", "request_seq" : 1, "success" : true, "body" : [{ "file" : "d:/Projects/MyProj/Source/MyOtherFile.mylang", "start" : { "line" : 125, "offset" : 3 }, "end" : { "line" : 145, "offset" : 11} }] }

If everything works VSCode will open MyOtherFile.mylang and set the cursor to line 124 in column 3.

Try it on your own ;-)

Wosi
  • 41,986
  • 17
  • 75
  • 82
5

Simplest recipe IMHO as of 2021 Q2:

  1. Follow Option 2 in Wosi's answer. You only need two files to get started. Just create the folder structure directly in your extensions directory.
    • Set "path": "./syntaxes/your_language.plist" in package.json
  2. Use IRO to build your regexes.
    • Make sure that in the "Scope Information" screen, anything to do with Textmate is green. Don't worry about the other editors.
    • Save the contents of the "Textmate" tab into the path above, i.e., .syntaxes/your_language.plist
  3. Reload VSCode

That's it. I also save the IRO (left pane) text into my own project.

Leo
  • 2,775
  • 27
  • 29
  • 1
    IRO is fantastic, thanks for the tip! Now, how is it possible to add simple intellisense for a custom language? _word based completions_ as they call it. – Daniel Lidström Sep 13 '21 at 08:33
  • @DanielLidström Is it safe to visit IRO site? I'm getting potential security risk warning for that site. – usmanharoon Oct 15 '22 at 07:28
4

You can read the source code of the built-in language extensions online:

https://github.com/microsoft/vscode/tree/main/extensions

You can pick an extension that is close to your language's syntax and change it as you wish. (e.g. you can do some modifications to the JavaScript extension and rebrand it for use with jQuery!)

It is important to note that this would be too much work if you choose a language that is so different from your desired language! If you didn't manage to find a language that is similar to your desired language, you may want to create a whole new extension from the ground up - https://stackoverflow.com/a/32996211/14467698 -.

0xENDER
  • 81
  • 1
  • 10