opencode-project-panel 0.1.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.
Files changed (4) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +47 -0
  3. package/dist/index.js +3975 -0
  4. package/package.json +52 -0
package/dist/index.js ADDED
@@ -0,0 +1,3975 @@
1
+ // @bun
2
+ // src/bottom-bar.tsx
3
+ import { RGBA as RGBA4 } from "@opentui/core";
4
+ import { useBindings as useBindings4 } from "@opentui/keymap/solid";
5
+ import { writeFileSync as writeFileSync4, existsSync as existsSync2 } from "fs";
6
+ import path4 from "path";
7
+
8
+ // src/new-file-manager.tsx
9
+ import { RGBA as RGBA2, SyntaxStyle as SyntaxStyle2, parseColor as parseColor2 } from "@opentui/core";
10
+ import { useTerminalDimensions as useTerminalDimensions2 } from "@opentui/solid";
11
+ import { useBindings as useBindings2 } from "@opentui/keymap/solid";
12
+ import { onCleanup } from "solid-js";
13
+ import { readdirSync, readFileSync as readFileSync2, openSync, readSync, closeSync, mkdirSync, writeFileSync as writeFileSync2, renameSync, rmSync, statSync } from "fs";
14
+ import path2 from "path";
15
+
16
+ // src/file-viewer.tsx
17
+ import { RGBA, SyntaxStyle, parseColor } from "@opentui/core";
18
+ import { useTerminalDimensions } from "@opentui/solid";
19
+ import { useBindings } from "@opentui/keymap/solid";
20
+ import { createSignal, onMount } from "solid-js";
21
+ import { readFileSync, writeFileSync } from "fs";
22
+ import path from "path";
23
+ import { jsxDEV } from "@opentui/solid/jsx-dev-runtime";
24
+ var SYNTAX_STYLE = SyntaxStyle.fromStyles({
25
+ default: { fg: parseColor("#E6EDF3") },
26
+ keyword: { fg: parseColor("#FF7B72"), bold: true },
27
+ string: { fg: parseColor("#A5D6FF") },
28
+ comment: { fg: parseColor("#8B949E"), italic: true },
29
+ number: { fg: parseColor("#79C0FF") },
30
+ function: { fg: parseColor("#D2A8FF") },
31
+ type: { fg: parseColor("#FFA657") },
32
+ operator: { fg: parseColor("#FF7B72") },
33
+ variable: { fg: parseColor("#E6EDF3") },
34
+ property: { fg: parseColor("#79C0FF") },
35
+ "punctuation.bracket": { fg: parseColor("#F0F6FC") },
36
+ "punctuation.delimiter": { fg: parseColor("#C9D1D9") },
37
+ "markup.heading": { fg: parseColor("#58A6FF"), bold: true },
38
+ "markup.bold": { fg: parseColor("#F0F6FC"), bold: true },
39
+ "markup.italic": { fg: parseColor("#F0F6FC"), italic: true },
40
+ "markup.list": { fg: parseColor("#FF7B72") },
41
+ "markup.quote": { fg: parseColor("#8B949E"), italic: true },
42
+ "markup.raw": { fg: parseColor("#A5D6FF"), bg: parseColor("#161B22") },
43
+ "markup.link": { fg: parseColor("#58A6FF"), underline: true },
44
+ "markup.link.url": { fg: parseColor("#58A6FF"), underline: true },
45
+ "diff.plus": { fg: parseColor("#3FB950") },
46
+ "diff.minus": { fg: parseColor("#F85149") },
47
+ conceal: { fg: parseColor("#6E7681") }
48
+ });
49
+ var SEARCH_HL_STYLE_ID = SYNTAX_STYLE.registerStyle("search-match", { bg: parseColor("#FF8C00"), fg: parseColor("#000000") });
50
+ var SEARCH_CURRENT_HL_STYLE_ID = SYNTAX_STYLE.registerStyle("search-current", { bg: parseColor("#FFFF00"), fg: parseColor("#000000"), bold: true });
51
+ var EXT_TO_FILETYPE = {
52
+ ".ts": "typescript",
53
+ ".tsx": "typescriptreact",
54
+ ".mts": "typescript",
55
+ ".cts": "typescript",
56
+ ".js": "javascript",
57
+ ".jsx": "javascriptreact",
58
+ ".mjs": "javascript",
59
+ ".cjs": "javascript",
60
+ ".json": "json",
61
+ ".md": "markdown",
62
+ ".mdx": "markdown",
63
+ ".css": "css",
64
+ ".html": "html",
65
+ ".xml": "xml",
66
+ ".yaml": "yaml",
67
+ ".yml": "yaml",
68
+ ".toml": "toml",
69
+ ".sh": "bash",
70
+ ".bash": "bash",
71
+ ".zsh": "bash",
72
+ ".py": "python",
73
+ ".rb": "ruby",
74
+ ".go": "go",
75
+ ".rs": "rust",
76
+ ".zig": "zig",
77
+ ".java": "java",
78
+ ".kt": "kotlin",
79
+ ".swift": "swift",
80
+ ".c": "c",
81
+ ".cpp": "cpp",
82
+ ".h": "c",
83
+ ".hpp": "cpp",
84
+ ".cs": "csharp",
85
+ ".lua": "lua",
86
+ ".sql": "sql",
87
+ ".graphql": "graphql",
88
+ ".proto": "protobuf",
89
+ ".tf": "terraform",
90
+ ".scala": "scala",
91
+ ".r": "r",
92
+ ".pl": "perl",
93
+ ".ex": "elixir",
94
+ ".exs": "elixir",
95
+ ".erl": "erlang",
96
+ ".clj": "clojure",
97
+ ".nix": "nix"
98
+ };
99
+ var MD_EXT = new Set([".md", ".mdx", ".markdown"]);
100
+ function isMarkdownPath(fp) {
101
+ return MD_EXT.has(path.extname(fp).toLowerCase());
102
+ }
103
+ var HINT_FG = RGBA.fromInts(180, 180, 180, 255);
104
+ var FG = RGBA.fromInts(255, 255, 255, 255);
105
+ function FileViewer(props) {
106
+ let codeRef;
107
+ let markdownRef;
108
+ let textareaRef;
109
+ let searchInputRef;
110
+ let previewScrollBox;
111
+ let dirtyEl;
112
+ let matchCountEl;
113
+ let previewButtonsBox;
114
+ let editButtonsBox;
115
+ let searchBox;
116
+ let bottomBarBox;
117
+ const dimensions = useTerminalDimensions();
118
+ const theme = () => props.api.theme.current;
119
+ const isMarkdown = isMarkdownPath(props.filePath);
120
+ const filetype = EXT_TO_FILETYPE[path.extname(props.filePath).toLowerCase()] ?? "";
121
+ const [mode, setMode] = createSignal(props.initialMode ?? "preview");
122
+ const [focusedId, setFocusedId] = createSignal("content");
123
+ const [textareaTarget, setTextareaTarget] = createSignal();
124
+ const [searchInputTarget, setSearchInputTarget] = createSignal();
125
+ let dirty = false;
126
+ let originalContent = "";
127
+ let searchQuery = "";
128
+ let matches = [];
129
+ let currentMatch = -1;
130
+ try {
131
+ originalContent = readFileSync(props.filePath, "utf-8");
132
+ } catch {
133
+ originalContent = "// Error reading file";
134
+ }
135
+ const panelWidth = () => Math.min(Math.max(dimensions().width - 2, 60), 116);
136
+ const panelHeight = () => Math.max(Math.floor(dimensions().height * 0.78) - 2, 22);
137
+ const refreshMatchCount = () => {
138
+ if (matches.length === 0) {
139
+ matchCountEl.content = searchQuery ? "0/0" : "";
140
+ } else {
141
+ matchCountEl.content = `${currentMatch + 1}/${matches.length}`;
142
+ }
143
+ };
144
+ function setFocusTarget(id) {
145
+ setFocusedId(id);
146
+ if (id === "content") {
147
+ searchInputRef?.blur();
148
+ if (mode() === "edit")
149
+ textareaRef?.focus();
150
+ } else {
151
+ if (mode() === "edit")
152
+ textareaRef?.blur();
153
+ searchInputRef?.focus();
154
+ }
155
+ }
156
+ function setModeVisible(next) {
157
+ setMode(next);
158
+ const isPrev = next === "preview";
159
+ if (previewScrollBox)
160
+ previewScrollBox.visible = isPrev;
161
+ if (textareaRef)
162
+ textareaRef.visible = !isPrev;
163
+ if (previewButtonsBox)
164
+ previewButtonsBox.visible = isPrev;
165
+ if (editButtonsBox)
166
+ editButtonsBox.visible = !isPrev;
167
+ if (searchBox)
168
+ searchBox.visible = !isPrev;
169
+ if (bottomBarBox)
170
+ bottomBarBox.paddingBottom = isPrev ? 1 : 0;
171
+ if (isPrev) {
172
+ if (isMarkdown)
173
+ markdownRef.content = originalContent;
174
+ else
175
+ codeRef.content = originalContent;
176
+ } else {
177
+ textareaRef.setText(originalContent);
178
+ }
179
+ setFocusTarget("content");
180
+ }
181
+ const switchMode = setModeVisible;
182
+ function reload() {
183
+ try {
184
+ const content = readFileSync(props.filePath, "utf-8");
185
+ originalContent = content;
186
+ if (isMarkdown)
187
+ markdownRef.content = content;
188
+ else
189
+ codeRef.content = content;
190
+ textareaRef.setText(content);
191
+ } catch {}
192
+ dirty = false;
193
+ dirtyEl.content = "";
194
+ matches = [];
195
+ currentMatch = -1;
196
+ refreshMatchCount();
197
+ }
198
+ function save() {
199
+ try {
200
+ writeFileSync(props.filePath, textareaRef.plainText, "utf-8");
201
+ originalContent = textareaRef.plainText;
202
+ } catch {}
203
+ dirty = false;
204
+ dirtyEl.content = "";
205
+ setModeVisible("preview");
206
+ }
207
+ function cancelEdit() {
208
+ textareaRef.setText(originalContent);
209
+ dirty = false;
210
+ dirtyEl.content = "";
211
+ setModeVisible("preview");
212
+ }
213
+ function pageUp() {
214
+ if (!textareaRef)
215
+ return;
216
+ const vp = textareaRef.editorView.getViewport();
217
+ const cur = textareaRef.logicalCursor.row;
218
+ textareaRef.gotoLine(Math.max(0, cur - vp.height));
219
+ }
220
+ function pageDown() {
221
+ if (!textareaRef)
222
+ return;
223
+ const vp = textareaRef.editorView.getViewport();
224
+ const cur = textareaRef.logicalCursor.row;
225
+ textareaRef.gotoLine(cur + vp.height);
226
+ }
227
+ function toggleMode() {
228
+ if (mode() === "preview")
229
+ switchMode("edit");
230
+ else
231
+ cancelEdit();
232
+ }
233
+ function offsetExcludingNewlines(text, offset) {
234
+ let nl = 0;
235
+ for (let i = 0;i < offset && i < text.length; i++) {
236
+ if (text[i] === `
237
+ `)
238
+ nl++;
239
+ }
240
+ return offset - nl;
241
+ }
242
+ function computeMatches(query) {
243
+ searchQuery = query;
244
+ if (!textareaRef)
245
+ return;
246
+ textareaRef.clearAllHighlights();
247
+ if (!query) {
248
+ matches = [];
249
+ currentMatch = -1;
250
+ refreshMatchCount();
251
+ return;
252
+ }
253
+ const found = [];
254
+ const text = textareaRef.plainText;
255
+ let pos = 0;
256
+ while (pos <= text.length) {
257
+ const idx = text.indexOf(query, pos);
258
+ if (idx === -1)
259
+ break;
260
+ found.push({ start: idx, end: idx + query.length });
261
+ pos = idx + query.length;
262
+ }
263
+ matches = found;
264
+ currentMatch = matches.length > 0 ? 0 : -1;
265
+ applyHighlights();
266
+ refreshMatchCount();
267
+ scrollToCurrentMatch();
268
+ }
269
+ function applyHighlights() {
270
+ if (!textareaRef || !matches.length)
271
+ return;
272
+ const text = textareaRef.plainText;
273
+ textareaRef.clearAllHighlights();
274
+ matches.forEach((m, i) => {
275
+ textareaRef.addHighlightByCharRange({
276
+ start: offsetExcludingNewlines(text, m.start),
277
+ end: offsetExcludingNewlines(text, m.end),
278
+ styleId: i === currentMatch ? SEARCH_CURRENT_HL_STYLE_ID : SEARCH_HL_STYLE_ID,
279
+ hlRef: i
280
+ });
281
+ });
282
+ }
283
+ function scrollToCurrentMatch() {
284
+ const match = matches[currentMatch];
285
+ if (!textareaRef || !match)
286
+ return;
287
+ textareaRef.cursorOffset = match.start;
288
+ }
289
+ function nextMatch() {
290
+ if (matches.length === 0)
291
+ return;
292
+ currentMatch = (currentMatch + 1) % matches.length;
293
+ applyHighlights();
294
+ refreshMatchCount();
295
+ scrollToCurrentMatch();
296
+ }
297
+ function prevMatch() {
298
+ if (matches.length === 0)
299
+ return;
300
+ currentMatch = (currentMatch - 1 + matches.length) % matches.length;
301
+ applyHighlights();
302
+ refreshMatchCount();
303
+ scrollToCurrentMatch();
304
+ }
305
+ useBindings(() => ({
306
+ priority: 2,
307
+ enabled: () => focusedId() !== "search",
308
+ bindings: [
309
+ { key: "f5", cmd: reload },
310
+ { key: "ctrl+e", cmd: toggleMode },
311
+ { key: "ctrl+q", cmd: cancelEdit }
312
+ ]
313
+ }));
314
+ useBindings(() => ({
315
+ priority: 2,
316
+ enabled: () => mode() === "edit",
317
+ bindings: [
318
+ { key: "ctrl+n", cmd: nextMatch },
319
+ { key: "ctrl+p", cmd: prevMatch },
320
+ { key: "f3", cmd: nextMatch },
321
+ { key: "pageup", cmd: pageUp },
322
+ { key: "pagedown", cmd: pageDown }
323
+ ]
324
+ }));
325
+ useBindings(() => ({
326
+ priority: 2,
327
+ enabled: () => mode() === "preview",
328
+ bindings: [
329
+ { key: "home", cmd: () => {
330
+ if (previewScrollBox)
331
+ previewScrollBox.scrollTop = 0;
332
+ } },
333
+ { key: "end", cmd: () => {
334
+ if (previewScrollBox)
335
+ previewScrollBox.scrollTop = previewScrollBox.scrollHeight - previewScrollBox.height;
336
+ } },
337
+ { key: "pageup", cmd: () => previewScrollBox?.scrollBy({ y: -(previewScrollBox?.height ?? 0) }) },
338
+ { key: "pagedown", cmd: () => previewScrollBox?.scrollBy({ y: previewScrollBox?.height ?? 0 }) },
339
+ { key: "up", cmd: () => previewScrollBox?.scrollBy({ y: -1 }) },
340
+ { key: "down", cmd: () => previewScrollBox?.scrollBy({ y: 1 }) }
341
+ ]
342
+ }));
343
+ useBindings(() => ({
344
+ target: textareaTarget,
345
+ enabled: textareaTarget() !== undefined,
346
+ priority: 1,
347
+ bindings: [
348
+ {
349
+ key: "return",
350
+ cmd: () => textareaRef?.newLine()
351
+ },
352
+ {
353
+ key: "home",
354
+ cmd: () => textareaRef?.gotoLineHome()
355
+ },
356
+ {
357
+ key: "end",
358
+ cmd: () => textareaRef?.gotoLineEnd()
359
+ },
360
+ {
361
+ key: "ctrl+s",
362
+ cmd: () => {
363
+ if (mode() === "edit")
364
+ save();
365
+ }
366
+ },
367
+ { key: "ctrl+f", cmd: () => setFocusTarget("search") }
368
+ ]
369
+ }));
370
+ useBindings(() => ({
371
+ target: searchInputTarget,
372
+ enabled: searchInputTarget() !== undefined,
373
+ priority: 1,
374
+ bindings: [
375
+ {
376
+ key: "escape",
377
+ cmd: () => setFocusTarget("content")
378
+ }
379
+ ]
380
+ }));
381
+ useBindings(() => ({
382
+ priority: 2,
383
+ enabled: () => focusedId() !== "search",
384
+ bindings: [
385
+ {
386
+ key: "escape",
387
+ cmd: () => {
388
+ if (props.onBack)
389
+ props.onBack();
390
+ }
391
+ }
392
+ ]
393
+ }));
394
+ onMount(() => {
395
+ if (props.initialMode === "edit") {
396
+ switchMode("edit");
397
+ }
398
+ });
399
+ return /* @__PURE__ */ jsxDEV("box", {
400
+ width: panelWidth(),
401
+ height: panelHeight(),
402
+ flexDirection: "column",
403
+ children: [
404
+ /* @__PURE__ */ jsxDEV("box", {
405
+ paddingLeft: 2,
406
+ paddingRight: 2,
407
+ flexShrink: 0,
408
+ border: ["bottom"],
409
+ borderColor: theme().textMuted,
410
+ flexDirection: "row",
411
+ children: [
412
+ /* @__PURE__ */ jsxDEV("text", {
413
+ fg: theme().text,
414
+ children: [
415
+ "File Path: ",
416
+ props.filePath
417
+ ]
418
+ }, undefined, true, undefined, this),
419
+ /* @__PURE__ */ jsxDEV("text", {
420
+ ref: (el) => {
421
+ dirtyEl = el;
422
+ },
423
+ fg: theme().textMuted
424
+ }, undefined, false, undefined, this),
425
+ /* @__PURE__ */ jsxDEV("box", {
426
+ flexGrow: 1
427
+ }, undefined, false, undefined, this),
428
+ /* @__PURE__ */ jsxDEV("box", {
429
+ flexDirection: "row",
430
+ onMouseUp: () => {
431
+ if (props.onBack)
432
+ props.onBack();
433
+ },
434
+ children: [
435
+ /* @__PURE__ */ jsxDEV("text", {
436
+ fg: HINT_FG,
437
+ children: "[ESC]"
438
+ }, undefined, false, undefined, this),
439
+ /* @__PURE__ */ jsxDEV("text", {
440
+ fg: FG,
441
+ children: " Close"
442
+ }, undefined, false, undefined, this)
443
+ ]
444
+ }, undefined, true, undefined, this)
445
+ ]
446
+ }, undefined, true, undefined, this),
447
+ /* @__PURE__ */ jsxDEV("scrollbox", {
448
+ ref: (el) => {
449
+ previewScrollBox = el;
450
+ },
451
+ width: "100%",
452
+ flexGrow: 1,
453
+ scrollbarOptions: { visible: true },
454
+ children: [
455
+ /* @__PURE__ */ jsxDEV("code", {
456
+ ref: (el) => {
457
+ codeRef = el;
458
+ el.content = originalContent;
459
+ el.filetype = filetype;
460
+ },
461
+ visible: !isMarkdown,
462
+ syntaxStyle: SYNTAX_STYLE,
463
+ selectable: true,
464
+ width: "100%",
465
+ onMouseDown: () => setFocusTarget("content")
466
+ }, undefined, false, undefined, this),
467
+ /* @__PURE__ */ jsxDEV("markdown", {
468
+ ref: (el) => {
469
+ markdownRef = el;
470
+ el.content = originalContent;
471
+ },
472
+ visible: isMarkdown,
473
+ syntaxStyle: SYNTAX_STYLE,
474
+ conceal: true,
475
+ fg: theme().text,
476
+ width: "100%"
477
+ }, undefined, false, undefined, this)
478
+ ]
479
+ }, undefined, true, undefined, this),
480
+ /* @__PURE__ */ jsxDEV("textarea", {
481
+ ref: (el) => {
482
+ textareaRef = el;
483
+ setTextareaTarget(el);
484
+ el.setText(originalContent);
485
+ },
486
+ visible: false,
487
+ syntaxStyle: SYNTAX_STYLE,
488
+ flexGrow: 1,
489
+ selectable: true,
490
+ onMouseDown: () => setFocusTarget("content"),
491
+ onContentChange: () => {
492
+ if (!dirty) {
493
+ dirty = true;
494
+ dirtyEl.content = "*";
495
+ }
496
+ if (searchQuery && mode() === "edit")
497
+ computeMatches(searchQuery);
498
+ }
499
+ }, undefined, false, undefined, this),
500
+ /* @__PURE__ */ jsxDEV("box", {
501
+ ref: (el) => {
502
+ bottomBarBox = el;
503
+ },
504
+ flexShrink: 0,
505
+ flexDirection: "row",
506
+ paddingLeft: 2,
507
+ paddingTop: 1,
508
+ paddingBottom: 1,
509
+ gap: 2,
510
+ border: ["top"],
511
+ borderColor: theme().textMuted,
512
+ children: /* @__PURE__ */ jsxDEV("box", {
513
+ flexDirection: "row",
514
+ gap: 3,
515
+ flexGrow: 1,
516
+ children: [
517
+ /* @__PURE__ */ jsxDEV("box", {
518
+ ref: (el) => {
519
+ previewButtonsBox = el;
520
+ },
521
+ visible: true,
522
+ flexDirection: "row",
523
+ gap: 3,
524
+ children: [
525
+ /* @__PURE__ */ jsxDEV("box", {
526
+ flexDirection: "row",
527
+ gap: 0,
528
+ onMouseDown: reload,
529
+ children: [
530
+ /* @__PURE__ */ jsxDEV("text", {
531
+ fg: HINT_FG,
532
+ children: "[F5]"
533
+ }, undefined, false, undefined, this),
534
+ /* @__PURE__ */ jsxDEV("text", {
535
+ fg: theme().text,
536
+ children: " Reload"
537
+ }, undefined, false, undefined, this)
538
+ ]
539
+ }, undefined, true, undefined, this),
540
+ /* @__PURE__ */ jsxDEV("box", {
541
+ flexDirection: "row",
542
+ gap: 0,
543
+ onMouseDown: () => switchMode("edit"),
544
+ children: [
545
+ /* @__PURE__ */ jsxDEV("text", {
546
+ fg: HINT_FG,
547
+ children: "[Ctrl+E]"
548
+ }, undefined, false, undefined, this),
549
+ /* @__PURE__ */ jsxDEV("text", {
550
+ fg: theme().text,
551
+ children: " Edit"
552
+ }, undefined, false, undefined, this)
553
+ ]
554
+ }, undefined, true, undefined, this)
555
+ ]
556
+ }, undefined, true, undefined, this),
557
+ /* @__PURE__ */ jsxDEV("box", {
558
+ ref: (el) => {
559
+ editButtonsBox = el;
560
+ },
561
+ visible: false,
562
+ flexDirection: "row",
563
+ gap: 3,
564
+ children: [
565
+ /* @__PURE__ */ jsxDEV("box", {
566
+ flexDirection: "row",
567
+ gap: 0,
568
+ onMouseDown: save,
569
+ children: [
570
+ /* @__PURE__ */ jsxDEV("text", {
571
+ fg: HINT_FG,
572
+ children: "[Ctrl+S]"
573
+ }, undefined, false, undefined, this),
574
+ /* @__PURE__ */ jsxDEV("text", {
575
+ fg: theme().text,
576
+ children: " Save"
577
+ }, undefined, false, undefined, this)
578
+ ]
579
+ }, undefined, true, undefined, this),
580
+ /* @__PURE__ */ jsxDEV("box", {
581
+ flexDirection: "row",
582
+ gap: 0,
583
+ onMouseDown: cancelEdit,
584
+ children: [
585
+ /* @__PURE__ */ jsxDEV("text", {
586
+ fg: HINT_FG,
587
+ children: "[Ctrl+Q]"
588
+ }, undefined, false, undefined, this),
589
+ /* @__PURE__ */ jsxDEV("text", {
590
+ fg: theme().text,
591
+ children: " Cancel"
592
+ }, undefined, false, undefined, this)
593
+ ]
594
+ }, undefined, true, undefined, this)
595
+ ]
596
+ }, undefined, true, undefined, this),
597
+ /* @__PURE__ */ jsxDEV("box", {
598
+ ref: (el) => {
599
+ searchBox = el;
600
+ },
601
+ visible: false,
602
+ flexDirection: "row",
603
+ flexGrow: 1,
604
+ border: ["bottom"],
605
+ borderColor: theme().textMuted,
606
+ children: [
607
+ /* @__PURE__ */ jsxDEV("text", {
608
+ fg: HINT_FG,
609
+ flexShrink: 0,
610
+ children: "[Ctrl+F]"
611
+ }, undefined, false, undefined, this),
612
+ /* @__PURE__ */ jsxDEV("text", {
613
+ fg: theme().textMuted,
614
+ children: " "
615
+ }, undefined, false, undefined, this),
616
+ /* @__PURE__ */ jsxDEV("input", {
617
+ ref: (el) => {
618
+ searchInputRef = el;
619
+ setSearchInputTarget(el);
620
+ },
621
+ placeholder: "Search...",
622
+ flexGrow: 1,
623
+ onMouseDown: () => setFocusTarget("search"),
624
+ onInput: (value) => computeMatches(value),
625
+ onSubmit: () => nextMatch()
626
+ }, undefined, false, undefined, this),
627
+ /* @__PURE__ */ jsxDEV("text", {
628
+ fg: theme().textMuted,
629
+ children: " "
630
+ }, undefined, false, undefined, this),
631
+ /* @__PURE__ */ jsxDEV("text", {
632
+ fg: theme().textMuted,
633
+ onMouseDown: prevMatch,
634
+ children: "\u25C0"
635
+ }, undefined, false, undefined, this),
636
+ /* @__PURE__ */ jsxDEV("text", {
637
+ fg: theme().textMuted,
638
+ onMouseDown: nextMatch,
639
+ children: "\u25B6"
640
+ }, undefined, false, undefined, this),
641
+ /* @__PURE__ */ jsxDEV("text", {
642
+ fg: theme().textMuted,
643
+ children: " "
644
+ }, undefined, false, undefined, this),
645
+ /* @__PURE__ */ jsxDEV("text", {
646
+ ref: (el) => {
647
+ matchCountEl = el;
648
+ },
649
+ fg: theme().textMuted
650
+ }, undefined, false, undefined, this)
651
+ ]
652
+ }, undefined, true, undefined, this)
653
+ ]
654
+ }, undefined, true, undefined, this)
655
+ }, undefined, false, undefined, this)
656
+ ]
657
+ }, undefined, true, undefined, this);
658
+ }
659
+
660
+ // src/new-file-manager.tsx
661
+ import { jsxDEV as jsxDEV2 } from "@opentui/solid/jsx-dev-runtime";
662
+ var currentFileActions = null;
663
+ var focusedPane = "select";
664
+ var isOverlayActive = false;
665
+ var TEXT_EXTENSIONS = new Set([
666
+ ".txt",
667
+ ".md",
668
+ ".mdx",
669
+ ".markdown",
670
+ ".ts",
671
+ ".tsx",
672
+ ".mts",
673
+ ".cts",
674
+ ".js",
675
+ ".jsx",
676
+ ".mjs",
677
+ ".cjs",
678
+ ".json",
679
+ ".jsonc",
680
+ ".json5",
681
+ ".yml",
682
+ ".yaml",
683
+ ".toml",
684
+ ".xml",
685
+ ".svg",
686
+ ".xsl",
687
+ ".xslt",
688
+ ".css",
689
+ ".scss",
690
+ ".sass",
691
+ ".less",
692
+ ".styl",
693
+ ".html",
694
+ ".htm",
695
+ ".xhtml",
696
+ ".vue",
697
+ ".svelte",
698
+ ".astro",
699
+ ".py",
700
+ ".pyw",
701
+ ".rb",
702
+ ".go",
703
+ ".rs",
704
+ ".java",
705
+ ".kt",
706
+ ".kts",
707
+ ".swift",
708
+ ".c",
709
+ ".cpp",
710
+ ".cxx",
711
+ ".cc",
712
+ ".h",
713
+ ".hpp",
714
+ ".hxx",
715
+ ".hh",
716
+ ".cs",
717
+ ".fs",
718
+ ".fsx",
719
+ ".ex",
720
+ ".exs",
721
+ ".erl",
722
+ ".hrl",
723
+ ".clj",
724
+ ".cljs",
725
+ ".cljc",
726
+ ".edn",
727
+ ".scala",
728
+ ".sbt",
729
+ ".zig",
730
+ ".r",
731
+ ".rda",
732
+ ".m",
733
+ ".mm",
734
+ ".pl",
735
+ ".pm",
736
+ ".t",
737
+ ".lua",
738
+ ".sql",
739
+ ".graphql",
740
+ ".gql",
741
+ ".proto",
742
+ ".tf",
743
+ ".tfvars",
744
+ ".nix",
745
+ ".sh",
746
+ ".bash",
747
+ ".zsh",
748
+ ".fish",
749
+ ".ps1",
750
+ ".bat",
751
+ ".cmd",
752
+ ".env",
753
+ ".ini",
754
+ ".cfg",
755
+ ".conf",
756
+ ".log",
757
+ ".gitignore",
758
+ ".dockerignore",
759
+ ".helmignore",
760
+ ".dockerfile",
761
+ ".makefile",
762
+ ".npmrc",
763
+ ".yarnrc",
764
+ ".pnpmrc",
765
+ ".editorconfig",
766
+ ".prettierrc",
767
+ ".eslintrc",
768
+ ".babelrc",
769
+ ".stylelintrc",
770
+ ".commitlintrc",
771
+ ".browserslistrc",
772
+ ".nvmrc",
773
+ ".node-version",
774
+ ".python-version",
775
+ ".ruby-version"
776
+ ]);
777
+ var HINT_FG2 = RGBA2.fromInts(180, 180, 180, 255);
778
+ var FG2 = RGBA2.fromInts(255, 255, 255, 255);
779
+ var KNOWN_TEXT_FILENAMES = new Set([
780
+ "makefile",
781
+ "dockerfile",
782
+ "composefile",
783
+ "rakefile",
784
+ "gemfile",
785
+ "podfile",
786
+ "cartfile",
787
+ "readme",
788
+ "license",
789
+ "changelog",
790
+ "contributing",
791
+ "build",
792
+ "workspace",
793
+ "cargo.toml",
794
+ "package.swift",
795
+ ".gitattributes",
796
+ ".gitmodules",
797
+ ".npmignore",
798
+ ".dockerignore",
799
+ "procfile",
800
+ ".slugignore",
801
+ "nginx.conf",
802
+ "httpd.conf"
803
+ ]);
804
+ function hasNullByte(filePath) {
805
+ try {
806
+ const fd = openSync(filePath, "r");
807
+ const buf = Buffer.alloc(4096);
808
+ const bytesRead = readSync(fd, buf, 0, 4096, 0);
809
+ closeSync(fd);
810
+ return bytesRead > 0 && buf.subarray(0, bytesRead).includes(0);
811
+ } catch {
812
+ return true;
813
+ }
814
+ }
815
+ function isTextFile(name, fullPath) {
816
+ const ext = path2.extname(name).toLowerCase();
817
+ if (TEXT_EXTENSIONS.has(ext))
818
+ return true;
819
+ if (KNOWN_TEXT_FILENAMES.has(name.toLowerCase()))
820
+ return true;
821
+ if (/^[^.]+$/.test(name) && KNOWN_TEXT_FILENAMES.has(name.toLowerCase()))
822
+ return true;
823
+ if (!ext && !KNOWN_TEXT_FILENAMES.has(name.toLowerCase())) {
824
+ return !hasNullByte(fullPath);
825
+ }
826
+ return !hasNullByte(fullPath);
827
+ }
828
+ var SYNTAX_STYLE2 = SyntaxStyle2.fromStyles({
829
+ default: { fg: parseColor2("#E6EDF3") },
830
+ keyword: { fg: parseColor2("#FF7B72"), bold: true },
831
+ string: { fg: parseColor2("#A5D6FF") },
832
+ comment: { fg: parseColor2("#8B949E"), italic: true },
833
+ number: { fg: parseColor2("#79C0FF") },
834
+ function: { fg: parseColor2("#D2A8FF") },
835
+ type: { fg: parseColor2("#FFA657") },
836
+ operator: { fg: parseColor2("#FF7B72") },
837
+ variable: { fg: parseColor2("#E6EDF3") },
838
+ property: { fg: parseColor2("#79C0FF") },
839
+ "punctuation.bracket": { fg: parseColor2("#F0F6FC") },
840
+ "punctuation.delimiter": { fg: parseColor2("#C9D1D9") },
841
+ "markup.heading": { fg: parseColor2("#58A6FF"), bold: true },
842
+ "markup.bold": { fg: parseColor2("#F0F6FC"), bold: true },
843
+ "markup.italic": { fg: parseColor2("#F0F6FC"), italic: true },
844
+ "markup.list": { fg: parseColor2("#FF7B72") },
845
+ "markup.quote": { fg: parseColor2("#8B949E"), italic: true },
846
+ "markup.raw": { fg: parseColor2("#A5D6FF"), bg: parseColor2("#161B22") },
847
+ "markup.link": { fg: parseColor2("#58A6FF"), underline: true },
848
+ "markup.link.url": { fg: parseColor2("#58A6FF"), underline: true },
849
+ "diff.plus": { fg: parseColor2("#3FB950") },
850
+ "diff.minus": { fg: parseColor2("#F85149") },
851
+ conceal: { fg: parseColor2("#6E7681") }
852
+ });
853
+ var EXT_TO_FILETYPE2 = {
854
+ ".ts": "typescript",
855
+ ".tsx": "typescriptreact",
856
+ ".mts": "typescript",
857
+ ".cts": "typescript",
858
+ ".js": "javascript",
859
+ ".jsx": "javascriptreact",
860
+ ".mjs": "javascript",
861
+ ".cjs": "javascript",
862
+ ".json": "json",
863
+ ".md": "markdown",
864
+ ".mdx": "markdown",
865
+ ".css": "css",
866
+ ".html": "html",
867
+ ".xml": "xml",
868
+ ".yaml": "yaml",
869
+ ".yml": "yaml",
870
+ ".toml": "toml",
871
+ ".sh": "bash",
872
+ ".bash": "bash",
873
+ ".zsh": "bash",
874
+ ".py": "python",
875
+ ".rb": "ruby",
876
+ ".go": "go",
877
+ ".rs": "rust",
878
+ ".zig": "zig",
879
+ ".java": "java",
880
+ ".kt": "kotlin",
881
+ ".swift": "swift",
882
+ ".c": "c",
883
+ ".cpp": "cpp",
884
+ ".h": "c",
885
+ ".hpp": "cpp",
886
+ ".cs": "csharp",
887
+ ".lua": "lua",
888
+ ".sql": "sql",
889
+ ".graphql": "graphql",
890
+ ".proto": "protobuf",
891
+ ".tf": "terraform",
892
+ ".scala": "scala",
893
+ ".r": "r",
894
+ ".pl": "perl",
895
+ ".ex": "elixir",
896
+ ".exs": "elixir",
897
+ ".erl": "erlang",
898
+ ".clj": "clojure",
899
+ ".nix": "nix"
900
+ };
901
+ function readDir(dir) {
902
+ try {
903
+ const items = readdirSync(dir, { withFileTypes: true });
904
+ const dirs = items.filter((e) => e.isDirectory()).map((e) => ({ name: e.name, fullPath: path2.join(dir, e.name), isDir: true })).sort((a, b) => a.name.localeCompare(b.name));
905
+ const files = items.filter((e) => e.isFile()).map((e) => ({ name: e.name, fullPath: path2.join(dir, e.name), isDir: false })).sort((a, b) => a.name.localeCompare(b.name));
906
+ const isRoot = path2.resolve(dir, "..") === dir;
907
+ const parent = isRoot ? undefined : { name: "..", fullPath: path2.resolve(dir, ".."), isDir: true };
908
+ return parent ? [parent, ...dirs, ...files] : [...dirs, ...files];
909
+ } catch {
910
+ return [];
911
+ }
912
+ }
913
+ function toOptions(entries) {
914
+ return entries.map((e) => ({
915
+ name: (e.isDir ? "\uD83D\uDCC1 " : "\uD83D\uDCC4 ") + e.name + (e.isDir ? "/" : ""),
916
+ description: e.isDir ? "directory" : path2.extname(e.name) || "(file)",
917
+ value: e.fullPath
918
+ }));
919
+ }
920
+ function describeFile(name) {
921
+ const ext = path2.extname(name).toLowerCase();
922
+ if (ext)
923
+ return ext;
924
+ const lower = name.toLowerCase();
925
+ if (KNOWN_TEXT_FILENAMES.has(lower))
926
+ return lower;
927
+ return "(file)";
928
+ }
929
+ function NewFileManager(props) {
930
+ currentFileActions = {
931
+ create: handleCreate,
932
+ rename: handleRename,
933
+ delete: handleDelete,
934
+ goto: handleGoto,
935
+ focusFilter: () => setFocusedPane("filter"),
936
+ focusSelect: () => setFocusedPane("select"),
937
+ hideOverlay
938
+ };
939
+ onCleanup(() => {
940
+ currentFileActions = null;
941
+ focusedPane = "select";
942
+ isOverlayActive = false;
943
+ if (rightScrollBox && rightScrollBoxOrigBg)
944
+ rightScrollBox.backgroundColor = rightScrollBoxOrigBg;
945
+ });
946
+ let selectRef;
947
+ let pathTextEl;
948
+ let rightNameEl;
949
+ let rightPathEl;
950
+ let rightDescEl;
951
+ let rightPreviewEl;
952
+ let rightDirListEl;
953
+ let rightMarkdownEl;
954
+ let rightCodeEl;
955
+ let lastClickTime = 0;
956
+ let lastClickIdx = 0;
957
+ const dimensions = useTerminalDimensions2();
958
+ const theme = () => props.api.theme.current;
959
+ let currentDir = props.initialDir || process.cwd();
960
+ let entries = readDir(currentDir);
961
+ let overlayMode = "";
962
+ let overlayConfirmAction = null;
963
+ let overlayPromptAction = null;
964
+ let promptInputValue = "";
965
+ let currentEntry = entries[0] ?? null;
966
+ let filterText = "";
967
+ let filteredEntries = entries;
968
+ let mainContentBox;
969
+ let confirmOverlayBox;
970
+ let promptOverlayBox;
971
+ let confirmTitleEl;
972
+ let confirmMessageEl;
973
+ let promptTitleEl;
974
+ let promptMessageEl;
975
+ let promptCancelBtn;
976
+ let promptOkBtn;
977
+ let promptInputEl;
978
+ let filterInputEl;
979
+ let rightScrollBox;
980
+ let rightScrollBoxOrigBg;
981
+ function applyFilter(text) {
982
+ filterText = text;
983
+ filteredEntries = text ? entries.filter((e) => e.name.toLowerCase().includes(text.toLowerCase())) : entries;
984
+ selectRef.options = toOptions(filteredEntries);
985
+ selectRef.setSelectedIndex(0);
986
+ currentEntry = filteredEntries[0] ?? null;
987
+ if (currentEntry)
988
+ setRightPanel(currentEntry);
989
+ else
990
+ setRightPanel(null);
991
+ }
992
+ function navigateTo(dir) {
993
+ currentDir = dir;
994
+ entries = readDir(currentDir);
995
+ if (filterInputEl)
996
+ filterInputEl.setText("");
997
+ filterText = "";
998
+ filteredEntries = entries;
999
+ selectRef.options = toOptions(entries);
1000
+ pathTextEl.content = "Project Path: " + currentDir;
1001
+ forceSelectFirst();
1002
+ currentEntry = entries[0] ?? null;
1003
+ if (entries[0])
1004
+ setRightPanel(entries[0]);
1005
+ else
1006
+ setRightPanel(null);
1007
+ }
1008
+ function setRightPanel(entry) {
1009
+ rightPreviewEl.visible = false;
1010
+ if (rightMarkdownEl)
1011
+ rightMarkdownEl.visible = false;
1012
+ if (rightCodeEl)
1013
+ rightCodeEl.visible = false;
1014
+ if (rightDirListEl)
1015
+ rightDirListEl.visible = false;
1016
+ if (!entry) {
1017
+ rightNameEl.content = "";
1018
+ rightPathEl.content = "";
1019
+ rightDescEl.content = "";
1020
+ rightPreviewEl.content = "(empty directory)";
1021
+ rightPreviewEl.visible = true;
1022
+ return;
1023
+ }
1024
+ rightNameEl.content = entry.name;
1025
+ rightPathEl.content = entry.fullPath;
1026
+ if (entry.isDir) {
1027
+ rightDescEl.content = "directory";
1028
+ const items = readDir(entry.fullPath);
1029
+ if (items.length === 0) {
1030
+ rightDirListEl.content = "(empty directory)";
1031
+ } else {
1032
+ rightDirListEl.content = items.map((e) => (e.isDir ? "\uD83D\uDCC1 " : "\uD83D\uDCC4 ") + e.name + (e.isDir ? "/" : "")).join(`
1033
+ `);
1034
+ }
1035
+ rightDirListEl.visible = true;
1036
+ return;
1037
+ }
1038
+ rightDescEl.content = describeFile(entry.name);
1039
+ if (!isTextFile(entry.name, entry.fullPath)) {
1040
+ rightPreviewEl.content = "(binary file)";
1041
+ rightPreviewEl.visible = true;
1042
+ return;
1043
+ }
1044
+ let content;
1045
+ try {
1046
+ content = readFileSync2(entry.fullPath, "utf-8");
1047
+ } catch {
1048
+ rightPreviewEl.content = "(preview unavailable)";
1049
+ rightPreviewEl.visible = true;
1050
+ return;
1051
+ }
1052
+ const ext = path2.extname(entry.name).toLowerCase();
1053
+ if (ext === ".md" || ext === ".mdx" || ext === ".markdown") {
1054
+ rightMarkdownEl.content = content;
1055
+ rightMarkdownEl.visible = true;
1056
+ } else {
1057
+ rightCodeEl.content = content;
1058
+ rightCodeEl.filetype = EXT_TO_FILETYPE2[ext] ?? "";
1059
+ rightCodeEl.visible = true;
1060
+ }
1061
+ }
1062
+ function openPreview(entry) {
1063
+ if (entry.isDir) {
1064
+ navigateTo(entry.fullPath);
1065
+ return;
1066
+ }
1067
+ if (isTextFile(entry.name, entry.fullPath)) {
1068
+ props.api.ui.dialog.replace(() => /* @__PURE__ */ jsxDEV2(FileViewer, {
1069
+ api: props.api,
1070
+ filePath: entry.fullPath,
1071
+ onBack: () => {
1072
+ props.api.ui.dialog.replace(() => /* @__PURE__ */ jsxDEV2(NewFileManager, {
1073
+ api: props.api,
1074
+ initialDir: currentDir
1075
+ }, undefined, false, undefined, this));
1076
+ props.api.ui.dialog.setSize("xlarge");
1077
+ }
1078
+ }, undefined, false, undefined, this));
1079
+ props.api.ui.dialog.setSize("xlarge");
1080
+ return;
1081
+ }
1082
+ const backDir = currentDir;
1083
+ props.api.ui.dialog.replace(() => /* @__PURE__ */ jsxDEV2(FilePreviewDialog, {
1084
+ api: props.api,
1085
+ path: entry.fullPath,
1086
+ content: "[Binary file]",
1087
+ backDir
1088
+ }, undefined, false, undefined, this));
1089
+ props.api.ui.dialog.setSize("xlarge");
1090
+ }
1091
+ const handleSelect = (_index, option) => {
1092
+ const fullPath = option?.value;
1093
+ if (!fullPath)
1094
+ return;
1095
+ const entry = entries.find((e) => e.fullPath === fullPath);
1096
+ if (entry)
1097
+ openPreview(entry);
1098
+ };
1099
+ const handleChange = (_index, option) => {
1100
+ const fullPath = option?.value;
1101
+ if (!fullPath) {
1102
+ currentEntry = null;
1103
+ setRightPanel(null);
1104
+ return;
1105
+ }
1106
+ const entry = entries.find((e) => e.fullPath === fullPath) ?? null;
1107
+ currentEntry = entry;
1108
+ if (entry)
1109
+ setRightPanel(entry);
1110
+ else
1111
+ setRightPanel(null);
1112
+ };
1113
+ function showConfirm(message, onConfirm) {
1114
+ overlayMode = "confirm";
1115
+ isOverlayActive = true;
1116
+ overlayConfirmAction = onConfirm;
1117
+ confirmTitleEl.content = "Confirm";
1118
+ confirmMessageEl.content = message;
1119
+ mainContentBox.visible = false;
1120
+ confirmOverlayBox.visible = true;
1121
+ promptOverlayBox.visible = false;
1122
+ }
1123
+ function hideOverlay() {
1124
+ overlayMode = "";
1125
+ isOverlayActive = false;
1126
+ overlayConfirmAction = null;
1127
+ overlayPromptAction = null;
1128
+ mainContentBox.visible = true;
1129
+ confirmOverlayBox.visible = false;
1130
+ promptOverlayBox.visible = false;
1131
+ navigateTo(currentDir);
1132
+ if (selectRef)
1133
+ selectRef.focus();
1134
+ }
1135
+ function forceSelectFirst() {
1136
+ if (selectRef && entries.length > 0) {
1137
+ selectRef.setSelectedIndex(0);
1138
+ }
1139
+ }
1140
+ function handleDelete() {
1141
+ const entry = currentEntry;
1142
+ if (!entry || entry.name === ".." || entry.name === ".")
1143
+ return;
1144
+ const label = entry.name + (entry.isDir ? "/" : "");
1145
+ showConfirm(`Delete "${label}"?`, () => {
1146
+ try {
1147
+ rmSync(entry.fullPath, { recursive: entry.isDir, force: true });
1148
+ } catch {}
1149
+ hideOverlay();
1150
+ });
1151
+ }
1152
+ function handleRename() {
1153
+ const entry = currentEntry;
1154
+ if (!entry || entry.name === ".." || entry.name === ".")
1155
+ return;
1156
+ overlayMode = "prompt";
1157
+ isOverlayActive = true;
1158
+ overlayPromptAction = (newName) => {
1159
+ if (!newName || newName === entry.name) {
1160
+ hideOverlay();
1161
+ return;
1162
+ }
1163
+ const newPath = path2.join(path2.dirname(entry.fullPath), newName);
1164
+ try {
1165
+ renameSync(entry.fullPath, newPath);
1166
+ } catch {}
1167
+ hideOverlay();
1168
+ };
1169
+ promptInputValue = entry.name;
1170
+ promptTitleEl.content = "Rename";
1171
+ promptMessageEl.content = `Rename "${entry.name}" to:`;
1172
+ if (promptInputEl) {
1173
+ promptInputEl.setText(entry.name);
1174
+ }
1175
+ mainContentBox.visible = false;
1176
+ confirmOverlayBox.visible = false;
1177
+ promptOverlayBox.visible = true;
1178
+ if (promptInputEl)
1179
+ promptInputEl.focus();
1180
+ }
1181
+ function handleGoto() {
1182
+ overlayMode = "prompt";
1183
+ isOverlayActive = true;
1184
+ overlayPromptAction = (pathStr) => {
1185
+ if (!pathStr) {
1186
+ hideOverlay();
1187
+ return;
1188
+ }
1189
+ const home = process.env.HOME || "/";
1190
+ const expanded = pathStr === "~" ? home : pathStr.startsWith("~/") ? path2.join(home, pathStr.slice(2)) : pathStr;
1191
+ try {
1192
+ const resolved = path2.resolve(currentDir, expanded);
1193
+ const s = statSync(resolved);
1194
+ hideOverlay();
1195
+ if (s.isDirectory()) {
1196
+ navigateTo(resolved);
1197
+ } else {
1198
+ props.api.ui.dialog.replace(() => /* @__PURE__ */ jsxDEV2(FileViewer, {
1199
+ api: props.api,
1200
+ filePath: resolved,
1201
+ onBack: () => {
1202
+ props.api.ui.dialog.replace(() => /* @__PURE__ */ jsxDEV2(NewFileManager, {
1203
+ api: props.api,
1204
+ initialDir: currentDir
1205
+ }, undefined, false, undefined, this));
1206
+ props.api.ui.dialog.setSize("xlarge");
1207
+ }
1208
+ }, undefined, false, undefined, this));
1209
+ props.api.ui.dialog.setSize("xlarge");
1210
+ }
1211
+ } catch {
1212
+ hideOverlay();
1213
+ }
1214
+ };
1215
+ promptInputValue = "";
1216
+ promptTitleEl.content = "Goto";
1217
+ promptMessageEl.content = "Enter path:";
1218
+ if (promptInputEl) {
1219
+ promptInputEl.setText("");
1220
+ }
1221
+ mainContentBox.visible = false;
1222
+ confirmOverlayBox.visible = false;
1223
+ promptOverlayBox.visible = true;
1224
+ if (promptInputEl)
1225
+ promptInputEl.focus();
1226
+ }
1227
+ function handleCreate() {
1228
+ overlayMode = "prompt";
1229
+ isOverlayActive = true;
1230
+ overlayPromptAction = (name) => {
1231
+ if (!name) {
1232
+ hideOverlay();
1233
+ return;
1234
+ }
1235
+ const isDir = name.endsWith("/");
1236
+ const cleanName = isDir ? name.slice(0, -1) : name;
1237
+ const newPath = path2.join(currentDir, cleanName);
1238
+ try {
1239
+ if (isDir)
1240
+ mkdirSync(newPath, { recursive: true });
1241
+ else {
1242
+ writeFileSync2(newPath, "", "utf-8");
1243
+ props.api.ui.dialog.replace(() => /* @__PURE__ */ jsxDEV2(FileViewer, {
1244
+ api: props.api,
1245
+ filePath: newPath,
1246
+ initialMode: "edit",
1247
+ onBack: () => {
1248
+ props.api.ui.dialog.replace(() => /* @__PURE__ */ jsxDEV2(NewFileManager, {
1249
+ api: props.api,
1250
+ initialDir: currentDir
1251
+ }, undefined, false, undefined, this));
1252
+ props.api.ui.dialog.setSize("xlarge");
1253
+ }
1254
+ }, undefined, false, undefined, this));
1255
+ props.api.ui.dialog.setSize("xlarge");
1256
+ return;
1257
+ }
1258
+ } catch {}
1259
+ hideOverlay();
1260
+ };
1261
+ promptInputValue = "";
1262
+ promptTitleEl.content = "Create";
1263
+ promptMessageEl.content = "Enter name (trailing / for directory):";
1264
+ if (promptInputEl) {
1265
+ promptInputEl.setText("");
1266
+ }
1267
+ mainContentBox.visible = false;
1268
+ confirmOverlayBox.visible = false;
1269
+ promptOverlayBox.visible = true;
1270
+ if (promptInputEl)
1271
+ promptInputEl.focus();
1272
+ }
1273
+ const projectRoot = () => props.api.state.path.worktree || props.api.state.path.directory;
1274
+ function returnToProjectRoot() {
1275
+ const root = projectRoot();
1276
+ if (root)
1277
+ navigateTo(root);
1278
+ }
1279
+ useBindings2(() => ({
1280
+ priority: 2,
1281
+ bindings: [
1282
+ { key: "ctrl+r", cmd: returnToProjectRoot }
1283
+ ]
1284
+ }));
1285
+ function cycleFocus(dir) {
1286
+ const order = ["select", "preview", "filter"];
1287
+ const idx = order.indexOf(focusedPane);
1288
+ const next = order[(idx + dir + 3) % 3];
1289
+ setFocusedPane(next);
1290
+ }
1291
+ function setFocusedPane(pane) {
1292
+ focusedPane = pane;
1293
+ if (rightScrollBox && rightScrollBoxOrigBg) {
1294
+ rightScrollBox.backgroundColor = pane === "preview" ? RGBA2.fromInts(40, 40, 50, 255) : rightScrollBoxOrigBg;
1295
+ }
1296
+ if (pane === "select") {
1297
+ selectRef?.focus();
1298
+ } else if (pane === "preview") {
1299
+ rightScrollBox?.focus();
1300
+ } else if (pane === "filter") {
1301
+ filterInputEl?.focus();
1302
+ }
1303
+ }
1304
+ useBindings2(() => ({
1305
+ priority: 1,
1306
+ bindings: [
1307
+ { key: "tab", cmd: () => cycleFocus(1) },
1308
+ { key: "shift+tab", cmd: () => cycleFocus(-1) }
1309
+ ]
1310
+ }));
1311
+ useBindings2(() => ({
1312
+ priority: 1,
1313
+ enabled: () => focusedPane === "preview",
1314
+ bindings: [
1315
+ { key: "up", cmd: () => rightScrollBox?.scrollBy(-1) },
1316
+ { key: "down", cmd: () => rightScrollBox?.scrollBy(1) },
1317
+ { key: "pageup", cmd: () => {
1318
+ if (rightScrollBox) {
1319
+ const h = rightScrollBox.height;
1320
+ if (h > 0)
1321
+ rightScrollBox.scrollTop -= h;
1322
+ }
1323
+ } },
1324
+ { key: "pagedown", cmd: () => {
1325
+ if (rightScrollBox) {
1326
+ const h = rightScrollBox.height;
1327
+ if (h > 0)
1328
+ rightScrollBox.scrollTop += h;
1329
+ }
1330
+ } },
1331
+ { key: "home", cmd: () => {
1332
+ if (rightScrollBox)
1333
+ rightScrollBox.scrollTop = 0;
1334
+ } },
1335
+ { key: "end", cmd: () => {
1336
+ if (rightScrollBox)
1337
+ rightScrollBox.scrollTop = rightScrollBox.scrollHeight - rightScrollBox.height;
1338
+ } }
1339
+ ]
1340
+ }));
1341
+ useBindings2(() => ({
1342
+ priority: 1,
1343
+ enabled: () => focusedPane === "select",
1344
+ bindings: [
1345
+ { key: "pageup", cmd: () => selectRef?.moveUp(10) },
1346
+ { key: "pagedown", cmd: () => selectRef?.moveDown(10) },
1347
+ { key: "home", cmd: () => {
1348
+ if (selectRef)
1349
+ selectRef.setSelectedIndex(0);
1350
+ } },
1351
+ { key: "end", cmd: () => {
1352
+ if (selectRef)
1353
+ selectRef.setSelectedIndex(filteredEntries.length - 1);
1354
+ } }
1355
+ ]
1356
+ }));
1357
+ const panelWidth = () => Math.min(Math.max(dimensions().width - 2, 60), 116);
1358
+ const panelHeight = () => Math.max(Math.floor(dimensions().height * 0.78) - 2, 22);
1359
+ const leftWidth = () => Math.floor(panelWidth() * 0.4);
1360
+ const rightWidth = () => panelWidth() - leftWidth();
1361
+ const first = filteredEntries[0];
1362
+ return /* @__PURE__ */ jsxDEV2("box", {
1363
+ width: panelWidth(),
1364
+ height: panelHeight(),
1365
+ flexDirection: "column",
1366
+ children: [
1367
+ /* @__PURE__ */ jsxDEV2("box", {
1368
+ paddingLeft: 2,
1369
+ paddingRight: 2,
1370
+ flexShrink: 0,
1371
+ border: ["bottom"],
1372
+ borderColor: theme().textMuted,
1373
+ flexDirection: "row",
1374
+ children: [
1375
+ /* @__PURE__ */ jsxDEV2("text", {
1376
+ ref: (el) => {
1377
+ pathTextEl = el;
1378
+ },
1379
+ fg: theme().text,
1380
+ children: [
1381
+ "Project Path: ",
1382
+ currentDir
1383
+ ]
1384
+ }, undefined, true, undefined, this),
1385
+ /* @__PURE__ */ jsxDEV2("box", {
1386
+ flexGrow: 1
1387
+ }, undefined, false, undefined, this),
1388
+ /* @__PURE__ */ jsxDEV2("box", {
1389
+ flexDirection: "row",
1390
+ gap: 3,
1391
+ children: [
1392
+ /* @__PURE__ */ jsxDEV2("box", {
1393
+ flexDirection: "row",
1394
+ gap: 0,
1395
+ onMouseUp: () => returnToProjectRoot(),
1396
+ children: [
1397
+ /* @__PURE__ */ jsxDEV2("text", {
1398
+ fg: HINT_FG2,
1399
+ children: "[Ctrl+R]"
1400
+ }, undefined, false, undefined, this),
1401
+ /* @__PURE__ */ jsxDEV2("text", {
1402
+ fg: FG2,
1403
+ children: " Return"
1404
+ }, undefined, false, undefined, this)
1405
+ ]
1406
+ }, undefined, true, undefined, this),
1407
+ /* @__PURE__ */ jsxDEV2("box", {
1408
+ flexDirection: "row",
1409
+ gap: 0,
1410
+ onMouseUp: () => props.api.ui.dialog.clear(),
1411
+ children: [
1412
+ /* @__PURE__ */ jsxDEV2("text", {
1413
+ fg: HINT_FG2,
1414
+ children: "[ESC]"
1415
+ }, undefined, false, undefined, this),
1416
+ /* @__PURE__ */ jsxDEV2("text", {
1417
+ fg: FG2,
1418
+ children: " Close"
1419
+ }, undefined, false, undefined, this)
1420
+ ]
1421
+ }, undefined, true, undefined, this)
1422
+ ]
1423
+ }, undefined, true, undefined, this)
1424
+ ]
1425
+ }, undefined, true, undefined, this),
1426
+ /* @__PURE__ */ jsxDEV2("box", {
1427
+ flexDirection: "row",
1428
+ flexGrow: 1,
1429
+ minHeight: 5,
1430
+ children: [
1431
+ /* @__PURE__ */ jsxDEV2("box", {
1432
+ ref: (el) => {
1433
+ mainContentBox = el;
1434
+ },
1435
+ flexDirection: "row",
1436
+ flexGrow: 1,
1437
+ children: [
1438
+ /* @__PURE__ */ jsxDEV2("select", {
1439
+ ref: (el) => {
1440
+ selectRef = el;
1441
+ },
1442
+ options: toOptions(filteredEntries),
1443
+ showDescription: false,
1444
+ focused: true,
1445
+ onChange: handleChange,
1446
+ onSelect: handleSelect,
1447
+ height: "100%",
1448
+ width: leftWidth(),
1449
+ onMouseDown: (event) => {
1450
+ selectRef?.focus();
1451
+ setFocusedPane("select");
1452
+ const idx = Math.floor(event.y - selectRef.screenY);
1453
+ if (idx >= 0 && idx < filteredEntries.length) {
1454
+ const now = Date.now();
1455
+ if (idx === lastClickIdx && now - lastClickTime < 500) {
1456
+ handleSelect(idx, selectRef.options[idx]);
1457
+ } else {
1458
+ selectRef.setSelectedIndex(idx);
1459
+ }
1460
+ lastClickTime = now;
1461
+ lastClickIdx = idx;
1462
+ }
1463
+ },
1464
+ onMouseScroll: (event) => {
1465
+ if (!event.scroll)
1466
+ return;
1467
+ selectRef?.focus();
1468
+ setFocusedPane("select");
1469
+ const cur = selectRef.getSelectedIndex();
1470
+ if (event.scroll.direction === "down" && cur < filteredEntries.length - 1) {
1471
+ selectRef.setSelectedIndex(Math.min(filteredEntries.length - 1, cur + event.scroll.delta));
1472
+ } else if (event.scroll.direction === "up" && cur > 0) {
1473
+ selectRef.setSelectedIndex(Math.max(0, cur - event.scroll.delta));
1474
+ }
1475
+ }
1476
+ }, undefined, false, undefined, this),
1477
+ /* @__PURE__ */ jsxDEV2("scrollbox", {
1478
+ ref: (el) => {
1479
+ rightScrollBox = el;
1480
+ rightScrollBoxOrigBg = el.backgroundColor;
1481
+ },
1482
+ width: rightWidth(),
1483
+ height: "100%",
1484
+ backgroundColor: theme().backgroundPanel,
1485
+ scrollbarOptions: { visible: false },
1486
+ onMouseDown: () => {
1487
+ setFocusedPane("preview");
1488
+ },
1489
+ children: /* @__PURE__ */ jsxDEV2("box", {
1490
+ padding: 1,
1491
+ flexDirection: "column",
1492
+ gap: 1,
1493
+ children: [
1494
+ /* @__PURE__ */ jsxDEV2("text", {
1495
+ ref: (el) => {
1496
+ rightNameEl = el;
1497
+ },
1498
+ fg: theme().text,
1499
+ children: first ? first.name : ""
1500
+ }, undefined, false, undefined, this),
1501
+ /* @__PURE__ */ jsxDEV2("text", {
1502
+ ref: (el) => {
1503
+ rightPathEl = el;
1504
+ },
1505
+ fg: theme().textMuted,
1506
+ children: first ? first.fullPath : ""
1507
+ }, undefined, false, undefined, this),
1508
+ /* @__PURE__ */ jsxDEV2("text", {
1509
+ ref: (el) => {
1510
+ rightDescEl = el;
1511
+ },
1512
+ fg: theme().textMuted,
1513
+ children: first ? first.isDir ? "directory" : describeFile(first.name) : ""
1514
+ }, undefined, false, undefined, this),
1515
+ /* @__PURE__ */ jsxDEV2("text", {
1516
+ ref: (el) => {
1517
+ rightPreviewEl = el;
1518
+ },
1519
+ fg: theme().text,
1520
+ visible: false
1521
+ }, undefined, false, undefined, this),
1522
+ /* @__PURE__ */ jsxDEV2("text", {
1523
+ ref: (el) => {
1524
+ rightDirListEl = el;
1525
+ },
1526
+ fg: theme().text,
1527
+ visible: false
1528
+ }, undefined, false, undefined, this),
1529
+ /* @__PURE__ */ jsxDEV2("markdown", {
1530
+ ref: (el) => {
1531
+ rightMarkdownEl = el;
1532
+ },
1533
+ content: "",
1534
+ syntaxStyle: SYNTAX_STYLE2,
1535
+ conceal: true,
1536
+ fg: theme().text,
1537
+ width: "100%",
1538
+ visible: false
1539
+ }, undefined, false, undefined, this),
1540
+ /* @__PURE__ */ jsxDEV2("code", {
1541
+ ref: (el) => {
1542
+ rightCodeEl = el;
1543
+ },
1544
+ content: "",
1545
+ filetype: "",
1546
+ syntaxStyle: SYNTAX_STYLE2,
1547
+ width: "100%",
1548
+ visible: false
1549
+ }, undefined, false, undefined, this)
1550
+ ]
1551
+ }, undefined, true, undefined, this)
1552
+ }, undefined, false, undefined, this)
1553
+ ]
1554
+ }, undefined, true, undefined, this),
1555
+ /* @__PURE__ */ jsxDEV2("box", {
1556
+ ref: (el) => {
1557
+ confirmOverlayBox = el;
1558
+ },
1559
+ visible: false,
1560
+ flexDirection: "column",
1561
+ flexGrow: 1,
1562
+ justifyContent: "center",
1563
+ alignItems: "center",
1564
+ backgroundColor: theme().backgroundPanel,
1565
+ children: /* @__PURE__ */ jsxDEV2("box", {
1566
+ padding: 2,
1567
+ flexDirection: "column",
1568
+ gap: 1,
1569
+ backgroundColor: theme().backgroundElement,
1570
+ children: [
1571
+ /* @__PURE__ */ jsxDEV2("text", {
1572
+ ref: (el) => {
1573
+ confirmTitleEl = el;
1574
+ },
1575
+ fg: theme().text
1576
+ }, undefined, false, undefined, this),
1577
+ /* @__PURE__ */ jsxDEV2("text", {
1578
+ ref: (el) => {
1579
+ confirmMessageEl = el;
1580
+ },
1581
+ fg: theme().textMuted
1582
+ }, undefined, false, undefined, this),
1583
+ /* @__PURE__ */ jsxDEV2("box", {
1584
+ flexDirection: "row",
1585
+ justifyContent: "flex-end",
1586
+ gap: 1,
1587
+ children: [
1588
+ /* @__PURE__ */ jsxDEV2("box", {
1589
+ paddingLeft: 2,
1590
+ paddingRight: 2,
1591
+ flexDirection: "row",
1592
+ onMouseUp: () => hideOverlay(),
1593
+ children: [
1594
+ /* @__PURE__ */ jsxDEV2("text", {
1595
+ fg: HINT_FG2,
1596
+ children: "[ESC]"
1597
+ }, undefined, false, undefined, this),
1598
+ /* @__PURE__ */ jsxDEV2("text", {
1599
+ fg: FG2,
1600
+ children: " Cancel"
1601
+ }, undefined, false, undefined, this)
1602
+ ]
1603
+ }, undefined, true, undefined, this),
1604
+ /* @__PURE__ */ jsxDEV2("box", {
1605
+ paddingLeft: 2,
1606
+ paddingRight: 2,
1607
+ flexDirection: "row",
1608
+ onMouseUp: () => overlayConfirmAction?.(),
1609
+ children: [
1610
+ /* @__PURE__ */ jsxDEV2("text", {
1611
+ fg: HINT_FG2,
1612
+ children: "[Enter]"
1613
+ }, undefined, false, undefined, this),
1614
+ /* @__PURE__ */ jsxDEV2("text", {
1615
+ fg: FG2,
1616
+ children: " Confirm"
1617
+ }, undefined, false, undefined, this)
1618
+ ]
1619
+ }, undefined, true, undefined, this)
1620
+ ]
1621
+ }, undefined, true, undefined, this)
1622
+ ]
1623
+ }, undefined, true, undefined, this)
1624
+ }, undefined, false, undefined, this),
1625
+ /* @__PURE__ */ jsxDEV2("box", {
1626
+ ref: (el) => {
1627
+ promptOverlayBox = el;
1628
+ },
1629
+ visible: false,
1630
+ flexDirection: "column",
1631
+ flexGrow: 1,
1632
+ justifyContent: "center",
1633
+ alignItems: "center",
1634
+ backgroundColor: theme().backgroundPanel,
1635
+ children: /* @__PURE__ */ jsxDEV2("box", {
1636
+ padding: 2,
1637
+ flexDirection: "column",
1638
+ gap: 1,
1639
+ backgroundColor: theme().backgroundElement,
1640
+ children: [
1641
+ /* @__PURE__ */ jsxDEV2("text", {
1642
+ ref: (el) => {
1643
+ promptTitleEl = el;
1644
+ },
1645
+ fg: theme().text
1646
+ }, undefined, false, undefined, this),
1647
+ /* @__PURE__ */ jsxDEV2("text", {
1648
+ ref: (el) => {
1649
+ promptMessageEl = el;
1650
+ },
1651
+ fg: theme().textMuted
1652
+ }, undefined, false, undefined, this),
1653
+ /* @__PURE__ */ jsxDEV2("input", {
1654
+ ref: (el) => {
1655
+ promptInputEl = el;
1656
+ },
1657
+ placeholder: "Name...",
1658
+ width: 40,
1659
+ onInput: (val) => {
1660
+ promptInputValue = val;
1661
+ },
1662
+ onSubmit: () => overlayPromptAction?.(promptInputValue)
1663
+ }, undefined, false, undefined, this),
1664
+ /* @__PURE__ */ jsxDEV2("box", {
1665
+ flexDirection: "row",
1666
+ justifyContent: "flex-end",
1667
+ gap: 1,
1668
+ children: [
1669
+ /* @__PURE__ */ jsxDEV2("box", {
1670
+ paddingLeft: 2,
1671
+ paddingRight: 2,
1672
+ flexDirection: "row",
1673
+ onMouseUp: () => hideOverlay(),
1674
+ children: [
1675
+ /* @__PURE__ */ jsxDEV2("text", {
1676
+ fg: HINT_FG2,
1677
+ children: "[ESC]"
1678
+ }, undefined, false, undefined, this),
1679
+ /* @__PURE__ */ jsxDEV2("text", {
1680
+ fg: FG2,
1681
+ children: " Cancel"
1682
+ }, undefined, false, undefined, this)
1683
+ ]
1684
+ }, undefined, true, undefined, this),
1685
+ /* @__PURE__ */ jsxDEV2("box", {
1686
+ paddingLeft: 2,
1687
+ paddingRight: 2,
1688
+ flexDirection: "row",
1689
+ onMouseUp: () => overlayPromptAction?.(promptInputValue),
1690
+ children: [
1691
+ /* @__PURE__ */ jsxDEV2("text", {
1692
+ fg: HINT_FG2,
1693
+ children: "[Enter]"
1694
+ }, undefined, false, undefined, this),
1695
+ /* @__PURE__ */ jsxDEV2("text", {
1696
+ fg: FG2,
1697
+ children: " Confirm"
1698
+ }, undefined, false, undefined, this)
1699
+ ]
1700
+ }, undefined, true, undefined, this)
1701
+ ]
1702
+ }, undefined, true, undefined, this)
1703
+ ]
1704
+ }, undefined, true, undefined, this)
1705
+ }, undefined, false, undefined, this)
1706
+ ]
1707
+ }, undefined, true, undefined, this),
1708
+ /* @__PURE__ */ jsxDEV2("box", {
1709
+ paddingLeft: 2,
1710
+ paddingTop: 1,
1711
+ flexShrink: 0,
1712
+ flexDirection: "row",
1713
+ gap: 3,
1714
+ children: [
1715
+ /* @__PURE__ */ jsxDEV2("box", {
1716
+ flexDirection: "row",
1717
+ gap: 0,
1718
+ onMouseUp: () => handleCreate(),
1719
+ children: [
1720
+ /* @__PURE__ */ jsxDEV2("text", {
1721
+ fg: theme().textMuted,
1722
+ children: "[F7]"
1723
+ }, undefined, false, undefined, this),
1724
+ /* @__PURE__ */ jsxDEV2("text", {
1725
+ fg: FG2,
1726
+ children: " New"
1727
+ }, undefined, false, undefined, this)
1728
+ ]
1729
+ }, undefined, true, undefined, this),
1730
+ /* @__PURE__ */ jsxDEV2("box", {
1731
+ flexDirection: "row",
1732
+ gap: 0,
1733
+ onMouseUp: () => handleRename(),
1734
+ children: [
1735
+ /* @__PURE__ */ jsxDEV2("text", {
1736
+ fg: theme().textMuted,
1737
+ children: "[F2]"
1738
+ }, undefined, false, undefined, this),
1739
+ /* @__PURE__ */ jsxDEV2("text", {
1740
+ fg: FG2,
1741
+ children: " Rename"
1742
+ }, undefined, false, undefined, this)
1743
+ ]
1744
+ }, undefined, true, undefined, this),
1745
+ /* @__PURE__ */ jsxDEV2("box", {
1746
+ flexDirection: "row",
1747
+ gap: 0,
1748
+ onMouseUp: () => handleDelete(),
1749
+ children: [
1750
+ /* @__PURE__ */ jsxDEV2("text", {
1751
+ fg: theme().textMuted,
1752
+ children: "[Del]"
1753
+ }, undefined, false, undefined, this),
1754
+ /* @__PURE__ */ jsxDEV2("text", {
1755
+ fg: FG2,
1756
+ children: " Delete"
1757
+ }, undefined, false, undefined, this)
1758
+ ]
1759
+ }, undefined, true, undefined, this),
1760
+ /* @__PURE__ */ jsxDEV2("box", {
1761
+ flexDirection: "row",
1762
+ gap: 0,
1763
+ onMouseUp: () => handleGoto(),
1764
+ children: [
1765
+ /* @__PURE__ */ jsxDEV2("text", {
1766
+ fg: theme().textMuted,
1767
+ children: "[Ctrl+G]"
1768
+ }, undefined, false, undefined, this),
1769
+ /* @__PURE__ */ jsxDEV2("text", {
1770
+ fg: FG2,
1771
+ children: " Goto"
1772
+ }, undefined, false, undefined, this)
1773
+ ]
1774
+ }, undefined, true, undefined, this),
1775
+ /* @__PURE__ */ jsxDEV2("box", {
1776
+ flexGrow: 1,
1777
+ flexDirection: "row",
1778
+ border: ["bottom"],
1779
+ borderColor: theme().textMuted,
1780
+ onMouseDown: () => {
1781
+ setFocusedPane("filter");
1782
+ },
1783
+ children: [
1784
+ /* @__PURE__ */ jsxDEV2("text", {
1785
+ fg: HINT_FG2,
1786
+ children: "[Ctrl+F]"
1787
+ }, undefined, false, undefined, this),
1788
+ /* @__PURE__ */ jsxDEV2("text", {
1789
+ fg: theme().textMuted,
1790
+ children: " "
1791
+ }, undefined, false, undefined, this),
1792
+ /* @__PURE__ */ jsxDEV2("input", {
1793
+ ref: (el) => {
1794
+ filterInputEl = el;
1795
+ },
1796
+ placeholder: "Filter...",
1797
+ onInput: (val) => applyFilter(val),
1798
+ flexGrow: 1
1799
+ }, undefined, false, undefined, this)
1800
+ ]
1801
+ }, undefined, true, undefined, this)
1802
+ ]
1803
+ }, undefined, true, undefined, this)
1804
+ ]
1805
+ }, undefined, true, undefined, this);
1806
+ }
1807
+ function FilePreviewDialog(props) {
1808
+ const theme = () => props.api.theme.current;
1809
+ useBindings2(() => ({
1810
+ bindings: [
1811
+ {
1812
+ key: "escape",
1813
+ cmd: () => {
1814
+ props.api.ui.dialog.replace(() => /* @__PURE__ */ jsxDEV2(NewFileManager, {
1815
+ api: props.api,
1816
+ initialDir: props.backDir
1817
+ }, undefined, false, undefined, this));
1818
+ props.api.ui.dialog.setSize("xlarge");
1819
+ }
1820
+ }
1821
+ ]
1822
+ }));
1823
+ return /* @__PURE__ */ jsxDEV2("scrollbox", {
1824
+ width: "100%",
1825
+ height: "100%",
1826
+ backgroundColor: theme().backgroundPanel,
1827
+ scrollbarOptions: { visible: false },
1828
+ children: /* @__PURE__ */ jsxDEV2("box", {
1829
+ padding: 1,
1830
+ children: [
1831
+ /* @__PURE__ */ jsxDEV2("text", {
1832
+ fg: theme().textMuted,
1833
+ children: props.path
1834
+ }, undefined, false, undefined, this),
1835
+ /* @__PURE__ */ jsxDEV2("text", {
1836
+ fg: theme().text,
1837
+ children: props.content
1838
+ }, undefined, false, undefined, this)
1839
+ ]
1840
+ }, undefined, true, undefined, this)
1841
+ }, undefined, false, undefined, this);
1842
+ }
1843
+
1844
+ // src/panel-permissions.tsx
1845
+ import { RGBA as RGBA3, SyntaxStyle as SyntaxStyle3 } from "@opentui/core";
1846
+ import { useTerminalDimensions as useTerminalDimensions3 } from "@opentui/solid";
1847
+ import { useBindings as useBindings3 } from "@opentui/keymap/solid";
1848
+
1849
+ // src/config-helper.ts
1850
+ import { readFileSync as readFileSync3, writeFileSync as writeFileSync3, existsSync } from "fs";
1851
+ import path3 from "path";
1852
+
1853
+ // node_modules/jsonc-parser/lib/esm/impl/scanner.js
1854
+ function createScanner(text, ignoreTrivia = false) {
1855
+ const len = text.length;
1856
+ let pos = 0, value = "", tokenOffset = 0, token = 16, lineNumber = 0, lineStartOffset = 0, tokenLineStartOffset = 0, prevTokenLineStartOffset = 0, scanError = 0;
1857
+ function scanHexDigits(count, exact) {
1858
+ let digits = 0;
1859
+ let value2 = 0;
1860
+ while (digits < count || !exact) {
1861
+ let ch = text.charCodeAt(pos);
1862
+ if (ch >= 48 && ch <= 57) {
1863
+ value2 = value2 * 16 + ch - 48;
1864
+ } else if (ch >= 65 && ch <= 70) {
1865
+ value2 = value2 * 16 + ch - 65 + 10;
1866
+ } else if (ch >= 97 && ch <= 102) {
1867
+ value2 = value2 * 16 + ch - 97 + 10;
1868
+ } else {
1869
+ break;
1870
+ }
1871
+ pos++;
1872
+ digits++;
1873
+ }
1874
+ if (digits < count) {
1875
+ value2 = -1;
1876
+ }
1877
+ return value2;
1878
+ }
1879
+ function setPosition(newPosition) {
1880
+ pos = newPosition;
1881
+ value = "";
1882
+ tokenOffset = 0;
1883
+ token = 16;
1884
+ scanError = 0;
1885
+ }
1886
+ function scanNumber() {
1887
+ let start = pos;
1888
+ if (text.charCodeAt(pos) === 48) {
1889
+ pos++;
1890
+ } else {
1891
+ pos++;
1892
+ while (pos < text.length && isDigit(text.charCodeAt(pos))) {
1893
+ pos++;
1894
+ }
1895
+ }
1896
+ if (pos < text.length && text.charCodeAt(pos) === 46) {
1897
+ pos++;
1898
+ if (pos < text.length && isDigit(text.charCodeAt(pos))) {
1899
+ pos++;
1900
+ while (pos < text.length && isDigit(text.charCodeAt(pos))) {
1901
+ pos++;
1902
+ }
1903
+ } else {
1904
+ scanError = 3;
1905
+ return text.substring(start, pos);
1906
+ }
1907
+ }
1908
+ let end = pos;
1909
+ if (pos < text.length && (text.charCodeAt(pos) === 69 || text.charCodeAt(pos) === 101)) {
1910
+ pos++;
1911
+ if (pos < text.length && text.charCodeAt(pos) === 43 || text.charCodeAt(pos) === 45) {
1912
+ pos++;
1913
+ }
1914
+ if (pos < text.length && isDigit(text.charCodeAt(pos))) {
1915
+ pos++;
1916
+ while (pos < text.length && isDigit(text.charCodeAt(pos))) {
1917
+ pos++;
1918
+ }
1919
+ end = pos;
1920
+ } else {
1921
+ scanError = 3;
1922
+ }
1923
+ }
1924
+ return text.substring(start, end);
1925
+ }
1926
+ function scanString() {
1927
+ let result = "", start = pos;
1928
+ while (true) {
1929
+ if (pos >= len) {
1930
+ result += text.substring(start, pos);
1931
+ scanError = 2;
1932
+ break;
1933
+ }
1934
+ const ch = text.charCodeAt(pos);
1935
+ if (ch === 34) {
1936
+ result += text.substring(start, pos);
1937
+ pos++;
1938
+ break;
1939
+ }
1940
+ if (ch === 92) {
1941
+ result += text.substring(start, pos);
1942
+ pos++;
1943
+ if (pos >= len) {
1944
+ scanError = 2;
1945
+ break;
1946
+ }
1947
+ const ch2 = text.charCodeAt(pos++);
1948
+ switch (ch2) {
1949
+ case 34:
1950
+ result += '"';
1951
+ break;
1952
+ case 92:
1953
+ result += "\\";
1954
+ break;
1955
+ case 47:
1956
+ result += "/";
1957
+ break;
1958
+ case 98:
1959
+ result += "\b";
1960
+ break;
1961
+ case 102:
1962
+ result += "\f";
1963
+ break;
1964
+ case 110:
1965
+ result += `
1966
+ `;
1967
+ break;
1968
+ case 114:
1969
+ result += "\r";
1970
+ break;
1971
+ case 116:
1972
+ result += "\t";
1973
+ break;
1974
+ case 117:
1975
+ const ch3 = scanHexDigits(4, true);
1976
+ if (ch3 >= 0) {
1977
+ result += String.fromCharCode(ch3);
1978
+ } else {
1979
+ scanError = 4;
1980
+ }
1981
+ break;
1982
+ default:
1983
+ scanError = 5;
1984
+ }
1985
+ start = pos;
1986
+ continue;
1987
+ }
1988
+ if (ch >= 0 && ch <= 31) {
1989
+ if (isLineBreak(ch)) {
1990
+ result += text.substring(start, pos);
1991
+ scanError = 2;
1992
+ break;
1993
+ } else {
1994
+ scanError = 6;
1995
+ }
1996
+ }
1997
+ pos++;
1998
+ }
1999
+ return result;
2000
+ }
2001
+ function scanNext() {
2002
+ value = "";
2003
+ scanError = 0;
2004
+ tokenOffset = pos;
2005
+ lineStartOffset = lineNumber;
2006
+ prevTokenLineStartOffset = tokenLineStartOffset;
2007
+ if (pos >= len) {
2008
+ tokenOffset = len;
2009
+ return token = 17;
2010
+ }
2011
+ let code = text.charCodeAt(pos);
2012
+ if (isWhiteSpace(code)) {
2013
+ do {
2014
+ pos++;
2015
+ value += String.fromCharCode(code);
2016
+ code = text.charCodeAt(pos);
2017
+ } while (isWhiteSpace(code));
2018
+ return token = 15;
2019
+ }
2020
+ if (isLineBreak(code)) {
2021
+ pos++;
2022
+ value += String.fromCharCode(code);
2023
+ if (code === 13 && text.charCodeAt(pos) === 10) {
2024
+ pos++;
2025
+ value += `
2026
+ `;
2027
+ }
2028
+ lineNumber++;
2029
+ tokenLineStartOffset = pos;
2030
+ return token = 14;
2031
+ }
2032
+ switch (code) {
2033
+ case 123:
2034
+ pos++;
2035
+ return token = 1;
2036
+ case 125:
2037
+ pos++;
2038
+ return token = 2;
2039
+ case 91:
2040
+ pos++;
2041
+ return token = 3;
2042
+ case 93:
2043
+ pos++;
2044
+ return token = 4;
2045
+ case 58:
2046
+ pos++;
2047
+ return token = 6;
2048
+ case 44:
2049
+ pos++;
2050
+ return token = 5;
2051
+ case 34:
2052
+ pos++;
2053
+ value = scanString();
2054
+ return token = 10;
2055
+ case 47:
2056
+ const start = pos - 1;
2057
+ if (text.charCodeAt(pos + 1) === 47) {
2058
+ pos += 2;
2059
+ while (pos < len) {
2060
+ if (isLineBreak(text.charCodeAt(pos))) {
2061
+ break;
2062
+ }
2063
+ pos++;
2064
+ }
2065
+ value = text.substring(start, pos);
2066
+ return token = 12;
2067
+ }
2068
+ if (text.charCodeAt(pos + 1) === 42) {
2069
+ pos += 2;
2070
+ const safeLength = len - 1;
2071
+ let commentClosed = false;
2072
+ while (pos < safeLength) {
2073
+ const ch = text.charCodeAt(pos);
2074
+ if (ch === 42 && text.charCodeAt(pos + 1) === 47) {
2075
+ pos += 2;
2076
+ commentClosed = true;
2077
+ break;
2078
+ }
2079
+ pos++;
2080
+ if (isLineBreak(ch)) {
2081
+ if (ch === 13 && text.charCodeAt(pos) === 10) {
2082
+ pos++;
2083
+ }
2084
+ lineNumber++;
2085
+ tokenLineStartOffset = pos;
2086
+ }
2087
+ }
2088
+ if (!commentClosed) {
2089
+ pos++;
2090
+ scanError = 1;
2091
+ }
2092
+ value = text.substring(start, pos);
2093
+ return token = 13;
2094
+ }
2095
+ value += String.fromCharCode(code);
2096
+ pos++;
2097
+ return token = 16;
2098
+ case 45:
2099
+ value += String.fromCharCode(code);
2100
+ pos++;
2101
+ if (pos === len || !isDigit(text.charCodeAt(pos))) {
2102
+ return token = 16;
2103
+ }
2104
+ case 48:
2105
+ case 49:
2106
+ case 50:
2107
+ case 51:
2108
+ case 52:
2109
+ case 53:
2110
+ case 54:
2111
+ case 55:
2112
+ case 56:
2113
+ case 57:
2114
+ value += scanNumber();
2115
+ return token = 11;
2116
+ default:
2117
+ while (pos < len && isUnknownContentCharacter(code)) {
2118
+ pos++;
2119
+ code = text.charCodeAt(pos);
2120
+ }
2121
+ if (tokenOffset !== pos) {
2122
+ value = text.substring(tokenOffset, pos);
2123
+ switch (value) {
2124
+ case "true":
2125
+ return token = 8;
2126
+ case "false":
2127
+ return token = 9;
2128
+ case "null":
2129
+ return token = 7;
2130
+ }
2131
+ return token = 16;
2132
+ }
2133
+ value += String.fromCharCode(code);
2134
+ pos++;
2135
+ return token = 16;
2136
+ }
2137
+ }
2138
+ function isUnknownContentCharacter(code) {
2139
+ if (isWhiteSpace(code) || isLineBreak(code)) {
2140
+ return false;
2141
+ }
2142
+ switch (code) {
2143
+ case 125:
2144
+ case 93:
2145
+ case 123:
2146
+ case 91:
2147
+ case 34:
2148
+ case 58:
2149
+ case 44:
2150
+ case 47:
2151
+ return false;
2152
+ }
2153
+ return true;
2154
+ }
2155
+ function scanNextNonTrivia() {
2156
+ let result;
2157
+ do {
2158
+ result = scanNext();
2159
+ } while (result >= 12 && result <= 15);
2160
+ return result;
2161
+ }
2162
+ return {
2163
+ setPosition,
2164
+ getPosition: () => pos,
2165
+ scan: ignoreTrivia ? scanNextNonTrivia : scanNext,
2166
+ getToken: () => token,
2167
+ getTokenValue: () => value,
2168
+ getTokenOffset: () => tokenOffset,
2169
+ getTokenLength: () => pos - tokenOffset,
2170
+ getTokenStartLine: () => lineStartOffset,
2171
+ getTokenStartCharacter: () => tokenOffset - prevTokenLineStartOffset,
2172
+ getTokenError: () => scanError
2173
+ };
2174
+ }
2175
+ function isWhiteSpace(ch) {
2176
+ return ch === 32 || ch === 9;
2177
+ }
2178
+ function isLineBreak(ch) {
2179
+ return ch === 10 || ch === 13;
2180
+ }
2181
+ function isDigit(ch) {
2182
+ return ch >= 48 && ch <= 57;
2183
+ }
2184
+ var CharacterCodes;
2185
+ (function(CharacterCodes2) {
2186
+ CharacterCodes2[CharacterCodes2["lineFeed"] = 10] = "lineFeed";
2187
+ CharacterCodes2[CharacterCodes2["carriageReturn"] = 13] = "carriageReturn";
2188
+ CharacterCodes2[CharacterCodes2["space"] = 32] = "space";
2189
+ CharacterCodes2[CharacterCodes2["_0"] = 48] = "_0";
2190
+ CharacterCodes2[CharacterCodes2["_1"] = 49] = "_1";
2191
+ CharacterCodes2[CharacterCodes2["_2"] = 50] = "_2";
2192
+ CharacterCodes2[CharacterCodes2["_3"] = 51] = "_3";
2193
+ CharacterCodes2[CharacterCodes2["_4"] = 52] = "_4";
2194
+ CharacterCodes2[CharacterCodes2["_5"] = 53] = "_5";
2195
+ CharacterCodes2[CharacterCodes2["_6"] = 54] = "_6";
2196
+ CharacterCodes2[CharacterCodes2["_7"] = 55] = "_7";
2197
+ CharacterCodes2[CharacterCodes2["_8"] = 56] = "_8";
2198
+ CharacterCodes2[CharacterCodes2["_9"] = 57] = "_9";
2199
+ CharacterCodes2[CharacterCodes2["a"] = 97] = "a";
2200
+ CharacterCodes2[CharacterCodes2["b"] = 98] = "b";
2201
+ CharacterCodes2[CharacterCodes2["c"] = 99] = "c";
2202
+ CharacterCodes2[CharacterCodes2["d"] = 100] = "d";
2203
+ CharacterCodes2[CharacterCodes2["e"] = 101] = "e";
2204
+ CharacterCodes2[CharacterCodes2["f"] = 102] = "f";
2205
+ CharacterCodes2[CharacterCodes2["g"] = 103] = "g";
2206
+ CharacterCodes2[CharacterCodes2["h"] = 104] = "h";
2207
+ CharacterCodes2[CharacterCodes2["i"] = 105] = "i";
2208
+ CharacterCodes2[CharacterCodes2["j"] = 106] = "j";
2209
+ CharacterCodes2[CharacterCodes2["k"] = 107] = "k";
2210
+ CharacterCodes2[CharacterCodes2["l"] = 108] = "l";
2211
+ CharacterCodes2[CharacterCodes2["m"] = 109] = "m";
2212
+ CharacterCodes2[CharacterCodes2["n"] = 110] = "n";
2213
+ CharacterCodes2[CharacterCodes2["o"] = 111] = "o";
2214
+ CharacterCodes2[CharacterCodes2["p"] = 112] = "p";
2215
+ CharacterCodes2[CharacterCodes2["q"] = 113] = "q";
2216
+ CharacterCodes2[CharacterCodes2["r"] = 114] = "r";
2217
+ CharacterCodes2[CharacterCodes2["s"] = 115] = "s";
2218
+ CharacterCodes2[CharacterCodes2["t"] = 116] = "t";
2219
+ CharacterCodes2[CharacterCodes2["u"] = 117] = "u";
2220
+ CharacterCodes2[CharacterCodes2["v"] = 118] = "v";
2221
+ CharacterCodes2[CharacterCodes2["w"] = 119] = "w";
2222
+ CharacterCodes2[CharacterCodes2["x"] = 120] = "x";
2223
+ CharacterCodes2[CharacterCodes2["y"] = 121] = "y";
2224
+ CharacterCodes2[CharacterCodes2["z"] = 122] = "z";
2225
+ CharacterCodes2[CharacterCodes2["A"] = 65] = "A";
2226
+ CharacterCodes2[CharacterCodes2["B"] = 66] = "B";
2227
+ CharacterCodes2[CharacterCodes2["C"] = 67] = "C";
2228
+ CharacterCodes2[CharacterCodes2["D"] = 68] = "D";
2229
+ CharacterCodes2[CharacterCodes2["E"] = 69] = "E";
2230
+ CharacterCodes2[CharacterCodes2["F"] = 70] = "F";
2231
+ CharacterCodes2[CharacterCodes2["G"] = 71] = "G";
2232
+ CharacterCodes2[CharacterCodes2["H"] = 72] = "H";
2233
+ CharacterCodes2[CharacterCodes2["I"] = 73] = "I";
2234
+ CharacterCodes2[CharacterCodes2["J"] = 74] = "J";
2235
+ CharacterCodes2[CharacterCodes2["K"] = 75] = "K";
2236
+ CharacterCodes2[CharacterCodes2["L"] = 76] = "L";
2237
+ CharacterCodes2[CharacterCodes2["M"] = 77] = "M";
2238
+ CharacterCodes2[CharacterCodes2["N"] = 78] = "N";
2239
+ CharacterCodes2[CharacterCodes2["O"] = 79] = "O";
2240
+ CharacterCodes2[CharacterCodes2["P"] = 80] = "P";
2241
+ CharacterCodes2[CharacterCodes2["Q"] = 81] = "Q";
2242
+ CharacterCodes2[CharacterCodes2["R"] = 82] = "R";
2243
+ CharacterCodes2[CharacterCodes2["S"] = 83] = "S";
2244
+ CharacterCodes2[CharacterCodes2["T"] = 84] = "T";
2245
+ CharacterCodes2[CharacterCodes2["U"] = 85] = "U";
2246
+ CharacterCodes2[CharacterCodes2["V"] = 86] = "V";
2247
+ CharacterCodes2[CharacterCodes2["W"] = 87] = "W";
2248
+ CharacterCodes2[CharacterCodes2["X"] = 88] = "X";
2249
+ CharacterCodes2[CharacterCodes2["Y"] = 89] = "Y";
2250
+ CharacterCodes2[CharacterCodes2["Z"] = 90] = "Z";
2251
+ CharacterCodes2[CharacterCodes2["asterisk"] = 42] = "asterisk";
2252
+ CharacterCodes2[CharacterCodes2["backslash"] = 92] = "backslash";
2253
+ CharacterCodes2[CharacterCodes2["closeBrace"] = 125] = "closeBrace";
2254
+ CharacterCodes2[CharacterCodes2["closeBracket"] = 93] = "closeBracket";
2255
+ CharacterCodes2[CharacterCodes2["colon"] = 58] = "colon";
2256
+ CharacterCodes2[CharacterCodes2["comma"] = 44] = "comma";
2257
+ CharacterCodes2[CharacterCodes2["dot"] = 46] = "dot";
2258
+ CharacterCodes2[CharacterCodes2["doubleQuote"] = 34] = "doubleQuote";
2259
+ CharacterCodes2[CharacterCodes2["minus"] = 45] = "minus";
2260
+ CharacterCodes2[CharacterCodes2["openBrace"] = 123] = "openBrace";
2261
+ CharacterCodes2[CharacterCodes2["openBracket"] = 91] = "openBracket";
2262
+ CharacterCodes2[CharacterCodes2["plus"] = 43] = "plus";
2263
+ CharacterCodes2[CharacterCodes2["slash"] = 47] = "slash";
2264
+ CharacterCodes2[CharacterCodes2["formFeed"] = 12] = "formFeed";
2265
+ CharacterCodes2[CharacterCodes2["tab"] = 9] = "tab";
2266
+ })(CharacterCodes || (CharacterCodes = {}));
2267
+
2268
+ // node_modules/jsonc-parser/lib/esm/impl/string-intern.js
2269
+ var cachedSpaces = new Array(20).fill(0).map((_, index) => {
2270
+ return " ".repeat(index);
2271
+ });
2272
+ var maxCachedValues = 200;
2273
+ var cachedBreakLinesWithSpaces = {
2274
+ " ": {
2275
+ "\n": new Array(maxCachedValues).fill(0).map((_, index) => {
2276
+ return `
2277
+ ` + " ".repeat(index);
2278
+ }),
2279
+ "\r": new Array(maxCachedValues).fill(0).map((_, index) => {
2280
+ return "\r" + " ".repeat(index);
2281
+ }),
2282
+ "\r\n": new Array(maxCachedValues).fill(0).map((_, index) => {
2283
+ return `\r
2284
+ ` + " ".repeat(index);
2285
+ })
2286
+ },
2287
+ "\t": {
2288
+ "\n": new Array(maxCachedValues).fill(0).map((_, index) => {
2289
+ return `
2290
+ ` + "\t".repeat(index);
2291
+ }),
2292
+ "\r": new Array(maxCachedValues).fill(0).map((_, index) => {
2293
+ return "\r" + "\t".repeat(index);
2294
+ }),
2295
+ "\r\n": new Array(maxCachedValues).fill(0).map((_, index) => {
2296
+ return `\r
2297
+ ` + "\t".repeat(index);
2298
+ })
2299
+ }
2300
+ };
2301
+ var supportedEols = [`
2302
+ `, "\r", `\r
2303
+ `];
2304
+
2305
+ // node_modules/jsonc-parser/lib/esm/impl/format.js
2306
+ function format(documentText, range, options) {
2307
+ let initialIndentLevel;
2308
+ let formatText;
2309
+ let formatTextStart;
2310
+ let rangeStart;
2311
+ let rangeEnd;
2312
+ if (range) {
2313
+ rangeStart = range.offset;
2314
+ rangeEnd = rangeStart + range.length;
2315
+ formatTextStart = rangeStart;
2316
+ while (formatTextStart > 0 && !isEOL(documentText, formatTextStart - 1)) {
2317
+ formatTextStart--;
2318
+ }
2319
+ let endOffset = rangeEnd;
2320
+ while (endOffset < documentText.length && !isEOL(documentText, endOffset)) {
2321
+ endOffset++;
2322
+ }
2323
+ formatText = documentText.substring(formatTextStart, endOffset);
2324
+ initialIndentLevel = computeIndentLevel(formatText, options);
2325
+ } else {
2326
+ formatText = documentText;
2327
+ initialIndentLevel = 0;
2328
+ formatTextStart = 0;
2329
+ rangeStart = 0;
2330
+ rangeEnd = documentText.length;
2331
+ }
2332
+ const eol = getEOL(options, documentText);
2333
+ const eolFastPathSupported = supportedEols.includes(eol);
2334
+ let numberLineBreaks = 0;
2335
+ let indentLevel = 0;
2336
+ let indentValue;
2337
+ if (options.insertSpaces) {
2338
+ indentValue = cachedSpaces[options.tabSize || 4] ?? repeat(cachedSpaces[1], options.tabSize || 4);
2339
+ } else {
2340
+ indentValue = "\t";
2341
+ }
2342
+ const indentType = indentValue === "\t" ? "\t" : " ";
2343
+ let scanner = createScanner(formatText, false);
2344
+ let hasError = false;
2345
+ function newLinesAndIndent() {
2346
+ if (numberLineBreaks > 1) {
2347
+ return repeat(eol, numberLineBreaks) + repeat(indentValue, initialIndentLevel + indentLevel);
2348
+ }
2349
+ const amountOfSpaces = indentValue.length * (initialIndentLevel + indentLevel);
2350
+ if (!eolFastPathSupported || amountOfSpaces > cachedBreakLinesWithSpaces[indentType][eol].length) {
2351
+ return eol + repeat(indentValue, initialIndentLevel + indentLevel);
2352
+ }
2353
+ if (amountOfSpaces <= 0) {
2354
+ return eol;
2355
+ }
2356
+ return cachedBreakLinesWithSpaces[indentType][eol][amountOfSpaces];
2357
+ }
2358
+ function scanNext() {
2359
+ let token = scanner.scan();
2360
+ numberLineBreaks = 0;
2361
+ while (token === 15 || token === 14) {
2362
+ if (token === 14 && options.keepLines) {
2363
+ numberLineBreaks += 1;
2364
+ } else if (token === 14) {
2365
+ numberLineBreaks = 1;
2366
+ }
2367
+ token = scanner.scan();
2368
+ }
2369
+ hasError = token === 16 || scanner.getTokenError() !== 0;
2370
+ return token;
2371
+ }
2372
+ const editOperations = [];
2373
+ function addEdit(text, startOffset, endOffset) {
2374
+ if (!hasError && (!range || startOffset < rangeEnd && endOffset > rangeStart) && documentText.substring(startOffset, endOffset) !== text) {
2375
+ editOperations.push({ offset: startOffset, length: endOffset - startOffset, content: text });
2376
+ }
2377
+ }
2378
+ let firstToken = scanNext();
2379
+ if (options.keepLines && numberLineBreaks > 0) {
2380
+ addEdit(repeat(eol, numberLineBreaks), 0, 0);
2381
+ }
2382
+ if (firstToken !== 17) {
2383
+ let firstTokenStart = scanner.getTokenOffset() + formatTextStart;
2384
+ let initialIndent = indentValue.length * initialIndentLevel < 20 && options.insertSpaces ? cachedSpaces[indentValue.length * initialIndentLevel] : repeat(indentValue, initialIndentLevel);
2385
+ addEdit(initialIndent, formatTextStart, firstTokenStart);
2386
+ }
2387
+ while (firstToken !== 17) {
2388
+ let firstTokenEnd = scanner.getTokenOffset() + scanner.getTokenLength() + formatTextStart;
2389
+ let secondToken = scanNext();
2390
+ let replaceContent = "";
2391
+ let needsLineBreak = false;
2392
+ while (numberLineBreaks === 0 && (secondToken === 12 || secondToken === 13)) {
2393
+ let commentTokenStart = scanner.getTokenOffset() + formatTextStart;
2394
+ addEdit(cachedSpaces[1], firstTokenEnd, commentTokenStart);
2395
+ firstTokenEnd = scanner.getTokenOffset() + scanner.getTokenLength() + formatTextStart;
2396
+ needsLineBreak = secondToken === 12;
2397
+ replaceContent = needsLineBreak ? newLinesAndIndent() : "";
2398
+ secondToken = scanNext();
2399
+ }
2400
+ if (secondToken === 2) {
2401
+ if (firstToken !== 1) {
2402
+ indentLevel--;
2403
+ }
2404
+ if (options.keepLines && numberLineBreaks > 0 || !options.keepLines && firstToken !== 1) {
2405
+ replaceContent = newLinesAndIndent();
2406
+ } else if (options.keepLines) {
2407
+ replaceContent = cachedSpaces[1];
2408
+ }
2409
+ } else if (secondToken === 4) {
2410
+ if (firstToken !== 3) {
2411
+ indentLevel--;
2412
+ }
2413
+ if (options.keepLines && numberLineBreaks > 0 || !options.keepLines && firstToken !== 3) {
2414
+ replaceContent = newLinesAndIndent();
2415
+ } else if (options.keepLines) {
2416
+ replaceContent = cachedSpaces[1];
2417
+ }
2418
+ } else {
2419
+ switch (firstToken) {
2420
+ case 3:
2421
+ case 1:
2422
+ indentLevel++;
2423
+ if (options.keepLines && numberLineBreaks > 0 || !options.keepLines) {
2424
+ replaceContent = newLinesAndIndent();
2425
+ } else {
2426
+ replaceContent = cachedSpaces[1];
2427
+ }
2428
+ break;
2429
+ case 5:
2430
+ if (options.keepLines && numberLineBreaks > 0 || !options.keepLines) {
2431
+ replaceContent = newLinesAndIndent();
2432
+ } else {
2433
+ replaceContent = cachedSpaces[1];
2434
+ }
2435
+ break;
2436
+ case 12:
2437
+ replaceContent = newLinesAndIndent();
2438
+ break;
2439
+ case 13:
2440
+ if (numberLineBreaks > 0) {
2441
+ replaceContent = newLinesAndIndent();
2442
+ } else if (!needsLineBreak) {
2443
+ replaceContent = cachedSpaces[1];
2444
+ }
2445
+ break;
2446
+ case 6:
2447
+ if (options.keepLines && numberLineBreaks > 0) {
2448
+ replaceContent = newLinesAndIndent();
2449
+ } else if (!needsLineBreak) {
2450
+ replaceContent = cachedSpaces[1];
2451
+ }
2452
+ break;
2453
+ case 10:
2454
+ if (options.keepLines && numberLineBreaks > 0) {
2455
+ replaceContent = newLinesAndIndent();
2456
+ } else if (secondToken === 6 && !needsLineBreak) {
2457
+ replaceContent = "";
2458
+ }
2459
+ break;
2460
+ case 7:
2461
+ case 8:
2462
+ case 9:
2463
+ case 11:
2464
+ case 2:
2465
+ case 4:
2466
+ if (options.keepLines && numberLineBreaks > 0) {
2467
+ replaceContent = newLinesAndIndent();
2468
+ } else {
2469
+ if ((secondToken === 12 || secondToken === 13) && !needsLineBreak) {
2470
+ replaceContent = cachedSpaces[1];
2471
+ } else if (secondToken !== 5 && secondToken !== 17) {
2472
+ hasError = true;
2473
+ }
2474
+ }
2475
+ break;
2476
+ case 16:
2477
+ hasError = true;
2478
+ break;
2479
+ }
2480
+ if (numberLineBreaks > 0 && (secondToken === 12 || secondToken === 13)) {
2481
+ replaceContent = newLinesAndIndent();
2482
+ }
2483
+ }
2484
+ if (secondToken === 17) {
2485
+ if (options.keepLines && numberLineBreaks > 0) {
2486
+ replaceContent = newLinesAndIndent();
2487
+ } else {
2488
+ replaceContent = options.insertFinalNewline ? eol : "";
2489
+ }
2490
+ }
2491
+ const secondTokenStart = scanner.getTokenOffset() + formatTextStart;
2492
+ addEdit(replaceContent, firstTokenEnd, secondTokenStart);
2493
+ firstToken = secondToken;
2494
+ }
2495
+ return editOperations;
2496
+ }
2497
+ function repeat(s, count) {
2498
+ let result = "";
2499
+ for (let i = 0;i < count; i++) {
2500
+ result += s;
2501
+ }
2502
+ return result;
2503
+ }
2504
+ function computeIndentLevel(content, options) {
2505
+ let i = 0;
2506
+ let nChars = 0;
2507
+ const tabSize = options.tabSize || 4;
2508
+ while (i < content.length) {
2509
+ let ch = content.charAt(i);
2510
+ if (ch === cachedSpaces[1]) {
2511
+ nChars++;
2512
+ } else if (ch === "\t") {
2513
+ nChars += tabSize;
2514
+ } else {
2515
+ break;
2516
+ }
2517
+ i++;
2518
+ }
2519
+ return Math.floor(nChars / tabSize);
2520
+ }
2521
+ function getEOL(options, text) {
2522
+ for (let i = 0;i < text.length; i++) {
2523
+ const ch = text.charAt(i);
2524
+ if (ch === "\r") {
2525
+ if (i + 1 < text.length && text.charAt(i + 1) === `
2526
+ `) {
2527
+ return `\r
2528
+ `;
2529
+ }
2530
+ return "\r";
2531
+ } else if (ch === `
2532
+ `) {
2533
+ return `
2534
+ `;
2535
+ }
2536
+ }
2537
+ return options && options.eol || `
2538
+ `;
2539
+ }
2540
+ function isEOL(text, offset) {
2541
+ return `\r
2542
+ `.indexOf(text.charAt(offset)) !== -1;
2543
+ }
2544
+
2545
+ // node_modules/jsonc-parser/lib/esm/impl/parser.js
2546
+ var ParseOptions;
2547
+ (function(ParseOptions2) {
2548
+ ParseOptions2.DEFAULT = {
2549
+ allowTrailingComma: false
2550
+ };
2551
+ })(ParseOptions || (ParseOptions = {}));
2552
+ function parseTree(text, errors = [], options = ParseOptions.DEFAULT) {
2553
+ let currentParent = { type: "array", offset: -1, length: -1, children: [], parent: undefined };
2554
+ function ensurePropertyComplete(endOffset) {
2555
+ if (currentParent.type === "property") {
2556
+ currentParent.length = endOffset - currentParent.offset;
2557
+ currentParent = currentParent.parent;
2558
+ }
2559
+ }
2560
+ function onValue(valueNode) {
2561
+ currentParent.children.push(valueNode);
2562
+ return valueNode;
2563
+ }
2564
+ const visitor = {
2565
+ onObjectBegin: (offset) => {
2566
+ currentParent = onValue({ type: "object", offset, length: -1, parent: currentParent, children: [] });
2567
+ },
2568
+ onObjectProperty: (name, offset, length) => {
2569
+ currentParent = onValue({ type: "property", offset, length: -1, parent: currentParent, children: [] });
2570
+ currentParent.children.push({ type: "string", value: name, offset, length, parent: currentParent });
2571
+ },
2572
+ onObjectEnd: (offset, length) => {
2573
+ ensurePropertyComplete(offset + length);
2574
+ currentParent.length = offset + length - currentParent.offset;
2575
+ currentParent = currentParent.parent;
2576
+ ensurePropertyComplete(offset + length);
2577
+ },
2578
+ onArrayBegin: (offset, length) => {
2579
+ currentParent = onValue({ type: "array", offset, length: -1, parent: currentParent, children: [] });
2580
+ },
2581
+ onArrayEnd: (offset, length) => {
2582
+ currentParent.length = offset + length - currentParent.offset;
2583
+ currentParent = currentParent.parent;
2584
+ ensurePropertyComplete(offset + length);
2585
+ },
2586
+ onLiteralValue: (value, offset, length) => {
2587
+ onValue({ type: getNodeType(value), offset, length, parent: currentParent, value });
2588
+ ensurePropertyComplete(offset + length);
2589
+ },
2590
+ onSeparator: (sep, offset, length) => {
2591
+ if (currentParent.type === "property") {
2592
+ if (sep === ":") {
2593
+ currentParent.colonOffset = offset;
2594
+ } else if (sep === ",") {
2595
+ ensurePropertyComplete(offset);
2596
+ }
2597
+ }
2598
+ },
2599
+ onError: (error, offset, length) => {
2600
+ errors.push({ error, offset, length });
2601
+ }
2602
+ };
2603
+ visit(text, visitor, options);
2604
+ const result = currentParent.children[0];
2605
+ if (result) {
2606
+ delete result.parent;
2607
+ }
2608
+ return result;
2609
+ }
2610
+ function findNodeAtLocation(root, path3) {
2611
+ if (!root) {
2612
+ return;
2613
+ }
2614
+ let node = root;
2615
+ for (let segment of path3) {
2616
+ if (typeof segment === "string") {
2617
+ if (node.type !== "object" || !Array.isArray(node.children)) {
2618
+ return;
2619
+ }
2620
+ let found = false;
2621
+ for (const propertyNode of node.children) {
2622
+ if (Array.isArray(propertyNode.children) && propertyNode.children[0].value === segment && propertyNode.children.length === 2) {
2623
+ node = propertyNode.children[1];
2624
+ found = true;
2625
+ break;
2626
+ }
2627
+ }
2628
+ if (!found) {
2629
+ return;
2630
+ }
2631
+ } else {
2632
+ const index = segment;
2633
+ if (node.type !== "array" || index < 0 || !Array.isArray(node.children) || index >= node.children.length) {
2634
+ return;
2635
+ }
2636
+ node = node.children[index];
2637
+ }
2638
+ }
2639
+ return node;
2640
+ }
2641
+ function visit(text, visitor, options = ParseOptions.DEFAULT) {
2642
+ const _scanner = createScanner(text, false);
2643
+ const _jsonPath = [];
2644
+ let suppressedCallbacks = 0;
2645
+ function toNoArgVisit(visitFunction) {
2646
+ return visitFunction ? () => suppressedCallbacks === 0 && visitFunction(_scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter()) : () => true;
2647
+ }
2648
+ function toOneArgVisit(visitFunction) {
2649
+ return visitFunction ? (arg) => suppressedCallbacks === 0 && visitFunction(arg, _scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter()) : () => true;
2650
+ }
2651
+ function toOneArgVisitWithPath(visitFunction) {
2652
+ return visitFunction ? (arg) => suppressedCallbacks === 0 && visitFunction(arg, _scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter(), () => _jsonPath.slice()) : () => true;
2653
+ }
2654
+ function toBeginVisit(visitFunction) {
2655
+ return visitFunction ? () => {
2656
+ if (suppressedCallbacks > 0) {
2657
+ suppressedCallbacks++;
2658
+ } else {
2659
+ let cbReturn = visitFunction(_scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter(), () => _jsonPath.slice());
2660
+ if (cbReturn === false) {
2661
+ suppressedCallbacks = 1;
2662
+ }
2663
+ }
2664
+ } : () => true;
2665
+ }
2666
+ function toEndVisit(visitFunction) {
2667
+ return visitFunction ? () => {
2668
+ if (suppressedCallbacks > 0) {
2669
+ suppressedCallbacks--;
2670
+ }
2671
+ if (suppressedCallbacks === 0) {
2672
+ visitFunction(_scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter());
2673
+ }
2674
+ } : () => true;
2675
+ }
2676
+ const onObjectBegin = toBeginVisit(visitor.onObjectBegin), onObjectProperty = toOneArgVisitWithPath(visitor.onObjectProperty), onObjectEnd = toEndVisit(visitor.onObjectEnd), onArrayBegin = toBeginVisit(visitor.onArrayBegin), onArrayEnd = toEndVisit(visitor.onArrayEnd), onLiteralValue = toOneArgVisitWithPath(visitor.onLiteralValue), onSeparator = toOneArgVisit(visitor.onSeparator), onComment = toNoArgVisit(visitor.onComment), onError = toOneArgVisit(visitor.onError);
2677
+ const disallowComments = options && options.disallowComments;
2678
+ const allowTrailingComma = options && options.allowTrailingComma;
2679
+ function scanNext() {
2680
+ while (true) {
2681
+ const token = _scanner.scan();
2682
+ switch (_scanner.getTokenError()) {
2683
+ case 4:
2684
+ handleError(14);
2685
+ break;
2686
+ case 5:
2687
+ handleError(15);
2688
+ break;
2689
+ case 3:
2690
+ handleError(13);
2691
+ break;
2692
+ case 1:
2693
+ if (!disallowComments) {
2694
+ handleError(11);
2695
+ }
2696
+ break;
2697
+ case 2:
2698
+ handleError(12);
2699
+ break;
2700
+ case 6:
2701
+ handleError(16);
2702
+ break;
2703
+ }
2704
+ switch (token) {
2705
+ case 12:
2706
+ case 13:
2707
+ if (disallowComments) {
2708
+ handleError(10);
2709
+ } else {
2710
+ onComment();
2711
+ }
2712
+ break;
2713
+ case 16:
2714
+ handleError(1);
2715
+ break;
2716
+ case 15:
2717
+ case 14:
2718
+ break;
2719
+ default:
2720
+ return token;
2721
+ }
2722
+ }
2723
+ }
2724
+ function handleError(error, skipUntilAfter = [], skipUntil = []) {
2725
+ onError(error);
2726
+ if (skipUntilAfter.length + skipUntil.length > 0) {
2727
+ let token = _scanner.getToken();
2728
+ while (token !== 17) {
2729
+ if (skipUntilAfter.indexOf(token) !== -1) {
2730
+ scanNext();
2731
+ break;
2732
+ } else if (skipUntil.indexOf(token) !== -1) {
2733
+ break;
2734
+ }
2735
+ token = scanNext();
2736
+ }
2737
+ }
2738
+ }
2739
+ function parseString(isValue) {
2740
+ const value = _scanner.getTokenValue();
2741
+ if (isValue) {
2742
+ onLiteralValue(value);
2743
+ } else {
2744
+ onObjectProperty(value);
2745
+ _jsonPath.push(value);
2746
+ }
2747
+ scanNext();
2748
+ return true;
2749
+ }
2750
+ function parseLiteral() {
2751
+ switch (_scanner.getToken()) {
2752
+ case 11:
2753
+ const tokenValue = _scanner.getTokenValue();
2754
+ let value = Number(tokenValue);
2755
+ if (isNaN(value)) {
2756
+ handleError(2);
2757
+ value = 0;
2758
+ }
2759
+ onLiteralValue(value);
2760
+ break;
2761
+ case 7:
2762
+ onLiteralValue(null);
2763
+ break;
2764
+ case 8:
2765
+ onLiteralValue(true);
2766
+ break;
2767
+ case 9:
2768
+ onLiteralValue(false);
2769
+ break;
2770
+ default:
2771
+ return false;
2772
+ }
2773
+ scanNext();
2774
+ return true;
2775
+ }
2776
+ function parseProperty() {
2777
+ if (_scanner.getToken() !== 10) {
2778
+ handleError(3, [], [2, 5]);
2779
+ return false;
2780
+ }
2781
+ parseString(false);
2782
+ if (_scanner.getToken() === 6) {
2783
+ onSeparator(":");
2784
+ scanNext();
2785
+ if (!parseValue()) {
2786
+ handleError(4, [], [2, 5]);
2787
+ }
2788
+ } else {
2789
+ handleError(5, [], [2, 5]);
2790
+ }
2791
+ _jsonPath.pop();
2792
+ return true;
2793
+ }
2794
+ function parseObject() {
2795
+ onObjectBegin();
2796
+ scanNext();
2797
+ let needsComma = false;
2798
+ while (_scanner.getToken() !== 2 && _scanner.getToken() !== 17) {
2799
+ if (_scanner.getToken() === 5) {
2800
+ if (!needsComma) {
2801
+ handleError(4, [], []);
2802
+ }
2803
+ onSeparator(",");
2804
+ scanNext();
2805
+ if (_scanner.getToken() === 2 && allowTrailingComma) {
2806
+ break;
2807
+ }
2808
+ } else if (needsComma) {
2809
+ handleError(6, [], []);
2810
+ }
2811
+ if (!parseProperty()) {
2812
+ handleError(4, [], [2, 5]);
2813
+ }
2814
+ needsComma = true;
2815
+ }
2816
+ onObjectEnd();
2817
+ if (_scanner.getToken() !== 2) {
2818
+ handleError(7, [2], []);
2819
+ } else {
2820
+ scanNext();
2821
+ }
2822
+ return true;
2823
+ }
2824
+ function parseArray() {
2825
+ onArrayBegin();
2826
+ scanNext();
2827
+ let isFirstElement = true;
2828
+ let needsComma = false;
2829
+ while (_scanner.getToken() !== 4 && _scanner.getToken() !== 17) {
2830
+ if (_scanner.getToken() === 5) {
2831
+ if (!needsComma) {
2832
+ handleError(4, [], []);
2833
+ }
2834
+ onSeparator(",");
2835
+ scanNext();
2836
+ if (_scanner.getToken() === 4 && allowTrailingComma) {
2837
+ break;
2838
+ }
2839
+ } else if (needsComma) {
2840
+ handleError(6, [], []);
2841
+ }
2842
+ if (isFirstElement) {
2843
+ _jsonPath.push(0);
2844
+ isFirstElement = false;
2845
+ } else {
2846
+ _jsonPath[_jsonPath.length - 1]++;
2847
+ }
2848
+ if (!parseValue()) {
2849
+ handleError(4, [], [4, 5]);
2850
+ }
2851
+ needsComma = true;
2852
+ }
2853
+ onArrayEnd();
2854
+ if (!isFirstElement) {
2855
+ _jsonPath.pop();
2856
+ }
2857
+ if (_scanner.getToken() !== 4) {
2858
+ handleError(8, [4], []);
2859
+ } else {
2860
+ scanNext();
2861
+ }
2862
+ return true;
2863
+ }
2864
+ function parseValue() {
2865
+ switch (_scanner.getToken()) {
2866
+ case 3:
2867
+ return parseArray();
2868
+ case 1:
2869
+ return parseObject();
2870
+ case 10:
2871
+ return parseString(true);
2872
+ default:
2873
+ return parseLiteral();
2874
+ }
2875
+ }
2876
+ scanNext();
2877
+ if (_scanner.getToken() === 17) {
2878
+ if (options.allowEmptyContent) {
2879
+ return true;
2880
+ }
2881
+ handleError(4, [], []);
2882
+ return false;
2883
+ }
2884
+ if (!parseValue()) {
2885
+ handleError(4, [], []);
2886
+ return false;
2887
+ }
2888
+ if (_scanner.getToken() !== 17) {
2889
+ handleError(9, [], []);
2890
+ }
2891
+ return true;
2892
+ }
2893
+ function stripComments(text, replaceCh) {
2894
+ let _scanner = createScanner(text), parts = [], kind, offset = 0, pos;
2895
+ do {
2896
+ pos = _scanner.getPosition();
2897
+ kind = _scanner.scan();
2898
+ switch (kind) {
2899
+ case 12:
2900
+ case 13:
2901
+ case 17:
2902
+ if (offset !== pos) {
2903
+ parts.push(text.substring(offset, pos));
2904
+ }
2905
+ if (replaceCh !== undefined) {
2906
+ parts.push(_scanner.getTokenValue().replace(/[^\r\n]/g, replaceCh));
2907
+ }
2908
+ offset = _scanner.getPosition();
2909
+ break;
2910
+ }
2911
+ } while (kind !== 17);
2912
+ return parts.join("");
2913
+ }
2914
+ function getNodeType(value) {
2915
+ switch (typeof value) {
2916
+ case "boolean":
2917
+ return "boolean";
2918
+ case "number":
2919
+ return "number";
2920
+ case "string":
2921
+ return "string";
2922
+ case "object": {
2923
+ if (!value) {
2924
+ return "null";
2925
+ } else if (Array.isArray(value)) {
2926
+ return "array";
2927
+ }
2928
+ return "object";
2929
+ }
2930
+ default:
2931
+ return "null";
2932
+ }
2933
+ }
2934
+
2935
+ // node_modules/jsonc-parser/lib/esm/impl/edit.js
2936
+ function setProperty(text, originalPath, value, options) {
2937
+ const path3 = originalPath.slice();
2938
+ const errors = [];
2939
+ const root = parseTree(text, errors);
2940
+ let parent = undefined;
2941
+ let lastSegment = undefined;
2942
+ while (path3.length > 0) {
2943
+ lastSegment = path3.pop();
2944
+ parent = findNodeAtLocation(root, path3);
2945
+ if (parent === undefined && value !== undefined) {
2946
+ if (typeof lastSegment === "string") {
2947
+ value = { [lastSegment]: value };
2948
+ } else {
2949
+ value = [value];
2950
+ }
2951
+ } else {
2952
+ break;
2953
+ }
2954
+ }
2955
+ if (!parent) {
2956
+ if (value === undefined) {
2957
+ throw new Error("Can not delete in empty document");
2958
+ }
2959
+ return withFormatting(text, { offset: root ? root.offset : 0, length: root ? root.length : 0, content: JSON.stringify(value) }, options);
2960
+ } else if (parent.type === "object" && typeof lastSegment === "string" && Array.isArray(parent.children)) {
2961
+ const existing = findNodeAtLocation(parent, [lastSegment]);
2962
+ if (existing !== undefined) {
2963
+ if (value === undefined) {
2964
+ if (!existing.parent) {
2965
+ throw new Error("Malformed AST");
2966
+ }
2967
+ const propertyIndex = parent.children.indexOf(existing.parent);
2968
+ let removeBegin;
2969
+ let removeEnd = existing.parent.offset + existing.parent.length;
2970
+ if (propertyIndex > 0) {
2971
+ let previous = parent.children[propertyIndex - 1];
2972
+ removeBegin = previous.offset + previous.length;
2973
+ } else {
2974
+ removeBegin = parent.offset + 1;
2975
+ if (parent.children.length > 1) {
2976
+ let next = parent.children[1];
2977
+ removeEnd = next.offset;
2978
+ }
2979
+ }
2980
+ return withFormatting(text, { offset: removeBegin, length: removeEnd - removeBegin, content: "" }, options);
2981
+ } else {
2982
+ return withFormatting(text, { offset: existing.offset, length: existing.length, content: JSON.stringify(value) }, options);
2983
+ }
2984
+ } else {
2985
+ if (value === undefined) {
2986
+ return [];
2987
+ }
2988
+ const newProperty = `${JSON.stringify(lastSegment)}: ${JSON.stringify(value)}`;
2989
+ const index = options.getInsertionIndex ? options.getInsertionIndex(parent.children.map((p) => p.children[0].value)) : parent.children.length;
2990
+ let edit;
2991
+ if (index > 0) {
2992
+ let previous = parent.children[index - 1];
2993
+ edit = { offset: previous.offset + previous.length, length: 0, content: "," + newProperty };
2994
+ } else if (parent.children.length === 0) {
2995
+ edit = { offset: parent.offset + 1, length: 0, content: newProperty };
2996
+ } else {
2997
+ edit = { offset: parent.offset + 1, length: 0, content: newProperty + "," };
2998
+ }
2999
+ return withFormatting(text, edit, options);
3000
+ }
3001
+ } else if (parent.type === "array" && typeof lastSegment === "number" && Array.isArray(parent.children)) {
3002
+ const insertIndex = lastSegment;
3003
+ if (insertIndex === -1) {
3004
+ const newProperty = `${JSON.stringify(value)}`;
3005
+ let edit;
3006
+ if (parent.children.length === 0) {
3007
+ edit = { offset: parent.offset + 1, length: 0, content: newProperty };
3008
+ } else {
3009
+ const previous = parent.children[parent.children.length - 1];
3010
+ edit = { offset: previous.offset + previous.length, length: 0, content: "," + newProperty };
3011
+ }
3012
+ return withFormatting(text, edit, options);
3013
+ } else if (value === undefined && parent.children.length >= 0) {
3014
+ const removalIndex = lastSegment;
3015
+ const toRemove = parent.children[removalIndex];
3016
+ let edit;
3017
+ if (parent.children.length === 1) {
3018
+ edit = { offset: parent.offset + 1, length: parent.length - 2, content: "" };
3019
+ } else if (parent.children.length - 1 === removalIndex) {
3020
+ let previous = parent.children[removalIndex - 1];
3021
+ let offset = previous.offset + previous.length;
3022
+ let parentEndOffset = parent.offset + parent.length;
3023
+ edit = { offset, length: parentEndOffset - 2 - offset, content: "" };
3024
+ } else {
3025
+ edit = { offset: toRemove.offset, length: parent.children[removalIndex + 1].offset - toRemove.offset, content: "" };
3026
+ }
3027
+ return withFormatting(text, edit, options);
3028
+ } else if (value !== undefined) {
3029
+ let edit;
3030
+ const newProperty = `${JSON.stringify(value)}`;
3031
+ if (!options.isArrayInsertion && parent.children.length > lastSegment) {
3032
+ const toModify = parent.children[lastSegment];
3033
+ edit = { offset: toModify.offset, length: toModify.length, content: newProperty };
3034
+ } else if (parent.children.length === 0 || lastSegment === 0) {
3035
+ edit = { offset: parent.offset + 1, length: 0, content: parent.children.length === 0 ? newProperty : newProperty + "," };
3036
+ } else {
3037
+ const index = lastSegment > parent.children.length ? parent.children.length : lastSegment;
3038
+ const previous = parent.children[index - 1];
3039
+ edit = { offset: previous.offset + previous.length, length: 0, content: "," + newProperty };
3040
+ }
3041
+ return withFormatting(text, edit, options);
3042
+ } else {
3043
+ throw new Error(`Can not ${value === undefined ? "remove" : options.isArrayInsertion ? "insert" : "modify"} Array index ${insertIndex} as length is not sufficient`);
3044
+ }
3045
+ } else {
3046
+ throw new Error(`Can not add ${typeof lastSegment !== "number" ? "index" : "property"} to parent of type ${parent.type}`);
3047
+ }
3048
+ }
3049
+ function withFormatting(text, edit, options) {
3050
+ if (!options.formattingOptions) {
3051
+ return [edit];
3052
+ }
3053
+ let newText = applyEdit(text, edit);
3054
+ let begin = edit.offset;
3055
+ let end = edit.offset + edit.content.length;
3056
+ if (edit.length === 0 || edit.content.length === 0) {
3057
+ while (begin > 0 && !isEOL(newText, begin - 1)) {
3058
+ begin--;
3059
+ }
3060
+ while (end < newText.length && !isEOL(newText, end)) {
3061
+ end++;
3062
+ }
3063
+ }
3064
+ const edits = format(newText, { offset: begin, length: end - begin }, { ...options.formattingOptions, keepLines: false });
3065
+ for (let i = edits.length - 1;i >= 0; i--) {
3066
+ const edit2 = edits[i];
3067
+ newText = applyEdit(newText, edit2);
3068
+ begin = Math.min(begin, edit2.offset);
3069
+ end = Math.max(end, edit2.offset + edit2.length);
3070
+ end += edit2.content.length - edit2.length;
3071
+ }
3072
+ const editLength = text.length - (newText.length - end) - begin;
3073
+ return [{ offset: begin, length: editLength, content: newText.substring(begin, end) }];
3074
+ }
3075
+ function applyEdit(text, edit) {
3076
+ return text.substring(0, edit.offset) + edit.content + text.substring(edit.offset + edit.length);
3077
+ }
3078
+
3079
+ // node_modules/jsonc-parser/lib/esm/main.js
3080
+ var ScanError;
3081
+ (function(ScanError2) {
3082
+ ScanError2[ScanError2["None"] = 0] = "None";
3083
+ ScanError2[ScanError2["UnexpectedEndOfComment"] = 1] = "UnexpectedEndOfComment";
3084
+ ScanError2[ScanError2["UnexpectedEndOfString"] = 2] = "UnexpectedEndOfString";
3085
+ ScanError2[ScanError2["UnexpectedEndOfNumber"] = 3] = "UnexpectedEndOfNumber";
3086
+ ScanError2[ScanError2["InvalidUnicode"] = 4] = "InvalidUnicode";
3087
+ ScanError2[ScanError2["InvalidEscapeCharacter"] = 5] = "InvalidEscapeCharacter";
3088
+ ScanError2[ScanError2["InvalidCharacter"] = 6] = "InvalidCharacter";
3089
+ })(ScanError || (ScanError = {}));
3090
+ var SyntaxKind;
3091
+ (function(SyntaxKind2) {
3092
+ SyntaxKind2[SyntaxKind2["OpenBraceToken"] = 1] = "OpenBraceToken";
3093
+ SyntaxKind2[SyntaxKind2["CloseBraceToken"] = 2] = "CloseBraceToken";
3094
+ SyntaxKind2[SyntaxKind2["OpenBracketToken"] = 3] = "OpenBracketToken";
3095
+ SyntaxKind2[SyntaxKind2["CloseBracketToken"] = 4] = "CloseBracketToken";
3096
+ SyntaxKind2[SyntaxKind2["CommaToken"] = 5] = "CommaToken";
3097
+ SyntaxKind2[SyntaxKind2["ColonToken"] = 6] = "ColonToken";
3098
+ SyntaxKind2[SyntaxKind2["NullKeyword"] = 7] = "NullKeyword";
3099
+ SyntaxKind2[SyntaxKind2["TrueKeyword"] = 8] = "TrueKeyword";
3100
+ SyntaxKind2[SyntaxKind2["FalseKeyword"] = 9] = "FalseKeyword";
3101
+ SyntaxKind2[SyntaxKind2["StringLiteral"] = 10] = "StringLiteral";
3102
+ SyntaxKind2[SyntaxKind2["NumericLiteral"] = 11] = "NumericLiteral";
3103
+ SyntaxKind2[SyntaxKind2["LineCommentTrivia"] = 12] = "LineCommentTrivia";
3104
+ SyntaxKind2[SyntaxKind2["BlockCommentTrivia"] = 13] = "BlockCommentTrivia";
3105
+ SyntaxKind2[SyntaxKind2["LineBreakTrivia"] = 14] = "LineBreakTrivia";
3106
+ SyntaxKind2[SyntaxKind2["Trivia"] = 15] = "Trivia";
3107
+ SyntaxKind2[SyntaxKind2["Unknown"] = 16] = "Unknown";
3108
+ SyntaxKind2[SyntaxKind2["EOF"] = 17] = "EOF";
3109
+ })(SyntaxKind || (SyntaxKind = {}));
3110
+ var stripComments2 = stripComments;
3111
+ var ParseErrorCode;
3112
+ (function(ParseErrorCode2) {
3113
+ ParseErrorCode2[ParseErrorCode2["InvalidSymbol"] = 1] = "InvalidSymbol";
3114
+ ParseErrorCode2[ParseErrorCode2["InvalidNumberFormat"] = 2] = "InvalidNumberFormat";
3115
+ ParseErrorCode2[ParseErrorCode2["PropertyNameExpected"] = 3] = "PropertyNameExpected";
3116
+ ParseErrorCode2[ParseErrorCode2["ValueExpected"] = 4] = "ValueExpected";
3117
+ ParseErrorCode2[ParseErrorCode2["ColonExpected"] = 5] = "ColonExpected";
3118
+ ParseErrorCode2[ParseErrorCode2["CommaExpected"] = 6] = "CommaExpected";
3119
+ ParseErrorCode2[ParseErrorCode2["CloseBraceExpected"] = 7] = "CloseBraceExpected";
3120
+ ParseErrorCode2[ParseErrorCode2["CloseBracketExpected"] = 8] = "CloseBracketExpected";
3121
+ ParseErrorCode2[ParseErrorCode2["EndOfFileExpected"] = 9] = "EndOfFileExpected";
3122
+ ParseErrorCode2[ParseErrorCode2["InvalidCommentToken"] = 10] = "InvalidCommentToken";
3123
+ ParseErrorCode2[ParseErrorCode2["UnexpectedEndOfComment"] = 11] = "UnexpectedEndOfComment";
3124
+ ParseErrorCode2[ParseErrorCode2["UnexpectedEndOfString"] = 12] = "UnexpectedEndOfString";
3125
+ ParseErrorCode2[ParseErrorCode2["UnexpectedEndOfNumber"] = 13] = "UnexpectedEndOfNumber";
3126
+ ParseErrorCode2[ParseErrorCode2["InvalidUnicode"] = 14] = "InvalidUnicode";
3127
+ ParseErrorCode2[ParseErrorCode2["InvalidEscapeCharacter"] = 15] = "InvalidEscapeCharacter";
3128
+ ParseErrorCode2[ParseErrorCode2["InvalidCharacter"] = 16] = "InvalidCharacter";
3129
+ })(ParseErrorCode || (ParseErrorCode = {}));
3130
+ function modify(text, path3, value, options) {
3131
+ return setProperty(text, path3, value, options);
3132
+ }
3133
+ function applyEdits(text, edits) {
3134
+ let sortedEdits = edits.slice(0).sort((a, b) => {
3135
+ const diff = a.offset - b.offset;
3136
+ if (diff === 0) {
3137
+ return a.length - b.length;
3138
+ }
3139
+ return diff;
3140
+ });
3141
+ let lastModifiedOffset = text.length;
3142
+ for (let i = sortedEdits.length - 1;i >= 0; i--) {
3143
+ let e = sortedEdits[i];
3144
+ if (e.offset + e.length <= lastModifiedOffset) {
3145
+ text = applyEdit(text, e);
3146
+ } else {
3147
+ throw new Error("Overlapping edit");
3148
+ }
3149
+ lastModifiedOffset = e.offset;
3150
+ }
3151
+ return text;
3152
+ }
3153
+
3154
+ // src/config-helper.ts
3155
+ function findConfig(directory, worktree) {
3156
+ let current = path3.resolve(directory);
3157
+ const root = path3.resolve(worktree);
3158
+ while (current.startsWith(root)) {
3159
+ for (const name of ["opencode.jsonc", "opencode.json"]) {
3160
+ const fp = path3.join(current, name);
3161
+ if (existsSync(fp))
3162
+ return fp;
3163
+ }
3164
+ if (current === root)
3165
+ break;
3166
+ const next = path3.dirname(current);
3167
+ if (next === current)
3168
+ break;
3169
+ current = next;
3170
+ }
3171
+ return null;
3172
+ }
3173
+ function detectIndent(text) {
3174
+ const m = text.match(/^( {2,4}|\t)/m);
3175
+ if (m) {
3176
+ const t = m[1];
3177
+ return { tabSize: t === "\t" ? 1 : t.length, insertSpaces: t !== "\t" };
3178
+ }
3179
+ return { tabSize: 2, insertSpaces: true };
3180
+ }
3181
+ function readPermissions(filePath) {
3182
+ const result = { allow: [], deny: [] };
3183
+ try {
3184
+ const raw = readFileSync3(filePath, "utf-8");
3185
+ const text = stripComments2(raw);
3186
+ const data = JSON.parse(text);
3187
+ const skill = data?.permission?.skill;
3188
+ if (!skill)
3189
+ return result;
3190
+ if (typeof skill === "string") {
3191
+ if (skill === "allow")
3192
+ result.allow.push("*");
3193
+ else if (skill === "deny")
3194
+ result.deny.push("*");
3195
+ return result;
3196
+ }
3197
+ if (typeof skill === "object" && !Array.isArray(skill)) {
3198
+ for (const [k, v] of Object.entries(skill)) {
3199
+ if (v === "allow")
3200
+ result.allow.push(k);
3201
+ else if (v === "deny")
3202
+ result.deny.push(k);
3203
+ }
3204
+ }
3205
+ } catch {}
3206
+ return result;
3207
+ }
3208
+ function setPermission(filePath, skillName, action) {
3209
+ try {
3210
+ let text = readFileSync3(filePath, "utf-8");
3211
+ const opts = { formattingOptions: detectIndent(text) };
3212
+ const edits = modify(text, ["permission", "skill", skillName], action, opts);
3213
+ text = applyEdits(text, edits);
3214
+ writeFileSync3(filePath, text, "utf-8");
3215
+ } catch {}
3216
+ }
3217
+ function readTools(filePath) {
3218
+ try {
3219
+ const raw = readFileSync3(filePath, "utf-8");
3220
+ const text = stripComments2(raw);
3221
+ const data = JSON.parse(text);
3222
+ const permission = data?.permission;
3223
+ if (!permission || typeof permission !== "object")
3224
+ return {};
3225
+ const result = {};
3226
+ for (const [k, v] of Object.entries(permission)) {
3227
+ if (k === "skill")
3228
+ continue;
3229
+ if (typeof v === "string")
3230
+ result[k] = v;
3231
+ }
3232
+ return result;
3233
+ } catch {
3234
+ return {};
3235
+ }
3236
+ }
3237
+ function setToolPermission(filePath, tool, action) {
3238
+ try {
3239
+ let text = readFileSync3(filePath, "utf-8");
3240
+ const opts = { formattingOptions: detectIndent(text) };
3241
+ const edits = modify(text, ["permission", tool], action, opts);
3242
+ text = applyEdits(text, edits);
3243
+ writeFileSync3(filePath, text, "utf-8");
3244
+ } catch {}
3245
+ }
3246
+ function readMCPs(filePath) {
3247
+ try {
3248
+ const raw = readFileSync3(filePath, "utf-8");
3249
+ const text = stripComments2(raw);
3250
+ const data = JSON.parse(text);
3251
+ const mcp = data?.mcp;
3252
+ if (!mcp || typeof mcp !== "object")
3253
+ return [];
3254
+ return Object.entries(mcp).map(([name, cfg]) => ({
3255
+ name,
3256
+ type: cfg?.type ?? "local",
3257
+ enabled: cfg?.enabled !== false,
3258
+ command: cfg?.command,
3259
+ url: cfg?.url
3260
+ }));
3261
+ } catch {
3262
+ return [];
3263
+ }
3264
+ }
3265
+ function setMCPEnabled(filePath, name, enabled) {
3266
+ try {
3267
+ let text = readFileSync3(filePath, "utf-8");
3268
+ const opts = { formattingOptions: detectIndent(text) };
3269
+ const edits = modify(text, ["mcp", name, "enabled"], enabled, opts);
3270
+ text = applyEdits(text, edits);
3271
+ writeFileSync3(filePath, text, "utf-8");
3272
+ } catch {}
3273
+ }
3274
+
3275
+ // src/panel-permissions.tsx
3276
+ import { jsxDEV as jsxDEV3 } from "@opentui/solid/jsx-dev-runtime";
3277
+ var HINT_FG3 = RGBA3.fromInts(180, 180, 180, 255);
3278
+ var FG3 = RGBA3.fromInts(255, 255, 255, 255);
3279
+ function PermissionsPanel(props) {
3280
+ const dimensions = useTerminalDimensions3();
3281
+ const theme = () => props.api.theme.current;
3282
+ let activeTab = 0;
3283
+ let tabSkillsEl;
3284
+ let tabToolsEl;
3285
+ let tabMcpEl;
3286
+ let selectRef;
3287
+ let skillsDetailBox;
3288
+ let toolsDetailBox;
3289
+ let mcpsDetailBox;
3290
+ let skNameEl;
3291
+ let skPathEl;
3292
+ let skCopyEl;
3293
+ let skStatusEl;
3294
+ let skLastClick = 0;
3295
+ let skLastIdx = -1;
3296
+ const skAllowSet = new Set(props.initialSkillAllow);
3297
+ const skDenySet = new Set(props.initialSkillDeny);
3298
+ const skCatchAllDeny = skDenySet.has("*");
3299
+ function skIsAllow(s) {
3300
+ if (skAllowSet.has("*"))
3301
+ return true;
3302
+ if (skDenySet.has(s.name))
3303
+ return false;
3304
+ if (skAllowSet.has(s.name))
3305
+ return true;
3306
+ return !skCatchAllDeny;
3307
+ }
3308
+ const skToOptions = () => props.skills.map((s) => ({
3309
+ name: (skIsAllow(s) ? "[allow] " : "[deny] ") + s.name,
3310
+ description: s.description ?? "",
3311
+ value: s.name
3312
+ }));
3313
+ function skUpdateDetail(s) {
3314
+ if (!s) {
3315
+ skNameEl.content = "";
3316
+ skPathEl.content = "";
3317
+ skCopyEl.content = "";
3318
+ skStatusEl.content = "";
3319
+ return;
3320
+ }
3321
+ skNameEl.content = s.name;
3322
+ skPathEl.content = s.location;
3323
+ skCopyEl.content = "[Copy]";
3324
+ skStatusEl.content = skIsAllow(s) ? "allowed" : "denied";
3325
+ }
3326
+ function skToggle(name) {
3327
+ const s = props.skills.find((x) => x.name === name);
3328
+ if (!s)
3329
+ return;
3330
+ const was = skIsAllow(s);
3331
+ setPermission(props.configFile, name, was ? "deny" : "allow");
3332
+ skAllowSet.delete(name);
3333
+ skDenySet.delete(name);
3334
+ if (was)
3335
+ skDenySet.add(name);
3336
+ else
3337
+ skAllowSet.add(name);
3338
+ selectRef.options = currentOptions();
3339
+ skUpdateDetail(s);
3340
+ }
3341
+ let tlNameEl;
3342
+ let tlActionEl;
3343
+ let tlLastClick = 0;
3344
+ let tlLastIdx = -1;
3345
+ const tlToOptions = () => props.tools.map((t) => ({
3346
+ name: (t.action === "allow" ? "[allow] " : t.action === "ask" ? "[ask] " : "[deny] ") + t.name,
3347
+ description: t.action,
3348
+ value: t.name
3349
+ }));
3350
+ function tlUpdateDetail(t) {
3351
+ if (!t) {
3352
+ tlNameEl.content = "";
3353
+ tlActionEl.content = "";
3354
+ return;
3355
+ }
3356
+ tlNameEl.content = t.name;
3357
+ tlActionEl.content = t.action === "allow" ? "allowed" : t.action === "ask" ? "ask" : "denied";
3358
+ }
3359
+ function tlToggle(name) {
3360
+ const t = props.tools.find((x) => x.name === name);
3361
+ if (!t)
3362
+ return;
3363
+ const order = ["allow", "ask", "deny"];
3364
+ const idx = order.indexOf(t.action);
3365
+ const next = order[(idx + 1) % order.length];
3366
+ setToolPermission(props.configFile, name, next);
3367
+ t.action = next;
3368
+ selectRef.options = currentOptions();
3369
+ tlUpdateDetail(t);
3370
+ }
3371
+ let mcpNameEl;
3372
+ let mcpTypeEl;
3373
+ let mcpDetailEl;
3374
+ let mcpStatusEl;
3375
+ let mcpLastClick = 0;
3376
+ let mcpLastIdx = -1;
3377
+ const mcpToOptions = () => props.mcps.map((m) => ({
3378
+ name: (m.enabled ? "[enabled] " : "[disabled]") + m.name,
3379
+ description: m.type,
3380
+ value: m.name
3381
+ }));
3382
+ function mcpUpdateDetail(m) {
3383
+ if (!m) {
3384
+ mcpNameEl.content = "";
3385
+ mcpTypeEl.content = "";
3386
+ mcpDetailEl.content = "";
3387
+ mcpStatusEl.content = "";
3388
+ return;
3389
+ }
3390
+ mcpNameEl.content = m.name;
3391
+ mcpTypeEl.content = m.type;
3392
+ mcpStatusEl.content = m.enabled ? "enabled" : "disabled";
3393
+ mcpDetailEl.content = m.type === "local" ? m.command?.join(" ") ?? "" : m.url ?? "";
3394
+ }
3395
+ function mcpToggle(name) {
3396
+ const m = props.mcps.find((x) => x.name === name);
3397
+ if (!m)
3398
+ return;
3399
+ const next = !m.enabled;
3400
+ setMCPEnabled(props.configFile, name, next);
3401
+ m.enabled = next;
3402
+ selectRef.options = currentOptions();
3403
+ mcpUpdateDetail(m);
3404
+ }
3405
+ function currentOptions() {
3406
+ if (activeTab === 0)
3407
+ return skToOptions();
3408
+ if (activeTab === 1)
3409
+ return tlToOptions();
3410
+ return mcpToOptions();
3411
+ }
3412
+ const handleChange = (_i, opt) => {
3413
+ const name = opt?.value;
3414
+ if (!name)
3415
+ return;
3416
+ if (activeTab === 0) {
3417
+ skUpdateDetail(props.skills.find((s) => s.name === name) ?? null);
3418
+ } else if (activeTab === 1) {
3419
+ tlUpdateDetail(props.tools.find((t) => t.name === name) ?? null);
3420
+ } else {
3421
+ mcpUpdateDetail(props.mcps.find((m) => m.name === name) ?? null);
3422
+ }
3423
+ };
3424
+ const handleSelect = (_i, opt) => {
3425
+ const name = opt?.value;
3426
+ if (!name)
3427
+ return;
3428
+ if (activeTab === 0)
3429
+ skToggle(name);
3430
+ else if (activeTab === 1)
3431
+ tlToggle(name);
3432
+ else
3433
+ mcpToggle(name);
3434
+ };
3435
+ const defaultTabColor = () => theme().textMuted;
3436
+ const activeTabColor = () => theme().text;
3437
+ function switchTab(idx) {
3438
+ activeTab = idx;
3439
+ tabSkillsEl.fg = idx === 0 ? activeTabColor() : defaultTabColor();
3440
+ tabToolsEl.fg = idx === 1 ? activeTabColor() : defaultTabColor();
3441
+ tabMcpEl.fg = idx === 2 ? activeTabColor() : defaultTabColor();
3442
+ skillsDetailBox.visible = idx === 0;
3443
+ toolsDetailBox.visible = idx === 1;
3444
+ mcpsDetailBox.visible = idx === 2;
3445
+ selectRef.options = currentOptions();
3446
+ }
3447
+ function cycleTab() {
3448
+ switchTab((activeTab + 1) % 3);
3449
+ }
3450
+ useBindings3(() => ({
3451
+ priority: 2,
3452
+ bindings: [
3453
+ { key: "1", cmd: () => switchTab(0) },
3454
+ { key: "2", cmd: () => switchTab(1) },
3455
+ { key: "3", cmd: () => switchTab(2) },
3456
+ { key: "tab", cmd: cycleTab }
3457
+ ]
3458
+ }));
3459
+ const syntaxStyle = () => SyntaxStyle3.fromStyles({ default: { fg: theme().markdownText } });
3460
+ const panelWidth = () => Math.min(Math.max(dimensions().width - 2, 60), 116);
3461
+ const panelHeight = () => Math.max(Math.floor(dimensions().height * 0.78) - 2, 22);
3462
+ const halfWidth = () => Math.floor(panelWidth() / 2);
3463
+ const firstSkill = props.skills[0];
3464
+ const firstTool = props.tools[0];
3465
+ const firstMcp = props.mcps[0];
3466
+ return /* @__PURE__ */ jsxDEV3("box", {
3467
+ width: panelWidth(),
3468
+ height: panelHeight(),
3469
+ flexDirection: "column",
3470
+ children: [
3471
+ /* @__PURE__ */ jsxDEV3("box", {
3472
+ paddingLeft: 2,
3473
+ paddingRight: 2,
3474
+ flexShrink: 0,
3475
+ flexDirection: "row",
3476
+ children: [
3477
+ /* @__PURE__ */ jsxDEV3("text", {
3478
+ fg: theme().text,
3479
+ children: "Permissions"
3480
+ }, undefined, false, undefined, this),
3481
+ /* @__PURE__ */ jsxDEV3("box", {
3482
+ flexGrow: 1
3483
+ }, undefined, false, undefined, this),
3484
+ /* @__PURE__ */ jsxDEV3("box", {
3485
+ flexDirection: "row",
3486
+ onMouseUp: () => props.api.ui.dialog.clear(),
3487
+ children: [
3488
+ /* @__PURE__ */ jsxDEV3("text", {
3489
+ fg: HINT_FG3,
3490
+ children: "[ESC]"
3491
+ }, undefined, false, undefined, this),
3492
+ /* @__PURE__ */ jsxDEV3("text", {
3493
+ fg: FG3,
3494
+ children: " Close"
3495
+ }, undefined, false, undefined, this)
3496
+ ]
3497
+ }, undefined, true, undefined, this)
3498
+ ]
3499
+ }, undefined, true, undefined, this),
3500
+ /* @__PURE__ */ jsxDEV3("box", {
3501
+ paddingLeft: 2,
3502
+ flexShrink: 0,
3503
+ children: /* @__PURE__ */ jsxDEV3("text", {
3504
+ fg: theme().textMuted,
3505
+ children: [
3506
+ "Path: ",
3507
+ props.configFile
3508
+ ]
3509
+ }, undefined, true, undefined, this)
3510
+ }, undefined, false, undefined, this),
3511
+ /* @__PURE__ */ jsxDEV3("box", {
3512
+ flexDirection: "row",
3513
+ gap: 2,
3514
+ paddingLeft: 2,
3515
+ paddingTop: 1,
3516
+ flexShrink: 0,
3517
+ border: ["bottom"],
3518
+ borderColor: theme().textMuted,
3519
+ children: [
3520
+ /* @__PURE__ */ jsxDEV3("text", {
3521
+ ref: (el) => {
3522
+ tabSkillsEl = el;
3523
+ },
3524
+ fg: activeTabColor(),
3525
+ onMouseDown: () => switchTab(0),
3526
+ children: "Skills"
3527
+ }, undefined, false, undefined, this),
3528
+ /* @__PURE__ */ jsxDEV3("text", {
3529
+ ref: (el) => {
3530
+ tabToolsEl = el;
3531
+ },
3532
+ fg: defaultTabColor(),
3533
+ onMouseDown: () => switchTab(1),
3534
+ children: "Tools"
3535
+ }, undefined, false, undefined, this),
3536
+ /* @__PURE__ */ jsxDEV3("text", {
3537
+ ref: (el) => {
3538
+ tabMcpEl = el;
3539
+ },
3540
+ fg: defaultTabColor(),
3541
+ onMouseDown: () => switchTab(2),
3542
+ children: "MCPs"
3543
+ }, undefined, false, undefined, this)
3544
+ ]
3545
+ }, undefined, true, undefined, this),
3546
+ /* @__PURE__ */ jsxDEV3("box", {
3547
+ flexDirection: "row",
3548
+ flexGrow: 1,
3549
+ minHeight: 5,
3550
+ children: [
3551
+ /* @__PURE__ */ jsxDEV3("select", {
3552
+ ref: (el) => {
3553
+ selectRef = el;
3554
+ },
3555
+ options: currentOptions(),
3556
+ showDescription: false,
3557
+ focused: true,
3558
+ onChange: handleChange,
3559
+ onSelect: handleSelect,
3560
+ height: "100%",
3561
+ width: halfWidth(),
3562
+ onMouseDown: (event) => {
3563
+ const len = activeTab === 0 ? props.skills.length : activeTab === 1 ? props.tools.length : props.mcps.length;
3564
+ const idx = Math.floor(event.y - selectRef.screenY);
3565
+ if (idx >= 0 && idx < len) {
3566
+ const now = Date.now();
3567
+ const lc = activeTab === 0 ? skLastClick : activeTab === 1 ? tlLastClick : mcpLastClick;
3568
+ const li = activeTab === 0 ? skLastIdx : activeTab === 1 ? tlLastIdx : mcpLastIdx;
3569
+ if (idx === li && now - lc < 500) {
3570
+ handleSelect(idx, selectRef.options[idx]);
3571
+ } else {
3572
+ selectRef.setSelectedIndex(idx);
3573
+ }
3574
+ if (activeTab === 0) {
3575
+ skLastClick = now;
3576
+ skLastIdx = idx;
3577
+ } else if (activeTab === 1) {
3578
+ tlLastClick = now;
3579
+ tlLastIdx = idx;
3580
+ } else {
3581
+ mcpLastClick = now;
3582
+ mcpLastIdx = idx;
3583
+ }
3584
+ }
3585
+ }
3586
+ }, undefined, false, undefined, this),
3587
+ /* @__PURE__ */ jsxDEV3("scrollbox", {
3588
+ width: halfWidth(),
3589
+ height: "100%",
3590
+ backgroundColor: theme().backgroundPanel,
3591
+ scrollbarOptions: { visible: false },
3592
+ children: [
3593
+ /* @__PURE__ */ jsxDEV3("box", {
3594
+ ref: (el) => {
3595
+ skillsDetailBox = el;
3596
+ },
3597
+ padding: 1,
3598
+ flexDirection: "column",
3599
+ gap: 1,
3600
+ children: [
3601
+ /* @__PURE__ */ jsxDEV3("text", {
3602
+ ref: (el) => {
3603
+ skNameEl = el;
3604
+ },
3605
+ fg: theme().text,
3606
+ children: firstSkill?.name ?? ""
3607
+ }, undefined, false, undefined, this),
3608
+ /* @__PURE__ */ jsxDEV3("text", {
3609
+ ref: (el) => {
3610
+ skStatusEl = el;
3611
+ },
3612
+ fg: theme().textMuted,
3613
+ children: firstSkill ? skIsAllow(firstSkill) ? "allowed" : "denied" : ""
3614
+ }, undefined, false, undefined, this),
3615
+ /* @__PURE__ */ jsxDEV3("box", {
3616
+ flexDirection: "row",
3617
+ gap: 1,
3618
+ children: [
3619
+ /* @__PURE__ */ jsxDEV3("text", {
3620
+ ref: (el) => {
3621
+ skPathEl = el;
3622
+ },
3623
+ fg: theme().textMuted,
3624
+ children: firstSkill?.location ?? ""
3625
+ }, undefined, false, undefined, this),
3626
+ /* @__PURE__ */ jsxDEV3("text", {
3627
+ ref: (el) => {
3628
+ skCopyEl = el;
3629
+ },
3630
+ fg: theme().primary,
3631
+ onMouseDown: () => {
3632
+ if (!firstSkill)
3633
+ return;
3634
+ props.api.renderer.copyToClipboardOSC52(firstSkill.location);
3635
+ skCopyEl.content = "Copied!";
3636
+ },
3637
+ children: "[Copy]"
3638
+ }, undefined, false, undefined, this)
3639
+ ]
3640
+ }, undefined, true, undefined, this),
3641
+ /* @__PURE__ */ jsxDEV3("markdown", {
3642
+ content: firstSkill?.description ?? "",
3643
+ syntaxStyle: syntaxStyle(),
3644
+ fg: theme().markdownText
3645
+ }, undefined, false, undefined, this)
3646
+ ]
3647
+ }, undefined, true, undefined, this),
3648
+ /* @__PURE__ */ jsxDEV3("box", {
3649
+ ref: (el) => {
3650
+ toolsDetailBox = el;
3651
+ },
3652
+ visible: false,
3653
+ padding: 1,
3654
+ flexDirection: "column",
3655
+ gap: 1,
3656
+ children: [
3657
+ /* @__PURE__ */ jsxDEV3("text", {
3658
+ ref: (el) => {
3659
+ tlNameEl = el;
3660
+ },
3661
+ fg: theme().text,
3662
+ children: firstTool?.name ?? ""
3663
+ }, undefined, false, undefined, this),
3664
+ /* @__PURE__ */ jsxDEV3("text", {
3665
+ ref: (el) => {
3666
+ tlActionEl = el;
3667
+ },
3668
+ fg: theme().textMuted,
3669
+ children: firstTool ? firstTool.action === "allow" ? "allowed" : "denied" : ""
3670
+ }, undefined, false, undefined, this)
3671
+ ]
3672
+ }, undefined, true, undefined, this),
3673
+ /* @__PURE__ */ jsxDEV3("box", {
3674
+ ref: (el) => {
3675
+ mcpsDetailBox = el;
3676
+ },
3677
+ visible: false,
3678
+ padding: 1,
3679
+ flexDirection: "column",
3680
+ gap: 1,
3681
+ children: [
3682
+ /* @__PURE__ */ jsxDEV3("text", {
3683
+ ref: (el) => {
3684
+ mcpNameEl = el;
3685
+ },
3686
+ fg: theme().text,
3687
+ children: firstMcp?.name ?? ""
3688
+ }, undefined, false, undefined, this),
3689
+ /* @__PURE__ */ jsxDEV3("text", {
3690
+ ref: (el) => {
3691
+ mcpTypeEl = el;
3692
+ },
3693
+ fg: theme().textMuted,
3694
+ children: firstMcp?.type ?? ""
3695
+ }, undefined, false, undefined, this),
3696
+ /* @__PURE__ */ jsxDEV3("text", {
3697
+ ref: (el) => {
3698
+ mcpDetailEl = el;
3699
+ },
3700
+ fg: theme().text,
3701
+ children: firstMcp ? firstMcp.type === "local" ? firstMcp.command?.join(" ") ?? "" : firstMcp.url ?? "" : ""
3702
+ }, undefined, false, undefined, this),
3703
+ /* @__PURE__ */ jsxDEV3("text", {
3704
+ ref: (el) => {
3705
+ mcpStatusEl = el;
3706
+ },
3707
+ fg: theme().textMuted,
3708
+ children: firstMcp ? firstMcp.enabled ? "enabled" : "disabled" : ""
3709
+ }, undefined, false, undefined, this)
3710
+ ]
3711
+ }, undefined, true, undefined, this)
3712
+ ]
3713
+ }, undefined, true, undefined, this)
3714
+ ]
3715
+ }, undefined, true, undefined, this),
3716
+ /* @__PURE__ */ jsxDEV3("box", {
3717
+ paddingLeft: 2,
3718
+ paddingTop: 1,
3719
+ paddingBottom: 1,
3720
+ flexShrink: 0,
3721
+ flexDirection: "row",
3722
+ gap: 3,
3723
+ children: [
3724
+ /* @__PURE__ */ jsxDEV3("box", {
3725
+ flexDirection: "row",
3726
+ gap: 0,
3727
+ onMouseDown: () => switchTab(0),
3728
+ children: [
3729
+ /* @__PURE__ */ jsxDEV3("text", {
3730
+ fg: HINT_FG3,
3731
+ children: "[1]"
3732
+ }, undefined, false, undefined, this),
3733
+ /* @__PURE__ */ jsxDEV3("text", {
3734
+ fg: FG3,
3735
+ children: " Skills"
3736
+ }, undefined, false, undefined, this)
3737
+ ]
3738
+ }, undefined, true, undefined, this),
3739
+ /* @__PURE__ */ jsxDEV3("box", {
3740
+ flexDirection: "row",
3741
+ gap: 0,
3742
+ onMouseDown: () => switchTab(1),
3743
+ children: [
3744
+ /* @__PURE__ */ jsxDEV3("text", {
3745
+ fg: HINT_FG3,
3746
+ children: "[2]"
3747
+ }, undefined, false, undefined, this),
3748
+ /* @__PURE__ */ jsxDEV3("text", {
3749
+ fg: FG3,
3750
+ children: " Tools"
3751
+ }, undefined, false, undefined, this)
3752
+ ]
3753
+ }, undefined, true, undefined, this),
3754
+ /* @__PURE__ */ jsxDEV3("box", {
3755
+ flexDirection: "row",
3756
+ gap: 0,
3757
+ onMouseDown: () => switchTab(2),
3758
+ children: [
3759
+ /* @__PURE__ */ jsxDEV3("text", {
3760
+ fg: HINT_FG3,
3761
+ children: "[3]"
3762
+ }, undefined, false, undefined, this),
3763
+ /* @__PURE__ */ jsxDEV3("text", {
3764
+ fg: FG3,
3765
+ children: " MCPs"
3766
+ }, undefined, false, undefined, this)
3767
+ ]
3768
+ }, undefined, true, undefined, this)
3769
+ ]
3770
+ }, undefined, true, undefined, this)
3771
+ ]
3772
+ }, undefined, true, undefined, this);
3773
+ }
3774
+
3775
+ // src/bottom-bar.tsx
3776
+ import { jsxDEV as jsxDEV4 } from "@opentui/solid/jsx-dev-runtime";
3777
+ function showPanel(api, panel) {
3778
+ api.ui.dialog.replace(panel);
3779
+ api.ui.dialog.setSize("xlarge");
3780
+ }
3781
+ async function showPermissions(api) {
3782
+ const directory = api.state.path.directory;
3783
+ const worktree = api.state.path.worktree;
3784
+ let filePath = findConfig(directory, worktree);
3785
+ if (!filePath) {
3786
+ filePath = path4.join(directory, "opencode.jsonc");
3787
+ if (!existsSync2(filePath)) {
3788
+ writeFileSync4(filePath, `{
3789
+ "$schema": "https://opencode.ai/config.json"
3790
+ }
3791
+ `, "utf-8");
3792
+ }
3793
+ }
3794
+ const [skillsResult] = await Promise.all([
3795
+ api.client.app.skills({}, { throwOnError: true }).then((r) => r.data ?? []).catch(() => [])
3796
+ ]);
3797
+ const skills = skillsResult.map((s) => ({
3798
+ name: s.name,
3799
+ description: s.description,
3800
+ location: s.location
3801
+ }));
3802
+ const { allow: skAllow, deny: skDeny } = filePath ? readPermissions(filePath) : { allow: [], deny: [] };
3803
+ const rawTools = filePath ? readTools(filePath) : {};
3804
+ const toolNames = [...new Set([...Object.keys(rawTools), ...["bash", "edit", "write", "read", "grep", "glob", "lsp", "patch", "skill", "todowrite", "webfetch", "websearch", "question"]])].sort();
3805
+ const tools = toolNames.map((name) => {
3806
+ const action = rawTools[name];
3807
+ return {
3808
+ name,
3809
+ action: action === "ask" || action === "deny" ? action : "allow"
3810
+ };
3811
+ });
3812
+ const mcps = filePath ? readMCPs(filePath) : [];
3813
+ showPanel(api, () => /* @__PURE__ */ jsxDEV4(PermissionsPanel, {
3814
+ api,
3815
+ configFile: filePath,
3816
+ skills,
3817
+ initialSkillAllow: skAllow,
3818
+ initialSkillDeny: skDeny,
3819
+ tools,
3820
+ mcps
3821
+ }, undefined, false, undefined, this));
3822
+ }
3823
+ var BG = RGBA4.fromInts(30, 30, 30, 255);
3824
+ var FG4 = RGBA4.fromInts(255, 255, 255, 255);
3825
+ var HINT_FG4 = RGBA4.fromInts(180, 180, 180, 255);
3826
+ var EmptyBorder = {
3827
+ topLeft: "",
3828
+ bottomLeft: "",
3829
+ vertical: "",
3830
+ topRight: "",
3831
+ bottomRight: "",
3832
+ horizontal: " ",
3833
+ bottomT: "",
3834
+ topT: "",
3835
+ cross: "",
3836
+ leftT: "",
3837
+ rightT: ""
3838
+ };
3839
+ function BottomBar(props) {
3840
+ const api = props.api;
3841
+ useBindings4(() => ({
3842
+ priority: 1,
3843
+ commands: [
3844
+ {
3845
+ name: "home.files.open",
3846
+ title: "Files",
3847
+ category: "Tools",
3848
+ namespace: "palette",
3849
+ slashName: "files",
3850
+ slashAliases: ["file"],
3851
+ run() {
3852
+ showPanel(api, () => /* @__PURE__ */ jsxDEV4(NewFileManager, {
3853
+ api
3854
+ }, undefined, false, undefined, this));
3855
+ }
3856
+ },
3857
+ {
3858
+ name: "home.permissions.open",
3859
+ title: "Permissions",
3860
+ category: "Tools",
3861
+ namespace: "palette",
3862
+ slashName: "permissions",
3863
+ run() {
3864
+ showPermissions(api);
3865
+ }
3866
+ }
3867
+ ],
3868
+ bindings: [
3869
+ { key: "f1", cmd: "home.files.open", desc: "Open file browser" },
3870
+ { key: "f3", cmd: "home.permissions.open", desc: "Open permissions" },
3871
+ { key: "f7", cmd: () => currentFileActions?.create?.() },
3872
+ { key: "f2", cmd: () => currentFileActions?.rename?.() },
3873
+ { key: "ctrl+r", cmd: () => currentFileActions?.rename?.() },
3874
+ { key: "delete", cmd: () => currentFileActions?.delete?.() },
3875
+ { key: "ctrl+g", cmd: () => currentFileActions?.goto?.() },
3876
+ { key: "ctrl+f", cmd: () => currentFileActions?.focusFilter?.() },
3877
+ { key: "escape", cmd: () => {
3878
+ if (isOverlayActive)
3879
+ currentFileActions?.hideOverlay?.();
3880
+ else if (focusedPane === "filter" || focusedPane === "preview")
3881
+ currentFileActions?.focusSelect?.();
3882
+ else
3883
+ api.ui.dialog.clear();
3884
+ return true;
3885
+ } }
3886
+ ]
3887
+ }));
3888
+ return /* @__PURE__ */ jsxDEV4("box", {
3889
+ width: "100%",
3890
+ flexDirection: "column",
3891
+ flexShrink: 0,
3892
+ zIndex: 100,
3893
+ children: [
3894
+ /* @__PURE__ */ jsxDEV4("box", {
3895
+ position: "absolute",
3896
+ top: -1,
3897
+ left: 0,
3898
+ width: "100%",
3899
+ height: 1,
3900
+ border: ["bottom"],
3901
+ borderColor: BG,
3902
+ customBorderChars: { ...EmptyBorder, horizontal: "\u2584" }
3903
+ }, undefined, false, undefined, this),
3904
+ /* @__PURE__ */ jsxDEV4("box", {
3905
+ height: 1,
3906
+ paddingLeft: 2,
3907
+ paddingRight: 2,
3908
+ flexDirection: "row",
3909
+ flexShrink: 0,
3910
+ gap: 3,
3911
+ backgroundColor: BG,
3912
+ children: [
3913
+ /* @__PURE__ */ jsxDEV4("box", {
3914
+ flexDirection: "row",
3915
+ gap: 0,
3916
+ onMouseUp: () => showPanel(api, () => /* @__PURE__ */ jsxDEV4(NewFileManager, {
3917
+ api
3918
+ }, undefined, false, undefined, this)),
3919
+ children: [
3920
+ /* @__PURE__ */ jsxDEV4("text", {
3921
+ fg: HINT_FG4,
3922
+ children: "[F1]"
3923
+ }, undefined, false, undefined, this),
3924
+ /* @__PURE__ */ jsxDEV4("text", {
3925
+ fg: FG4,
3926
+ children: " Files"
3927
+ }, undefined, false, undefined, this)
3928
+ ]
3929
+ }, undefined, true, undefined, this),
3930
+ /* @__PURE__ */ jsxDEV4("box", {
3931
+ flexDirection: "row",
3932
+ gap: 0,
3933
+ onMouseUp: () => showPermissions(api),
3934
+ children: [
3935
+ /* @__PURE__ */ jsxDEV4("text", {
3936
+ fg: HINT_FG4,
3937
+ children: "[F3]"
3938
+ }, undefined, false, undefined, this),
3939
+ /* @__PURE__ */ jsxDEV4("text", {
3940
+ fg: FG4,
3941
+ children: " Permissions"
3942
+ }, undefined, false, undefined, this)
3943
+ ]
3944
+ }, undefined, true, undefined, this)
3945
+ ]
3946
+ }, undefined, true, undefined, this),
3947
+ /* @__PURE__ */ jsxDEV4("box", {
3948
+ height: 1,
3949
+ flexShrink: 0,
3950
+ border: ["bottom"],
3951
+ borderColor: BG,
3952
+ customBorderChars: { ...EmptyBorder, horizontal: "\u2580" }
3953
+ }, undefined, false, undefined, this)
3954
+ ]
3955
+ }, undefined, true, undefined, this);
3956
+ }
3957
+
3958
+ // src/index.tsx
3959
+ import { jsxDEV as jsxDEV5 } from "@opentui/solid/jsx-dev-runtime";
3960
+ var plugin = async (api) => {
3961
+ api.slots.register({
3962
+ order: 100,
3963
+ slots: {
3964
+ app_bottom() {
3965
+ return /* @__PURE__ */ jsxDEV5(BottomBar, {
3966
+ api
3967
+ }, undefined, false, undefined, this);
3968
+ }
3969
+ }
3970
+ });
3971
+ };
3972
+ var src_default = { id: "opencode-project-panel", tui: plugin };
3973
+ export {
3974
+ src_default as default
3975
+ };