feat: VS Code extension, web playground, LSP server

This commit is contained in:
2026-06-07 18:34:41 +03:00
parent 3ffa9f7d54
commit a2617e9954
6 changed files with 499 additions and 0 deletions
+36
View File
@@ -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*\\}"
}
}
+77
View File
@@ -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"
}
}
+162
View File
@@ -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"
}
}
+54
View File
@@ -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();
}
+157
View File
@@ -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)"
}
]
}
}
}
+13
View File
@@ -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"]
}