archymedes-cli 2.3.0 → 2.6.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 (25) hide show
  1. package/dist/{archymedes-aj30app4.mjs → archymedes-06fh0z84.mjs} +370 -159
  2. package/dist/{archymedes-sf9t1hz9.mjs → archymedes-086xsz64.mjs} +176 -77
  3. package/dist/{archymedes-d5wqcmdr.mjs → archymedes-0jxzsh4z.mjs} +97 -97
  4. package/dist/{archymedes-h13ap0za.mjs → archymedes-1g1y6q74.mjs} +1 -1
  5. package/dist/{archymedes-4kx65anz.mjs → archymedes-1jcn326m.mjs} +43 -12
  6. package/dist/{archymedes-g8y3rt6t.mjs → archymedes-kn6wtq32.mjs} +332 -9
  7. package/dist/archymedes-main.mjs +31010 -27842
  8. package/dist/archymedes-s4qcy0q4.mjs +1250 -0
  9. package/dist/{archymedes-twbks7g3.mjs → archymedes-t1jtzkmp.mjs} +214 -5
  10. package/dist/{archymedes-tsne2m7p.mjs → archymedes-twanftqk.mjs} +2 -2
  11. package/dist/archymedes-w4bjfye7.mjs +280 -0
  12. package/dist/{archymedes-dz59nvw7.mjs → archymedes-zvcs68bv.mjs} +21 -11
  13. package/dist/{editor-screen-g08zzt70.mjs → editor-screen-pf252j2r.mjs} +49 -14
  14. package/dist/{factory-7vtm2fed.mjs → factory-hyv8agr0.mjs} +326 -326
  15. package/dist/{file-screen-ma9yxq2b.mjs → file-screen-1j65f7b4.mjs} +11 -9
  16. package/dist/{guide-screen-gd129txd.mjs → guide-screen-9vxsk83x.mjs} +10 -8
  17. package/dist/{index-qvgcwsvm.mjs → index-teq1cta4.mjs} +1 -1
  18. package/dist/{node-mdgzx68h.mjs → node-0fh63p8z.mjs} +7 -7
  19. package/dist/pager-screen-aamt6xv0.mjs +155 -0
  20. package/dist/projection-x6x6hm9t.mjs +248 -0
  21. package/dist/{sandbox-templates-9jcjws23.mjs → sandbox-templates-8sd1psez.mjs} +2 -2
  22. package/dist/workspace-screen-ntdcgfq9.mjs +70 -0
  23. package/package.json +2 -2
  24. package/dist/archymedes-a10k8yrk.mjs +0 -464
  25. package/dist/workspace-screen-8cwk6jz9.mjs +0 -241
@@ -1,20 +1,21 @@
1
1
  import {
2
2
  diffLines,
3
3
  languageOf
4
- } from "./archymedes-dz59nvw7.mjs";
5
- import"./archymedes-tsne2m7p.mjs";
4
+ } from "./archymedes-zvcs68bv.mjs";
5
+ import"./archymedes-twanftqk.mjs";
6
6
  import {
7
- NO_COLOR_PALETTE
8
- } from "./archymedes-a10k8yrk.mjs";
7
+ NO_COLOR_PALETTE,
8
+ exitTopTermUIApp
9
+ } from "./archymedes-s4qcy0q4.mjs";
9
10
  import {
10
11
  __require
11
12
  } from "./archymedes-x67v3n58.mjs";
12
13
 
13
- // src/ui/editor-screen.tsx
14
- import { useInput, useState } from "@termuijs/jsx";
14
+ // packages/archymedes-cli/src/ui/editor-screen.tsx
15
+ import { useEffect, useInput, useRef, useState } from "@termuijs/jsx";
15
16
  import { Box, Text } from "@termuijs/widgets";
16
17
 
