mirror of
https://onedev.site.tesses.net/crosslang/crosslangextras
synced 2026-02-08 09:05:46 +00:00
Add more to plugin
This commit is contained in:
@@ -19,12 +19,12 @@ int main(int argc, char** argv)
|
||||
|
||||
TStd::RegisterStd(&gc,env);
|
||||
{
|
||||
auto ms = std::shared_ptr<Tesses::Framework::Streams::MemoryStream>(false);
|
||||
auto ms = std::make_shared<Tesses::Framework::Streams::MemoryStream>(false);
|
||||
auto& buff = ms->GetBuffer();
|
||||
buff.resize(@<<CAPS_VERSION>>@_length);
|
||||
memcpy(buff.data(),@<<CAPS_VERSION>>@_data,@<<CAPS_VERSION>>@_length);
|
||||
auto file = TFile::Create(ls);
|
||||
file->Load(&gc, &ms);
|
||||
file->Load(&gc, ms);
|
||||
env->LoadFile(&gc,file);
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ int main(int argc, char** argv)
|
||||
port = std::stoi(item.second);
|
||||
}
|
||||
}
|
||||
env->EnsureDictionary(&gc,"Net")->SetValue("WebServerPort", (int64_t)port);
|
||||
TList* args2 = TList::Create(ls);
|
||||
args2->Add(exePath.ToString());
|
||||
for(auto& item : args.positional)
|
||||
@@ -48,9 +49,9 @@ int main(int argc, char** argv)
|
||||
args2->Add(item);
|
||||
}
|
||||
|
||||
auto res = env->CallFunction(ls, "WebAppMain", {args2});
|
||||
TObjectHttpServer http(&gc, res);
|
||||
Tesses::Framework::Http::HttpServer svr(port,http,false);
|
||||
auto res = env->CallFunctionWithFatalError(ls, "WebAppMain", {args2});
|
||||
auto http=std::make_shared<TObjectHttpServer>(&gc, res);
|
||||
Tesses::Framework::Http::HttpServer svr((uint16_t)port,http);
|
||||
|
||||
svr.StartAccepting();
|
||||
TF_RunEventLoop();
|
||||
@@ -71,7 +72,7 @@ int main(int argc, char** argv)
|
||||
args->Add(exePath.ToString());
|
||||
for(int arg=1;arg<argc;arg++)
|
||||
args->Add(argv[arg]);
|
||||
auto res = env->CallFunction(ls,"main",{args});
|
||||
auto res = env->CallFunctionWithFatalError(ls,"main",{args});
|
||||
int64_t iresult;
|
||||
if(GetObject(res,iresult))
|
||||
return (int)iresult;
|
||||
|
||||
262
Tesses.CrossLang.BuildEssentials/src/FilePublisher.tcross
Normal file
262
Tesses.CrossLang.BuildEssentials/src/FilePublisher.tcross
Normal file
@@ -0,0 +1,262 @@
|
||||
class FilePublisher {
|
||||
public FilePublisher(program, publish)
|
||||
{
|
||||
this.Program = program;
|
||||
this.OutputDirectory = publish;
|
||||
}
|
||||
|
||||
/^
|
||||
The file to publish
|
||||
^/
|
||||
public Program;
|
||||
|
||||
/^
|
||||
The {name,version,info} from executable
|
||||
^/
|
||||
public ProjectInfo;
|
||||
/^
|
||||
Where we output the published files
|
||||
^/
|
||||
public OutputDirectory;
|
||||
/^
|
||||
The runtime identifier
|
||||
|
||||
builtins:
|
||||
"crvm" (merge to one crvm)
|
||||
"header" (merge to one crvm and generate C header)
|
||||
"cmake" (merge to one crvm and generate C header and create a cmake project)
|
||||
|
||||
actual runtimes can be found here: https://cpkg.tesseslanguage.com/packages?q=Tesses.CrossLang.Runtime. (you need to strip the Tesses.CrossLang.Runtime. from the names)
|
||||
|
||||
^/
|
||||
public RuntimeIdentifier="crvm";
|
||||
/^
|
||||
The prefix of the package (to prepend onto runtime identifier, we put the trailing period for you)
|
||||
^/
|
||||
public PackagePrefix = "Tesses.CrossLang.Runtime";
|
||||
/^
|
||||
Merge for runtimes (one crvm file)
|
||||
^/
|
||||
public MergeForRuntimes = false;
|
||||
|
||||
|
||||
private Build()
|
||||
{
|
||||
var strm = FS.Local.OpenFile(this.Program, "rb");
|
||||
var exec=VM.LoadExecutable(strm);
|
||||
strm.Close();
|
||||
this.ProgramInfo = {
|
||||
name = exec.Name,
|
||||
version = exec.Version.ToString(),
|
||||
info = Json.Decode(exec.Info)
|
||||
};
|
||||
|
||||
return FS.MakeFull(this.Program);
|
||||
}
|
||||
|
||||
private Merge()
|
||||
{
|
||||
var path = this.Build();
|
||||
var packPath = path / "__merge";
|
||||
if(packPath.Count > 0 && FS.Local.DirectoryExists(packPath))
|
||||
{
|
||||
FS.Local.DeleteDirectoryRecurse(packPath);
|
||||
}
|
||||
FS.Local.CreateDirectory(packPath);
|
||||
|
||||
var pack_dir = new SubdirFilesystem(FS.Local, packPath);
|
||||
|
||||
return packPath / VM.Merge(FS.Local,path,pack_dir);
|
||||
}
|
||||
private CopyBuild(destPath)
|
||||
{
|
||||
func CopyCRVM(src,dest)
|
||||
{
|
||||
func copyFile(src,dest)
|
||||
{
|
||||
var _src = FS.Local.OpenFile(src,"rb");
|
||||
var _dest = FS.Local.OpenFile(dest, "wb");
|
||||
_src.CopyTo(_dest);
|
||||
_src.Close();
|
||||
_dest.Close();
|
||||
Console.WriteLine($"{src} -> {dest}");
|
||||
}
|
||||
if(FS.Local.FileExists(dest)) return;
|
||||
copyFile(src,dest);
|
||||
|
||||
|
||||
var srcStrm = FS.Local.OpenFile(src,"rb");
|
||||
var crvm = VM.LoadExecutable(srcStrm);
|
||||
|
||||
srcStrm.Close();
|
||||
each(var dep : crvm.Dependencies)
|
||||
{
|
||||
var name = $"{dep.Name}-{dep.Version.ToString()}.crvm";
|
||||
CopyCRVM(src.GetParent()/name, dest.GetParent()/name);
|
||||
}
|
||||
}
|
||||
each(var item : FS.Local.EnumeratePaths(destPath.GetParent()))
|
||||
{
|
||||
if(item.GetExtension() == ".crvm" && FS.Local.FileExists(item))
|
||||
{
|
||||
FS.Local.DeleteFile(item);
|
||||
}
|
||||
}
|
||||
CopyCRVM(this.Build(), destPath);
|
||||
}
|
||||
|
||||
private CreateCMake(dir, short_name)
|
||||
{
|
||||
FS.Local.CreateDirectory(dir / "src");
|
||||
var path = this.Merge();
|
||||
var bytes = FS.ReadAllBytes(FS.Local, path);
|
||||
var caps_version = this.FixCHeaderName(short_name);
|
||||
|
||||
FS.WriteAllText(FS.Local, dir / "src" / $"{short_name}.h", bytes.ToCHeaderFile(caps_version));
|
||||
|
||||
if(!FS.Local.RegularFileExists(dir / "CMakeLists.txt"))
|
||||
{
|
||||
var cmake_file = embed("cml.txt").ToString().Replace("@<<caps_version>>@",caps_version).Replace("@<<short_name>>@",short_name);
|
||||
FS.WriteAllText(FS.Local,dir / "CMakeLists.txt", cmake_file);
|
||||
}
|
||||
|
||||
if(!FS.Local.RegularFileExists(dir / "src"/"main.cpp"))
|
||||
{
|
||||
|
||||
var cppFile = embed("cppfiletemplate.cpp").ToString().Replace("@<<CAPS_VERSION>>@", caps_version).Replace("@<<HEADER>>@",short_name);
|
||||
|
||||
FS.WriteAllText(FS.Local,dir / "src"/"main.cpp", cppFile);
|
||||
}
|
||||
}
|
||||
|
||||
private CopyFile(src,dest)
|
||||
{
|
||||
var srcStrm = FS.Local.OpenFile(src,"rb");
|
||||
var destStrm = FS.Local.OpenFile(dest, "wb");
|
||||
|
||||
srcStrm.CopyTo(destStrm);
|
||||
srcStrm.Close();
|
||||
destStrm.Close();
|
||||
}
|
||||
|
||||
private FixCHeaderName(name)
|
||||
{
|
||||
var myStr = name.ToUpper();
|
||||
name = "";
|
||||
each(var item : myStr)
|
||||
{
|
||||
if((item >= 'A' && item <= 'Z') || (item >= '0' && item <= '9') || item == '_')
|
||||
name += item;
|
||||
}
|
||||
if(name.Length == 0) return "NONAME";
|
||||
else if(name[0] >= '0' && name[0] <= '9')
|
||||
return $"_{name}";
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
/^ Start the publishing process ^/
|
||||
public Publish()
|
||||
{
|
||||
|
||||
|
||||
var outDir =this.OutputDirectory;
|
||||
var short_name = TypeOf(this.ProjectInfo.info.short_name) == "String" ? this.ProjectInfo.info.short_name : this.ProjectInfo.name;
|
||||
|
||||
FS.Local.CreateDirectory(outDir);
|
||||
|
||||
switch(this.RuntimeIdentifier)
|
||||
{
|
||||
case "copy":
|
||||
{
|
||||
if(this.MergeForRuntimes)
|
||||
{
|
||||
FS.Local.MoveFile(this.Merge(), outDir / short_name + ".crvm");
|
||||
}
|
||||
else {
|
||||
this.CopyBuild(outDir / short_name + ".crvm");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "crvm":
|
||||
{
|
||||
var path = this.Merge();
|
||||
FS.Local.MoveFile(path, outDir / $"{short_name}.crvm");
|
||||
}
|
||||
break;
|
||||
case "header":
|
||||
{
|
||||
var path = this.Merge();
|
||||
var bytes = FS.ReadAllBytes(FS.Local, path);
|
||||
FS.WriteAllText(FS.Local, outDir / $"{short_name}.h", bytes.ToCHeaderFile(this.FixCHeaderName(short_name)));
|
||||
}
|
||||
break;
|
||||
case "cmake":
|
||||
{
|
||||
this.CreateCMake(outDir, short_name);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
var runtimePackageName = this.PackagePrefix;
|
||||
|
||||
if(runtimePackageName.Count > 0 && !runtimePackageName.EndsWith('.'))
|
||||
runtimePackageName += ".";
|
||||
|
||||
runtimePackageName += this.RuntimeIdentifier;
|
||||
|
||||
var version = this.ProjectBuilder.PackageManager.GetLatest(runtimePackageName);
|
||||
if(TypeOf(version) != "String")
|
||||
{
|
||||
throw {
|
||||
Type="PackageNotFoundException",
|
||||
Message=$"Could not find package {runtimePackageName}.",
|
||||
ToString=(this)=>$"{this.Type} on line: {this.Line} {this.Message}"
|
||||
};
|
||||
}
|
||||
|
||||
var pkgObj = this.ProjectBuilder.PackageManager.GetPackage(runtimePackageName, version);
|
||||
var strm = new MemoryStream(true);
|
||||
strm.WriteBlock(pkgObj,0,pkgObj.Length);
|
||||
strm.Seek(0,0);
|
||||
var sdfs = new SubdirFilesystem(FS.Local, outDir);
|
||||
var archiveResponse = FS.ExtractArchive(strm,sdfs);
|
||||
sdfs.Close();
|
||||
|
||||
var archiveInfo = Json.Decode(archiveResponse.Info);
|
||||
|
||||
if(archiveInfo.executable_can_be_renamed)
|
||||
{
|
||||
var executable_name_path = /archiveInfo.executable_name;
|
||||
var executable_extension = executable_name_path.GetExtension();
|
||||
var newName = outDir/short_name;
|
||||
if(executable_extension.Length > 0) newName += executable_extension;
|
||||
|
||||
FS.Local.MoveFile(outDir/archiveInfo.executable_name,newName);
|
||||
FS.Local.Chmod(newName, 0755);
|
||||
if(this.MergeForRuntimes)
|
||||
{
|
||||
FS.Local.MoveFile(this.Merge(), outDir / short_name + ".crvm");
|
||||
}
|
||||
else {
|
||||
this.CopyBuild(outDir / short_name + ".crvm");
|
||||
}
|
||||
}
|
||||
else {
|
||||
var executable_name_path = /archiveInfo.executable_name;
|
||||
FS.Local.Chmod(outDir/archiveInfo.executable_name, 0755);
|
||||
var executable_name_no_ext = executable_name_path.ChangeExtension(null).GetFileName();
|
||||
if(this.MergeForRuntimes)
|
||||
{
|
||||
FS.Local.MoveFile(this.Merge(), outDir / executable_name_no_ext + ".crvm");
|
||||
}
|
||||
else {
|
||||
this.CopyBuild(outDir / executable_name_no_ext + ".crvm");
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,8 @@ class Tesses.CrossLang.BuildTool
|
||||
srcStrm.Close();
|
||||
destStrm.Close();
|
||||
}
|
||||
/^ Whether debug is enabled ^/
|
||||
public Debug = false;
|
||||
/^ Package Manager Object ^/
|
||||
public PackageManager;
|
||||
/^ Directories compiled ^/
|
||||
@@ -355,7 +357,8 @@ class Tesses.CrossLang.BuildTool
|
||||
ResourceFileSystem = new SubdirFilesystem(FS.Local, dir / resDir),
|
||||
Dependencies = file_deps,
|
||||
Output = outFile,
|
||||
CompTime = compTimeEnv
|
||||
CompTime = compTimeEnv,
|
||||
Debug = this.Debug
|
||||
});
|
||||
|
||||
outFile.Close();
|
||||
|
||||
@@ -3,27 +3,33 @@ func Tesses.CrossLang.Shell.Build(dd)
|
||||
var offline=false;
|
||||
var allowFullCompTime=false;
|
||||
var buildPath = ".";
|
||||
var debug=false;
|
||||
if(dd.Arguments.Count > 1)
|
||||
{
|
||||
buildPath = dd.Arguments[1];
|
||||
}
|
||||
each(var flag : dd.Flags)
|
||||
{
|
||||
if(flag == "offline")
|
||||
if(flag == "debug")
|
||||
{
|
||||
debug = true;
|
||||
}
|
||||
else if(flag == "offline")
|
||||
{
|
||||
offline = true;
|
||||
}
|
||||
if(flag == "allow-insecure-comptime")
|
||||
else if(flag == "allow-insecure-comptime")
|
||||
{
|
||||
allowFullCompTime=true;
|
||||
}
|
||||
if(flag == "help")
|
||||
else if(flag == "help")
|
||||
{
|
||||
Console.WriteLine("USAGE: crosslang build [build-flags-and-options]");
|
||||
Console.WriteLine("FLAGS:");
|
||||
Console.WriteLine("offline: build with no internet (don't fetch files)");
|
||||
Console.WriteLine("help: this help");
|
||||
Console.WriteLine("allow-insecure-comptime: Allow full comptime");
|
||||
Console.WriteLine("debug: emit line info into executable");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("OPTIONS:");
|
||||
Console.WriteLine("conf=CONFIGSTRING: specify a conf string for compile_tool(s), is the property Config");
|
||||
@@ -42,6 +48,7 @@ func Tesses.CrossLang.Shell.Build(dd)
|
||||
pm.Offline = offline;
|
||||
var bt = new Tesses.CrossLang.BuildTool(pm);
|
||||
bt.Config = conf;
|
||||
bt.Debug = debug;
|
||||
bt.AllowFullCompTime = allowFullCompTime;
|
||||
bt.BuildProject(buildPath);
|
||||
|
||||
|
||||
@@ -61,6 +61,7 @@ func Tesses.CrossLang.Shell.Debug(dd)
|
||||
var pm = new Tesses.CrossLang.PackageManager();
|
||||
pm.Offline = offline;
|
||||
var bt = new Tesses.CrossLang.BuildTool(pm);
|
||||
bt.Debug = true;
|
||||
bt.Config = conf;
|
||||
output = bt.BuildProject(buildPath).Output;
|
||||
}
|
||||
|
||||
@@ -5,9 +5,14 @@ func Tesses.CrossLang.Shell.Run(dd)
|
||||
var nobuild=false;
|
||||
var allowFullCompTime=false;
|
||||
var output="";
|
||||
var debug = false;
|
||||
each(var flag : dd.Flags)
|
||||
{
|
||||
if(flag == "offline")
|
||||
if(flag == "debug")
|
||||
{
|
||||
debug = true;
|
||||
}
|
||||
else if(flag == "offline")
|
||||
{
|
||||
offline = true;
|
||||
}
|
||||
@@ -23,6 +28,7 @@ func Tesses.CrossLang.Shell.Run(dd)
|
||||
Console.WriteLine("offline: build with no internet (don't fetch files)");
|
||||
Console.WriteLine("allow-insecure-comptime: Allow full comptime");
|
||||
Console.WriteLine("nobuild: don't build, just run");
|
||||
Console.WriteLine("debug: emit line info into executable");
|
||||
Console.WriteLine("help: this help");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("OPTIONS:");
|
||||
@@ -68,6 +74,7 @@ func Tesses.CrossLang.Shell.Run(dd)
|
||||
pm.Offline = offline;
|
||||
var bt = new Tesses.CrossLang.BuildTool(pm);
|
||||
bt.Config = conf;
|
||||
bt.Debug = debug;
|
||||
bt.AllowFullCompTime = allowFullCompTime;
|
||||
output = bt.BuildProject(buildPath).Output;
|
||||
}
|
||||
|
||||
@@ -20,11 +20,14 @@ func Tesses.CrossLang.Shell.WebAppTest(dd)
|
||||
var proj=bt.BuildProject(".");
|
||||
|
||||
var output = proj.Output;
|
||||
|
||||
var env = VM.CreateEnvironment({});
|
||||
const _dict = {};
|
||||
var env = VM.CreateEnvironment(_dict);
|
||||
env.RegisterEverything();
|
||||
env.LockRegister();
|
||||
|
||||
_dict.Net ?? = {};
|
||||
_dict.Net.WebServerPort = port;
|
||||
|
||||
env.LoadFileWithDependencies(FS.Local,output);
|
||||
var myArgs = [output.ToString()];
|
||||
for(var i = 1; i < dd.Arguments.Count; i++)
|
||||
|
||||
@@ -27,13 +27,18 @@ func Tesses.CrossLang.Shell.WebApp(dd)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(FS.Local.FileExists(webapppath))
|
||||
{
|
||||
|
||||
var env = VM.CreateEnvironment({});
|
||||
const _dict = {};
|
||||
const env = VM.CreateEnvironment(_dict);
|
||||
env.RegisterEverything();
|
||||
env.LockRegister();
|
||||
|
||||
_dict.Net ?? = {};
|
||||
_dict.Net.WebServerPort = port;
|
||||
|
||||
|
||||
env.LoadFileWithDependencies(FS.Local,webapppath);
|
||||
var myArgs = [webapppath.ToString()];
|
||||
for(var i = 2; i < dd.Arguments.Count; i++)
|
||||
|
||||
27
vscode-extension/eslint.config.mjs
Normal file
27
vscode-extension/eslint.config.mjs
Normal 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
BIN
vscode-extension/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
79
vscode-extension/media/add-package.js
Normal file
79
vscode-extension/media/add-package.js
Normal 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;
|
||||
}
|
||||
});
|
||||
}());
|
||||
19
vscode-extension/media/jsconfig.json
Normal file
19
vscode-extension/media/jsconfig.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"target": "es2020",
|
||||
"jsx": "preserve",
|
||||
"lib": [
|
||||
"dom"
|
||||
]
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"**/node_modules/*"
|
||||
],
|
||||
"typeAcquisition": {
|
||||
"include": [
|
||||
"@types/vscode-webview"
|
||||
]
|
||||
}
|
||||
}
|
||||
30
vscode-extension/media/reset.css
Normal file
30
vscode-extension/media/reset.css
Normal 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;
|
||||
}
|
||||
118
vscode-extension/media/vscode.css
Normal file
118
vscode-extension/media/vscode.css
Normal 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;
|
||||
}
|
||||
@@ -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
541
vscode-extension/src/api.ts
Normal 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;
|
||||
}
|
||||
31
vscode-extension/src/extension.ts
Normal file
31
vscode-extension/src/extension.ts
Normal 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() {}
|
||||
15
vscode-extension/src/test/extension.test.ts
Normal file
15
vscode-extension/src/test/extension.test.ts
Normal 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));
|
||||
});
|
||||
});
|
||||
133
vscode-extension/syntaxes/crossasm.tmLanguage.json
Normal file
133
vscode-extension/syntaxes/crossasm.tmLanguage.json
Normal 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"
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
17
vscode-extension/tsconfig.json
Normal file
17
vscode-extension/tsconfig.json
Normal 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. */
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user