jsmdcui 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +76 -0
- package/LICENSE +22 -0
- package/README.md +285 -0
- package/package.json +17 -0
- package/project_structure.txt +35 -0
- package/runmd.mjs +240 -0
- package/runtime/colorschemes/atom-dark.micro +33 -0
- package/runtime/colorschemes/bubblegum.micro +31 -0
- package/runtime/colorschemes/cmc-16.micro +47 -0
- package/runtime/colorschemes/cmc-tc.micro +43 -0
- package/runtime/colorschemes/darcula.micro +34 -0
- package/runtime/colorschemes/default.micro +1 -0
- package/runtime/colorschemes/dracula-tc.micro +49 -0
- package/runtime/colorschemes/dukedark-tc.micro +38 -0
- package/runtime/colorschemes/dukelight-tc.micro +38 -0
- package/runtime/colorschemes/dukeubuntu-tc.micro +38 -0
- package/runtime/colorschemes/geany.micro +29 -0
- package/runtime/colorschemes/gotham.micro +29 -0
- package/runtime/colorschemes/gruvbox-tc.micro +29 -0
- package/runtime/colorschemes/gruvbox.micro +26 -0
- package/runtime/colorschemes/material-tc.micro +36 -0
- package/runtime/colorschemes/monokai-dark.micro +28 -0
- package/runtime/colorschemes/monokai.micro +34 -0
- package/runtime/colorschemes/one-dark.micro +39 -0
- package/runtime/colorschemes/railscast.micro +37 -0
- package/runtime/colorschemes/simple.micro +33 -0
- package/runtime/colorschemes/solarized-tc.micro +31 -0
- package/runtime/colorschemes/solarized.micro +30 -0
- package/runtime/colorschemes/sunny-day.micro +29 -0
- package/runtime/colorschemes/twilight.micro +40 -0
- package/runtime/colorschemes/zenburn.micro +30 -0
- package/runtime/help/actions.md +161 -0
- package/runtime/help/cdp.md +119 -0
- package/runtime/help/colors.md +421 -0
- package/runtime/help/commands.md +161 -0
- package/runtime/help/copypaste.md +149 -0
- package/runtime/help/defaultkeys.md +148 -0
- package/runtime/help/help.md +285 -0
- package/runtime/help/keybindings.md +355 -0
- package/runtime/help/linter.md +90 -0
- package/runtime/help/options.md +709 -0
- package/runtime/help/plugins.md +544 -0
- package/runtime/help/tutorial.md +112 -0
- package/runtime/jsplugins/cdp/cdp-server.js +1161 -0
- package/runtime/jsplugins/cdp/cdp.js +192 -0
- package/runtime/jsplugins/chapter/chapter.js +108 -0
- package/runtime/jsplugins/diff/diff.js +46 -0
- package/runtime/jsplugins/example/example.js +110 -0
- package/runtime/jsplugins/linter/linter.js +281 -0
- package/runtime/plugins/autoclose/autoclose.lua +75 -0
- package/runtime/plugins/ftoptions/ftoptions.lua +17 -0
- package/runtime/plugins/literate/README.md +5 -0
- package/runtime/plugins/literate/literate.lua +55 -0
- package/runtime/plugins/status/help/status.md +21 -0
- package/runtime/plugins/status/status.lua +62 -0
- package/runtime/syntax/LICENSE +22 -0
- package/runtime/syntax/PowerShell.yaml +128 -0
- package/runtime/syntax/README.md +63 -0
- package/runtime/syntax/ada.yaml +43 -0
- package/runtime/syntax/apacheconf.yaml +59 -0
- package/runtime/syntax/arduino.yaml +101 -0
- package/runtime/syntax/asciidoc.yaml +51 -0
- package/runtime/syntax/asm.yaml +123 -0
- package/runtime/syntax/ats.yaml +99 -0
- package/runtime/syntax/awk.yaml +44 -0
- package/runtime/syntax/b.yaml +87 -0
- package/runtime/syntax/bat.yaml +57 -0
- package/runtime/syntax/c.yaml +60 -0
- package/runtime/syntax/caddyfile.yaml +23 -0
- package/runtime/syntax/cake.yaml +7 -0
- package/runtime/syntax/clojure.yaml +38 -0
- package/runtime/syntax/cmake.yaml +42 -0
- package/runtime/syntax/coffeescript.yaml +56 -0
- package/runtime/syntax/colortest.yaml +19 -0
- package/runtime/syntax/conky.yaml +17 -0
- package/runtime/syntax/cpp.yaml +91 -0
- package/runtime/syntax/crontab.yaml +36 -0
- package/runtime/syntax/crystal.yaml +72 -0
- package/runtime/syntax/csharp.yaml +52 -0
- package/runtime/syntax/css.yaml +44 -0
- package/runtime/syntax/csx.yaml +8 -0
- package/runtime/syntax/cuda.yaml +68 -0
- package/runtime/syntax/cython.yaml +52 -0
- package/runtime/syntax/d.yaml +121 -0
- package/runtime/syntax/dart.yaml +46 -0
- package/runtime/syntax/default.yaml +10 -0
- package/runtime/syntax/dockerfile.yaml +36 -0
- package/runtime/syntax/dot.yaml +29 -0
- package/runtime/syntax/elixir.yaml +30 -0
- package/runtime/syntax/elm.yaml +38 -0
- package/runtime/syntax/erb.yaml +42 -0
- package/runtime/syntax/erlang.yaml +45 -0
- package/runtime/syntax/fish.yaml +48 -0
- package/runtime/syntax/forth.yaml +34 -0
- package/runtime/syntax/fortran.yaml +64 -0
- package/runtime/syntax/freebsd-kernel.yaml +14 -0
- package/runtime/syntax/fsharp.yaml +48 -0
- package/runtime/syntax/gdscript.yaml +61 -0
- package/runtime/syntax/gemini.yaml +19 -0
- package/runtime/syntax/gentoo-ebuild.yaml +48 -0
- package/runtime/syntax/gentoo-etc-portage.yaml +23 -0
- package/runtime/syntax/git-commit.yaml +35 -0
- package/runtime/syntax/git-config.yaml +14 -0
- package/runtime/syntax/git-rebase-todo.yaml +19 -0
- package/runtime/syntax/gleam.yaml +69 -0
- package/runtime/syntax/glsl.yaml +26 -0
- package/runtime/syntax/gnuplot.yaml +15 -0
- package/runtime/syntax/go.yaml +62 -0
- package/runtime/syntax/godoc.yaml +17 -0
- package/runtime/syntax/golo.yaml +73 -0
- package/runtime/syntax/gomod.yaml +31 -0
- package/runtime/syntax/graphql.yaml +47 -0
- package/runtime/syntax/groff.yaml +30 -0
- package/runtime/syntax/groovy.yaml +111 -0
- package/runtime/syntax/haml.yaml +16 -0
- package/runtime/syntax/hare.yaml +52 -0
- package/runtime/syntax/haskell.yaml +52 -0
- package/runtime/syntax/hc.yaml +52 -0
- package/runtime/syntax/html.yaml +70 -0
- package/runtime/syntax/html4.yaml +25 -0
- package/runtime/syntax/html5.yaml +25 -0
- package/runtime/syntax/ini.yaml +23 -0
- package/runtime/syntax/inputrc.yaml +14 -0
- package/runtime/syntax/java.yaml +37 -0
- package/runtime/syntax/javascript.yaml +124 -0
- package/runtime/syntax/jinja2.yaml +19 -0
- package/runtime/syntax/json.yaml +39 -0
- package/runtime/syntax/jsonnet.yaml +92 -0
- package/runtime/syntax/julia.yaml +57 -0
- package/runtime/syntax/justfile.yaml +40 -0
- package/runtime/syntax/keymap.yaml +27 -0
- package/runtime/syntax/kickstart.yaml +16 -0
- package/runtime/syntax/kotlin.yaml +66 -0
- package/runtime/syntax/kvlang.yaml +67 -0
- package/runtime/syntax/ledger.yaml +14 -0
- package/runtime/syntax/lfe.yaml +17 -0
- package/runtime/syntax/lilypond.yaml +26 -0
- package/runtime/syntax/lisp.yaml +17 -0
- package/runtime/syntax/log.yaml +92 -0
- package/runtime/syntax/lua.yaml +111 -0
- package/runtime/syntax/mail.yaml +25 -0
- package/runtime/syntax/makefile.yaml +38 -0
- package/runtime/syntax/man.yaml +12 -0
- package/runtime/syntax/markdown.yaml +49 -0
- package/runtime/syntax/mc.yaml +23 -0
- package/runtime/syntax/meson.yaml +51 -0
- package/runtime/syntax/micro.yaml +34 -0
- package/runtime/syntax/mpdconf.yaml +13 -0
- package/runtime/syntax/msbuild.yaml +6 -0
- package/runtime/syntax/nanorc.yaml +16 -0
- package/runtime/syntax/nftables.yaml +30 -0
- package/runtime/syntax/nginx.yaml +22 -0
- package/runtime/syntax/nim.yaml +27 -0
- package/runtime/syntax/nix.yaml +32 -0
- package/runtime/syntax/nu.yaml +114 -0
- package/runtime/syntax/objc.yaml +60 -0
- package/runtime/syntax/ocaml.yaml +43 -0
- package/runtime/syntax/octave.yaml +83 -0
- package/runtime/syntax/odin.yaml +64 -0
- package/runtime/syntax/pascal.yaml +45 -0
- package/runtime/syntax/patch.yaml +14 -0
- package/runtime/syntax/peg.yaml +16 -0
- package/runtime/syntax/perl.yaml +58 -0
- package/runtime/syntax/php.yaml +60 -0
- package/runtime/syntax/pkg-config.yaml +12 -0
- package/runtime/syntax/po.yaml +12 -0
- package/runtime/syntax/pony.yaml +37 -0
- package/runtime/syntax/pov.yaml +21 -0
- package/runtime/syntax/privoxy-action.yaml +14 -0
- package/runtime/syntax/privoxy-config.yaml +10 -0
- package/runtime/syntax/privoxy-filter.yaml +12 -0
- package/runtime/syntax/proto.yaml +40 -0
- package/runtime/syntax/prql.yaml +84 -0
- package/runtime/syntax/puppet.yaml +22 -0
- package/runtime/syntax/python2.yaml +60 -0
- package/runtime/syntax/python3.yaml +80 -0
- package/runtime/syntax/r.yaml +32 -0
- package/runtime/syntax/raku.yaml +42 -0
- package/runtime/syntax/reST.yaml +18 -0
- package/runtime/syntax/renpy.yaml +15 -0
- package/runtime/syntax/rpmspec.yaml +43 -0
- package/runtime/syntax/ruby.yaml +73 -0
- package/runtime/syntax/rust.yaml +78 -0
- package/runtime/syntax/sage.yaml +60 -0
- package/runtime/syntax/scad.yaml +53 -0
- package/runtime/syntax/scala.yaml +33 -0
- package/runtime/syntax/sed.yaml +13 -0
- package/runtime/syntax/sh.yaml +69 -0
- package/runtime/syntax/sls.yaml +15 -0
- package/runtime/syntax/smalltalk.yaml +55 -0
- package/runtime/syntax/solidity.yaml +41 -0
- package/runtime/syntax/sql.yaml +35 -0
- package/runtime/syntax/stata.yaml +67 -0
- package/runtime/syntax/svelte.yaml +27 -0
- package/runtime/syntax/swift.yaml +103 -0
- package/runtime/syntax/systemd.yaml +16 -0
- package/runtime/syntax/tcl.yaml +18 -0
- package/runtime/syntax/terraform.yaml +87 -0
- package/runtime/syntax/tex.yaml +32 -0
- package/runtime/syntax/toml.yaml +56 -0
- package/runtime/syntax/twig.yaml +55 -0
- package/runtime/syntax/typescript.yaml +49 -0
- package/runtime/syntax/v.yaml +80 -0
- package/runtime/syntax/vala.yaml +26 -0
- package/runtime/syntax/verilog.yaml +60 -0
- package/runtime/syntax/vhdl.yaml +37 -0
- package/runtime/syntax/vi.yaml +31 -0
- package/runtime/syntax/vue.yaml +64 -0
- package/runtime/syntax/xml.yaml +37 -0
- package/runtime/syntax/xresources.yaml +14 -0
- package/runtime/syntax/yaml.yaml +34 -0
- package/runtime/syntax/yum.yaml +12 -0
- package/runtime/syntax/zig.yaml +52 -0
- package/runtime/syntax/zscript.yaml +72 -0
- package/runtime/syntax/zsh.yaml +52 -0
- package/single-exe/README.md +80 -0
- package/single-exe/assetsHelper.js +90 -0
- package/single-exe/assetsLoader.mjs +85 -0
- package/single-exe/compiled.js +149 -0
- package/single-exe/entry.mjs +9 -0
- package/single-exe/packAssets.sh +7 -0
- package/src/buffer/backup.js +160 -0
- package/src/buffer/buffer.js +126 -0
- package/src/buffer/fixed3-codec.js +140 -0
- package/src/buffer/loc.js +38 -0
- package/src/buffer/message.js +29 -0
- package/src/config/clean.js +172 -0
- package/src/config/colorscheme.js +99 -0
- package/src/config/config.js +122 -0
- package/src/config/defaults.js +109 -0
- package/src/cui/rpc.mjs +259 -0
- package/src/cui/server.mjs +116 -0
- package/src/display/ansi-style.js +60 -0
- package/src/highlight/highlighter.js +243 -0
- package/src/highlight/parser.js +225 -0
- package/src/index.js +8009 -0
- package/src/lua/engine.js +71 -0
- package/src/platform/archive.js +50 -0
- package/src/platform/clipboard.js +278 -0
- package/src/platform/commands.js +137 -0
- package/src/plugins/js-bridge.js +983 -0
- package/src/plugins/manager.js +674 -0
- package/src/runtime/assets.js +90 -0
- package/src/runtime/compiled.js +25 -0
- package/src/runtime/encodings.js +10 -0
- package/src/runtime/registry.js +134 -0
- package/src/screen/cell-buffer.js +81 -0
- package/src/screen/events.js +263 -0
- package/src/screen/screen.js +142 -0
- package/src/screen/vt100.js +571 -0
- package/src/shell/shell.js +70 -0
- package/testapp.md +55 -0
- package/tests/backup.test.js +133 -0
- package/tests/cmphex3b64.js +95 -0
- package/tests/pty-demo.js +492 -0
- package/tests/wv-client.js +96 -0
- package/tui +5 -0
- package/wui +5 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
const textDecoder = new TextDecoder();
|
|
2
|
+
const textEncoder = new TextEncoder();
|
|
3
|
+
|
|
4
|
+
export function hasInternalAssets() {
|
|
5
|
+
return Boolean(getAssetStore());
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function assetPath(...parts) {
|
|
9
|
+
return parts
|
|
10
|
+
.flatMap((part) => String(part).split(/[\\/]+/))
|
|
11
|
+
.filter(Boolean)
|
|
12
|
+
.join("/");
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function listInternalAssetPaths(prefix = "") {
|
|
16
|
+
const store = getAssetStore();
|
|
17
|
+
if (!store) return [];
|
|
18
|
+
|
|
19
|
+
const normalizedPrefix = assetPath(prefix);
|
|
20
|
+
const entries = iterateAssetKeys(store);
|
|
21
|
+
if (!normalizedPrefix) {
|
|
22
|
+
return entries.sort();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const base = `${normalizedPrefix}/`;
|
|
26
|
+
return entries.filter((path) => path === normalizedPrefix || path.startsWith(base)).sort();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function listInternalAssetDirs(prefix = "") {
|
|
30
|
+
const normalizedPrefix = assetPath(prefix);
|
|
31
|
+
const base = normalizedPrefix ? `${normalizedPrefix}/` : "";
|
|
32
|
+
const dirs = new Set();
|
|
33
|
+
|
|
34
|
+
for (const path of listInternalAssetPaths(prefix)) {
|
|
35
|
+
const rest = normalizedPrefix ? path.slice(base.length) : path;
|
|
36
|
+
const [dir] = rest.split("/");
|
|
37
|
+
if (dir) dirs.add(dir);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return [...dirs].sort();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function getInternalAsset(path) {
|
|
44
|
+
const store = getAssetStore();
|
|
45
|
+
if (!store) return null;
|
|
46
|
+
const key = assetPath(path);
|
|
47
|
+
if (store instanceof Map) return store.get(key) ?? null;
|
|
48
|
+
return store[key] ?? store[path] ?? null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function readInternalAssetBytes(path) {
|
|
52
|
+
const value = getInternalAsset(path);
|
|
53
|
+
if (value == null) return null;
|
|
54
|
+
if (value instanceof Uint8Array) return value;
|
|
55
|
+
if (ArrayBuffer.isView(value)) {
|
|
56
|
+
return new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
|
|
57
|
+
}
|
|
58
|
+
if (value instanceof ArrayBuffer) return new Uint8Array(value);
|
|
59
|
+
if (typeof value === "string") return textEncoder.encode(value);
|
|
60
|
+
return textEncoder.encode(String(value));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function readInternalAssetText(path) {
|
|
64
|
+
const bytes = readInternalAssetBytes(path);
|
|
65
|
+
if (!bytes) return null;
|
|
66
|
+
return textDecoder.decode(bytes);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function internalAssetSource(path) {
|
|
70
|
+
return {
|
|
71
|
+
name: path.split("/").pop() ?? path,
|
|
72
|
+
path,
|
|
73
|
+
async text() {
|
|
74
|
+
return readInternalAssetText(path) ?? "";
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function getAssetStore() {
|
|
80
|
+
const store = globalThis.internalAssets;
|
|
81
|
+
if (!store) return null;
|
|
82
|
+
if (store instanceof Map) return store;
|
|
83
|
+
if (typeof store === "object") return store;
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function iterateAssetKeys(store) {
|
|
88
|
+
if (store instanceof Map) return [...store.keys()].map(String);
|
|
89
|
+
return Object.keys(store);
|
|
90
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { basename, dirname, resolve } from "node:path";
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
|
|
5
|
+
export function isCompiledBinary(argv = process.argv) {
|
|
6
|
+
return Boolean(argv?.[1]?.startsWith?.("/$bunfs/"));
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function resolveCompiledBaseDir({ argv = process.argv, execPath = process.execPath } = {}) {
|
|
10
|
+
const bn = basename(execPath);
|
|
11
|
+
if (bn.startsWith("ld") ||
|
|
12
|
+
bn.startsWith("libld") ||
|
|
13
|
+
bn.startsWith("linker") ) {
|
|
14
|
+
const realArgv = readFileSync("/proc/self/cmdline", "utf8").match(/[^\0]+/g);
|
|
15
|
+
return dirname(realArgv?.[1] ?? execPath);
|
|
16
|
+
}
|
|
17
|
+
return dirname(execPath) || process.cwd();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function resolveRepoRoot(importMetaUrl, options = {}) {
|
|
21
|
+
if (isCompiledBinary(options.argv)) {
|
|
22
|
+
return resolveCompiledBaseDir(options);
|
|
23
|
+
}
|
|
24
|
+
return resolve(dirname(fileURLToPath(importMetaUrl)), "..");
|
|
25
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
const HEX3_ENCODINGS = new Set(["hex3", "hex3gz", "hex3zst"]);
|
|
2
|
+
const MDCUI_ENCODING = "mdcui";
|
|
3
|
+
|
|
4
|
+
export function isHex3Encoding(encoding) {
|
|
5
|
+
return HEX3_ENCODINGS.has(String(encoding || "utf-8").toLowerCase());
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function isMdcuiEncoding(encoding) {
|
|
9
|
+
return String(encoding || "utf-8").toLowerCase() === MDCUI_ENCODING;
|
|
10
|
+
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { readdir, readFile } from "node:fs/promises";
|
|
3
|
+
import { basename, extname, join } from "node:path";
|
|
4
|
+
import { assetPath, hasInternalAssets, listInternalAssetPaths, readInternalAssetBytes } from "./assets.js";
|
|
5
|
+
|
|
6
|
+
export const RTColorscheme = 0;
|
|
7
|
+
export const RTSyntax = 1;
|
|
8
|
+
export const RTHelp = 2;
|
|
9
|
+
export const RTPlugin = 3;
|
|
10
|
+
export const RTSyntaxHeader = 4;
|
|
11
|
+
|
|
12
|
+
export class RuntimeRegistry {
|
|
13
|
+
constructor({ repoRoot, configDir }) {
|
|
14
|
+
this.repoRoot = repoRoot;
|
|
15
|
+
this.configDir = configDir;
|
|
16
|
+
this.files = [[], [], [], [], []];
|
|
17
|
+
this.realFiles = [[], [], [], [], []];
|
|
18
|
+
this.fallbackFiles = [[], [], [], [], []];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async init({ user = true } = {}) {
|
|
22
|
+
this.files = [[], [], [], [], []];
|
|
23
|
+
this.realFiles = [[], [], [], [], []];
|
|
24
|
+
this.fallbackFiles = [[], [], [], [], []];
|
|
25
|
+
await this.addRuntimeKind(RTColorscheme, "colorschemes", ".micro", user);
|
|
26
|
+
await this.addRuntimeKind(RTSyntax, "syntax", ".yaml", user);
|
|
27
|
+
await this.addRuntimeKind(RTSyntaxHeader, "syntax", ".hdr", user);
|
|
28
|
+
await this.addRuntimeKind(RTHelp, "help", ".md", user);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async addRuntimeKind(kind, dir, extension, user) {
|
|
32
|
+
if (user) await this.addDirectory(kind, join(this.configDir, dir), extension, true);
|
|
33
|
+
const internalPrefix = assetPath("runtime", dir);
|
|
34
|
+
if (hasInternalAssets() && await this.addInternalDirectory(kind, internalPrefix, extension, false)) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
await this.addDirectory(kind, join(this.repoRoot, "runtime", dir), extension, false);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async addDirectory(kind, dir, extension, real) {
|
|
41
|
+
if (!existsSync(dir)) return;
|
|
42
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
43
|
+
for (const entry of entries) {
|
|
44
|
+
if (entry.isDirectory() || !entry.name.endsWith(extension)) continue;
|
|
45
|
+
const file = new RuntimeFile(join(dir, entry.name), real);
|
|
46
|
+
if (!real && this.realFiles[kind].some((f) => f.name === file.name)) {
|
|
47
|
+
this.fallbackFiles[kind].push(file);
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
this.files[kind].push(file);
|
|
51
|
+
if (real) this.realFiles[kind].push(file);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async addInternalDirectory(kind, prefix, extension, real) {
|
|
56
|
+
const entries = listInternalAssetPaths(prefix);
|
|
57
|
+
if (entries.length === 0) return false;
|
|
58
|
+
|
|
59
|
+
const base = `${assetPath(prefix)}/`;
|
|
60
|
+
let added = false;
|
|
61
|
+
for (const path of entries) {
|
|
62
|
+
const rel = path.slice(base.length);
|
|
63
|
+
if (!rel || rel.includes("/")) continue;
|
|
64
|
+
if (!rel.endsWith(extension)) continue;
|
|
65
|
+
|
|
66
|
+
const data = readInternalAssetBytes(path);
|
|
67
|
+
if (!data) continue;
|
|
68
|
+
const file = new MemoryRuntimeFile(path, data);
|
|
69
|
+
if (!real && this.realFiles[kind].some((f) => f.name === file.name)) {
|
|
70
|
+
this.fallbackFiles[kind].push(file);
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
this.files[kind].push(file);
|
|
74
|
+
if (real) this.realFiles[kind].push(file);
|
|
75
|
+
added = true;
|
|
76
|
+
}
|
|
77
|
+
return added;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
addMemoryFile(kind, name, data) {
|
|
81
|
+
this.files[kind].push(new MemoryRuntimeFile(name, data));
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
list(kind) {
|
|
85
|
+
return this.files[kind] ?? [];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
find(kind, name) {
|
|
89
|
+
return this.list(kind).find((file) => file.name === name) ?? null;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
fallback(kind, name) {
|
|
93
|
+
return this.fallbackFiles[kind]?.find((file) => file.name === name) ?? null;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
class RuntimeFile {
|
|
98
|
+
constructor(path, real) {
|
|
99
|
+
this.path = path;
|
|
100
|
+
this.real = real;
|
|
101
|
+
this.name = basename(path, extname(path));
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async data() {
|
|
105
|
+
return readFile(this.path);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
async text() {
|
|
109
|
+
return readFile(this.path, "utf8");
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
class MemoryRuntimeFile {
|
|
114
|
+
constructor(name, data) {
|
|
115
|
+
this.name = basename(name, extname(name));
|
|
116
|
+
this.path = name;
|
|
117
|
+
this.real = false;
|
|
118
|
+
this._data = data;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
async data() {
|
|
122
|
+
if (this._data instanceof Uint8Array) return this._data;
|
|
123
|
+
if (ArrayBuffer.isView(this._data)) {
|
|
124
|
+
return new Uint8Array(this._data.buffer, this._data.byteOffset, this._data.byteLength);
|
|
125
|
+
}
|
|
126
|
+
if (this._data instanceof ArrayBuffer) return new Uint8Array(this._data);
|
|
127
|
+
return new TextEncoder().encode(String(this._data));
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
async text() {
|
|
131
|
+
if (typeof this._data === "string") return this._data;
|
|
132
|
+
return new TextDecoder().decode(await this.data());
|
|
133
|
+
}
|
|
134
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
export class Cell {
|
|
2
|
+
constructor(ch = " ", style = null, combining = [], filler = false) {
|
|
3
|
+
this.ch = ch;
|
|
4
|
+
this.style = style ? { ...style } : null;
|
|
5
|
+
this.combining = [...combining];
|
|
6
|
+
this.filler = filler; // right-half placeholder for a wide (double-width) character
|
|
7
|
+
this.styleKey = styleKey(this.style);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
equals(other) {
|
|
11
|
+
return this.ch === other?.ch && this.styleKey === other?.styleKey && this.filler === other?.filler && arrayEquals(this.combining, other?.combining);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
clone() {
|
|
15
|
+
return new Cell(this.ch, this.style, this.combining, this.filler);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export class CellBuffer {
|
|
20
|
+
constructor(cols, rows, style = null) {
|
|
21
|
+
this.cols = cols;
|
|
22
|
+
this.rows = rows;
|
|
23
|
+
this.cells = Array.from({ length: rows }, () => Array.from({ length: cols }, () => new Cell(" ", style)));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
resize(cols, rows, style = null) {
|
|
27
|
+
if (cols === this.cols && rows === this.rows) return;
|
|
28
|
+
this.cols = cols;
|
|
29
|
+
this.rows = rows;
|
|
30
|
+
this.cells = Array.from({ length: rows }, (_, y) =>
|
|
31
|
+
Array.from({ length: cols }, (_, x) => this.cells[y]?.[x] ?? new Cell(" ", style)));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
setContent(x, y, ch, style = null, combining = [], filler = false) {
|
|
35
|
+
if (x < 0 || y < 0 || x >= this.cols || y >= this.rows) return;
|
|
36
|
+
this.cells[y][x] = new Cell(ch, style, combining, filler);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
setFiller(x, y, style = null) {
|
|
40
|
+
if (x < 0 || y < 0 || x >= this.cols || y >= this.rows) return;
|
|
41
|
+
this.cells[y][x] = new Cell(" ", style, [], true);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
getContent(x, y) {
|
|
45
|
+
if (x < 0 || y < 0 || x >= this.cols || y >= this.rows) return new Cell();
|
|
46
|
+
return this.cells[y][x];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
fill(ch = " ", style = null) {
|
|
50
|
+
for (let y = 0; y < this.rows; y++) {
|
|
51
|
+
for (let x = 0; x < this.cols; x++) this.setContent(x, y, ch, style);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
diff(previous) {
|
|
56
|
+
const changes = [];
|
|
57
|
+
for (let y = 0; y < this.rows; y++) {
|
|
58
|
+
for (let x = 0; x < this.cols; x++) {
|
|
59
|
+
const cell = this.getContent(x, y);
|
|
60
|
+
if (!cell.equals(previous?.getContent(x, y))) changes.push({ x, y, cell });
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return changes;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
clone() {
|
|
67
|
+
const copy = new CellBuffer(this.cols, this.rows);
|
|
68
|
+
copy.cells = this.cells.map((row) => row.map((cell) => cell.clone()));
|
|
69
|
+
return copy;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function styleKey(style) {
|
|
74
|
+
if (!style) return "";
|
|
75
|
+
return JSON.stringify(Object.keys(style).sort().map((key) => [key, style[key]]));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function arrayEquals(a = [], b = []) {
|
|
79
|
+
if (a.length !== b.length) return false;
|
|
80
|
+
return a.every((value, index) => value === b[index]);
|
|
81
|
+
}
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
const decoder = new TextDecoder();
|
|
2
|
+
|
|
3
|
+
export const ENABLE_MOUSE = "\x1b[?1000h\x1b[?1002h\x1b[?1006h";
|
|
4
|
+
export const DISABLE_MOUSE = "\x1b[?1006l\x1b[?1002l\x1b[?1000l";
|
|
5
|
+
export const ENABLE_PASTE = "\x1b[?2004h";
|
|
6
|
+
export const DISABLE_PASTE = "\x1b[?2004l";
|
|
7
|
+
|
|
8
|
+
export class KeyEvent {
|
|
9
|
+
constructor(key, raw) {
|
|
10
|
+
this.type = "key";
|
|
11
|
+
this.key = key;
|
|
12
|
+
this.raw = raw;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export class MouseEvent {
|
|
17
|
+
constructor({ x, y, button, action, modifiers = 0, raw = "" }) {
|
|
18
|
+
this.type = "mouse";
|
|
19
|
+
this.x = x;
|
|
20
|
+
this.y = y;
|
|
21
|
+
this.button = button;
|
|
22
|
+
this.action = action;
|
|
23
|
+
this.modifiers = modifiers;
|
|
24
|
+
this.raw = raw;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export class PasteEvent {
|
|
29
|
+
constructor(text, raw) {
|
|
30
|
+
this.type = "paste";
|
|
31
|
+
this.text = text;
|
|
32
|
+
this.raw = raw;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export class ResizeEvent {
|
|
37
|
+
constructor(cols, rows) {
|
|
38
|
+
this.type = "resize";
|
|
39
|
+
this.cols = cols;
|
|
40
|
+
this.rows = rows;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function parseInputEvents(data) {
|
|
45
|
+
const bytes = typeof data === "string" ? new TextEncoder().encode(data) : new Uint8Array(data);
|
|
46
|
+
const text = typeof data === "string" ? data : decoder.decode(data);
|
|
47
|
+
const paste = parseBracketedPaste(text);
|
|
48
|
+
if (paste) return [paste];
|
|
49
|
+
const events = [...parseSgrMouseEvents(text), ...parseX10MouseEvents(bytes)];
|
|
50
|
+
if (events.length > 0) return events.sort((a, b) => text.indexOf(a.raw) - text.indexOf(b.raw));
|
|
51
|
+
return parseKeyEvents(text);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function parseBracketedPaste(text) {
|
|
55
|
+
const start = text.indexOf("\x1b[200~");
|
|
56
|
+
const end = text.indexOf("\x1b[201~");
|
|
57
|
+
if (start === -1 || end === -1 || end < start) return null;
|
|
58
|
+
const raw = text.slice(start, end + 7);
|
|
59
|
+
return new PasteEvent(text.slice(start + 6, end), raw);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function parseSgrMouse(text) {
|
|
63
|
+
return parseSgrMouseSequence(text);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function parseSgrMouseEvents(text) {
|
|
67
|
+
const events = [];
|
|
68
|
+
const re = /\x1b\[<(\d+);(\d+);(\d+)([mM])/g;
|
|
69
|
+
for (const match of text.matchAll(re)) {
|
|
70
|
+
const event = sgrMatchToEvent(match);
|
|
71
|
+
if (event) events.push(event);
|
|
72
|
+
}
|
|
73
|
+
return events;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function parseSgrMouseSequence(text) {
|
|
77
|
+
const match = /^\x1b\[<(\d+);(\d+);(\d+)([mM])$/.exec(text);
|
|
78
|
+
return match ? sgrMatchToEvent(match) : null;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function sgrMatchToEvent(match) {
|
|
82
|
+
const code = Number(match[1]);
|
|
83
|
+
const x = Number(match[2]) - 1;
|
|
84
|
+
const y = Number(match[3]) - 1;
|
|
85
|
+
const release = match[4] === "m";
|
|
86
|
+
const buttonCode = code & 0b11;
|
|
87
|
+
const wheel = (code & 64) !== 0;
|
|
88
|
+
const drag = (code & 32) !== 0;
|
|
89
|
+
const modifiers = code & (4 | 8 | 16);
|
|
90
|
+
let button = "left";
|
|
91
|
+
if (wheel) button = buttonCode === 0 ? "wheel-up" : "wheel-down";
|
|
92
|
+
else if (buttonCode === 1) button = "middle";
|
|
93
|
+
else if (buttonCode === 2) button = "right";
|
|
94
|
+
else if (buttonCode === 3) button = "none";
|
|
95
|
+
const action = release ? "up" : drag ? "drag" : "down";
|
|
96
|
+
return new MouseEvent({ x, y, button, action, modifiers, raw: match[0] });
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function parseX10MouseEvents(bytes) {
|
|
100
|
+
const events = [];
|
|
101
|
+
for (let i = 0; i + 5 < bytes.length; i++) {
|
|
102
|
+
if (bytes[i] !== 0x1b || bytes[i + 1] !== 0x5b || bytes[i + 2] !== 0x4d) continue;
|
|
103
|
+
const code = bytes[i + 3] - 32;
|
|
104
|
+
const x = bytes[i + 4] - 33;
|
|
105
|
+
const y = bytes[i + 5] - 33;
|
|
106
|
+
if (x < 0 || y < 0) continue;
|
|
107
|
+
const buttonCode = code & 0b11;
|
|
108
|
+
const wheel = (code & 64) !== 0;
|
|
109
|
+
const drag = (code & 32) !== 0;
|
|
110
|
+
let button = "left";
|
|
111
|
+
if (wheel) button = buttonCode === 0 ? "wheel-up" : "wheel-down";
|
|
112
|
+
else if (buttonCode === 1) button = "middle";
|
|
113
|
+
else if (buttonCode === 2) button = "right";
|
|
114
|
+
else if (buttonCode === 3) button = "none";
|
|
115
|
+
const action = buttonCode === 3 ? "up" : drag ? "drag" : "down";
|
|
116
|
+
events.push(new MouseEvent({ x, y, button, action, modifiers: code & (4 | 8 | 16), raw: decoder.decode(bytes.slice(i, i + 6)) }));
|
|
117
|
+
i += 5;
|
|
118
|
+
}
|
|
119
|
+
return events;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const KEY_MAP = {
|
|
123
|
+
"\x01": "ctrl-a",
|
|
124
|
+
"\x02": "ctrl-b",
|
|
125
|
+
"\x03": "ctrl-c",
|
|
126
|
+
"\x04": "ctrl-d",
|
|
127
|
+
"\x05": "ctrl-e",
|
|
128
|
+
"\x0c": "ctrl-l",
|
|
129
|
+
"\x06": "ctrl-f",
|
|
130
|
+
"\x07": "ctrl-g",
|
|
131
|
+
"\t": "tab",
|
|
132
|
+
"\x0b": "ctrl-k",
|
|
133
|
+
"\x0e": "ctrl-n",
|
|
134
|
+
"\x0f": "ctrl-o",
|
|
135
|
+
"\x10": "ctrl-p",
|
|
136
|
+
"\x11": "ctrl-q",
|
|
137
|
+
"\x12": "ctrl-r",
|
|
138
|
+
"\x13": "ctrl-s",
|
|
139
|
+
"\x14": "ctrl-t",
|
|
140
|
+
"\x15": "ctrl-u",
|
|
141
|
+
"\x16": "ctrl-v",
|
|
142
|
+
"\x17": "ctrl-w",
|
|
143
|
+
"\x18": "ctrl-x",
|
|
144
|
+
"\x19": "ctrl-y",
|
|
145
|
+
"\x1a": "ctrl-z",
|
|
146
|
+
"\x1f": "ctrl-underscore",
|
|
147
|
+
"\x7f": "backspace",
|
|
148
|
+
"\b": "backspace",
|
|
149
|
+
"\r": "enter",
|
|
150
|
+
"\n": "enter",
|
|
151
|
+
"\x1b": "escape",
|
|
152
|
+
"\x1b[A": "up",
|
|
153
|
+
"\x1b[B": "down",
|
|
154
|
+
"\x1b[C": "right",
|
|
155
|
+
"\x1b[D": "left",
|
|
156
|
+
"\x1b[1;2A": "shift-up",
|
|
157
|
+
"\x1b[1;2B": "shift-down",
|
|
158
|
+
"\x1b[1;2C": "shift-right",
|
|
159
|
+
"\x1b[1;2D": "shift-left",
|
|
160
|
+
"\x1b[2A": "shift-up",
|
|
161
|
+
"\x1b[2B": "shift-down",
|
|
162
|
+
"\x1b[2C": "shift-right",
|
|
163
|
+
"\x1b[2D": "shift-left",
|
|
164
|
+
"\x1b[1;5A": "ctrl-up",
|
|
165
|
+
"\x1b[1;5B": "ctrl-down",
|
|
166
|
+
"\x1b[1;5C": "ctrl-right",
|
|
167
|
+
"\x1b[1;5D": "ctrl-left",
|
|
168
|
+
"\x1b[1;5H": "ctrl-home",
|
|
169
|
+
"\x1b[1;5F": "ctrl-end",
|
|
170
|
+
"\x1b[5H": "ctrl-home",
|
|
171
|
+
"\x1b[5F": "ctrl-end",
|
|
172
|
+
"\x1b[5A": "ctrl-up",
|
|
173
|
+
"\x1b[5B": "ctrl-down",
|
|
174
|
+
"\x1b[5C": "ctrl-right",
|
|
175
|
+
"\x1b[5D": "ctrl-left",
|
|
176
|
+
"\x1b[1;6A": "shift-ctrl-up",
|
|
177
|
+
"\x1b[1;6B": "shift-ctrl-down",
|
|
178
|
+
"\x1b[1;6C": "shift-ctrl-right",
|
|
179
|
+
"\x1b[1;6D": "shift-ctrl-left",
|
|
180
|
+
// Shift+Home/End
|
|
181
|
+
"\x1b[1;2H": "shift-home",
|
|
182
|
+
"\x1b[2;1H": "shift-home",
|
|
183
|
+
"\x1b[1;2F": "shift-end",
|
|
184
|
+
"\x1b[2;1F": "shift-end",
|
|
185
|
+
// Shift+PageUp/Down
|
|
186
|
+
"\x1b[5;2~": "shift-pageup",
|
|
187
|
+
"\x1b[6;2~": "shift-pagedown",
|
|
188
|
+
// Alt+arrows
|
|
189
|
+
"\x1b[1;3A": "alt-up",
|
|
190
|
+
"\x1b[1;3B": "alt-down",
|
|
191
|
+
"\x1b[1;3C": "alt-right",
|
|
192
|
+
"\x1b[1;3D": "alt-left",
|
|
193
|
+
// Alt+Shift+arrows
|
|
194
|
+
"\x1b[1;4A": "alt-shift-up",
|
|
195
|
+
"\x1b[1;4B": "alt-shift-down",
|
|
196
|
+
"\x1b[1;4C": "alt-shift-right",
|
|
197
|
+
"\x1b[1;4D": "alt-shift-left",
|
|
198
|
+
"\x1b[H": "home",
|
|
199
|
+
"\x1b[F": "end",
|
|
200
|
+
"\x1b[1~": "home",
|
|
201
|
+
"\x1b[4~": "end",
|
|
202
|
+
"\x1b[3~": "delete",
|
|
203
|
+
"\x1b[5~": "pageup",
|
|
204
|
+
"\x1b[6~": "pagedown",
|
|
205
|
+
"\x1b[5;5~": "ctrl-pageup",
|
|
206
|
+
"\x1b[6;5~": "ctrl-pagedown",
|
|
207
|
+
"\x1b[7;5~": "ctrl-home",
|
|
208
|
+
"\x1b[8;5~": "ctrl-end",
|
|
209
|
+
"\x1b[Z": "backtab",
|
|
210
|
+
"\x1b,": "alt-comma",
|
|
211
|
+
"\x1b.": "alt-period",
|
|
212
|
+
"\x1b/": "alt-/",
|
|
213
|
+
"\x1b[": "alt-[",
|
|
214
|
+
"\x1b]": "alt-]",
|
|
215
|
+
"\x1b\t": "alt-tab",
|
|
216
|
+
"\x1b\r": "alt-enter",
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
const KEY_SEQUENCES = Object.keys(KEY_MAP)
|
|
220
|
+
.filter((seq) => seq !== "\x1b")
|
|
221
|
+
.sort((a, b) => b.length - a.length);
|
|
222
|
+
|
|
223
|
+
function parseKeyEvents(text) {
|
|
224
|
+
const events = [];
|
|
225
|
+
let i = 0;
|
|
226
|
+
while (i < text.length) {
|
|
227
|
+
const match = KEY_SEQUENCES.find((seq) => text.startsWith(seq, i));
|
|
228
|
+
if (match) {
|
|
229
|
+
events.push(new KeyEvent(parseKey(match), match));
|
|
230
|
+
i += match.length;
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if (text.charCodeAt(i) === 0x1b) {
|
|
235
|
+
const alt = text.slice(i, i + 2);
|
|
236
|
+
if (alt.length === 2 && alt[1] >= " " && alt[1] <= "~") {
|
|
237
|
+
events.push(new KeyEvent(parseKey(alt), alt));
|
|
238
|
+
i += 2;
|
|
239
|
+
} else {
|
|
240
|
+
events.push(new KeyEvent("escape", "\x1b"));
|
|
241
|
+
i++;
|
|
242
|
+
}
|
|
243
|
+
continue;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
let j = i + 1;
|
|
247
|
+
while (j < text.length && text.charCodeAt(j) !== 0x1b && !KEY_MAP[text[j]]) j++;
|
|
248
|
+
const raw = text.slice(i, j);
|
|
249
|
+
events.push(new KeyEvent(parseKey(raw), raw));
|
|
250
|
+
i = j;
|
|
251
|
+
}
|
|
252
|
+
return events;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
export function parseKey(text) {
|
|
256
|
+
if (KEY_MAP[text]) return KEY_MAP[text];
|
|
257
|
+
// ESC + single printable ASCII -> alt-{char}
|
|
258
|
+
if (text.length === 2 && text.charCodeAt(0) === 0x1b) {
|
|
259
|
+
const ch = text[1];
|
|
260
|
+
if (ch >= " " && ch <= "~") return `alt-${ch}`;
|
|
261
|
+
}
|
|
262
|
+
return text;
|
|
263
|
+
}
|