17
- // src/ui/editor.ts
18
+ // packages/archymedes-cli/src/ui/editor.ts
18
19
  function initialEditorState(path, content, viewportRows = 20) {
19
20
  const lines = content.split(`
20
21
  `);
@@ -79,6 +80,15 @@ function keyToEditorAction(key, character, state) {
79
80
  return { kind: "save" };
80
81
  if (key.ctrl && (name === "q" || name === "c"))
81
82
  return { kind: "quit" };
83
+ if (state.confirmLeave) {
84
+ if (character === "y" || character === "Y" || isEnter)
85
+ return { kind: "save" };
86
+ if (character === "n" || character === "N")
87
+ return { kind: "quit" };
88
+ if (isEscape)
89
+ return { kind: "cancelLeave" };
90
+ return { kind: "none" };
91
+ }
82
92
  if (state.search.typing) {
83
93
  if (isEscape)
84
94
  return { kind: "searchCommit" };
@@ -116,7 +126,7 @@ function keyToEditorAction(key, character, state) {
116
126
  if (state.pending === "g")
117
127
  return name === "g" || character === "g" ? { kind: "jump", to: "fileStart" } : { kind: "normal" };
118
128
  if (isEscape)
119
- return { kind: "normal" };
129
+ return { kind: "leave" };
120
130
  if (name === "up" || character === "k")
121
131
  return { kind: "move", rows: -1 };
122
132
  if (name === "down" || character === "j")
@@ -269,7 +279,15 @@ function applyEditorAction(state, action) {
269
279
  case "save":
270
280
  return { state: clamp({ ...state, dirty: false, message: `saved ${state.path}`, pending: undefined }), effect: { kind: "save" } };
271
281
  case "quit":
272
- return { state, effect: { kind: "quit" } };
282
+ return { state: { ...state, confirmLeave: false }, effect: { kind: "quit" } };
283
+ case "leave":
284
+ if (!state.dirty)
285
+ return { state, effect: { kind: "quit" } };
286
+ return { state: { ...state, pending: undefined, confirmLeave: true, message: "Save changes? y yes · n discard · Esc keep editing" }, effect: undefined };
287
+ case "cancelLeave":
288
+ return plain({ ...state, confirmLeave: false, message: undefined });
289
+ case "autosaved":
290
+ return editorContent(state) === action.content ? plain({ ...state, dirty: false, message: "auto-saved" }) : plain(state);
273
291
  case "search":
274
292
  return plain({ ...state, search: { query: "", typing: true }, message: undefined });
275
293
  case "searchType":
@@ -311,7 +329,8 @@ function editorKeyBar(state, columns = Number.POSITIVE_INFINITY) {
311
329
  { text: "u undo" },
312
330
  { text: "/ find" },
313
331
  { text: "^S save", essential: true },
314
- { text: "^Q quit", essential: true }
332
+ { text: "^Q quit", essential: true },
333
+ { text: "esc back", essential: true }
315
334
  ];
316
335
  const optional = hints.filter((hint) => !hint.essential);
317
336
  for (let dropped = 0;dropped <= optional.length; dropped += 1) {
@@ -347,7 +366,7 @@ function caretInto(text, cursorCol) {
347
366
  return `${padded.slice(0, cursorCol)}█${padded.slice(cursorCol + 1)}`;
348
367
  }
349
368
 
350
- // src/ui/explain-view.ts
369
+ // packages/archymedes-cli/src/ui/explain-view.ts
351
370
  var PATTERNS = {
352
371
  typescript: {
353
372
  imports: /^\s*import\b.*from\s+["'](.+)["']/,
@@ -531,7 +550,7 @@ function composeExplainPanel(input, width, height, colors = DEFAULT_EXPLAIN_COLO
531
550
  return padded;
532
551
  }
533
552
 
534
- // src/ui/editor-screen.tsx
553
+ // packages/archymedes-cli/src/ui/editor-screen.tsx
535
554
  import { jsxDEV } from "@termuijs/jsx/jsx-dev-runtime";
536
555
  var Panel = Box;
537
556
  var Line = Text;
@@ -543,8 +562,22 @@ function panelWidthFor(columns) {
543
562
  return 0;
544
563
  return Math.min(MAX_PANEL_COLUMNS, Math.floor(columns * 0.38), columns - MIN_CODE_COLUMNS);
545
564
  }
546
- function EditorScreen({ columns, rows, path, content, onExit, palette = NO_COLOR_PALETTE, explain }) {
565
+ function EditorScreen({ columns, rows, path, content, onExit, palette = NO_COLOR_PALETTE, explain, autosave, autosaveDelayMs = 1000 }) {
547
566
  const [state, setState] = useState(() => initialEditorState(path, content, Math.max(1, rows - CHROME_ROWS)));
567
+ const timer = useRef(undefined);
568
+ const text = editorContent(state);
569
+ useEffect(() => {
570
+ if (!autosave || !state.dirty || state.confirmLeave)
571
+ return;
572
+ const pending = text;
573
+ timer.current = setTimeout(() => {
574
+ autosave(pending).then(() => setState((current) => applyEditorAction(current, { kind: "autosaved", content: pending }).state), () => setState((current) => ({ ...current, message: "auto-save failed — Ctrl+S to retry" })));
575
+ }, autosaveDelayMs);
576
+ return () => {
577
+ if (timer.current)
578
+ clearTimeout(timer.current);
579
+ };
580
+ }, [text, state.dirty, state.confirmLeave]);
548
581
  const [panel, setPanel] = useState(() => initialExplainPanelState());
549
582
  const panelWidth = panel.open ? panelWidthFor(columns) : 0;
550
583
  const codeWidth = panelWidth > 0 ? columns - panelWidth - 1 : columns;
@@ -554,7 +587,7 @@ function EditorScreen({ columns, rows, path, content, onExit, palette = NO_COLOR
554
587
  return;
555
588
  }
556
589
  setPanel((current) => withAiExplanation(current, { status: "loading" }));
557
- explain(currentContent, path).then((text) => setPanel((current) => withAiExplanation(current, { status: "ready", text })), (error) => setPanel((current) => withAiExplanation(current, { status: "error", message: error instanceof Error ? error.message : String(error) })));
590
+ explain(currentContent, path).then((text2) => setPanel((current) => withAiExplanation(current, { status: "ready", text: text2 })), (error) => setPanel((current) => withAiExplanation(current, { status: "error", message: error instanceof Error ? error.message : String(error) })));
558
591
  };
559
592
  useInput((input, key) => {
560
593
  if (key?.ctrl && key?.key === "e") {
@@ -629,6 +662,7 @@ async function runEditorScreen(options) {
629
662
  if (settled)
630
663
  return;
631
664
  settled = true;
665
+ exitTopTermUIApp();
632
666
  resolve(saved);
633
667
  };
634
668
  renderApp(EditorScreen, {
@@ -638,6 +672,7 @@ async function runEditorScreen(options) {
638
672
  content: options.content,
639
673
  palette: options.palette,
640
674
  explain: options.explain,
675
+ autosave: options.autosave,
641
676
  onExit: finish,
642
677
  fullscreen: true
643
678
  }).catch(() => finish(undefined));