@aigne/afs-cli 1.11.0-beta.3 → 1.11.0-beta.5

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 (70) hide show
  1. package/README.md +224 -31
  2. package/dist/cli.cjs +119 -27
  3. package/dist/cli.mjs +119 -27
  4. package/dist/cli.mjs.map +1 -1
  5. package/dist/commands/ls.cjs +6 -4
  6. package/dist/commands/ls.mjs +7 -4
  7. package/dist/commands/ls.mjs.map +1 -1
  8. package/dist/commands/mount.cjs +39 -15
  9. package/dist/commands/mount.mjs +39 -15
  10. package/dist/commands/mount.mjs.map +1 -1
  11. package/dist/commands/serve.cjs +9 -6
  12. package/dist/commands/serve.mjs +9 -6
  13. package/dist/commands/serve.mjs.map +1 -1
  14. package/dist/config/loader.cjs +30 -10
  15. package/dist/config/loader.mjs +30 -10
  16. package/dist/config/loader.mjs.map +1 -1
  17. package/dist/config/provider-factory.cjs +1 -0
  18. package/dist/config/provider-factory.mjs +1 -0
  19. package/dist/config/provider-factory.mjs.map +1 -1
  20. package/dist/config/schema.cjs +58 -3
  21. package/dist/config/schema.mjs +57 -3
  22. package/dist/config/schema.mjs.map +1 -1
  23. package/dist/explorer/actions.cjs +246 -0
  24. package/dist/explorer/actions.mjs +240 -0
  25. package/dist/explorer/actions.mjs.map +1 -0
  26. package/dist/explorer/components/dialog.cjs +231 -0
  27. package/dist/explorer/components/dialog.mjs +232 -0
  28. package/dist/explorer/components/dialog.mjs.map +1 -0
  29. package/dist/explorer/components/file-list.cjs +107 -0
  30. package/dist/explorer/components/file-list.mjs +107 -0
  31. package/dist/explorer/components/file-list.mjs.map +1 -0
  32. package/dist/explorer/components/function-bar.cjs +55 -0
  33. package/dist/explorer/components/function-bar.mjs +55 -0
  34. package/dist/explorer/components/function-bar.mjs.map +1 -0
  35. package/dist/explorer/components/index.cjs +5 -0
  36. package/dist/explorer/components/index.mjs +7 -0
  37. package/dist/explorer/components/metadata-panel.cjs +122 -0
  38. package/dist/explorer/components/metadata-panel.mjs +122 -0
  39. package/dist/explorer/components/metadata-panel.mjs.map +1 -0
  40. package/dist/explorer/components/status-bar.cjs +53 -0
  41. package/dist/explorer/components/status-bar.mjs +54 -0
  42. package/dist/explorer/components/status-bar.mjs.map +1 -0
  43. package/dist/explorer/keybindings.cjs +214 -0
  44. package/dist/explorer/keybindings.mjs +213 -0
  45. package/dist/explorer/keybindings.mjs.map +1 -0
  46. package/dist/explorer/screen.cjs +200 -0
  47. package/dist/explorer/screen.mjs +199 -0
  48. package/dist/explorer/screen.mjs.map +1 -0
  49. package/dist/explorer/state.cjs +53 -0
  50. package/dist/explorer/state.mjs +53 -0
  51. package/dist/explorer/state.mjs.map +1 -0
  52. package/dist/explorer/theme.cjs +158 -0
  53. package/dist/explorer/theme.mjs +155 -0
  54. package/dist/explorer/theme.mjs.map +1 -0
  55. package/dist/path-utils.cjs +104 -0
  56. package/dist/path-utils.mjs +104 -0
  57. package/dist/path-utils.mjs.map +1 -0
  58. package/dist/runtime.cjs +47 -33
  59. package/dist/runtime.mjs +47 -33
  60. package/dist/runtime.mjs.map +1 -1
  61. package/dist/ui/header.cjs +60 -0
  62. package/dist/ui/header.mjs +59 -0
  63. package/dist/ui/header.mjs.map +1 -0
  64. package/dist/ui/index.cjs +17 -0
  65. package/dist/ui/index.mjs +15 -0
  66. package/dist/ui/index.mjs.map +1 -0
  67. package/dist/ui/terminal.cjs +97 -0
  68. package/dist/ui/terminal.mjs +95 -0
  69. package/dist/ui/terminal.mjs.map +1 -0
  70. package/package.json +9 -7
