jsmdcui 0.7.0 → 0.9.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 +127 -0
- package/README.md +189 -19
- package/cdp-maze.js +141 -0
- package/demos/maze.md +149 -0
- package/demos/todo-zh.md +98 -0
- package/demos/todo.md +98 -0
- package/edit +9 -0
- package/llm-maze.txt +94 -0
- package/package.json +1 -1
- package/runmd.mjs +44 -2
- package/runtime/help/cdp.md +5 -0
- package/runtime/help/help.md +189 -19
- package/runtime/jsplugins/cdp/cdp-server.js +26 -2
- package/runtime/jsplugins/cdp/cdp.js +60 -51
- package/runtime/jsplugins/chapter/chapter.js +6 -3
- package/runtime/jsplugins/example/example.js +12 -7
- package/runtime/syntax/markdown.yaml +1 -0
- package/single-exe/README.md +223 -45
- package/single-exe/compiled.js +6 -3
- package/single-exe/entry.mjs +4 -3
- package/single-exe/packAssets.sh +1 -1
- package/src/cui/fence-events.mjs +106 -0
- package/src/cui/id-collision.mjs +10 -28
- package/src/cui/kitty-debug.mjs +1 -1
- package/src/cui/kitty-images.mjs +11 -1
- package/src/cui/rpc.mjs +6 -3
- package/src/cui/server.mjs +13 -2
- package/src/index.js +425 -72
- package/src/lua/engine.js +1 -4
- package/src/platform/terminal.js +5 -0
- package/src/plugins/js-bridge.js +157 -8
- package/tests/compiled-runtime.test.js +8 -0
- package/tests/demo.test.js +40 -0
- package/tests/fence-events.test.js +405 -0
- package/tests/id-collision.test.js +11 -0
- package/tests/js-plugin-prompts.test.js +46 -0
- package/tests/key-event.md +10 -0
- package/tests/kitty-demo.md +1 -1
- package/tests/kitty-images.test.js +22 -0
- package/tests/platform-terminal.test.js +8 -0
- package/tests/textarea.md +8 -0
- package/tests/wui.test.js +16 -1
- package/demo.resized.jpg +0 -0
- package/src/runtime/compiled.js +0 -25
package/src/index.js
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
|
|
3
|
-
let mainPromise = globalThis.assetsLoaderPromise ||
|
|
4
|
-
Promise.resolve();
|
|
5
|
-
|
|
6
3
|
const jsStart = globalThis.Bun ? Bun.nanoseconds() : Date.now() * 1e6;
|
|
7
4
|
const checkpoints = [
|
|
8
5
|
{ name: "Bun Engine Boot", time: 0 },
|
|
@@ -93,12 +90,13 @@ function printProfileReport() {
|
|
|
93
90
|
}
|
|
94
91
|
|
|
95
92
|
import child_process from "node:child_process"
|
|
96
|
-
import { accessSync, constants, existsSync, readdirSync, statSync, unlinkSync } from "node:fs";
|
|
93
|
+
import { accessSync, closeSync, constants, existsSync, openSync, readSync, readdirSync, statSync, unlinkSync } from "node:fs";
|
|
97
94
|
import { mkdir } from "node:fs/promises";
|
|
98
95
|
import { dirname, basename, join, resolve, sep } from "node:path";
|
|
99
96
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
100
97
|
import process from "node:process";
|
|
101
98
|
import { toggleTaskCheckboxBeforeColumn, updateAnsiTaskCheckbox } from "./cui/task-checkbox.mjs";
|
|
99
|
+
import { fenceEventMap, inlineFenceEventCode } from "./cui/fence-events.mjs";
|
|
102
100
|
import { checkMarkdownIdCollisions, formatMarkdownIdCheckAnsi } from "./cui/id-collision.mjs";
|
|
103
101
|
import { fitKittyImageToWidth, prepareKittyImages } from "./cui/kitty-images.mjs";
|
|
104
102
|
import { logKittyPlacement } from "./cui/kitty-debug.mjs";
|
|
@@ -108,7 +106,7 @@ import { cleanConfig } from "./config/clean.js";
|
|
|
108
106
|
import { RuntimeRegistry, RTColorscheme, RTHelp } from "./runtime/registry.js";
|
|
109
107
|
import { assetPath, hasInternalAssets, listInternalAssetDirs, listInternalAssetPaths, readInternalAssetText } from "./runtime/assets.js";
|
|
110
108
|
//import { PluginManager } from "./plugins/manager.js";
|
|
111
|
-
import { JsPluginManager, buildMicroGlobal, runAction, listActions } from "./plugins/js-bridge.js";
|
|
109
|
+
import { JsPluginManager, buildMicroGlobal, buildTuiBlockIndex, findTuiBlockInIndex, insertTuiTextareaNewline, mergeTuiTextareaBackward, mergeTuiTextareaForward, runAction, listActions } from "./plugins/js-bridge.js";
|
|
112
110
|
import { Colorscheme } from "./config/colorscheme.js";
|
|
113
111
|
import { detectSyntax, loadSyntaxDefinitions } from "./highlight/parser.js";
|
|
114
112
|
import { Highlighter } from "./highlight/highlighter.js";
|
|
@@ -117,6 +115,7 @@ import { Screen } from "./screen/screen.js";
|
|
|
117
115
|
import { VT100 } from "./screen/vt100.js";
|
|
118
116
|
import { ClipboardManager, probeOSC52, osc52Clipboard } from "./platform/clipboard.js";
|
|
119
117
|
import { platformId, run as runCommand, runSync, fetchHttpBytes, detectHttpBackend } from "./platform/commands.js";
|
|
118
|
+
import { controllingTerminalInputPath } from "./platform/terminal.js";
|
|
120
119
|
import { shellSplit } from "./shell/shell.js";
|
|
121
120
|
import { styleToAnsi } from "./display/ansi-style.js";
|
|
122
121
|
import { encodeBinaryToBuffer, decodeBinaryBytes } from "./buffer/fixed3-codec.js";
|
|
@@ -145,7 +144,12 @@ if(!globalThis.Bun)
|
|
|
145
144
|
//console.log(process.argv)
|
|
146
145
|
|
|
147
146
|
console.error('Ran by node, changed to run by bun')
|
|
148
|
-
|
|
147
|
+
const launched = child_process.spawnSync(bunbinary, process.argv.slice(1), {
|
|
148
|
+
stdio: "inherit",
|
|
149
|
+
env: process.env,
|
|
150
|
+
});
|
|
151
|
+
if (launched.error) throw launched.error;
|
|
152
|
+
process.exit(launched.status ?? 1);
|
|
149
153
|
}
|
|
150
154
|
catch(e){
|
|
151
155
|
console.log(`
|
|
@@ -368,6 +372,7 @@ async function renderMdcui(markdown, width = process.stdout.columns || 80, mdpat
|
|
|
368
372
|
? { rendered: tui, images: [] }
|
|
369
373
|
: await prepareKittyImages(tui, resolvedImageBasePath, width, {
|
|
370
374
|
allowUrl: allowRemoteKittyImages,
|
|
375
|
+
kittyMode: kittyImageMode,
|
|
371
376
|
});
|
|
372
377
|
return {
|
|
373
378
|
rendered: prepared.rendered,
|
|
@@ -668,6 +673,21 @@ function canEditMdcuiSelection(buf, selection) {
|
|
|
668
673
|
return first.y === last.y && prefixLength > 0 && first.x >= prefixLength;
|
|
669
674
|
}
|
|
670
675
|
|
|
676
|
+
function mdcuiTextareaAtCursor(buf) {
|
|
677
|
+
if (!isMdcuiEncoding(buf?.encoding)) return null;
|
|
678
|
+
let cache = buf._mdcuiControlBlockIndex;
|
|
679
|
+
if (!cache || cache.lines !== buf.lines || cache.lineCount !== buf.lines.length) {
|
|
680
|
+
cache = {
|
|
681
|
+
lines: buf.lines,
|
|
682
|
+
lineCount: buf.lines.length,
|
|
683
|
+
blocks: buildTuiBlockIndex(buf.lines),
|
|
684
|
+
};
|
|
685
|
+
buf._mdcuiControlBlockIndex = cache;
|
|
686
|
+
}
|
|
687
|
+
const block = findTuiBlockInIndex(cache.blocks, buf.cursor.y);
|
|
688
|
+
return block?.header?.tag === "textarea" ? block : null;
|
|
689
|
+
}
|
|
690
|
+
|
|
671
691
|
function isEditLockedBuffer(buf) {
|
|
672
692
|
return isMdcuiEncoding(buf?.encoding ?? buf?.Settings?.encoding);
|
|
673
693
|
}
|
|
@@ -970,6 +990,100 @@ function takeDisplay(text, maxWidth) {
|
|
|
970
990
|
return out;
|
|
971
991
|
}
|
|
972
992
|
|
|
993
|
+
function keyboardEventJson(event) {
|
|
994
|
+
const target = event?.target;
|
|
995
|
+
return {
|
|
996
|
+
type: String(event?.type ?? ""),
|
|
997
|
+
key: String(event?.key ?? ""),
|
|
998
|
+
code: String(event?.code ?? ""),
|
|
999
|
+
raw: String(event?.raw ?? ""),
|
|
1000
|
+
ctrlKey: Boolean(event?.ctrlKey),
|
|
1001
|
+
shiftKey: Boolean(event?.shiftKey),
|
|
1002
|
+
altKey: Boolean(event?.altKey),
|
|
1003
|
+
metaKey: Boolean(event?.metaKey),
|
|
1004
|
+
repeat: Boolean(event?.repeat),
|
|
1005
|
+
defaultPrevented: Boolean(event?.defaultPrevented),
|
|
1006
|
+
target: {
|
|
1007
|
+
id: String(target?.id ?? ""),
|
|
1008
|
+
tagName: String(target?.tagName ?? ""),
|
|
1009
|
+
className: String(target?.className ?? ""),
|
|
1010
|
+
value: String(target?.value ?? ""),
|
|
1011
|
+
},
|
|
1012
|
+
};
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
function tuiKeyEventForFront(event, target, type) {
|
|
1016
|
+
const sequence = String(event?.key ?? "");
|
|
1017
|
+
const parts = sequence.split("-");
|
|
1018
|
+
const aliases = {
|
|
1019
|
+
enter: "Enter",
|
|
1020
|
+
escape: "Escape",
|
|
1021
|
+
tab: "Tab",
|
|
1022
|
+
backtab: "Tab",
|
|
1023
|
+
backspace: "Backspace",
|
|
1024
|
+
delete: "Delete",
|
|
1025
|
+
left: "ArrowLeft",
|
|
1026
|
+
right: "ArrowRight",
|
|
1027
|
+
up: "ArrowUp",
|
|
1028
|
+
down: "ArrowDown",
|
|
1029
|
+
home: "Home",
|
|
1030
|
+
end: "End",
|
|
1031
|
+
pageup: "PageUp",
|
|
1032
|
+
pagedown: "PageDown",
|
|
1033
|
+
space: " ",
|
|
1034
|
+
};
|
|
1035
|
+
let base = parts.at(-1) || sequence;
|
|
1036
|
+
if (sequence === "backtab") base = "tab";
|
|
1037
|
+
const raw = String(event?.raw ?? "");
|
|
1038
|
+
const key = aliases[base] ?? (sequence === raw && [...raw].length === 1 ? raw : base);
|
|
1039
|
+
let defaultPrevented = false;
|
|
1040
|
+
let propagationStopped = false;
|
|
1041
|
+
const result = {
|
|
1042
|
+
type,
|
|
1043
|
+
key,
|
|
1044
|
+
raw,
|
|
1045
|
+
ctrlKey: parts.includes("ctrl"),
|
|
1046
|
+
altKey: parts.includes("alt"),
|
|
1047
|
+
shiftKey: sequence === "backtab" || parts.includes("shift"),
|
|
1048
|
+
metaKey: parts.includes("meta"),
|
|
1049
|
+
repeat: false,
|
|
1050
|
+
target,
|
|
1051
|
+
currentTarget: target,
|
|
1052
|
+
get defaultPrevented() { return defaultPrevented; },
|
|
1053
|
+
get propagationStopped() { return propagationStopped; },
|
|
1054
|
+
preventDefault() { defaultPrevented = true; },
|
|
1055
|
+
stopPropagation() { propagationStopped = true; },
|
|
1056
|
+
};
|
|
1057
|
+
Object.defineProperty(result, "toJSON", {
|
|
1058
|
+
configurable: true,
|
|
1059
|
+
value() { return keyboardEventJson(this); },
|
|
1060
|
+
});
|
|
1061
|
+
return result;
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
function indexedMdcuiFenceBlockAtLine(buffer, lineIndex) {
|
|
1065
|
+
const declarations = buffer?._mdcuiFenceEvents;
|
|
1066
|
+
if (!isMdcuiEncoding(buffer?.encoding) || declarations?.size === 0) return null;
|
|
1067
|
+
let cache = buffer._mdcuiFenceBlockIndex;
|
|
1068
|
+
// Render/reopen replaces the lines array; structural selector edits explicitly
|
|
1069
|
+
// clear this cache. Ordinary character edits leave block boundaries unchanged.
|
|
1070
|
+
if (
|
|
1071
|
+
!cache
|
|
1072
|
+
|| cache.lines !== buffer.lines
|
|
1073
|
+
|| cache.lineCount !== buffer.lines.length
|
|
1074
|
+
|| cache.declarations !== declarations
|
|
1075
|
+
) {
|
|
1076
|
+
cache = {
|
|
1077
|
+
lines: buffer.lines,
|
|
1078
|
+
lineCount: buffer.lines.length,
|
|
1079
|
+
declarations,
|
|
1080
|
+
blocks: buildTuiBlockIndex(buffer.lines, declarations),
|
|
1081
|
+
};
|
|
1082
|
+
buffer._mdcuiFenceBlockIndex = cache;
|
|
1083
|
+
}
|
|
1084
|
+
return findTuiBlockInIndex(cache.blocks, lineIndex);
|
|
1085
|
+
}
|
|
1086
|
+
|
|
973
1087
|
function parseArgs(argv) {
|
|
974
1088
|
const flags = {
|
|
975
1089
|
version: false,
|
|
@@ -980,6 +1094,7 @@ function parseArgs(argv) {
|
|
|
980
1094
|
cat: false,
|
|
981
1095
|
docs: false,
|
|
982
1096
|
exportReadme: false,
|
|
1097
|
+
exportCdpMaze: false,
|
|
983
1098
|
changelog: false,
|
|
984
1099
|
testapp: false,
|
|
985
1100
|
demoList: false,
|
|
@@ -991,6 +1106,7 @@ function parseArgs(argv) {
|
|
|
991
1106
|
debug: false,
|
|
992
1107
|
profile: false,
|
|
993
1108
|
plugin: "",
|
|
1109
|
+
cdpMaze: false,
|
|
994
1110
|
cdpPort: 0,
|
|
995
1111
|
cdpAddress: "",
|
|
996
1112
|
kittyMode: "off",
|
|
@@ -1024,9 +1140,14 @@ function parseArgs(argv) {
|
|
|
1024
1140
|
}
|
|
1025
1141
|
else if (arg === "--docs" || arg === "--readme") flags.docs = true;
|
|
1026
1142
|
else if (arg === "--export-readme") flags.exportReadme = true;
|
|
1143
|
+
else if (arg === "--export-cdp-maze") flags.exportCdpMaze = true;
|
|
1027
1144
|
else if (arg === "--changelog") flags.changelog = true;
|
|
1028
1145
|
else if (arg === "--testapp.md") flags.testapp = true;
|
|
1029
1146
|
else if (arg === "--demo-list") flags.demoList = true;
|
|
1147
|
+
else if (arg === "--cdp-maze") {
|
|
1148
|
+
flags.cdpMaze = true;
|
|
1149
|
+
flags.demo = { option: arg, filename: "maze.md", asset: "demos/maze.md" };
|
|
1150
|
+
}
|
|
1030
1151
|
else if (arg === "--demo") {
|
|
1031
1152
|
flags.demo = { option: arg, filename: "testapp.md", asset: "testapp.md" };
|
|
1032
1153
|
}
|
|
@@ -1066,6 +1187,8 @@ function parseArgs(argv) {
|
|
|
1066
1187
|
}
|
|
1067
1188
|
}
|
|
1068
1189
|
|
|
1190
|
+
if (flags.cdpMaze && !flags.cdpPort) flags.cdpPort = 9222;
|
|
1191
|
+
|
|
1069
1192
|
return { flags, files };
|
|
1070
1193
|
}
|
|
1071
1194
|
|
|
@@ -1108,6 +1231,8 @@ Settings:
|
|
|
1108
1231
|
List all setting names and defaults, then exit.
|
|
1109
1232
|
|
|
1110
1233
|
CDP:
|
|
1234
|
+
--cdp-maze
|
|
1235
|
+
Open the maze demo, start CDP on localhost:9222, and solve it automatically
|
|
1111
1236
|
--remote-debugging-port=PORT
|
|
1112
1237
|
Start CDP (Chrome DevTools Protocol) server on PORT at launch
|
|
1113
1238
|
--remote-debugging-address=ADDRESS
|
|
@@ -1122,6 +1247,8 @@ Information:
|
|
|
1122
1247
|
Show ${pkg.name}'s README.md & exit
|
|
1123
1248
|
--export-readme
|
|
1124
1249
|
Write or overwrite ./README.md with the bundled README.md & exit
|
|
1250
|
+
--export-cdp-maze
|
|
1251
|
+
Write or overwrite ./cdp-maze.js with the bundled CDP maze solver & exit
|
|
1125
1252
|
--changelog
|
|
1126
1253
|
Show CHANGELOG.md & exit
|
|
1127
1254
|
-profile, --profile
|
|
@@ -1207,6 +1334,7 @@ class BufferModel {
|
|
|
1207
1334
|
this._mdcuiAnsiText = isMdcuiEncoding(this.encoding) ? String(ansiText ?? "") : null;
|
|
1208
1335
|
this._mdcuiSourceText = isMdcuiEncoding(this.encoding) ? String(sourceText ?? text) : null;
|
|
1209
1336
|
this._mdcuiTuiSourceText = isMdcuiEncoding(this.encoding) ? String(tuiSourceText ?? sourceText ?? text) : null;
|
|
1337
|
+
this._mdcuiFenceEvents = isMdcuiEncoding(this.encoding) ? fenceEventMap(sourceText ?? tuiSourceText ?? text) : new Map();
|
|
1210
1338
|
this._mdcuiImages = isMdcuiEncoding(this.encoding) ? (mdcuiImages ?? []) : [];
|
|
1211
1339
|
this._mdcuiRenderWidth = Math.trunc(Number(mdcuiRenderWidth) || 0);
|
|
1212
1340
|
this.cursor = { x: 0, y: 0 };
|
|
@@ -1565,9 +1693,39 @@ class BufferModel {
|
|
|
1565
1693
|
this.cursor.x = x;
|
|
1566
1694
|
}
|
|
1567
1695
|
|
|
1696
|
+
_historyState() {
|
|
1697
|
+
return {
|
|
1698
|
+
lines: this.lines.slice(),
|
|
1699
|
+
cursor: { ...this.cursor },
|
|
1700
|
+
serial: this._undoSerial,
|
|
1701
|
+
ansiStyleLines: Array.isArray(this._ansiStyleLines)
|
|
1702
|
+
? this._ansiStyleLines.map((line) => Array.isArray(line) ? line.slice() : line)
|
|
1703
|
+
: this._ansiStyleLines,
|
|
1704
|
+
mdcuiAnsiText: this._mdcuiAnsiText,
|
|
1705
|
+
mdcuiImages: Array.isArray(this._mdcuiImages)
|
|
1706
|
+
? this._mdcuiImages.map((image) => ({ ...image }))
|
|
1707
|
+
: this._mdcuiImages,
|
|
1708
|
+
headingTaskListAnchors: this._mdcuiHeadingTaskListAnchors instanceof Map
|
|
1709
|
+
? new Map([...this._mdcuiHeadingTaskListAnchors].map(([key, value]) => [key, { ...value }]))
|
|
1710
|
+
: this._mdcuiHeadingTaskListAnchors,
|
|
1711
|
+
};
|
|
1712
|
+
}
|
|
1713
|
+
|
|
1714
|
+
_restoreHistoryState(state) {
|
|
1715
|
+
this.lines = state.lines;
|
|
1716
|
+
this.cursor = { ...state.cursor };
|
|
1717
|
+
this._undoSerial = state.serial ?? 0;
|
|
1718
|
+
this._ansiStyleLines = state.ansiStyleLines;
|
|
1719
|
+
this._mdcuiAnsiText = state.mdcuiAnsiText;
|
|
1720
|
+
this._mdcuiImages = state.mdcuiImages;
|
|
1721
|
+
this._mdcuiHeadingTaskListAnchors = state.headingTaskListAnchors;
|
|
1722
|
+
this._mdcuiFenceBlockIndex = null;
|
|
1723
|
+
this._mdcuiControlBlockIndex = null;
|
|
1724
|
+
}
|
|
1725
|
+
|
|
1568
1726
|
pushUndo(force = false) {
|
|
1569
1727
|
if (!force && this.isEditLocked() && !canEditMdcuiAtCursor(this)) return;
|
|
1570
|
-
this.undoStack.push(
|
|
1728
|
+
this.undoStack.push(this._historyState());
|
|
1571
1729
|
this._undoSerial = (this._undoSerial ?? 0) + 1;
|
|
1572
1730
|
if (this.undoStack.length > 500) this.undoStack.shift();
|
|
1573
1731
|
this.redoStack = [];
|
|
@@ -1576,12 +1734,10 @@ class BufferModel {
|
|
|
1576
1734
|
undo() {
|
|
1577
1735
|
if (this.isEditLocked() && !isMdcuiEncoding(this.encoding)) return false;
|
|
1578
1736
|
if (!this.undoStack.length) return false;
|
|
1579
|
-
this.redoStack.push(
|
|
1737
|
+
this.redoStack.push(this._historyState());
|
|
1580
1738
|
const s = this.undoStack.pop();
|
|
1581
|
-
this.
|
|
1739
|
+
this._restoreHistoryState(s);
|
|
1582
1740
|
this.invalidateHighlightFrom(0, { force: true });
|
|
1583
|
-
this.cursor = { ...s.cursor };
|
|
1584
|
-
this._undoSerial = s.serial ?? 0;
|
|
1585
1741
|
this.modified = this._undoSerial !== this._savedSerial;
|
|
1586
1742
|
return true;
|
|
1587
1743
|
}
|
|
@@ -1589,12 +1745,10 @@ class BufferModel {
|
|
|
1589
1745
|
redo() {
|
|
1590
1746
|
if (this.isEditLocked() && !isMdcuiEncoding(this.encoding)) return false;
|
|
1591
1747
|
if (!this.redoStack.length) return false;
|
|
1592
|
-
this.undoStack.push(
|
|
1748
|
+
this.undoStack.push(this._historyState());
|
|
1593
1749
|
const s = this.redoStack.pop();
|
|
1594
|
-
this.
|
|
1750
|
+
this._restoreHistoryState(s);
|
|
1595
1751
|
this.invalidateHighlightFrom(0, { force: true });
|
|
1596
|
-
this.cursor = { ...s.cursor };
|
|
1597
|
-
this._undoSerial = s.serial ?? 0;
|
|
1598
1752
|
this.modified = this._undoSerial !== this._savedSerial;
|
|
1599
1753
|
return true;
|
|
1600
1754
|
}
|
|
@@ -1725,6 +1879,7 @@ class BufferModel {
|
|
|
1725
1879
|
this._mdcuiAnsiText = isMdcuiEncoding(this.encoding) ? String(decoded.ansiText ?? "") : null;
|
|
1726
1880
|
this._mdcuiSourceText = isMdcuiEncoding(this.encoding) ? String(decoded.sourceText ?? text) : null;
|
|
1727
1881
|
this._mdcuiTuiSourceText = isMdcuiEncoding(this.encoding) ? String(decoded.tuiSourceText ?? decoded.sourceText ?? text) : null;
|
|
1882
|
+
this._mdcuiFenceEvents = isMdcuiEncoding(this.encoding) ? fenceEventMap(decoded.sourceText ?? decoded.tuiSourceText ?? text) : new Map();
|
|
1728
1883
|
this._mdcuiRenderWidth = decoded.mdcuiRenderWidth ?? 0;
|
|
1729
1884
|
this._mdcuiImages = decoded.mdcuiImages ?? [];
|
|
1730
1885
|
const readonly = isMdcuiEncoding(this.encoding);
|
|
@@ -1758,6 +1913,7 @@ class BufferModel {
|
|
|
1758
1913
|
this._mdcuiAnsiText = isMdcuiEncoding(this.encoding) ? String(decoded.ansiText ?? "") : null;
|
|
1759
1914
|
this._mdcuiSourceText = isMdcuiEncoding(this.encoding) ? String(decoded.sourceText ?? text) : null;
|
|
1760
1915
|
this._mdcuiTuiSourceText = isMdcuiEncoding(this.encoding) ? String(decoded.tuiSourceText ?? decoded.sourceText ?? text) : null;
|
|
1916
|
+
this._mdcuiFenceEvents = isMdcuiEncoding(this.encoding) ? fenceEventMap(decoded.sourceText ?? decoded.tuiSourceText ?? text) : new Map();
|
|
1761
1917
|
this._mdcuiRenderWidth = decoded.mdcuiRenderWidth ?? 0;
|
|
1762
1918
|
this._mdcuiImages = decoded.mdcuiImages ?? [];
|
|
1763
1919
|
this.fileformat = detectFileFormat(text, this.Settings.fileformat ?? DEFAULT_SETTINGS.fileformat);
|
|
@@ -2503,16 +2659,14 @@ class App {
|
|
|
2503
2659
|
}
|
|
2504
2660
|
|
|
2505
2661
|
async start() {
|
|
2506
|
-
this.
|
|
2662
|
+
this.installProtectedPrompts();
|
|
2507
2663
|
// When stdin was a pipe (content already consumed in loadBuffers), open the
|
|
2508
2664
|
// controlling terminal directly so the event loop has a live handle and
|
|
2509
|
-
// keyboard input works.
|
|
2665
|
+
// keyboard input works. Unix: /dev/tty; Windows: CONIN$.
|
|
2510
2666
|
if (!process.stdin.isTTY) {
|
|
2511
2667
|
try {
|
|
2512
|
-
const { openSync } = await import("node:fs");
|
|
2513
2668
|
const { ReadStream } = await import("node:tty");
|
|
2514
|
-
const
|
|
2515
|
-
const fd = openSync(ttyPath, "r+");
|
|
2669
|
+
const fd = openSync(controllingTerminalInputPath(), "r");
|
|
2516
2670
|
this._ttyStream = new ReadStream(fd);
|
|
2517
2671
|
} catch {
|
|
2518
2672
|
this._ttyStream = process.stdin;
|
|
@@ -2542,6 +2696,7 @@ class App {
|
|
|
2542
2696
|
});
|
|
2543
2697
|
process.on("SIGINT", () => {}); // Ctrl+C is handled as copy in handleEvent
|
|
2544
2698
|
this.screen.init();
|
|
2699
|
+
this._started = true;
|
|
2545
2700
|
// Update backup prompt to screen-aware version now that TUI is running.
|
|
2546
2701
|
if (this.context._termPrompt) {
|
|
2547
2702
|
this.context._termPrompt = async (msg) => {
|
|
@@ -2626,6 +2781,8 @@ class App {
|
|
|
2626
2781
|
if (p.type === "term") p.terminal?.close();
|
|
2627
2782
|
(this._ttyStream ?? process.stdin).setRawMode?.(false);
|
|
2628
2783
|
this.screen.fini();
|
|
2784
|
+
this._started = false;
|
|
2785
|
+
this.restoreProtectedPrompts();
|
|
2629
2786
|
|
|
2630
2787
|
if (this.context?.config?.getGlobalOption("savehistory") !== false) {
|
|
2631
2788
|
try { await saveHistory(this.context.config.configDir); } catch {}
|
|
@@ -2644,6 +2801,157 @@ class App {
|
|
|
2644
2801
|
process.exit(code);
|
|
2645
2802
|
}
|
|
2646
2803
|
|
|
2804
|
+
installProtectedPrompts() {
|
|
2805
|
+
if (this._protectedPrompts) return;
|
|
2806
|
+
const saved = {
|
|
2807
|
+
alert: {
|
|
2808
|
+
had: Object.prototype.hasOwnProperty.call(globalThis, "alert"),
|
|
2809
|
+
value: globalThis.alert,
|
|
2810
|
+
},
|
|
2811
|
+
confirm: {
|
|
2812
|
+
had: Object.prototype.hasOwnProperty.call(globalThis, "confirm"),
|
|
2813
|
+
value: globalThis.confirm,
|
|
2814
|
+
},
|
|
2815
|
+
prompt: {
|
|
2816
|
+
had: Object.prototype.hasOwnProperty.call(globalThis, "prompt"),
|
|
2817
|
+
value: globalThis.prompt,
|
|
2818
|
+
},
|
|
2819
|
+
};
|
|
2820
|
+
this._protectedPrompts = saved;
|
|
2821
|
+
this._protectedPromptGlobals = {
|
|
2822
|
+
alert: this.protectedAlert.bind(this),
|
|
2823
|
+
confirm: this.protectedConfirm.bind(this),
|
|
2824
|
+
prompt: this.protectedPrompt.bind(this),
|
|
2825
|
+
};
|
|
2826
|
+
Object.assign(globalThis, this._protectedPromptGlobals);
|
|
2827
|
+
}
|
|
2828
|
+
|
|
2829
|
+
runProtectedPrompt(name, fallback, args) {
|
|
2830
|
+
const nativeFn = this._protectedPrompts?.[name]?.value;
|
|
2831
|
+
const tty = this._ttyStream ?? process.stdin;
|
|
2832
|
+
const wasRaw = typeof tty?.isRaw === "boolean" ? tty.isRaw : true;
|
|
2833
|
+
if (
|
|
2834
|
+
!this._started
|
|
2835
|
+
|| this.shellRunning
|
|
2836
|
+
|| this._alertRunning
|
|
2837
|
+
|| !wasRaw
|
|
2838
|
+
|| typeof nativeFn !== "function"
|
|
2839
|
+
) {
|
|
2840
|
+
this.message = String(args[0] ?? "");
|
|
2841
|
+
return fallback;
|
|
2842
|
+
}
|
|
2843
|
+
|
|
2844
|
+
const inputHandler = this._inputHandler;
|
|
2845
|
+
const listenerAttached = Boolean(
|
|
2846
|
+
inputHandler && tty.listeners?.("data").includes(inputHandler),
|
|
2847
|
+
);
|
|
2848
|
+
const wasPaused = tty.isPaused?.() ?? false;
|
|
2849
|
+
let value;
|
|
2850
|
+
let failed = false;
|
|
2851
|
+
let failure;
|
|
2852
|
+
const cleanupFailures = [];
|
|
2853
|
+
const cleanup = (fn) => {
|
|
2854
|
+
try { fn(); } catch (error) { cleanupFailures.push(error); }
|
|
2855
|
+
};
|
|
2856
|
+
|
|
2857
|
+
try {
|
|
2858
|
+
this._alertRunning = true;
|
|
2859
|
+
// Do not let the editor's flowing-mode data listener race the blocking
|
|
2860
|
+
// prompt for bytes from the same terminal.
|
|
2861
|
+
if (listenerAttached) tty.removeListener("data", inputHandler);
|
|
2862
|
+
tty.pause?.();
|
|
2863
|
+
tty.setRawMode?.(false);
|
|
2864
|
+
this.screen.fini();
|
|
2865
|
+
this.screen.previous = null;
|
|
2866
|
+
// Bun's native prompts always read fd 0. If Markdown itself came from a
|
|
2867
|
+
// pipe, read synchronously from the controlling terminal instead.
|
|
2868
|
+
value = tty !== process.stdin
|
|
2869
|
+
? this.runProtectedTtyPrompt(name, fallback, args)
|
|
2870
|
+
: Reflect.apply(nativeFn, globalThis, args);
|
|
2871
|
+
} catch (error) {
|
|
2872
|
+
failed = true;
|
|
2873
|
+
failure = error;
|
|
2874
|
+
} finally {
|
|
2875
|
+
cleanup(() => tty.setRawMode?.(wasRaw));
|
|
2876
|
+
cleanup(() => { this.screen.previous = null; });
|
|
2877
|
+
cleanup(() => this.screen.init());
|
|
2878
|
+
cleanup(() => { this._alertRunning = false; });
|
|
2879
|
+
cleanup(() => {
|
|
2880
|
+
if (listenerAttached) tty.on("data", inputHandler);
|
|
2881
|
+
});
|
|
2882
|
+
cleanup(() => {
|
|
2883
|
+
if (!wasPaused) tty.resume?.();
|
|
2884
|
+
});
|
|
2885
|
+
cleanup(() => this.render());
|
|
2886
|
+
}
|
|
2887
|
+
if (failed) throw failure;
|
|
2888
|
+
if (cleanupFailures.length > 0) throw cleanupFailures[0];
|
|
2889
|
+
return value;
|
|
2890
|
+
}
|
|
2891
|
+
|
|
2892
|
+
runProtectedTtyPrompt(name, fallback, args) {
|
|
2893
|
+
const message = String(args[0] ?? "");
|
|
2894
|
+
const defaultValue = String(args[1] ?? "");
|
|
2895
|
+
const fd = openSync(controllingTerminalInputPath(), "r");
|
|
2896
|
+
try {
|
|
2897
|
+
if (name === "alert") {
|
|
2898
|
+
process.stdout.write(`${message}\n\nPress ENTER to continue...`);
|
|
2899
|
+
this.readProtectedPromptLine(fd);
|
|
2900
|
+
return undefined;
|
|
2901
|
+
}
|
|
2902
|
+
const suffix = name === "confirm"
|
|
2903
|
+
? " [y/N] "
|
|
2904
|
+
: defaultValue ? ` (${defaultValue}) ` : " ";
|
|
2905
|
+
process.stdout.write(message + suffix);
|
|
2906
|
+
const answer = this.readProtectedPromptLine(fd);
|
|
2907
|
+
if (answer == null) return fallback;
|
|
2908
|
+
if (name === "confirm") return /^(?:y|yes)$/i.test(answer.trim());
|
|
2909
|
+
return answer === "" ? defaultValue : answer;
|
|
2910
|
+
} finally {
|
|
2911
|
+
closeSync(fd);
|
|
2912
|
+
}
|
|
2913
|
+
}
|
|
2914
|
+
|
|
2915
|
+
readProtectedPromptLine(fd) {
|
|
2916
|
+
const chunks = [];
|
|
2917
|
+
const chunk = Buffer.allocUnsafe(1024);
|
|
2918
|
+
while (true) {
|
|
2919
|
+
const length = readSync(fd, chunk, 0, chunk.length, null);
|
|
2920
|
+
if (length === 0) return chunks.length > 0 ? Buffer.concat(chunks).toString() : null;
|
|
2921
|
+
const bytes = chunk.subarray(0, length);
|
|
2922
|
+
const newline = bytes.findIndex((byte) => byte === 0x0a || byte === 0x0d);
|
|
2923
|
+
chunks.push(Buffer.from(newline < 0 ? bytes : bytes.subarray(0, newline)));
|
|
2924
|
+
if (newline >= 0) return Buffer.concat(chunks).toString();
|
|
2925
|
+
}
|
|
2926
|
+
}
|
|
2927
|
+
|
|
2928
|
+
protectedAlert(msg = "") {
|
|
2929
|
+
return this.runProtectedPrompt("alert", undefined, [String(msg)]);
|
|
2930
|
+
}
|
|
2931
|
+
|
|
2932
|
+
protectedConfirm(msg = "") {
|
|
2933
|
+
return this.runProtectedPrompt("confirm", false, [String(msg)]);
|
|
2934
|
+
}
|
|
2935
|
+
|
|
2936
|
+
protectedPrompt(msg = "", defaultValue = "") {
|
|
2937
|
+
return this.runProtectedPrompt(
|
|
2938
|
+
"prompt",
|
|
2939
|
+
defaultValue,
|
|
2940
|
+
[String(msg), String(defaultValue)],
|
|
2941
|
+
);
|
|
2942
|
+
}
|
|
2943
|
+
|
|
2944
|
+
restoreProtectedPrompts() {
|
|
2945
|
+
const saved = this._protectedPrompts;
|
|
2946
|
+
if (!saved) return;
|
|
2947
|
+
for (const name of ["alert", "confirm", "prompt"]) {
|
|
2948
|
+
if (saved[name].had) globalThis[name] = saved[name].value;
|
|
2949
|
+
else delete globalThis[name];
|
|
2950
|
+
}
|
|
2951
|
+
this._protectedPrompts = null;
|
|
2952
|
+
this._protectedPromptGlobals = null;
|
|
2953
|
+
}
|
|
2954
|
+
|
|
2647
2955
|
layoutEditorArea() {
|
|
2648
2956
|
const promptHeight = this.prompt ? 1 : 0;
|
|
2649
2957
|
const tabBarHeight = this.tabs.length > 1 ? 1 : 0;
|
|
@@ -3754,6 +4062,7 @@ class App {
|
|
|
3754
4062
|
|
|
3755
4063
|
const text = event.raw;
|
|
3756
4064
|
const seq = event.key;
|
|
4065
|
+
const keydownBlock = indexedMdcuiFenceBlockAtLine(buf, buf?.cursor.y);
|
|
3757
4066
|
if (buf) buf.allowCursorOffscreen = false;
|
|
3758
4067
|
|
|
3759
4068
|
if (this._rawMode) {
|
|
@@ -3764,6 +4073,12 @@ class App {
|
|
|
3764
4073
|
return;
|
|
3765
4074
|
}
|
|
3766
4075
|
|
|
4076
|
+
const keydownEvent = await this.dispatchMdcuiFenceEvent(buf, keydownBlock, event, "keydown");
|
|
4077
|
+
if (keydownEvent?.defaultPrevented && !["ctrl-q", "alt-q", "escape"].includes(seq)) {
|
|
4078
|
+
this.render();
|
|
4079
|
+
return;
|
|
4080
|
+
}
|
|
4081
|
+
|
|
3767
4082
|
// Reset undo insert chain on any non-printable-char key
|
|
3768
4083
|
if (!(seq === text && text.length === 1 && text >= " ")) this._undoInsertChain = false;
|
|
3769
4084
|
|
|
@@ -3952,15 +4267,28 @@ class App {
|
|
|
3952
4267
|
case "backspace":
|
|
3953
4268
|
buf.pushUndo();
|
|
3954
4269
|
if (this.pane?.selection) deleteSelection(buf, this.pane);
|
|
3955
|
-
else if (await this.runPluginBool("preBackspace"))
|
|
4270
|
+
else if (await this.runPluginBool("preBackspace")) {
|
|
4271
|
+
const textarea = mdcuiTextareaAtCursor(buf);
|
|
4272
|
+
if (!mergeTuiTextareaBackward(buf, textarea)) buf.backspace();
|
|
4273
|
+
}
|
|
3956
4274
|
break;
|
|
3957
4275
|
case "delete":
|
|
3958
4276
|
buf.pushUndo();
|
|
3959
4277
|
if (this.pane?.selection) deleteSelection(buf, this.pane);
|
|
3960
|
-
else
|
|
4278
|
+
else {
|
|
4279
|
+
const textarea = mdcuiTextareaAtCursor(buf);
|
|
4280
|
+
if (!mergeTuiTextareaForward(buf, textarea)) buf.deleteForward();
|
|
4281
|
+
}
|
|
3961
4282
|
break;
|
|
3962
4283
|
case "enter":
|
|
3963
4284
|
if (isMdcuiEncoding(buf?.encoding)) {
|
|
4285
|
+
const textarea = mdcuiTextareaAtCursor(buf);
|
|
4286
|
+
if (textarea && canEditMdcuiAtCursor(buf)) {
|
|
4287
|
+
buf.pushUndo();
|
|
4288
|
+
if (this.pane?.selection) deleteSelection(buf, this.pane);
|
|
4289
|
+
insertTuiTextareaNewline(buf, textarea);
|
|
4290
|
+
break;
|
|
4291
|
+
}
|
|
3964
4292
|
await this.handleMdcuiCellCallback(buf, buf.cursor.y, buf.cursor.x, "enter");
|
|
3965
4293
|
break;
|
|
3966
4294
|
}
|
|
@@ -4136,6 +4464,48 @@ class App {
|
|
|
4136
4464
|
this.render();
|
|
4137
4465
|
}
|
|
4138
4466
|
|
|
4467
|
+
async dispatchMdcuiFenceEvent(buf, block, inputEvent, eventName) {
|
|
4468
|
+
const id = block?.header?.id;
|
|
4469
|
+
const declaration = id ? buf?._mdcuiFenceEvents?.get(id) : null;
|
|
4470
|
+
const handler = declaration?.events?.get(eventName);
|
|
4471
|
+
const code = inlineFenceEventCode(handler);
|
|
4472
|
+
if (
|
|
4473
|
+
!code
|
|
4474
|
+
|| declaration.tag !== block?.header?.tag
|
|
4475
|
+
|| !buf?.path
|
|
4476
|
+
|| isHttpUrl(buf.path)
|
|
4477
|
+
) return false;
|
|
4478
|
+
|
|
4479
|
+
const frontPath = `${buf.path}.front.js`;
|
|
4480
|
+
if (!existsSync(frontPath)) return false;
|
|
4481
|
+
try {
|
|
4482
|
+
const selection = globalThis.$?.(`${declaration.tag}#${id}`);
|
|
4483
|
+
const target = {
|
|
4484
|
+
id,
|
|
4485
|
+
tagName: declaration.tag.toUpperCase(),
|
|
4486
|
+
className: declaration.classes.join(" "),
|
|
4487
|
+
};
|
|
4488
|
+
Object.defineProperty(target, "value", {
|
|
4489
|
+
enumerable: true,
|
|
4490
|
+
get: () => selection?.val?.() ?? "",
|
|
4491
|
+
set: (value) => selection?.val?.(value),
|
|
4492
|
+
});
|
|
4493
|
+
const event = tuiKeyEventForFront(inputEvent, target, eventName);
|
|
4494
|
+
const [{ evalFront }, frontMod] = await Promise.all([
|
|
4495
|
+
import("./cui/rpc.mjs"),
|
|
4496
|
+
import(localModuleUrl(frontPath)),
|
|
4497
|
+
]);
|
|
4498
|
+
const result = await evalFront(frontMod, code, { event });
|
|
4499
|
+
if (result && typeof result === "object" && result.ok === false) {
|
|
4500
|
+
this.message = `mdcui ${eventName}: ${String(result.error ?? "Unknown error")}`;
|
|
4501
|
+
}
|
|
4502
|
+
return event;
|
|
4503
|
+
} catch (error) {
|
|
4504
|
+
this.message = `mdcui ${eventName}: ${String(error?.message || error)}`;
|
|
4505
|
+
return null;
|
|
4506
|
+
}
|
|
4507
|
+
}
|
|
4508
|
+
|
|
4139
4509
|
async handleMdcuiCellCallback(buf, y = buf?.cursor?.y ?? 0, x = buf?.cursor?.x ?? 0, trigger = "unknown") {
|
|
4140
4510
|
const payload = mdcuiCellPayload(buf, y, x, trigger);
|
|
4141
4511
|
if (!payload) return false;
|
|
@@ -4162,50 +4532,11 @@ class App {
|
|
|
4162
4532
|
import("./cui/rpc.mjs"),
|
|
4163
4533
|
import(localModuleUrl(`${buf.path}.front.js`)),
|
|
4164
4534
|
]);
|
|
4165
|
-
const
|
|
4166
|
-
|
|
4167
|
-
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
const prevPrompt = globalThis.prompt;
|
|
4171
|
-
const nativeAlert = typeof prevAlert === "function" ? prevAlert : null;
|
|
4172
|
-
const withNativePrompt = (nativeFn, fallback, args) => {
|
|
4173
|
-
if (!this._started || typeof nativeFn !== "function") {
|
|
4174
|
-
this.message = String(args[0] ?? "");
|
|
4175
|
-
return fallback;
|
|
4176
|
-
}
|
|
4177
|
-
const tty = this._ttyStream ?? process.stdin;
|
|
4178
|
-
this._alertRunning = true;
|
|
4179
|
-
tty.setRawMode?.(false);
|
|
4180
|
-
this.screen.fini();
|
|
4181
|
-
this.screen.previous = null;
|
|
4182
|
-
try {
|
|
4183
|
-
return nativeFn(...args);
|
|
4184
|
-
} finally {
|
|
4185
|
-
tty.setRawMode?.(true);
|
|
4186
|
-
this.screen.previous = null;
|
|
4187
|
-
this.screen.init();
|
|
4188
|
-
this._alertRunning = false;
|
|
4189
|
-
this.render();
|
|
4190
|
-
}
|
|
4191
|
-
};
|
|
4192
|
-
globalThis.alert = (msg = "") => withNativePrompt(nativeAlert, undefined, [String(msg)]);
|
|
4193
|
-
globalThis.confirm = (msg = "") => withNativePrompt(prevConfirm, false, [String(msg)]);
|
|
4194
|
-
globalThis.prompt = (msg = "", defaultValue = "") => withNativePrompt(prevPrompt, defaultValue, [String(msg), String(defaultValue)]);
|
|
4195
|
-
try {
|
|
4196
|
-
const result = await evalFront(frontMod, payload.link);
|
|
4197
|
-
if (result && typeof result === "object" && result.ok === false) {
|
|
4198
|
-
globalThis.alert(String(result.error ?? "Unknown error"));
|
|
4199
|
-
} else if (result != null) {
|
|
4200
|
-
this.message = String(result);
|
|
4201
|
-
}
|
|
4202
|
-
} finally {
|
|
4203
|
-
if (hadAlert) globalThis.alert = prevAlert;
|
|
4204
|
-
else delete globalThis.alert;
|
|
4205
|
-
if (hadConfirm) globalThis.confirm = prevConfirm;
|
|
4206
|
-
else delete globalThis.confirm;
|
|
4207
|
-
if (hadPrompt) globalThis.prompt = prevPrompt;
|
|
4208
|
-
else delete globalThis.prompt;
|
|
4535
|
+
const result = await evalFront(frontMod, payload.link);
|
|
4536
|
+
if (result && typeof result === "object" && result.ok === false) {
|
|
4537
|
+
this.protectedAlert(String(result.error ?? "Unknown error"));
|
|
4538
|
+
} else if (result != null) {
|
|
4539
|
+
this.message = String(result);
|
|
4209
4540
|
}
|
|
4210
4541
|
return true;
|
|
4211
4542
|
} catch (error) {
|
|
@@ -7687,6 +8018,12 @@ async function exportReadme() {
|
|
|
7687
8018
|
console.log(`Wrote ${readmePath}`);
|
|
7688
8019
|
}
|
|
7689
8020
|
|
|
8021
|
+
async function exportCdpMaze() {
|
|
8022
|
+
const outputPath = resolve("cdp-maze.js");
|
|
8023
|
+
await Bun.write(outputPath, await bundledMarkdownSource("cdp-maze.js"));
|
|
8024
|
+
console.log(`Wrote ${outputPath}`);
|
|
8025
|
+
}
|
|
8026
|
+
|
|
7690
8027
|
async function printChangelogDocs() {
|
|
7691
8028
|
const changelog = readInternalAssetText("CHANGELOG.md") ?? await Bun.file(join(REPO_ROOT, "CHANGELOG.md")).text();
|
|
7692
8029
|
process.stdout.write(Bun.markdown.ansi(changelog, { hyperlinks: true }));
|
|
@@ -7808,6 +8145,10 @@ async function main() {
|
|
|
7808
8145
|
await exportReadme();
|
|
7809
8146
|
return;
|
|
7810
8147
|
}
|
|
8148
|
+
if (flags.exportCdpMaze) {
|
|
8149
|
+
await exportCdpMaze();
|
|
8150
|
+
return;
|
|
8151
|
+
}
|
|
7811
8152
|
if (flags.changelog) {
|
|
7812
8153
|
await printChangelogDocs();
|
|
7813
8154
|
return;
|
|
@@ -8033,6 +8374,7 @@ async function main() {
|
|
|
8033
8374
|
addCheckpoint("App Instantiation");
|
|
8034
8375
|
const app = new App(buffers, context);
|
|
8035
8376
|
jsPlugins.setApp(app);
|
|
8377
|
+
app.installProtectedPrompts();
|
|
8036
8378
|
// if (plugins && !pluginErr && app.buffer) plugins.curPaneAdapter = makePaneAdapter(app.buffer, app);
|
|
8037
8379
|
// Dispatch all JS plugin lifecycle hooks after setApp so TermMessage,
|
|
8038
8380
|
// CurPane, cmd/action proxies, and buffer APIs all work correctly.
|
|
@@ -8053,6 +8395,23 @@ async function main() {
|
|
|
8053
8395
|
if (flags.cdpAddress) cdpArgs.push(`--address=${flags.cdpAddress}`);
|
|
8054
8396
|
await app.handleCommand(`cdp ${cdpArgs.join(" ")}`);
|
|
8055
8397
|
}
|
|
8398
|
+
|
|
8399
|
+
if (flags.cdpMaze) {
|
|
8400
|
+
const solverHost = !flags.cdpAddress || flags.cdpAddress === "0.0.0.0"
|
|
8401
|
+
? "127.0.0.1"
|
|
8402
|
+
: flags.cdpAddress;
|
|
8403
|
+
const solverUrl = `ws://${solverHost}:${flags.cdpPort}/devtools/browser/cdp-server`;
|
|
8404
|
+
setTimeout(async () => {
|
|
8405
|
+
try {
|
|
8406
|
+
const { runCdpMaze } = await import("../cdp-maze.js");
|
|
8407
|
+
app.message = await runCdpMaze(solverUrl);
|
|
8408
|
+
app.render?.();
|
|
8409
|
+
} catch (error) {
|
|
8410
|
+
app.message = `CDP maze solver failed: ${error?.message || error}`;
|
|
8411
|
+
app.render?.();
|
|
8412
|
+
}
|
|
8413
|
+
}, 3000);
|
|
8414
|
+
}
|
|
8056
8415
|
|
|
8057
8416
|
if (flags.profile) {
|
|
8058
8417
|
addCheckpoint("Clipboard Probing");
|
|
@@ -8520,9 +8879,6 @@ async function catFiles(files, colorscheme, syntaxDefinitions, encoding = DEFAUL
|
|
|
8520
8879
|
}
|
|
8521
8880
|
|
|
8522
8881
|
|
|
8523
|
-
mainPromise.then(r=>{
|
|
8524
|
-
|
|
8525
|
-
|
|
8526
8882
|
main().catch((error) => {
|
|
8527
8883
|
try {
|
|
8528
8884
|
(_activeTtyStream ?? process.stdin).setRawMode?.(false);
|
|
@@ -8532,6 +8888,3 @@ main().catch((error) => {
|
|
|
8532
8888
|
process.exit(1);
|
|
8533
8889
|
}
|
|
8534
8890
|
});
|
|
8535
|
-
|
|
8536
|
-
|
|
8537
|
-
})
|