Add more to plugin

This commit is contained in:
2025-12-23 16:54:07 -06:00
parent e5ca42be84
commit bf59abda07
21 changed files with 1394 additions and 19 deletions

View File

@@ -0,0 +1,27 @@
import typescriptEslint from "typescript-eslint";
export default [{
files: ["**/*.ts"],
}, {
plugins: {
"@typescript-eslint": typescriptEslint.plugin,
},
languageOptions: {
parser: typescriptEslint.parser,
ecmaVersion: 2022,
sourceType: "module",
},
rules: {
"@typescript-eslint/naming-convention": ["warn", {
selector: "import",
format: ["camelCase", "PascalCase"],
}],
curly: "warn",
eqeqeq: "warn",
"no-throw-literal": "warn",
semi: "warn",
},
}];

BIN
vscode-extension/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@@ -0,0 +1,79 @@
(function(){
const vscode = acquireVsCodeApi();
const searchbtn = document.getElementById('searchbtn');
const query = document.getElementById('query');
const body = document.getElementById('packages');
const prevPage = document.getElementById('prevPage');
const currentPage = document.getElementById('currentPage');
const nextPage = document.getElementById('nextPage');
var page = 1;
if(searchbtn)
searchbtn.onclick = ()=>{
page = 1;
currentPage.innerText = "1";
vscode.postMessage(
{command: 'query', query: query.value, page: 1},
);
};
if(prevPage)
prevPage.onclick = ()=>{
page--;
if(page < 1) page=1;
currentPage.innerText = page.toString();
vscode.postMessage(
{command: 'query', query: query.value, page: page},
);
};
if(nextPage)
nextPage.onclick = ()=>{
page++;
currentPage.innerText = page.toString();
vscode.postMessage(
{command: 'query', query: query.value, page: page},
);
};
window.addEventListener('message', event => {
const message = event.data; // The json data that the extension sent
switch (message.command) {
case "searchResponse":
{
body.innerHTML = "";
for(var i = 0; i < message.packages.length; i++)
{
const pkg = message.packages[i];
const node = document.createElement('div');
node.classList.add('package');
const img = document.createElement('img');
img.src = pkg.icon;
img.width = 64;
img.height = 64;
node.appendChild(img);
const title = document.createElement('span');
title.innerText = pkg.name;
node.appendChild(title);
const btn = document.createElement('button');
btn.innerText = pkg.installText;
btn.onclick = ()=>{
vscode.postMessage({
command: "manage-pkg",
name: pkg.name,
version: pkg.version,
query: message.query,
page: message.page
});
};
node.appendChild(btn);
body.appendChild(node);
}
}
break;
}
});
}());

View File

@@ -0,0 +1,19 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es2020",
"jsx": "preserve",
"lib": [
"dom"
]
},
"exclude": [
"node_modules",
"**/node_modules/*"
],
"typeAcquisition": {
"include": [
"@types/vscode-webview"
]
}
}

View File

