Create Custom Language in Visual Studio Code - visual-studio-code

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?

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.

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.

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 ;-)

Simplest recipe IMHO as of 2021 Q2:
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
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
Reload VSCode
That's it. I also save the IRO (left pane) text into my own project.

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 -.

Related

VSCode extension authoring: How to get a file extension from a languageId?

I'm authoring a VSCode extension and want to create a file in my extension's context.globalStorageUri with a languageId appropriate file extension. For example, given languageId = 'javascript' a valid file extension would be .js.
I would prefer to get the information through vs code's APIs rather than a separate npm language to extension mapping package since users may have unknown languages and custom file extensions registered.
According to the docs https://code.visualstudio.com/docs/languages/identifiers, each
extension has its configuration specified in an extension specific package.json.
"languages": [{
"id": "java",
"extensions": [ ".java", ".jav" ],
"aliases": [ "Java", "java" ]
}]
I suppose one way would be to iterate through all extension's package.json files and find the "languages" tag, and apply vscode.workspace.getConfiguration("files.associations"); on top of it, but this seems cumbersome, invasive, and error prone.
Is there a more correct way to address this case?

Visual studio path configuration on Windows for LEAN theorem prover

I am trying to set up my VS Code environment to work with LEAN the automated theorem prover.
I set up a new project following the tutorial at here and have a file called test.lean, given as follows:
import data.real.basic
I get the following error:
invalid import: data.real.basic
could not resolve import: data.real.basic
The error message suggested I call lean --path, so I did, and obtained:
PS C:\Users\user\lean_test2> lean --path
{
"is_user_leanpkg_path": false,
"leanpkg_path_file": "C:\\Users\\user\\lean_test2\\leanpkg.path",
"path": [
"C:\\Users\\user\\.elan\\toolchains\\leanprover-community--lean---3.35.1\\bin\\..\\library",
"C:\\Users\\user\\.elan\\toolchains\\leanprover-community--lean---3.35.1\\bin\\..\\lib\\lean\\library",
"C:\\Users\\user\\lean_test2\\_target/deps/mathlib/src",
"C:\\Users\\user\\lean_test2\\./src"
]
}
I noticed the paths use a mix of / and \\, but I don't think this will be a problem. I checked the third entry in the paths list, and found that the following file
C:\Users\user\lean_test2\_target\deps\mathlib\src\data\real\basic.lean
does indeed exist. So, what might be going wrong?
I don't know exactly what the problem is, but you should usually either use the "open folder" feature in VScode to open the folder containing mathlib or open the folder containing a project depending on mathlib. There's also a leanproject global-install command you can use to globally install mathlib without having to open a folder in VScode, but I've never used this command myself.

WebdriverIO autocomplete in VSCODE

I am wonder, if it is way how to enable autocompletion for WDIO global variables ( $, $$, browser ) in VSCode. I know, that wdio has support for Webstorm, but it doesn't work for VSCode.
Any idea, how to use autocompletion in VSCode? Without it is pretty hard to create some tests.
I struggled with this as well. Firstly, ensure you've followed the "Autocompletion" Setup described on the website; for example, they require something like the following exist in a file called jsconfig.json at the root of your project:
{
"include": [
"**/*.js",
"**/*.json",
"node_modules/#wdio/sync",
"node_modules/#wdio/mocha-framework"
]
}
You may already have a jsconfig.json; if so, ensure that the node_modules directories are not in a section called "exclude": { ... }. When setting up other things like Babel (for mocha) this may get installed as a default configuration entry. When node_modules is in both include and exclude, exclude takes precedence.
I had zero success importing npm #types pacakges, adding typeAcquisition: {} to jsconfig.json, or adding interface browser; into the file global.d.ts as other people have suggested in various forums.
Auto completion is pre-installed on vs code. If it is not working you might want to check through extension and install. And to use, once the open tag is created, it often auto suggest, just do appropriately then input your attribute.

Get Visual Studio Code to look locally when no path is supplied

I have a statement like this:
var {ShipmentValidation} = require('ShipmentValidation');
In most projects I work on, I think this means look in my NPM packages for ShipmentValidation. (I usually use './ShipmentValidation' to indicate I need to look locally.)
But I am working on a project now (TestComplete) where I need the "no path" option to look in the local folder for the file. (Because I can't change how TestComplete works.)
Is it possible to configure VS Code to look for "non-path requires" in the local folder (same folder as the current file)?
Looks like I just needed to make a file called jsconfig.json and put this in it:
{
"compilerOptions": {
// This must be specified if "paths" is set
"baseUrl": "."
}
}

How to install typings for Visual Studio Code in an offline development environment?

I'm using VisualStudio Code, and trying to enable IntelliSense. It seems to be dependent on typings. How can I install these offline? In PowerShell, running
typings search leaflet
returned an error (unsurprising, because I'm offline).
Unable to connect to "https://api.typings.org/search?query=leaflet"
Running that web query on an online computer resulted in a difficult to read JSON file. A further google search resulted in this likely candidate:
https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/leaflet/index.d.ts
My question has three parts, and I'd appreciate pointers on any of these.
1) How can I figure out what typings I need?
2) Which files do I need to take to the offline computer? Do I just need the d.ts file?
2) Where should this file be installed so that VS Code can read it?
1) Simply put: if your Visual Studio Code is complaining about not being able to resolve something. Lets say I'm working with jQuery, I'm using $ a lot in my project and it's going to give me an error because it's not Typescript/JavaScript.
To resolve this, I create a JSON file to the root of my project called typings.json. It will look like this:
{
"resolution": "typings/",
"globalDependencies": {
"jquery": "github:DefinitelyTyped/DefinitelyTyped/jquery/index.d.ts"
}
}
Then in the Terminal tab (CTRL + SHIFT + <) execute the following command:
typings install
Now it will download the required typings and put the contents to root/typings/. You'll need to reference it in each file you're using (in this case) jQuery in by adding the following to the top of your TS file:
/// <reference path="./typings/globals/jquery/index.d.ts" />
You can also create a definition (.d.ts) file in the root/typings folder and add all the references there so you only have to reference that file.
2) After installing the typings in the previous step, you can copy the typings folder and put it on your offline computer. It's as easy as that. You don't need other files (not even the typings.json file, if you wish).
2) You need to reference definition (d.ts) files at the top of your .ts files.