feat: VS Code extension, web playground, LSP server
This commit is contained in:
@@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
"comments": {
|
||||||
|
"lineComment": "//",
|
||||||
|
"blockComment": ["/*", "*/"]
|
||||||
|
},
|
||||||
|
"brackets": [
|
||||||
|
["{", "}"],
|
||||||
|
["[", "]"],
|
||||||
|
["(", ")"]
|
||||||
|
],
|
||||||
|
"autoClosingPairs": [
|
||||||
|
{ "open": "{", "close": "}" },
|
||||||
|
{ "open": "[", "close": "]" },
|
||||||
|
{ "open": "(", "close": ")" },
|
||||||
|
{ "open": "\"", "close": "\"" },
|
||||||
|
{ "open": "`", "close": "`" }
|
||||||
|
],
|
||||||
|
"surroundingPairs": [
|
||||||
|
{ "open": "{", "close": "}" },
|
||||||
|
{ "open": "[", "close": "]" },
|
||||||
|
{ "open": "(", "close": ")" },
|
||||||
|
{ "open": "\"", "close": "\"" },
|
||||||
|
{ "open": "`", "close": "`" }
|
||||||
|
],
|
||||||
|
"folding": {
|
||||||
|
"markers": {
|
||||||
|
"start": "^\\s*//\\s*region\\b",
|
||||||
|
"end": "^\\s*//\\s*endregion\\b"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"wordPattern": "[a-zA-Z_][a-zA-Z0-9_]*",
|
||||||
|
"indentationRules": {
|
||||||
|
"increaseIndentPattern": "\\{[^}]*$",
|
||||||
|
"decreaseIndentPattern": "^\\s*\\}"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
{
|
||||||
|
"name": "bux-lang",
|
||||||
|
"displayName": "Bux Language Support",
|
||||||
|
"description": "Syntax highlighting, snippets, and LSP support for the Bux programming language",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"publisher": "bux-lang",
|
||||||
|
"license": "MIT",
|
||||||
|
"icon": "icon.png",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/katehonz/bux"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"vscode": "^1.85.0"
|
||||||
|
},
|
||||||
|
"categories": [
|
||||||
|
"Programming Languages",
|
||||||
|
"Snippets",
|
||||||
|
"Linters"
|
||||||
|
],
|
||||||
|
"activationEvents": [
|
||||||
|
"onLanguage:bux"
|
||||||
|
],
|
||||||
|
"main": "./out/extension.js",
|
||||||
|
"contributes": {
|
||||||
|
"languages": [
|
||||||
|
{
|
||||||
|
"id": "bux",
|
||||||
|
"aliases": ["Bux", "bux"],
|
||||||
|
"extensions": [".bux"],
|
||||||
|
"configuration": "./language-configuration.json",
|
||||||
|
"icon": {
|
||||||
|
"dark": "./icon.png",
|
||||||
|
"light": "./icon.png"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"grammars": [
|
||||||
|
{
|
||||||
|
"language": "bux",
|
||||||
|
"scopeName": "source.bux",
|
||||||
|
"path": "./syntaxes/bux.tmLanguage.json"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"snippets": [
|
||||||
|
{
|
||||||
|
"language": "bux",
|
||||||
|
"path": "./snippets/bux.json"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"configuration": {
|
||||||
|
"title": "Bux",
|
||||||
|
"properties": {
|
||||||
|
"bux.lsp.enabled": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": true,
|
||||||
|
"description": "Enable LSP server for diagnostics and autocomplete"
|
||||||
|
},
|
||||||
|
"bux.lsp.path": {
|
||||||
|
"type": "string",
|
||||||
|
"default": "bux-lsp",
|
||||||
|
"description": "Path to the bux-lsp binary"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"vscode:prepublish": "npm run compile",
|
||||||
|
"compile": "tsc -p ./",
|
||||||
|
"watch": "tsc -watch -p ./"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/vscode": "^1.85.0",
|
||||||
|
"typescript": "^5.0.0",
|
||||||
|
"vscode-languageclient": "^9.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,162 @@
|
|||||||
|
{
|
||||||
|
"Main function": {
|
||||||
|
"prefix": "main",
|
||||||
|
"body": [
|
||||||
|
"func Main() -> int {",
|
||||||
|
" $1",
|
||||||
|
" return 0;",
|
||||||
|
"}"
|
||||||
|
],
|
||||||
|
"description": "Main entry point function"
|
||||||
|
},
|
||||||
|
"Function": {
|
||||||
|
"prefix": "func",
|
||||||
|
"body": [
|
||||||
|
"func ${1:Name}(${2:params}) -> ${3:void} {",
|
||||||
|
" $4",
|
||||||
|
"}"
|
||||||
|
],
|
||||||
|
"description": "Function declaration"
|
||||||
|
},
|
||||||
|
"Async Function": {
|
||||||
|
"prefix": "afunc",
|
||||||
|
"body": [
|
||||||
|
"async func ${1:Name}(${2:params}) -> ${3:void} {",
|
||||||
|
" $4",
|
||||||
|
"}"
|
||||||
|
],
|
||||||
|
"description": "Async function declaration"
|
||||||
|
},
|
||||||
|
"Variable (let)": {
|
||||||
|
"prefix": "let",
|
||||||
|
"body": [
|
||||||
|
"let ${1:name}: ${2:Type} = ${3:value};"
|
||||||
|
],
|
||||||
|
"description": "Immutable variable"
|
||||||
|
},
|
||||||
|
"Variable (var)": {
|
||||||
|
"prefix": "var",
|
||||||
|
"body": [
|
||||||
|
"var ${1:name}: ${2:Type} = ${3:value};"
|
||||||
|
],
|
||||||
|
"description": "Mutable variable"
|
||||||
|
},
|
||||||
|
"Struct": {
|
||||||
|
"prefix": "struct",
|
||||||
|
"body": [
|
||||||
|
"struct ${1:Name} {",
|
||||||
|
" ${2:field}: ${3:Type};",
|
||||||
|
"}"
|
||||||
|
],
|
||||||
|
"description": "Struct declaration"
|
||||||
|
},
|
||||||
|
"Enum": {
|
||||||
|
"prefix": "enum",
|
||||||
|
"body": [
|
||||||
|
"enum ${1:Name} {",
|
||||||
|
" ${2:Variant1},",
|
||||||
|
" ${3:Variant2},",
|
||||||
|
"}"
|
||||||
|
],
|
||||||
|
"description": "Enum declaration"
|
||||||
|
},
|
||||||
|
"If statement": {
|
||||||
|
"prefix": "if",
|
||||||
|
"body": [
|
||||||
|
"if ${1:condition} {",
|
||||||
|
" ${2:body}",
|
||||||
|
"}"
|
||||||
|
],
|
||||||
|
"description": "If statement"
|
||||||
|
},
|
||||||
|
"If-else": {
|
||||||
|
"prefix": "ifelse",
|
||||||
|
"body": [
|
||||||
|
"if ${1:condition} {",
|
||||||
|
" ${2:body}",
|
||||||
|
"} else {",
|
||||||
|
" ${3:elseBody}",
|
||||||
|
"}"
|
||||||
|
],
|
||||||
|
"description": "If-else statement"
|
||||||
|
},
|
||||||
|
"While loop": {
|
||||||
|
"prefix": "while",
|
||||||
|
"body": [
|
||||||
|
"while ${1:condition} {",
|
||||||
|
" ${2:body}",
|
||||||
|
"}"
|
||||||
|
],
|
||||||
|
"description": "While loop"
|
||||||
|
},
|
||||||
|
"For loop": {
|
||||||
|
"prefix": "for",
|
||||||
|
"body": [
|
||||||
|
"for ${1:item} in ${2:iterable} {",
|
||||||
|
" ${3:body}",
|
||||||
|
"}"
|
||||||
|
],
|
||||||
|
"description": "For-in loop"
|
||||||
|
},
|
||||||
|
"Match": {
|
||||||
|
"prefix": "match",
|
||||||
|
"body": [
|
||||||
|
"match ${1:expr} {",
|
||||||
|
" ${2:pattern} => ${3:action},",
|
||||||
|
" _ => ${4:default},",
|
||||||
|
"}"
|
||||||
|
],
|
||||||
|
"description": "Pattern match expression"
|
||||||
|
},
|
||||||
|
"Import": {
|
||||||
|
"prefix": "import",
|
||||||
|
"body": [
|
||||||
|
"import Std::${1:Module}::{${2:items}};"
|
||||||
|
],
|
||||||
|
"description": "Import statement"
|
||||||
|
},
|
||||||
|
"Module": {
|
||||||
|
"prefix": "module",
|
||||||
|
"body": [
|
||||||
|
"module ${1:Name} {",
|
||||||
|
"${2:body}",
|
||||||
|
"}"
|
||||||
|
],
|
||||||
|
"description": "Module declaration"
|
||||||
|
},
|
||||||
|
"Extend": {
|
||||||
|
"prefix": "extend",
|
||||||
|
"body": [
|
||||||
|
"extend ${1:Type} {",
|
||||||
|
" ${2:methods}",
|
||||||
|
"}"
|
||||||
|
],
|
||||||
|
"description": "Extend block for methods"
|
||||||
|
},
|
||||||
|
"@Checked": {
|
||||||
|
"prefix": "checked",
|
||||||
|
"body": [
|
||||||
|
"@[Checked]",
|
||||||
|
"func ${1:Name}(${2:params}) -> ${3:void} {",
|
||||||
|
" ${4:body}",
|
||||||
|
"}"
|
||||||
|
],
|
||||||
|
"description": "Checked function with borrow checker enabled"
|
||||||
|
},
|
||||||
|
"PrintLine": {
|
||||||
|
"prefix": "pl",
|
||||||
|
"body": [
|
||||||
|
"PrintLine(\"${1:message}\");"
|
||||||
|
],
|
||||||
|
"description": "Print with newline"
|
||||||
|
},
|
||||||
|
"Generic function": {
|
||||||
|
"prefix": "gfunc",
|
||||||
|
"body": [
|
||||||
|
"func ${1:Name}<${2:T}>(${3:param}: ${2:T}) -> ${2:T} {",
|
||||||
|
" ${4:body}",
|
||||||
|
"}"
|
||||||
|
],
|
||||||
|
"description": "Generic function"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
/* Bux Language Server Protocol client for VS Code
|
||||||
|
* Launches bux-lsp binary and connects via stdin/stdout.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import * as path from 'path';
|
||||||
|
import * as vscode from 'vscode';
|
||||||
|
import {
|
||||||
|
LanguageClient,
|
||||||
|
LanguageClientOptions,
|
||||||
|
ServerOptions,
|
||||||
|
TransportKind
|
||||||
|
} from 'vscode-languageclient/node';
|
||||||
|
|
||||||
|
let client: LanguageClient;
|
||||||
|
|
||||||
|
export function activate(context: vscode.ExtensionContext) {
|
||||||
|
const config = vscode.workspace.getConfiguration('bux.lsp');
|
||||||
|
const enabled = config.get<boolean>('enabled', true);
|
||||||
|
if (!enabled) {
|
||||||
|
vscode.window.showInformationMessage('Bux LSP is disabled in settings');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const lspPath = config.get<string>('path', 'bux-lsp');
|
||||||
|
|
||||||
|
const serverOptions: ServerOptions = {
|
||||||
|
command: lspPath,
|
||||||
|
transport: TransportKind.stdio
|
||||||
|
};
|
||||||
|
|
||||||
|
const clientOptions: LanguageClientOptions = {
|
||||||
|
documentSelector: [{ scheme: 'file', language: 'bux' }],
|
||||||
|
synchronize: {
|
||||||
|
fileEvents: vscode.workspace.createFileSystemWatcher('**/*.bux')
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
client = new LanguageClient(
|
||||||
|
'bux-lsp',
|
||||||
|
'Bux Language Server',
|
||||||
|
serverOptions,
|
||||||
|
clientOptions
|
||||||
|
);
|
||||||
|
|
||||||
|
client.start();
|
||||||
|
vscode.window.showInformationMessage('Bux LSP started');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function deactivate(): Thenable<void> | undefined {
|
||||||
|
if (!client) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return client.stop();
|
||||||
|
}
|
||||||
@@ -0,0 +1,157 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json",
|
||||||
|
"name": "Bux",
|
||||||
|
"scopeName": "source.bux",
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"include": "#comments"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include": "#strings"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include": "#keywords"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include": "#types"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include": "#functions"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include": "#constants"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include": "#operators"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include": "#numbers"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include": "#attributes"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"repository": {
|
||||||
|
"comments": {
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"name": "comment.block.bux",
|
||||||
|
"begin": "/\\*",
|
||||||
|
"end": "\\*/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "comment.line.bux",
|
||||||
|
"match": "//.*$"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"strings": {
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"name": "string.quoted.double.bux",
|
||||||
|
"begin": "\"",
|
||||||
|
"end": "\"",
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"name": "constant.character.escape.bux",
|
||||||
|
"match": "\\\\."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "string.quoted.backtick.bux",
|
||||||
|
"begin": "`",
|
||||||
|
"end": "`"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"keywords": {
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"name": "keyword.control.bux",
|
||||||
|
"match": "\\b(if|else|while|for|do|loop|in|break|continue|return|match|case|default|spawn|async|await|try|catch|throw|discard)\\b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "keyword.declaration.bux",
|
||||||
|
"match": "\\b(func|var|let|const|type|struct|enum|union|interface|extend|module|import|extern|pub)\\b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "keyword.operator.bux",
|
||||||
|
"match": "\\b(as|is|sizeof|comptime|static_assert|dyn)\\b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "keyword.ownership.bux",
|
||||||
|
"match": "\\b(own|mut|borrow)\\b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "storage.modifier.bux",
|
||||||
|
"match": "@\\[(Checked|Shared|Import)\\]"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"types": {
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"name": "support.type.bux",
|
||||||
|
"match": "\\b(int|int8|int16|int32|int64|uint|uint8|uint16|uint32|uint64|float32|float64|bool|char8|char32|String|void)\\b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "entity.name.type.bux",
|
||||||
|
"match": "\\b[A-Z][a-zA-Z0-9_]*\\b"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"functions": {
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"name": "entity.name.function.bux",
|
||||||
|
"match": "\\b([a-z_][a-zA-Z0-9_]*)(?=\\s*\\()"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"constants": {
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"name": "constant.language.bux",
|
||||||
|
"match": "\\b(true|false|null)\\b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "constant.numeric.bux",
|
||||||
|
"match": "\\b(true|false|null|self|super)\\b"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"numbers": {
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"name": "constant.numeric.float.bux",
|
||||||
|
"match": "\\b[0-9]+\\.[0-9]+(?:[eE][+-]?[0-9]+)?\\b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "constant.numeric.hex.bux",
|
||||||
|
"match": "\\b0[xX][0-9a-fA-F]+\\b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "constant.numeric.bux",
|
||||||
|
"match": "\\b[0-9]+\\b"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"operators": {
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"name": "keyword.operator.bux",
|
||||||
|
"match": "->|=>|==|!=|<=|>=|&&|\\|\\||[+\\-*/%<>=!&|^~@]"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"attributes": {
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"name": "storage.modifier.bux",
|
||||||
|
"match": "@(Checked|Shared|Import)"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"module": "commonjs",
|
||||||
|
"target": "ES2020",
|
||||||
|
"outDir": "out",
|
||||||
|
"rootDir": "src",
|
||||||
|
"sourceMap": true,
|
||||||
|
"strict": true,
|
||||||
|
"esModuleInterop": true
|
||||||
|
},
|
||||||
|
"include": ["src"],
|
||||||
|
"exclude": ["node_modules", ".vscode-test"]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user