@@ -0,0 +1,30 @@
html {
box-sizing: border-box;
font-size: 13px;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
body,
h1,
h2,
h3,
h4,
h5,
h6,
p,
ol,
ul {
margin: 0;
padding: 0;
font-weight: normal;
}
img {
max-width: 100%;
height: auto;
}

View File

@@ -0,0 +1,118 @@
:root {
--container-padding: 20px;
--input-padding-vertical: 6px;
--input-padding-horizontal: 4px;
--input-margin-vertical: 4px;
--input-margin-horizontal: 0;
}
body {
padding: 0 var(--container-padding);
color: var(--vscode-foreground);
font-size: var(--vscode-font-size);
font-weight: var(--vscode-font-weight);
font-family: var(--vscode-font-family);
background-color: var(--vscode-editor-background);
}
ol,
ul {
padding-left: var(--container-padding);
}
body > *,
form > * {
margin-block-start: var(--input-margin-vertical);
margin-block-end: var(--input-margin-vertical);
}
*:focus {
outline-color: var(--vscode-focusBorder) !important;
}
a {
color: var(--vscode-textLink-foreground);
}
a:hover,
a:active {
color: var(--vscode-textLink-activeForeground);
}
code {
font-size: var(--vscode-editor-font-size);
font-family: var(--vscode-editor-font-family);
}
button {
border: none;
padding: var(--input-padding-vertical) var(--input-padding-horizontal);
width: 100%;
text-align: center;
outline: 1px solid transparent;
outline-offset: 2px !important;
color: var(--vscode-button-foreground);
background: var(--vscode-button-background);
}
button:hover {
cursor: pointer;
background: var(--vscode-button-hoverBackground);
}
button:focus {
outline-color: var(--vscode-focusBorder);
}
button.secondary {
color: var(--vscode-button-secondaryForeground);
background: var(--vscode-button-secondaryBackground);
}
button.secondary:hover {
background: var(--vscode-button-secondaryHoverBackground);
}
input:not([type='checkbox']),
textarea {
display: block;
width: 100%;
border: none;
font-family: var(--vscode-font-family);
padding: var(--input-padding-vertical) var(--input-padding-horizontal);
color: var(--vscode-input-foreground);
outline-color: var(--vscode-input-border);
background-color: var(--vscode-input-background);
}
input::placeholder,
textarea::placeholder {
color: var(--vscode-input-placeholderForeground);
}
.search-box {
display: grid;
grid-template-columns: minmax(100px,auto) 100px;
column-gap: 1rem;
}
.package {
display: grid;
grid-template-columns: 64px minmax(100px,auto) 100px;
column-gap: 1rem;
}
.package button {
height: fit-content;
}
.pagination {
display: grid;
grid-template-columns: auto 100px 50px 100px auto;
column-gap: 1rem;
}
.pagination span {
width: 100%;
text-align: center;
}

View File

@@ -17,11 +17,87 @@
"aliases": ["CrossLang", "crosslang"],
"extensions": [".tcross"],
"configuration": "./language-configuration.json"
},{
"id": "crossasm",
"aliases": ["CrossAsm", "crossasm"],
"extensions": [".tcasm"],
"configuration": "./language-configuration.json"
}],
"grammars": [{
"language": "crosslang",
"scopeName": "source.crosslang",
"path": "./syntaxes/crosslang.tmLanguage.json"
}]
}
},{
"language": "crossasm",
"scopeName": "source.crossasm",
"path": "./syntaxes/crossasm.tmLanguage.json"
}],
"commands": [
{
"command": "crosslang.createProject",
"title": "Create Project",
"category": "CrossLang"
},
{
"command": "crosslang.createProjectWorkspace",
"title": "Create Project in workspace",
"category": "CrossLang"
},
{
"command": "crosslang.uploadPackage",
"title": "Upload package to CPKG",
"category": "CrossLang"
},
{
"command": "crosslang.addPackage",
"title": "Add Package",
"category": "CrossLang"
}
],
"debuggers": [
{
"type": "crosslang",
"languages": [
"crosslang"
],
"configurationSnippets": [
{
"label": "CrossLang: Launch",
"description": "A new configuration for CrossLang",
"body": {
"name": "Run crosslang program",
"type": "node-terminal",
"request": "launch",
"command": "crosslang run",
"cwd": "^\"\\${workspaceFolder}/\""
}
}
]
}
]
},
"activationEvents": [],
"main": "./out/extension.js",
"scripts": {
"vscode:prepublish": "npm run compile",
"compile": "tsc -p ./",
"watch": "tsc -watch -p ./",
"pretest": "npm run compile && npm run lint",
"lint": "eslint src",
"test": "vscode-test"
},
"devDependencies": {
"@types/mocha": "^10.0.10",
"@types/node": "22.x",
"@types/vscode": "^1.107.0",
"@vscode/test-cli": "^0.0.12",
"@vscode/test-electron": "^2.5.2",
"eslint": "^9.39.1",
"typescript": "^5.9.3",
"typescript-eslint": "^8.46.3"
},
"dependencies": {
"platform-folders": "^0.6.1"
},
"icon": "logo.png"
}

