diff --git a/README.md b/README.md
index e9a564fc..640bdd54 100644
--- a/README.md
+++ b/README.md
@@ -79,6 +79,38 @@ The recommended way to install Swarm at the moment is as follows:
tutorial](TUTORIAL.md) to help get you started. Eventually there
will be an in-game tutorial.
+
+Programming swarm
+=================
+
+Your base has a dictionary to store definitions, like this one:
+
+```
+def moveUntil : cmd bool -> cmd () = \predicate.
+ res <- predicate;
+ if res {
+ noop
+ } {
+ moveUntil predicate
+ }
+end
+```
+
+The indentation is not required but `;` is, as it is similar
+to Haskell `>>` - that is the command monad, which imperative
+programmers can ignore. :wink:
+
+
+This allows you to program robots to perform complicated tasks.
+
+While you can write commands and definitions like the one above
+in the REPL, swarm also has a editor support with highlighting
+and LSP integration:
+
+![Editor with problem popup](images/editor.png)
+
+See the `editors` folder for details on how to configure your editor.
+
Community
=========
diff --git a/TUTORIAL.md b/TUTORIAL.md
index 05463bae..255b4a35 100644
--- a/TUTORIAL.md
+++ b/TUTORIAL.md
@@ -393,7 +393,7 @@ than nothing for now.
There is some rudimentary [Language Server-based editor
support](https://github.com/byorgey/swarm/blob/main/docs/EDITORS.md)
giving syntax and error highlighting for `.sw` files; at the moment
-Emacs is supported, and VSCode will be added shortly.
+Emacs is supported along with VSCode.
World generation
----------------
diff --git a/docs/EDITORS.md b/docs/EDITORS.md
deleted file mode 100644
index e7e30825..00000000
--- a/docs/EDITORS.md
+++ /dev/null
@@ -1,20 +0,0 @@
-# Text Editor Configuration
-
-Validate a swarm-lang file using: `swarm format ./file.sw`
-
-Swarm comes with a language server protocol (LSP) server.
-Make sure the `swarm` program is present in your PATH, then
-configure your editor:
-
-* [Emacs](#EMACS)
-
-The current LSP implementation features the following extensions:
-
-* error diagnostic on load/save
-
-## EMACS
-
-Using [lsp-mode](https://github.com/emacs-lsp/lsp-mode):
-
-Load the [swarm-mode.el](../contribs/swarm-mode.el) and start
-the `M-x lsp` service in a *swarm-mode* buffer.
diff --git a/editors/README.md b/editors/README.md
new file mode 100644
index 00000000..65fcd4e1
--- /dev/null
+++ b/editors/README.md
@@ -0,0 +1,35 @@
+# Text Editor Configuration
+
+Validate a swarm-lang file using: `swarm format ./file.sw`
+
+Swarm comes with a language server protocol (LSP) server.
+Make sure the `swarm` program is present in your PATH, then
+configure your editor.
+
+## EMACS
+
+The current LSP implementation features the following extensions:
+
+* error diagnostic on load/save
+
+Using [lsp-mode](https://github.com/emacs-lsp/lsp-mode):
+
+Load the [swarm-mode.el](../contribs/swarm-mode.el) and start
+the `M-x lsp` service in a *swarm-mode* buffer.
+
+## VS Code and VS Codium
+
+The [swarm-lang](./vscode) extension provides highlighting and an
+LSP client. That is if you have `swarm` executable in PATH, then
+the executable will be used as LSP server to show errors as you type.
+
+You can get it by:
+- installing from MS marketplace ([link](https://marketplace.visualstudio.com/items?itemName=xsebek.swarm-language))
+- building from source in the [vscode folder](./vscode/DEVELOPING.md)
+- **TBD** get the VSIX from GitHub releases
+- **TBD** installing from the VS codium free marketplace
+
+## Vim and Neovim
+
+Currently there is neither highlighting nor LSP support for Vim,
+but we would be happy to [accept a contribution](../CONTRIBUTING.md).
\ No newline at end of file
diff --git a/contribs/swarm-mode.el b/editors/emacs/swarm-mode.el
similarity index 100%
rename from contribs/swarm-mode.el
rename to editors/emacs/swarm-mode.el
diff --git a/editors/vscode/.gitignore b/editors/vscode/.gitignore
new file mode 100644
index 00000000..507b6fdb
--- /dev/null
+++ b/editors/vscode/.gitignore
@@ -0,0 +1,4 @@
+node_modules
+*.vsix
+*-lock.json
+out/
diff --git a/editors/vscode/.vscode/launch.json b/editors/vscode/.vscode/launch.json
new file mode 100644
index 00000000..0e191b59
--- /dev/null
+++ b/editors/vscode/.vscode/launch.json
@@ -0,0 +1,17 @@
+// A launch configuration that launches the extension inside a new window
+// Use IntelliSense to learn about possible attributes.
+// Hover to view descriptions of existing attributes.
+// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
+{
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "Extension",
+ "type": "extensionHost",
+ "request": "launch",
+ "args": [
+ "--extensionDevelopmentPath=${workspaceFolder}"
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/editors/vscode/.vscodeignore b/editors/vscode/.vscodeignore
new file mode 100644
index 00000000..c2e45c2f
--- /dev/null
+++ b/editors/vscode/.vscodeignore
@@ -0,0 +1,4 @@
+.vscode/**
+.vscode-test/**
+.gitignore
+DEVELOPING.md
diff --git a/editors/vscode/CHANGELOG.md b/editors/vscode/CHANGELOG.md
new file mode 100644
index 00000000..7927e51b
--- /dev/null
+++ b/editors/vscode/CHANGELOG.md
@@ -0,0 +1,19 @@
+# Change Log
+
+All notable changes to the "swarm-language" extension will be documented in this file.
+
+## version 0.0.3
+
+- [Highlighter] Update reserved word list (include `drill`, `has`, etc.)
+- [Highlighter] Recognize sum types (`a + b`)
+- [Highlighter] Recognize explicit `forall a b.`
+- moved the package to `byorgey/swarm` repository
+- added a logo (featuring base and four robots)
+
+## version 0.0.2
+
+- Add LSP integration (requires `swarm` executable).
+
+## version 0.0.1
+
+- Initial release with support for higlighting
\ No newline at end of file
diff --git a/editors/vscode/DEVELOPING.md b/editors/vscode/DEVELOPING.md
new file mode 100644
index 00000000..f831a41c
--- /dev/null
+++ b/editors/vscode/DEVELOPING.md
@@ -0,0 +1,72 @@
+## Developing
+
+> The extension was created using [`yo code`](https://code.visualstudio.com/api/language-extensions/syntax-highlight-guide#developing-a-new-grammar-extension)
+> and further extended to suport LSP by including modified
+> [Microsoft lsp-sample](https://github.com/microsoft/vscode-extension-samples/tree/main/lsp-sample).
+>
+> As a note, this is deliberately a separate file from `README.md` which shows in the VSCode extension view.
+
+### What's in the folder
+
+* `package.json` - this is the manifest file in which you declare your language support and define the location of the grammar file that has been copied into your extension.
+* `syntaxes/swarm.tmLanguage.json` - this is the Text mate grammar file that is used for tokenization.
+* `language-configuration.json` - this is the language configuration, defining the tokens that are used for comments and brackets.
+* `client/src/extension.ts` - this is the LSP client, that will connect to `swarm` executable which can serve as LSP server.
+
+### Get up and running straight away
+
+* Make sure the language configuration settings in `language-configuration.json` are accurate.
+* Press `F5` to open a new window with your extension loaded.
+* Create a new file with a file name suffix matching your language.
+* Verify that syntax highlighting works and that the language configuration settings are working.
+
+### Make changes
+
+* You can relaunch the extension from the debug toolbar after making changes to the files listed above.
+* You can also reload (`Ctrl+R` or `Cmd+R` on Mac) the VS Code window with your extension to load your changes.
+
+### Updating the syntax highlighting
+
+Whenever swarm language adds new features, the highlighing needs to be updated.
+
+To save some time, get the current reserved words by running `cabal repl`:
+```haskell
+import Swarm.Language.Syntax
+import qualified Data.Text as T
+:set -XOverloadedStrings
+
+-- get basic functions/commands
+T.intercalate "|" $ map (syntax . constInfo) (filter isUserFunc allConst)
+
+-- get list of directions
+T.intercalate "|" $ map (dirSyntax . dirInfo) allDirs
+```
+
+You still have to add for example types manually.
+
+
+### Add more language features
+
+To add features such as intellisense, hovers and validators check out the VS Code extenders documentation
+at [VSCode docs](https://code.visualstudio.com/docs).
+
+## Install your extension
+
+First install the dependencies:
+```bash
+npm update
+npm install
+```
+
+If you want to include the LSP client then after the previous install do:
+```sh
+cd client
+tsc --build
+```
+
+To build the VSIX package do:
+```sh
+vsce package --baseImagesUrl "https://raw.githubusercontent.com/byorgey/swarm/editors/vscode"
+```
+
+To share this extension with the world, read on https://code.visualstudio.com/docs about publishing an extension or ask @xsebek to do it.
diff --git a/editors/vscode/README.md b/editors/vscode/README.md
new file mode 100644
index 00000000..9f7987c8
--- /dev/null
+++ b/editors/vscode/README.md
@@ -0,0 +1,17 @@
+# swarm-language README
+
+This VSCode extension provides a basic highlighting and LSP client for the swarm programming language.
+
+![VSCode screenshot](images/editor_debug.png)
+
+## Extension Settings
+
+There are no customizations yet, sorry.
+
+## Known Issues
+
+- The highlighter expects type and `=` sign on the same line as `def`/`let`, i.e.
+ ```haskell
+ def missionImpossible : cmd a -> a = ...
+ ```
+ This regexp limitation is unlikely to impact many users, but is still a departure from real swarm.
diff --git a/editors/vscode/client/package.json b/editors/vscode/client/package.json
new file mode 100644
index 00000000..d67ac15b
--- /dev/null
+++ b/editors/vscode/client/package.json
@@ -0,0 +1,23 @@
+
+{
+ "name": "swarm-lsp-client",
+ "description": "VSCode part of the swarm language server",
+ "author": "Ondřej Šebek",
+ "license": "MIT",
+ "version": "0.0.3",
+ "publisher": "vscode",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/byorgey/swarm"
+ },
+ "engines": {
+ "vscode": "^1.52.0"
+ },
+ "dependencies": {
+ "vscode-languageclient": "^7.0.0"
+ },
+ "devDependencies": {
+ "@types/vscode": "^1.52.0",
+ "@vscode/test-electron": "^1.6.1"
+ }
+}
\ No newline at end of file
diff --git a/editors/vscode/client/src/extension.ts b/editors/vscode/client/src/extension.ts
new file mode 100644
index 00000000..ada86702
--- /dev/null
+++ b/editors/vscode/client/src/extension.ts
@@ -0,0 +1,51 @@
+import * as path from 'path';
+import * as process from 'process';
+import { workspace, ExtensionContext, DebugAdapterExecutable } from 'vscode';
+
+import {
+ Executable,
+ LanguageClient,
+ LanguageClientOptions,
+ ServerOptions,
+ TextDocumentSyncKind,
+ TransportKind
+} from 'vscode-languageclient/node';
+
+let client: LanguageClient;
+
+export function activate(context: ExtensionContext) {
+ // The server is implemented in node
+ const serverModule : Executable = {
+ command: "swarm",
+ args: ["lsp"],
+ options: {detached:true, shell:true},
+ }
+
+
+ var serverOptions: ServerOptions = serverModule;
+ TextDocumentSyncKind
+
+ // Options to control the language client
+ const clientOptions: LanguageClientOptions = {
+ // Register the server for swarm files
+ documentSelector: [{ scheme: 'file', language: 'swarm' }]
+ };
+
+ // Create the language client and start the client.
+ client = new LanguageClient(
+ 'languageServerSwarm',
+ 'Language Server Swarm',
+ serverOptions,
+ clientOptions
+ );
+
+ // Start the client. This will also launch the server
+ client.start();
+}
+
+export function deactivate(): Thenable | undefined {
+ if (!client) {
+ return undefined;
+ }
+ return client.stop();
+}
diff --git a/editors/vscode/client/tsconfig.json b/editors/vscode/client/tsconfig.json
new file mode 100644
index 00000000..c2e0507f
--- /dev/null
+++ b/editors/vscode/client/tsconfig.json
@@ -0,0 +1,12 @@
+{
+ "compilerOptions": {
+ "module": "commonjs",
+ "target": "es2019",
+ "lib": ["ES2019"],
+ "outDir": "out",
+ "rootDir": "src",
+ "sourceMap": true
+ },
+ "include": ["src"],
+ "exclude": ["node_modules", ".vscode-test"]
+}
\ No newline at end of file
diff --git a/editors/vscode/images/editor_debug.png b/editors/vscode/images/editor_debug.png
new file mode 100644
index 00000000..4b004860
Binary files /dev/null and b/editors/vscode/images/editor_debug.png differ
diff --git a/editors/vscode/images/swarm-logo.png b/editors/vscode/images/swarm-logo.png
new file mode 100644
index 00000000..4ef37afb
Binary files /dev/null and b/editors/vscode/images/swarm-logo.png differ
diff --git a/editors/vscode/images/swarm-logo.svg b/editors/vscode/images/swarm-logo.svg
new file mode 100644
index 00000000..c09008c9
--- /dev/null
+++ b/editors/vscode/images/swarm-logo.svg
@@ -0,0 +1,104 @@
+
+
+
+
diff --git a/editors/vscode/language-configuration.json b/editors/vscode/language-configuration.json
new file mode 100644
index 00000000..0c8efd1e
--- /dev/null
+++ b/editors/vscode/language-configuration.json
@@ -0,0 +1,27 @@
+{
+ "comments": {
+ // symbol used for single line comment. Remove this entry if your language does not support line comments
+ "lineComment": "//",
+ // symbols used for start and end a block comment. Remove this entry if your language does not support block comments
+ "blockComment": [ "/*", "*/" ]
+ },
+ // symbols used as brackets
+ "brackets": [
+ ["{", "}"],
+ ["(", ")"]
+ ],
+ // symbols that are auto closed when typing
+ "autoClosingPairs": [
+ ["{", "}"],
+ ["(", ")"],
+ ["\"", "\""],
+ ],
+ // symbols that can be used to surround a selection
+ "surroundingPairs": [
+ ["{", "}"],
+ ["(", ")"],
+ ["\"", "\""],
+ ["def", "end"],
+ ["let", "end"],
+ ]
+}
\ No newline at end of file
diff --git a/editors/vscode/package.json b/editors/vscode/package.json
new file mode 100644
index 00000000..b672d987
--- /dev/null
+++ b/editors/vscode/package.json
@@ -0,0 +1,83 @@
+{
+ "name": "swarm-language",
+ "displayName": "swarm-language",
+ "description": "VSCode support for swarm (the game) programming language.",
+ "version": "0.0.3",
+ "icon": "images/swarm-logo.png",
+ "publisher": "xsebek",
+ "repository": {
+ "url": "https://github.com/byorgey/swarm"
+ },
+ "engines": {
+ "vscode": "^1.61.0"
+ },
+ "categories": [
+ "Programming Languages"
+ ],
+ "activationEvents": [
+ "onLanguage:swarm"
+ ],
+ "main": "./client/out/extension",
+ "contributes": {
+ "languages": [
+ {
+ "id": "swarm",
+ "aliases": [
+ "swarm",
+ "swarm"
+ ],
+ "extensions": [
+ ".sw"
+ ],
+ "configuration": "./language-configuration.json"
+ }
+ ],
+ "grammars": [
+ {
+ "language": "swarm",
+ "scopeName": "source.swarm",
+ "path": "./syntaxes/swarm.tmLanguage.json"
+ }
+ ],
+ "configuration": {
+ "type": "object",
+ "title": "Swarm language configuration",
+ "properties": {
+ "languageServerExample.maxNumberOfProblems": {
+ "scope": "resource",
+ "type": "number",
+ "default": 100,
+ "description": "Controls the maximum number of problems produced by the server."
+ },
+ "languageServerExample.trace.server": {
+ "scope": "window",
+ "type": "string",
+ "enum": [
+ "off",
+ "messages",
+ "verbose"
+ ],
+ "default": "off",
+ "description": "Traces the communication between VS Code and the language server."
+ }
+ }
+ }
+ },
+ "devDependencies": {
+ "@types/mocha": "^8.2.2",
+ "@types/node": "^12.12.0",
+ "@typescript-eslint/eslint-plugin": "^4.23.0",
+ "@typescript-eslint/parser": "^4.23.0",
+ "esbuild": "^0.13.13",
+ "eslint": "^7.26.0",
+ "mocha": "^8.3.2",
+ "typescript": "^4.4.3"
+ },
+ "scripts": {
+ "vscode:prepublish": "npm run esbuild-base -- --minify",
+ "esbuild-base": "esbuild ./client/src/extension.ts --bundle --outfile=out/main.js --external:vscode --format=cjs --platform=node",
+ "esbuild": "npm run esbuild-base -- --sourcemap",
+ "esbuild-watch": "npm run esbuild-base -- --sourcemap --watch",
+ "test-compile": "tsc -p ./"
+ }
+}
diff --git a/editors/vscode/syntaxes/swarm.tmLanguage.json b/editors/vscode/syntaxes/swarm.tmLanguage.json
new file mode 100644
index 00000000..b6b86f24
--- /dev/null
+++ b/editors/vscode/syntaxes/swarm.tmLanguage.json
@@ -0,0 +1,109 @@
+{
+ "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json",
+ "name": "swarm",
+ "patterns": [
+ {"include": "#keywords"},
+ {"include": "#comments"},
+ {"include": "#strings"},
+ {"include": "#variables"},
+ {"include": "#constants"}
+ ],
+ "repository": {
+ "keywords": {
+ "patterns": [
+ {
+ "name": "keyword.control.dictionary.def",
+ "begin": "def\\s+(\\w+)\\s*(:((\\s*(cmd|dir|string|int|\\(|\\)|\\{|\\}|(\\*|\\+|->)|[a-z]\\w*|forall ([a-z]\\w*\\s*)+.)\\s*)+))?=",
+ "end": "end",
+ "beginCaptures": {
+ "1": {"name": "variable.other"},
+ "3": {"name": "storage.type"},
+ "5": {"name": "storage.modifier"}
+ },
+ "patterns": [
+ {"include": "#keywords"},
+ {"include": "#comments"},
+ {"include": "#strings"},
+ {"include": "#variables"},
+ {"include": "#constants"}
+ ]
+ },
+ {
+ "name": "keyword.control.dictionary.let",
+ "begin": "let\\s+(\\w+)\\s*(:((\\s*(cmd|dir|string|int|\\(|\\)|(\\*|\\+|->)|[a-z]\\w*|forall ([a-z]\\w*\\s*)+.)\\s*)+))?=",
+ "end": "in",
+ "beginCaptures": {
+ "1": {"name": "variable.other"},
+ "3": {"name": "storage.type"},
+ "5": {"name": "storage.modifier"}
+ },
+ "patterns": [
+ {"include": "#keywords"},
+ {"include": "#comments"},
+ {"include": "#strings"},
+ {"include": "#variables"},
+ {"include": "#constants"}
+ ]
+ },
+ {
+ "name": "keyword.operator",
+ "match": "(<|>|==|<=|>=|!=|=|;|<-|-|\\+|\\*|\\^|\\$|/(?![/|*]))"
+ },
+ {
+ "name": "keyword.operator.lambda",
+ "match": "\\\\(\\w+)\\.",
+ "captures": { "1": {"name": "variable.other"} }
+ },
+ {
+ "name": "keyword.other",
+ "match": "\\b(?i)(noop|wait|selfdestruct|move|turn|grab|place|give|install|make|has|count|drill|build|salvage|reprogram|say|log|view|appear|create|whereami|blocked|scan|upload|ishere|whoami|random|run|if|inl|inr|case|fst|snd|force|return|try|raise|not)\\b"
+ }
+ ]
+ },
+ "comments": {
+ "patterns": [
+ {
+ "name": "comment.line.double-slash",
+ "begin": "//",
+ "end": "\n"
+ },
+ {
+ "name":"comment.block",
+ "begin": "\/[*]",
+ "end": "[*](\/)"
+ }
+ ]
+ },
+ "strings":{
+ "patterns": [
+ {
+ "name":"string.quoted.double",
+ "begin": "\"",
+ "end": "\""
+ }
+ ]
+ },
+ "variables":{
+ "patterns": [
+ {
+ "name": "variable.language.dir",
+ "match": "\\b(?i)(left|right|back|forward|north|south|east|west|down)\\b"
+ },
+ {
+ "name": "variable.other" ,
+ "match": "\\b(?i)([a-z]\\w*)\\b"
+ }
+ ]
+ },
+ "constants": {
+ "patterns": [
+ {
+ "name": "constant.numeric",
+ "match": "[0-9]"
+ }
+ ]
+ }
+
+ },
+ "scopeName": "source.swarm"
+}
\ No newline at end of file
diff --git a/images/editor.png b/images/editor.png
new file mode 100644
index 00000000..d33f2cfa
Binary files /dev/null and b/images/editor.png differ