@@ -0,0 +1,214 @@
1
+
2
+ //#region src/explorer/keybindings.ts
3
+ /**
4
+ * Key binding registry
5
+ */
6
+ var KeyBindingRegistry = class {
7
+ bindings = /* @__PURE__ */ new Map();
8
+ keyToAction = /* @__PURE__ */ new Map();
9
+ /**
10
+ * Register a new key binding
11
+ */
12
+ register(binding) {
13
+ this.bindings.set(binding.action, binding);
14
+ const keys = Array.isArray(binding.key) ? binding.key : [binding.key];
15
+ for (const key of keys) this.keyToAction.set(this.normalizeKey(key), binding.action);
16
+ }
17
+ /**
18
+ * Unregister a key binding by action id
19
+ */
20
+ unregister(action) {
21
+ const binding = this.bindings.get(action);
22
+ if (!binding) return;
23
+ const keys = Array.isArray(binding.key) ? binding.key : [binding.key];
24
+ for (const key of keys) this.keyToAction.delete(this.normalizeKey(key));
25
+ this.bindings.delete(action);
26
+ }
27
+ /**
28
+ * Get all registered bindings
29
+ */
30
+ getBindings() {
31
+ return Array.from(this.bindings.values());
32
+ }
33
+ /**
34
+ * Get binding for a specific key
35
+ */
36
+ getBindingForKey(key, ctx) {
37
+ const action = this.keyToAction.get(this.normalizeKey(key));
38
+ if (!action) return void 0;
39
+ const binding = this.bindings.get(action);
40
+ if (!binding) return void 0;
41
+ if (ctx && binding.when && !binding.when(ctx)) return;
42
+ return binding;
43
+ }
44
+ /**
45
+ * Get binding by action id
46
+ */
47
+ getBindingByAction(action) {
48
+ return this.bindings.get(action);
49
+ }
50
+ /**
51
+ * Get bindings for function bar display (sorted by priority)
52
+ */
53
+ getFunctionBarBindings() {
54
+ return this.getBindings().filter((b) => b.label !== void 0).sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
55
+ }
56
+ /**
57
+ * Check if a key is bound
58
+ */
59
+ hasKey(key) {
60
+ return this.keyToAction.has(this.normalizeKey(key));
61
+ }
62
+ /**
63
+ * Normalize key string for consistent lookup
64
+ */
65
+ normalizeKey(key) {
66
+ return key.toLowerCase().trim();
67
+ }
68
+ /**
69
+ * Clear all bindings
70
+ */
71
+ clear() {
72
+ this.bindings.clear();
73
+ this.keyToAction.clear();
74
+ }
75
+ };
76
+ /**
77
+ * Default key bindings for the explorer
78
+ *
79
+ * Uses single letter keys for simplicity. Labels show highlighted key.
80
+ * Navigation uses vim-style hjkl keys.
81
+ */
82
+ const defaultBindings = [
83
+ {
84
+ key: "?",
85
+ label: "[?]Help",
86
+ description: "Show help dialog",
87
+ action: "help",
88
+ priority: 100
89
+ },
90
+ {
91
+ key: "e",
92
+ label: "[E]xplain",
93
+ description: "Show AFS explain for selected item",
94
+ action: "explain",
95
+ priority: 90
96
+ },
97
+ {
98
+ key: "v",
99
+ label: "[V]iew",
100
+ description: "View file content",
101
+ action: "view",
102
+ priority: 80
103
+ },
104
+ {
105
+ key: "x",
106
+ label: "E[x]ec",
107
+ description: "Execute AFS action on selected item",
108
+ action: "exec",
109
+ priority: 70
110
+ },
111
+ {
112
+ key: "r",
113
+ label: "[R]efresh",
114
+ description: "Refresh current directory",
115
+ action: "refresh",
116
+ priority: 60
117
+ },
118
+ {
119
+ key: "q",
120
+ label: "[Q]uit",
121
+ description: "Exit explorer",
122
+ action: "quit",
123
+ priority: 0
124
+ },
125
+ {
126
+ key: ["up", "k"],
127
+ description: "Move selection up",
128
+ action: "nav:up"
129
+ },
130
+ {
131
+ key: ["down", "j"],
132
+ description: "Move selection down",
133
+ action: "nav:down"
134
+ },
135
+ {
136
+ key: [
137
+ "enter",
138
+ "return",
139
+ "l"
140
+ ],
141
+ description: "Enter directory or view file",
142
+ action: "nav:enter"
143
+ },
144
+ {
145
+ key: ["backspace", "h"],
146
+ description: "Go to parent directory",
147
+ action: "nav:back"
148
+ },
149
+ {
150
+ key: ["home", "g"],
151
+ description: "Go to first item",
152
+ action: "nav:home"
153
+ },
154
+ {
155
+ key: ["end", "G"],
156
+ description: "Go to last item",
157
+ action: "nav:end"
158
+ },
159
+ {
160
+ key: ["pageup", "C-u"],
161
+ description: "Page up",
162
+ action: "nav:pageup"
163
+ },
164
+ {
165
+ key: ["pagedown", "C-d"],
166
+ description: "Page down",
167
+ action: "nav:pagedown"
168
+ },
169
+ {
170
+ key: "/",
171
+ description: "Search/filter",
172
+ action: "filter"
173
+ },
174
+ {
175
+ key: "escape",
176
+ description: "Cancel/close dialog",
177
+ action: "cancel"
178
+ }
179
+ ];
180
+ /**
181
+ * Create a new registry with default bindings
182
+ */
183
+ function createDefaultRegistry() {
184
+ const registry = new KeyBindingRegistry();
185
+ for (const binding of defaultBindings) registry.register(binding);
186
+ return registry;
187
+ }
188
+ /**
189
+ * Format key name for display (e.g., "C-h" -> "^H", "f1" -> "F1")
190
+ */
191
+ function formatKeyName(key) {
192
+ const k = Array.isArray(key) ? key[0] : key;
193
+ if (!k) return "";
194
+ if (k.startsWith("C-") && k.length === 3) return `^${k[2].toUpperCase()}`;
195
+ if (k.startsWith("f") && k.length <= 3) return k.toUpperCase();
196
+ return {
197
+ enter: "Enter",
198
+ return: "Enter",
199
+ backspace: "Bksp",
200
+ escape: "Esc",
201
+ pageup: "PgUp",
202
+ pagedown: "PgDn",
203
+ home: "Home",
204
+ end: "End",
205
+ up: "↑",
206
+ down: "↓",
207
+ left: "←",
208
+ right: "→"
209
+ }[k.toLowerCase()] || k;
210
+ }
211
+
212
+ //#endregion
213
+ exports.createDefaultRegistry = createDefaultRegistry;
214
+ exports.formatKeyName = formatKeyName;
@@ -0,0 +1,213 @@
1
+ //#region src/explorer/keybindings.ts
2
+ /**
3
+ * Key binding registry
4
+ */
5
+ var KeyBindingRegistry = class {
6
+ bindings = /* @__PURE__ */ new Map();
7
+ keyToAction = /* @__PURE__ */ new Map();
8
+ /**
9
+ * Register a new key binding
10
+ */
11
+ register(binding) {
12
+ this.bindings.set(binding.action, binding);
13
+ const keys = Array.isArray(binding.key) ? binding.key : [binding.key];
14
+ for (const key of keys) this.keyToAction.set(this.normalizeKey(key), binding.action);
15
+ }
16
+ /**
17
+ * Unregister a key binding by action id
18
+ */
19
+ unregister(action) {
20
+ const binding = this.bindings.get(action);
21
+ if (!binding) return;
22
+ const keys = Array.isArray(binding.key) ? binding.key : [binding.key];
23
+ for (const key of keys) this.keyToAction.delete(this.normalizeKey(key));
24
+ this.bindings.delete(action);
25
+ }
26
+ /**
27
+ * Get all registered bindings
28
+ */
29
+ getBindings() {
30
+ return Array.from(this.bindings.values());
31
+ }
32
+ /**
33
+ * Get binding for a specific key
34
+ */
35
+ getBindingForKey(key, ctx) {
36
+ const action = this.keyToAction.get(this.normalizeKey(key));
37
+ if (!action) return void 0;
38
+ const binding = this.bindings.get(action);
39
+ if (!binding) return void 0;
40
+ if (ctx && binding.when && !binding.when(ctx)) return;
41
+ return binding;
42
+ }
43
+ /**
44
+ * Get binding by action id
45
+ */
46
+ getBindingByAction(action) {
47
+ return this.bindings.get(action);
48
+ }
49
+ /**
50
+ * Get bindings for function bar display (sorted by priority)
51
+ */
52
+ getFunctionBarBindings() {
53
+ return this.getBindings().filter((b) => b.label !== void 0).sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
54
+ }
55
+ /**
56
+ * Check if a key is bound
57
+ */
58
+ hasKey(key) {
59
+ return this.keyToAction.has(this.normalizeKey(key));
60
+ }
61
+ /**
62
+ * Normalize key string for consistent lookup
63
+ */
64
+ normalizeKey(key) {
65
+ return key.toLowerCase().trim();
66
+ }
67
+ /**
68
+ * Clear all bindings
69
+ */
70
+ clear() {
71
+ this.bindings.clear();
72
+ this.keyToAction.clear();
73
+ }
74
+ };
75
+ /**
76
+ * Default key bindings for the explorer
77
+ *
78
+ * Uses single letter keys for simplicity. Labels show highlighted key.
79
+ * Navigation uses vim-style hjkl keys.
80
+ */
81
+ const defaultBindings = [
82
+ {
83
+ key: "?",
84
+ label: "[?]Help",
85
+ description: "Show help dialog",
86
+ action: "help",
87
+ priority: 100
88
+ },
89
+ {
90
+ key: "e",
91
+ label: "[E]xplain",
92
+ description: "Show AFS explain for selected item",
93
+ action: "explain",
94
+ priority: 90
95
+ },
96
+ {
97
+ key: "v",
98
+ label: "[V]iew",
99
+ description: "View file content",
100
+ action: "view",
101
+ priority: 80
102
+ },
103
+ {
104
+ key: "x",
105
+ label: "E[x]ec",
106
+ description: "Execute AFS action on selected item",
107
+ action: "exec",
108
+ priority: 70
109
+ },
110
+ {
111
+ key: "r",
112
+ label: "[R]efresh",
113
+ description: "Refresh current directory",
114
+ action: "refresh",
115
+ priority: 60
116
+ },
117
+ {
118
+ key: "q",
119
+ label: "[Q]uit",
120
+ description: "Exit explorer",
121
+ action: "quit",
122
+ priority: 0
123
+ },
124
+ {
125
+ key: ["up", "k"],
126
+ description: "Move selection up",
127
+ action: "nav:up"
128
+ },
129
+ {
130
+ key: ["down", "j"],
131
+ description: "Move selection down",
132
+ action: "nav:down"
133
+ },
134
+ {
135
+ key: [
136
+ "enter",
137
+ "return",
138
+ "l"
139
+ ],
140
+ description: "Enter directory or view file",
141
+ action: "nav:enter"
142
+ },
143
+ {
144
+ key: ["backspace", "h"],
145
+ description: "Go to parent directory",
146
+ action: "nav:back"
147
+ },
148
+ {
149
+ key: ["home", "g"],
150
+ description: "Go to first item",
151
+ action: "nav:home"
152
+ },
153
+ {
154
+ key: ["end", "G"],
155
+ description: "Go to last item",
156
+ action: "nav:end"
157
+ },
158
+ {
159
+ key: ["pageup", "C-u"],
160
+ description: "Page up",
161
+ action: "nav:pageup"
162
+ },
163
+ {
164
+ key: ["pagedown", "C-d"],
165
+ description: "Page down",
166
+ action: "nav:pagedown"
167
+ },
168
+ {
169
+ key: "/",
170
+ description: "Search/filter",
171
+ action: "filter"
172
+ },
173
+ {
174
+ key: "escape",
175
+ description: "Cancel/close dialog",
176
+ action: "cancel"
177
+ }
178
+ ];
179
+ /**
180
+ * Create a new registry with default bindings
181
+ */
182
+ function createDefaultRegistry() {
183
+ const registry = new KeyBindingRegistry();
184
+ for (const binding of defaultBindings) registry.register(binding);
185
+ return registry;
186
+ }
187
+ /**
188
+ * Format key name for display (e.g., "C-h" -> "^H", "f1" -> "F1")
189
+ */
190
+ function formatKeyName(key) {
191
+ const k = Array.isArray(key) ? key[0] : key;
192
+ if (!k) return "";
193
+ if (k.startsWith("C-") && k.length === 3) return `^${k[2].toUpperCase()}`;
194
+ if (k.startsWith("f") && k.length <= 3) return k.toUpperCase();
195
+ return {
196
+ enter: "Enter",
197
+ return: "Enter",
198
+ backspace: "Bksp",
199
+ escape: "Esc",
200
+ pageup: "PgUp",
201
+ pagedown: "PgDn",
202
+ home: "Home",
203
+ end: "End",
204
+ up: "↑",
205
+ down: "↓",
206
+ left: "←",
207
+ right: "→"
208
+ }[k.toLowerCase()] || k;
209
+ }
210
+
211
+ //#endregion
212
+ export { createDefaultRegistry, formatKeyName };
213
+ //# sourceMappingURL=keybindings.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keybindings.mjs","names":[],"sources":["../../src/explorer/keybindings.ts"],"sourcesContent":["/**\n * AFS Explorer Keybindings\n *\n * Extensible key binding system for the TUI explorer.\n * Allows registering, unregistering, and querying key bindings.\n */\n\nimport type { ExplorerContext, KeyBinding } from \"./types.js\";\n\n/**\n * Key binding registry\n */\nexport class KeyBindingRegistry {\n private bindings: Map<string, KeyBinding> = new Map();\n private keyToAction: Map<string, string> = new Map();\n\n /**\n * Register a new key binding\n */\n register(binding: KeyBinding): void {\n // Store binding by action id\n this.bindings.set(binding.action, binding);\n\n // Map keys to action\n const keys = Array.isArray(binding.key) ? binding.key : [binding.key];\n for (const key of keys) {\n this.keyToAction.set(this.normalizeKey(key), binding.action);\n }\n }\n\n /**\n * Unregister a key binding by action id\n */\n unregister(action: string): void {\n const binding = this.bindings.get(action);\n if (!binding) return;\n\n // Remove key mappings\n const keys = Array.isArray(binding.key) ? binding.key : [binding.key];\n for (const key of keys) {\n this.keyToAction.delete(this.normalizeKey(key));\n }\n\n // Remove binding\n this.bindings.delete(action);\n }\n\n /**\n * Get all registered bindings\n */\n getBindings(): KeyBinding[] {\n return Array.from(this.bindings.values());\n }\n\n /**\n * Get binding for a specific key\n */\n getBindingForKey(key: string, ctx?: ExplorerContext): KeyBinding | undefined {\n const action = this.keyToAction.get(this.normalizeKey(key));\n if (!action) return undefined;\n\n const binding = this.bindings.get(action);\n if (!binding) return undefined;\n\n // Check condition if context provided\n if (ctx && binding.when && !binding.when(ctx)) {\n return undefined;\n }\n\n return binding;\n }\n\n /**\n * Get binding by action id\n */\n getBindingByAction(action: string): KeyBinding | undefined {\n return this.bindings.get(action);\n }\n\n /**\n * Get bindings for function bar display (sorted by priority)\n */\n getFunctionBarBindings(): KeyBinding[] {\n return this.getBindings()\n .filter((b) => b.label !== undefined)\n .sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));\n }\n\n /**\n * Check if a key is bound\n */\n hasKey(key: string): boolean {\n return this.keyToAction.has(this.normalizeKey(key));\n }\n\n /**\n * Normalize key string for consistent lookup\n */\n private normalizeKey(key: string): string {\n return key.toLowerCase().trim();\n }\n\n /**\n * Clear all bindings\n */\n clear(): void {\n this.bindings.clear();\n this.keyToAction.clear();\n }\n}\n\n/**\n * Default key bindings for the explorer\n *\n * Uses single letter keys for simplicity. Labels show highlighted key.\n * Navigation uses vim-style hjkl keys.\n */\nexport const defaultBindings: KeyBinding[] = [\n // Single letter commands (shown in function bar)\n {\n key: \"?\",\n label: \"[?]Help\",\n description: \"Show help dialog\",\n action: \"help\",\n priority: 100,\n },\n {\n key: \"e\",\n label: \"[E]xplain\",\n description: \"Show AFS explain for selected item\",\n action: \"explain\",\n priority: 90,\n },\n {\n key: \"v\",\n label: \"[V]iew\",\n description: \"View file content\",\n action: \"view\",\n priority: 80,\n },\n {\n key: \"x\",\n label: \"E[x]ec\",\n description: \"Execute AFS action on selected item\",\n action: \"exec\",\n priority: 70,\n },\n {\n key: \"r\",\n label: \"[R]efresh\",\n description: \"Refresh current directory\",\n action: \"refresh\",\n priority: 60,\n },\n {\n key: \"q\",\n label: \"[Q]uit\",\n description: \"Exit explorer\",\n action: \"quit\",\n priority: 0,\n },\n\n // Navigation keys (vim-style hjkl)\n {\n key: [\"up\", \"k\"],\n description: \"Move selection up\",\n action: \"nav:up\",\n },\n {\n key: [\"down\", \"j\"],\n description: \"Move selection down\",\n action: \"nav:down\",\n },\n {\n key: [\"enter\", \"return\", \"l\"],\n description: \"Enter directory or view file\",\n action: \"nav:enter\",\n },\n {\n key: [\"backspace\", \"h\"],\n description: \"Go to parent directory\",\n action: \"nav:back\",\n },\n {\n key: [\"home\", \"g\"],\n description: \"Go to first item\",\n action: \"nav:home\",\n },\n {\n key: [\"end\", \"G\"],\n description: \"Go to last item\",\n action: \"nav:end\",\n },\n {\n key: [\"pageup\", \"C-u\"],\n description: \"Page up\",\n action: \"nav:pageup\",\n },\n {\n key: [\"pagedown\", \"C-d\"],\n description: \"Page down\",\n action: \"nav:pagedown\",\n },\n\n // Other\n {\n key: \"/\",\n description: \"Search/filter\",\n action: \"filter\",\n },\n\n // Cancel (for dialogs)\n {\n key: \"escape\",\n description: \"Cancel/close dialog\",\n action: \"cancel\",\n },\n];\n\n/**\n * Create a new registry with default bindings\n */\nexport function createDefaultRegistry(): KeyBindingRegistry {\n const registry = new KeyBindingRegistry();\n for (const binding of defaultBindings) {\n registry.register(binding);\n }\n return registry;\n}\n\n/**\n * Format key name for display (e.g., \"C-h\" -> \"^H\", \"f1\" -> \"F1\")\n */\nexport function formatKeyName(key: string | string[]): string {\n const k = Array.isArray(key) ? key[0] : key;\n if (!k) return \"\";\n\n // Ctrl+letter keys (C-h -> ^H)\n if (k.startsWith(\"C-\") && k.length === 3) {\n return `^${k[2]!.toUpperCase()}`;\n }\n\n // Function keys\n if (k.startsWith(\"f\") && k.length <= 3) {\n return k.toUpperCase();\n }\n\n // Special keys\n const specialKeys: Record<string, string> = {\n enter: \"Enter\",\n return: \"Enter\",\n backspace: \"Bksp\",\n escape: \"Esc\",\n pageup: \"PgUp\",\n pagedown: \"PgDn\",\n home: \"Home\",\n end: \"End\",\n up: \"↑\",\n down: \"↓\",\n left: \"←\",\n right: \"→\",\n };\n\n return specialKeys[k.toLowerCase()] || k;\n}\n"],"mappings":"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"}
@@ -0,0 +1,200 @@
1
+ const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
2
+ const require_index = require('../ui/index.cjs');
3
+ const require_actions = require('./actions.cjs');
4
+ const require_keybindings = require('./keybindings.cjs');
5
+ const require_dialog = require('./components/dialog.cjs');
6
+ const require_file_list = require('./components/file-list.cjs');
7
+ const require_function_bar = require('./components/function-bar.cjs');
8
+ const require_metadata_panel = require('./components/metadata-panel.cjs');
9
+ const require_status_bar = require('./components/status-bar.cjs');
10
+ require('./components/index.cjs');
11
+ const require_state = require('./state.cjs');
12
+ let blessed = require("blessed");
13
+ blessed = require_rolldown_runtime.__toESM(blessed);
14
+
15
+ //#region src/explorer/screen.ts
16
+ /**
17
+ * AFS Explorer Screen
18
+ *
19
+ * Main screen controller that manages all UI components and user interaction.
20
+ */
21
+ /**
22
+ * Create and run the explorer screen
23
+ */
24
+ async function createExplorerScreen(options) {
25
+ const { runtime, startPath = "/", version, mountCount } = options;
26
+ const store = require_state.createStore(require_actions.createInitialState(startPath));
27
+ const registry = require_keybindings.createDefaultRegistry();
28
+ const screen = blessed.default.screen({
29
+ smartCSR: true,
30
+ title: "AFS Explorer",
31
+ terminal: "xterm",
32
+ fullUnicode: true,
33
+ warnings: false
34
+ });
35
+ require_status_bar.createStatusBar(blessed.default, {
36
+ parent: screen,
37
+ store,
38
+ width: "100%",
39
+ top: 0
40
+ });
41
+ const fileList = require_file_list.createFileList(blessed.default, {
42
+ parent: screen,
43
+ store,
44
+ width: "70%",
45
+ height: "100%-2",
46
+ top: 1,
47
+ left: 0
48
+ });
49
+ const metadataPanel = require_metadata_panel.createMetadataPanel(blessed.default, {
50
+ parent: screen,
51
+ width: "30%",
52
+ height: "100%-2",
53
+ top: 1,
54
+ right: 0
55
+ });
56
+ require_function_bar.createFunctionBar(blessed.default, {
57
+ parent: screen,
58
+ registry,
59
+ width: "100%",
60
+ bottom: 0
61
+ });
62
+ const dialogs = require_dialog.createDialogManager(blessed.default, { parent: screen });
63
+ async function loadPath(path) {
64
+ store.setState({
65
+ loading: true,
66
+ error: void 0
67
+ });
68
+ const result = await require_actions.loadDirectory(runtime, path);
69
+ store.setState({
70
+ currentPath: path,
71
+ entries: result.entries,
72
+ selectedIndex: 0,
73
+ scrollOffset: 0,
74
+ loading: false,
75
+ error: result.error
76
+ });
77
+ updateMetadata();
78
+ }
79
+ async function updateMetadata() {
80
+ const selected = require_actions.navigation.getSelected(store.getState());
81
+ if (selected) {
82
+ const metadata = await require_actions.loadMetadata(runtime, selected);
83
+ metadataPanel.update(selected, metadata);
84
+ } else metadataPanel.clear();
85
+ }
86
+ async function handleEnter() {
87
+ const selected = require_actions.navigation.getSelected(store.getState());
88
+ if (!selected) return;
89
+ if (selected.type === "directory" || selected.type === "up") await loadPath(selected.path);
90
+ else if (selected.type === "file") await handleView();
91
+ }
92
+ async function handleBack() {
93
+ const state = store.getState();
94
+ const parentPath = require_actions.navigation.getParentPath(state.currentPath);
95
+ if (parentPath !== state.currentPath) await loadPath(parentPath);
96
+ }
97
+ async function handleView() {
98
+ const selected = require_actions.navigation.getSelected(store.getState());
99
+ if (!selected || selected.type === "up") return;
100
+ if (selected.type === "file") {
101
+ dialogs.showLoading("Loading file");
102
+ const result = await require_actions.readFileContent(runtime, selected.path);
103
+ if (result.error) dialogs.showError("View Error", result.error);
104
+ else dialogs.showFileView(selected.path, result.content);
105
+ } else if (selected.type === "directory") await loadPath(selected.path);
106
+ }
107
+ async function handleExplain() {
108
+ const selected = require_actions.navigation.getSelected(store.getState());
109
+ if (!selected || selected.type === "up") return;
110
+ dialogs.showLoading("Getting explain info");
111
+ const result = await require_actions.getExplain(runtime, selected.path);
112
+ if (result.error) dialogs.showError("Explain Error", result.error);
113
+ else dialogs.showExplain(selected.path, result.content);
114
+ }
115
+ async function handleExec() {
116
+ const selected = require_actions.navigation.getSelected(store.getState());
117
+ if (!selected || selected.type === "up") return;
118
+ dialogs.showLoading("Executing action");
119
+ const result = await require_actions.executeAction(runtime, selected.path, "default");
120
+ dialogs.showActionResult("default", result.success, result.message, result.data);
121
+ }
122
+ async function handleRefresh() {
123
+ await loadPath(store.getState().currentPath);
124
+ }
125
+ const actionHandlers = {
126
+ help: () => dialogs.showHelp(registry),
127
+ explain: handleExplain,
128
+ view: handleView,
129
+ exec: handleExec,
130
+ refresh: handleRefresh,
131
+ quit: () => {
132
+ dialogs.showConfirm("Are you sure you want to quit?", () => {
133
+ screen.destroy();
134
+ require_index.printLogo();
135
+ const versionPart = require_index.colors.green(`v${version}`);
136
+ const mountPart = require_index.colors.yellow(`${mountCount} ${mountCount === 1 ? "mount" : "mounts"}`);
137
+ console.log(`${versionPart} ${require_index.colors.dim("•")} ${mountPart}`);
138
+ console.log(require_index.colors.dim("\nThanks for using AFS Explorer!\n"));
139
+ process.exit(0);
140
+ });
141
+ },
142
+ "nav:up": () => {
143
+ store.setState(require_actions.navigation.up(store.getState()));
144
+ updateMetadata();
145
+ },
146
+ "nav:down": () => {
147
+ store.setState(require_actions.navigation.down(store.getState()));
148
+ updateMetadata();
149
+ },
150
+ "nav:enter": handleEnter,
151
+ "nav:back": handleBack,
152
+ "nav:home": () => {
153
+ store.setState(require_actions.navigation.home(store.getState()));
154
+ updateMetadata();
155
+ },
156
+ "nav:end": () => {
157
+ store.setState(require_actions.navigation.end(store.getState()));
158
+ updateMetadata();
159
+ },
160
+ "nav:pageup": () => {
161
+ store.setState(require_actions.navigation.pageUp(store.getState(), fileList.getVisibleHeight()));
162
+ updateMetadata();
163
+ },
164
+ "nav:pagedown": () => {
165
+ store.setState(require_actions.navigation.pageDown(store.getState(), fileList.getVisibleHeight()));
166
+ updateMetadata();
167
+ },
168
+ cancel: () => {
169
+ if (dialogs.isOpen()) dialogs.close();
170
+ else actionHandlers.quit?.();
171
+ }
172
+ };
173
+ screen.on("keypress", async (ch, key) => {
174
+ if (dialogs.isOpen()) return;
175
+ const keyName = key.name || ch;
176
+ if (!keyName) return;
177
+ const binding = registry.getBindingForKey(keyName);
178
+ if (binding) {
179
+ const handler = actionHandlers[binding.action];
180
+ if (handler) {
181
+ await handler();
182
+ screen.render();
183
+ }
184
+ }
185
+ });
186
+ screen.on("resize", () => {
187
+ screen.render();
188
+ });
189
+ fileList.focus();
190
+ await loadPath(startPath);
191
+ screen.render();
192
+ return new Promise((resolve) => {
193
+ screen.on("destroy", () => {
194
+ resolve();
195
+ });
196
+ });
197
+ }
198
+
199
+ //#endregion
200
+ exports.createExplorerScreen = createExplorerScreen;