541
vscode-extension/src/api.ts Normal file
View File

@@ -0,0 +1,541 @@
import { spawn } from "node:child_process";
import { QuickPickItem } from "vscode";
import * as vscode from 'vscode';
import { getDocumentsFolder } from 'platform-folders';
import { join } from "node:path";
import { existsSync, mkdirSync } from "node:fs";
import { readFile, writeFile } from "node:fs/promises";
export interface CrossLangProjectConfigInfo
{
type: string
maintainer?: string
repo?: string
homepage?: string
license?: string
plugin_host?: string
description?: string
executable_name?: string
executable_can_be_renamed?: boolean
executable_runtime?: string
template_ignored_files?: string[]
template_info?: CrossLangProjectConfigInfo
}
export interface CrossLangProjectDependency {
name: string
version: string
}
export interface CrossLangProjectConfig {
name: string
version: string
info: CrossLangProjectConfigInfo
resource_directory?: string
source_directory?: string
bin_directory?: string
obj_directory?: string
project_dependencies?: string[]
dependencies?: CrossLangProjectDependency[]
}
export interface CrossLangTemplate {
name: string
description: string
}
export interface PackageServerResponseItem {
accountName: string
description: string
homepage: string
license: string
maintainer: string
packageName: string
repo: string
type: string
uploadDate: string
uploadTime: number
version: string
}
export interface PackageServerResponse {
packages: PackageServerResponseItem[]
}
export function readCommandToEnd(name: string, args: Array<string>, working?:string) : Promise<string>
{
return new Promise<string>((resolve,reject)=>{
var str: string = "";
const program = spawn(name, args, {cwd: working});
program.stdout.on('data',(data)=>{
str += `${data}`;
});
program.on('close',(signal)=>{
if(signal && signal != 0)
reject("Didn't exit successfully");
resolve(str);
})
});
}
export async function ensureWorkingShell()
{
if(!await hasShell())
{
const install = await vscode.window.showInformationMessage('CrossLang shell is not installed, install?',"Yes","No");
if(install === "Yes")
{
await updateShell();
}
}
}
export async function getCrossLangConfigDir() : Promise<string>
{
return (await readCommandToEnd('crosslang',['configdir'])).replace('\r','').replace('\n','');
}
export async function hasShell() : Promise<boolean>
{
try {
return existsSync(join(await getCrossLangConfigDir(),"Shell/Shell.crvm"));
} catch(ex) {return false;}
}
export async function updateShell()
{
await readCommandToEnd('crosslang',['update-shell']);
}
export async function getWorkspace() : Promise<string|null>
{
const wsf = vscode.workspace.workspaceFolders;
if(wsf)
{
if(wsf.length === 1) return wsf[0].uri.fsPath ?? null;
if(wsf.length > 1)
{
return await new Promise<string|null>((resolve,reject)=>{
const qp=vscode.window.createQuickPick();
qp.title = "Which workspace folder?";
const qpItems :QuickPickItem[] = [];
for(var i = 0; i < wsf.length; i++)
{
qpItems.push({
label: wsf[i].name,
description: wsf[i].uri.fsPath
});
}
qp.items = qpItems;
qp.onDidAccept(()=>{
if(qp.activeItems.length ==1)
{
qp.hide();
resolve(qp.activeItems[0].description ?? null);
}
else {
qp.hide();
resolve(null);
}
});
qp.show();
});
}
}
return null;
}
export async function getTemplatesAsync() : Promise<CrossLangTemplate[]>
{
const text = await readCommandToEnd('crosslang',['new','--list-json']);
return JSON.parse(text);
}
async function pickTemplate() : Promise<string>
{
const templates=await getTemplatesAsync();
return await new Promise<string>((resolve,reject)=>{
const qp=vscode.window.createQuickPick();
qp.title = "Select the template";
const qpItems :QuickPickItem[] = [];
for(var i = 0; i < templates.length; i++)
qpItems.push({label: templates[i].name, description: templates[i].description});
qp.items = qpItems;
qp.onDidAccept(()=>{
if(qp.activeItems.length ==1)
{
qp.hide();
resolve(qp.activeItems[0].label);
}
else {
qp.hide();
}
});
qp.show();
});
}
export async function uploadPackage()
{
const projectDir = await getWorkspace();
if(projectDir)
{
try {
await readCommandToEnd('crosslang',['upload-package'],projectDir);
await vscode.window.showInformationMessage('Uploaded package successfully');
} catch(ex) {
await vscode.window.showErrorMessage('Failed to upload to CPKG');
}
}
}
export async function createTemplate()
{
const templateName = await pickTemplate();
const project_name = await vscode.window.showInputBox({title: "Project name"});
if(project_name)
{
const dir = join(getDocumentsFolder(),"CrossLangProjects",project_name);
mkdirSync(dir);
await readCommandToEnd("crosslang",["new",templateName,dir]);
let uri = vscode.Uri.file(dir);
await vscode.commands.executeCommand('vscode.openFolder', uri, true)
}
}
export async function createTemplateInWorkspace()
{
const templateName = await pickTemplate();
const workspace = await getWorkspace();
console.log(workspace);
if(workspace)
{
await readCommandToEnd("crosslang",["new",templateName,workspace]);
}
}
export async function getServerUrl() : Promise<string|null> {
try {
const confDir = await getCrossLangConfigDir();
const pkgServersFile = join(confDir,"package_servers.json");
if(existsSync(pkgServersFile))
{
const data = await readFile(pkgServersFile);
const array: string[] = JSON.parse(data.toString());
if(array.length === 0) return null;
if(array.length === 1) return array[0];
return await new Promise<string|null>((resolve,reject)=>{
const qp=vscode.window.createQuickPick();
qp.title = "Select the server";
const qpItems :QuickPickItem[] = [];
for(var i = 0; i < array.length; i++)
qpItems.push({label: array[i]});
qp.items = qpItems;
qp.onDidAccept(()=>{
if(qp.activeItems.length ==1)
{
qp.hide();
resolve(qp.activeItems[0].label);
}
else {
qp.hide();
resolve(null);
}
});
qp.show();
});
}
}catch(ex) {
return null;
}
return "https://cpkg.tesseslanguage.com/";
}
export function trimEndChar(str: string, trim: string): string
{
if(trim.length!==1) throw new Error("trim must be one char");
var i = str.length-1;
for(;i>=0;i--)
{
if(str[i] !== trim[0]) break;
}
return str.substring(0,i+1);
}
export async function addPackagePage(extensionUri: vscode.Uri)
{
//package_servers.json
const projectDir =await getWorkspace();
if(projectDir)
{
if(existsSync(join(projectDir,"cross.json")))
{
await addPackagePageInternal(extensionUri,projectDir);
}
else {
await vscode.window.showErrorMessage('Workspace does not have cross.json');
}
}
else {
await vscode.window.showErrorMessage('No workspace selected');
}
}
export async function getProjectInfo(projectDir: string): Promise<CrossLangProjectConfig | null>
{
const file = join(projectDir,"cross.json");
if(existsSync(file))
{
const bytes = await readFile(file);
return JSON.parse(bytes.toString());
}
return null;
}
export async function setProjectInfo(projectDir: string, config: CrossLangProjectConfig)
{
const file = join(projectDir,"cross.json");
await writeFile(file,JSON.stringify(config,null,4));
}
export function version2number(version: string) : number
{
const parts = version.split('-');
if(parts.length === 2)
{
const dotPart = parts[0].split('.');
if(dotPart.length === 4)
{
var number = 0;
switch(parts[1])
{
case 'alpha':
number = 1;
break;
case 'beta':
number = 2;
break;
case 'prod':
number = 3;
break;
}
number += (parseInt(parts[3],10) % 65536) * 4;
number += (parseInt(parts[2],10) % 256) * 65536;
number += (parseInt(parts[1],10) % 256) * 16777216;
number += (parseInt(parts[0],10) % 256) * 4294967296;
return number;
}
}
return -1;
}
async function addPackagePageInternal(extensionUri: vscode.Uri, projectDir: string) : Promise<void>
{
const server = await getServerUrl();
const scriptPathOnDisk = vscode.Uri.joinPath(extensionUri, 'media', 'add-package.js');
// And the uri we use to load this script in the webview
var panel = vscode.window.createWebviewPanel(
'toolbox',
'CrossLang Package Manager',
vscode.ViewColumn.One
);
panel.webview.options = {
enableScripts: true
};
panel.webview.onDidReceiveMessage(
async message => {
console.log(message.command);
switch (message.command) {
case 'manage-pkg':
{
//console.log(`${message.name} ${message.version}`);
const info = await getProjectInfo(projectDir);
var install=true;
if(info)
{
if(info.dependencies)
for(var j = 0; j < info.dependencies.length; j++)
{
if(message.name === info.dependencies[j].name)
{
install=false;
if(version2number(message.version) > version2number(info.dependencies[j].version))
{
//upgrade or remove
const result= await new Promise<boolean|null>((resolve,reject)=>{
const qp=vscode.window.createQuickPick();
qp.title = "Update or remove package";
qp.items = [
{label: "Update",description: `Update ${message.name} to ${message.version}`},
{label: "Remove",description: `Remove ${message.name}`}
];
qp.onDidAccept(()=>{
if(qp.activeItems.length ==1)
{
qp.hide();
resolve(qp.activeItems[0].label === "Update");
}
else {
qp.hide();
resolve(null);
}
});
qp.show();
});
if(result !== null)
{
if(result)
{
info.dependencies[j].version = message.version;
break;
}
else
{
info.dependencies.splice(j,1);
break;
}
}
}
else
{
//remove
info.dependencies.splice(j,1);
break;
}
}
}
if(install)
(info.dependencies ??= []).push({name: message.name, version: message.version});
await setProjectInfo(projectDir,info);
}
}
case 'query':
{
const info = await getProjectInfo(projectDir);
if(server && info)
{
const url = `${trimEndChar(server,'/')}/api/v1/search?q=${encodeURIComponent(message.query)}&type=lib,compile_tool&offset=${encodeURIComponent(message.page-1)}`;
console.log(url);
const response = await fetch(url);
if(response.status === 200)
{
const packageServerResponse : PackageServerResponse = await response.json() as PackageServerResponse;
const packages = [];
for(var i = 0; i < packageServerResponse.packages.length;i++)
{
var installText = "Install";
const pkg = packageServerResponse.packages[i];
if(info.dependencies)
for(var j = 0; j < info.dependencies.length; j++)
{
if(pkg.packageName === info.dependencies[j].name)
{
installText = (version2number(pkg.version) > version2number(info.dependencies[j].version)) ? "Upgrade/Remove" : "Remove";
}
}
packages.push({
name: pkg.packageName,
version: pkg.version,
icon: `${trimEndChar(server,'/')}/api/v1/package_icon.png?name=${encodeURIComponent(pkg.packageName)}&version=${pkg.version}`,
installText: installText
});
}
panel.webview.postMessage({
command: "searchResponse",
packages: packages,
page: message.page,
query: message.query
});
}
}
}
break;
}
},
null
);
const scriptUri = panel.webview.asWebviewUri(scriptPathOnDisk);
// Local path to css styles
const styleResetPath = vscode.Uri.joinPath(extensionUri, 'media', 'reset.css');
const stylesPathMainPath = vscode.Uri.joinPath(extensionUri, 'media', 'vscode.css');
// Uri to load styles into webview
const stylesResetUri = panel.webview.asWebviewUri(styleResetPath);
const stylesMainUri = panel.webview.asWebviewUri(stylesPathMainPath);
const nonce = getNonce();
panel.webview.html = `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!--
Use a content security policy to only allow loading images from https or from our extension directory,
and only allow scripts that have a specific nonce.
-->
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src ${panel.webview.cspSource}; img-src ${panel.webview.cspSource} https:; script-src 'nonce-${nonce}';">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="${stylesResetUri}" rel="stylesheet">
<link href="${stylesMainUri}" rel="stylesheet">
</head>
<body>
<div class="search-box">
<input type="text" id="query" placeholder="Search for packages">
<button id="searchbtn">Search</button>
</div>
<div id="packages">
</div>
<div class="pagination">
<div></div>
<button id="prevPage">Previous</button>
<span id="currentPage">1</span>
<button id="nextPage">Next</button>
<div></div>
</div>
<script nonce="${nonce}" src="${scriptUri}"></script>
</body>
</html>`;
}
function getNonce() : string {
let text = '';
const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
for (let i = 0; i < 32; i++) {
text += possible.charAt(Math.floor(Math.random() * possible.length));
}
return text;
}

View File

@@ -0,0 +1,31 @@
// The module 'vscode' contains the VS Code extensibility API
// Import the module and reference it with the alias vscode in your code below
import * as vscode from 'vscode';
import { addPackagePage, createTemplate, createTemplateInWorkspace, ensureWorkingShell, uploadPackage } from './api';
// This method is called when your extension is activated
// Your extension is activated the very first time the command is executed
export function activate(context: vscode.ExtensionContext) {
ensureWorkingShell();
const createProjectCommand = vscode.commands.registerCommand('crosslang.createProject', async() => {
await createTemplate();
});
const createProjectWorkspaceCommand = vscode.commands.registerCommand('crosslang.createProjectWorkspace', async()=>{
await createTemplateInWorkspace();
});
const uploadPackageCommand = vscode.commands.registerCommand('crosslang.uploadPackage', async()=>{
await uploadPackage();
});
const addPackageCommand = vscode.commands.registerCommand('crosslang.addPackage', async()=>{
await addPackagePage(context.extensionUri);
});
context.subscriptions.push(createProjectCommand);
context.subscriptions.push(createProjectWorkspaceCommand);
context.subscriptions.push(uploadPackageCommand);
context.subscriptions.push(addPackageCommand);
}
// This method is called when your extension is deactivated
export function deactivate() {}

View File

@@ -0,0 +1,15 @@
import * as assert from 'assert';
// You can import and use all API from the 'vscode' module
// as well as import your extension to test it
import * as vscode from 'vscode';
// import * as myExtension from '../../extension';
suite('Extension Test Suite', () => {
vscode.window.showInformationMessage('Start all tests.');
test('Sample test', () => {
assert.strictEqual(-1, [1, 2, 3].indexOf(5));
assert.strictEqual(-1, [1, 2, 3].indexOf(0));
});
});

View File

@@ -0,0 +1,133 @@
{
"$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json",
"name": "CrossAsm",
"patterns": [
{
"include": "#comment"
},
{
"include": "#keywords"
},
{
"include": "#chars"
},
{
"include": "#operators"
},
{
"include": "#function"
},
{
"include": "#identifier"
},
{
"include": "#consts"
},
{
"include": "#double"
},
{
"include": "#long"
},
{
"include": "#strings"
}
],
"repository": {
"comment": {
"patterns": [{
"name": "comment.line.double-slash.crossasm",
"begin": "//",
"end": "\\n"
},
{
"name": "comment.block.crossasm",
"begin": "\\/\\*",
"end": "\\*\\/"
},
{
"name": "comment.line.crossasm",
"begin": "#",
"end": "\\n"
},
{
"name":"comment.block.documentation.crossasm",
"begin": "\\/\\^",
"end": "\\^\\/"
}
]
},
"strings": {
"name": "string.quoted.double.crossasm",
"begin": "\\\"",
"end": "\\\"",
"patterns": [
{
"name": "constant.character.escape.crossasm",
"match": "\\\\."
}
]
},
"operators": {
"patterns": [{
"name": "keyword.operator",
"match": "(\\+|\\-|\\*|\\\/|\\%|\\!|\\||\\&|\\^|\\<\\<|\\>\\>|\\<|\\>|\\=)"
}]
},
"function": {
"patterns": [{
"name": "entity.name.function.crossasm",
"match": "\\b[_a-zA-Z\\x80-\\xFF\\$][_a-zA-Z0-9\\x80-\\xFF\\$]*\\("
}]
},
"identifier": {
"patterns": [{
"name": "entity.name.crossasm",
"match": "\\b[_a-zA-Z\\x80-\\xFF\\$][_a-zA-Z0-9\\x80-\\xFF\\$]*"
}]
},
"double": {
"name": "constant.numeric.crossasm",
"match": "\\b[0-9][0-9]*\\.[0-9]*\\b"
},
"long": {
"patterns": [
{
"name": "constant.numeric.crossasm",
"match": "\\b[0-9][0-9]*\\b"
}
]
},
"keywords": {
"patterns": [
{
"name": "constant.language.crossasm",
"match": "\\b(true|false|null|undefined|this)\\b"
},
{
"name": "keyword.control.crossasm",
"match": "\\b(add|sub|mul|div|mod|lsh|rsh|bor|band|bnot|lt|gt|lte|gte|eq|neq|not|neg|xor|pop|dup|nop|lineinfo|embeddir|pushclosure|createdict|createarray|appendlist|appenddict|embed|embedstrm|push|scopebegin|scopeend|scopeendtimes|setvariable|getvariable|declarevariable|declareconstvariable|setfield|getfield|callfunction|callmethod|ret|jmpc|jmp|jmpundefined|defer|trycatch|throw|pushscopelessclosure|yield|breakpoint|jmpifbreak|jmpifcontinue|jmpifdefined|lbl)\\b"
},
{
"name": "keyword.crossasm",
"match": "\\b(root|func|class|public|private|protected|static)\\b"
}
]
},
"chars": {
"name": "constant.character.crossasm",
"begin": "'",
"end": "'",
"patterns": [
{
"name": "constant.character.escape.crossasm",
"match": "\\\\."
}
]
}
},
"scopeName": "source.crossasm"
}

View File

@@ -112,11 +112,11 @@
},
{
"name": "keyword.control.crosslang",
"match": "\\b(if|else|while|for|do|return|each|break|try|catch|finally|defer|enumerable|yield|switch|case|default|await)\\b"
"match": "\\b(if|else|while|for|do|return|each|break|try|catch|finally|defer|enumerable|yield|switch|case|default|await|breakpoint|throw)\\b"
},
{
"name": "keyword.crosslang",
"match": "\\b(var|const|func|class|public|private|protected|static|operator|embed|async)\\b"
"match": "\\b(var|const|func|class|public|private|protected|static|operator|embed|embeddir|embedstrm|comptime|async)\\b"
}
]
},

View File

@@ -0,0 +1,17 @@
{
"compilerOptions": {
"module": "Node16",
"target": "ES2022",
"outDir": "out",
"lib": [
"ES2022"
],
"sourceMap": true,
"rootDir": "src",
"strict": true, /* enable all strict type-checking options */
/* Additional Checks */
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
// "noUnusedParameters": true, /* Report errors on unused parameters. */
}
}