@aigne/afs-cli 1.11.0-beta.1 → 1.11.0-beta.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +262 -15
- package/dist/_virtual/rolldown_runtime.cjs +29 -0
- package/dist/_virtual/rolldown_runtime.mjs +7 -0
- package/dist/cli.cjs +40 -0
- package/dist/cli.d.cts +2 -0
- package/dist/cli.d.mts +2 -1
- package/dist/cli.mjs +36 -24
- package/dist/cli.mjs.map +1 -0
- package/dist/config/afs-loader.cjs +578 -0
- package/dist/config/afs-loader.d.cts +19 -0
- package/dist/config/afs-loader.d.cts.map +1 -0
- package/dist/config/afs-loader.d.mts +19 -0
- package/dist/config/afs-loader.d.mts.map +1 -0
- package/dist/config/afs-loader.mjs +576 -0
- package/dist/config/afs-loader.mjs.map +1 -0
- package/dist/config/env.cjs +46 -0
- package/dist/config/env.mjs +46 -0
- package/dist/config/env.mjs.map +1 -0
- package/dist/config/loader.cjs +219 -0
- package/dist/config/loader.mjs +217 -0
- package/dist/config/loader.mjs.map +1 -0
- package/dist/config/mount-commands.cjs +226 -0
- package/dist/config/mount-commands.d.cts +14 -0
- package/dist/config/mount-commands.d.cts.map +1 -0
- package/dist/config/mount-commands.d.mts +14 -0
- package/dist/config/mount-commands.d.mts.map +1 -0
- package/dist/config/mount-commands.mjs +220 -0
- package/dist/config/mount-commands.mjs.map +1 -0
- package/dist/config/schema.cjs +99 -0
- package/dist/config/schema.mjs +98 -0
- package/dist/config/schema.mjs.map +1 -0
- package/dist/core/commands/delete.cjs +41 -0
- package/dist/core/commands/delete.d.cts +18 -0
- package/dist/core/commands/delete.d.cts.map +1 -0
- package/dist/core/commands/delete.d.mts +18 -0
- package/dist/core/commands/delete.d.mts.map +1 -0
- package/dist/core/commands/delete.mjs +42 -0
- package/dist/core/commands/delete.mjs.map +1 -0
- package/dist/core/commands/exec.cjs +98 -0
- package/dist/core/commands/exec.d.cts +26 -0
- package/dist/core/commands/exec.d.cts.map +1 -0
- package/dist/core/commands/exec.d.mts +26 -0
- package/dist/core/commands/exec.d.mts.map +1 -0
- package/dist/core/commands/exec.mjs +99 -0
- package/dist/core/commands/exec.mjs.map +1 -0
- package/dist/core/commands/explain.cjs +278 -0
- package/dist/core/commands/explain.d.cts +25 -0
- package/dist/core/commands/explain.d.cts.map +1 -0
- package/dist/core/commands/explain.d.mts +25 -0
- package/dist/core/commands/explain.d.mts.map +1 -0
- package/dist/core/commands/explain.mjs +279 -0
- package/dist/core/commands/explain.mjs.map +1 -0
- package/dist/core/commands/explore.cjs +30 -0
- package/dist/core/commands/explore.d.mts +2 -0
- package/dist/core/commands/explore.mjs +31 -0
- package/dist/core/commands/explore.mjs.map +1 -0
- package/dist/core/commands/index.cjs +36 -0
- package/dist/core/commands/index.d.cts +21 -0
- package/dist/core/commands/index.d.cts.map +1 -0
- package/dist/core/commands/index.d.mts +24 -0
- package/dist/core/commands/index.d.mts.map +1 -0
- package/dist/core/commands/index.mjs +37 -0
- package/dist/core/commands/index.mjs.map +1 -0
- package/dist/core/commands/ls.cjs +57 -0
- package/dist/core/commands/ls.d.cts +21 -0
- package/dist/core/commands/ls.d.cts.map +1 -0
- package/dist/core/commands/ls.d.mts +21 -0
- package/dist/core/commands/ls.d.mts.map +1 -0
- package/dist/core/commands/ls.mjs +58 -0
- package/dist/core/commands/ls.mjs.map +1 -0
- package/dist/core/commands/mount.cjs +222 -0
- package/dist/core/commands/mount.d.cts +35 -0
- package/dist/core/commands/mount.d.cts.map +1 -0
- package/dist/core/commands/mount.d.mts +35 -0
- package/dist/core/commands/mount.d.mts.map +1 -0
- package/dist/core/commands/mount.mjs +223 -0
- package/dist/core/commands/mount.mjs.map +1 -0
- package/dist/core/commands/read.cjs +48 -0
- package/dist/core/commands/read.d.cts +17 -0
- package/dist/core/commands/read.d.cts.map +1 -0
- package/dist/core/commands/read.d.mts +17 -0
- package/dist/core/commands/read.d.mts.map +1 -0
- package/dist/core/commands/read.mjs +49 -0
- package/dist/core/commands/read.mjs.map +1 -0
- package/dist/core/commands/search.cjs +40 -0
- package/dist/core/commands/search.d.mts +2 -0
- package/dist/core/commands/search.mjs +41 -0
- package/dist/core/commands/search.mjs.map +1 -0
- package/dist/core/commands/serve.cjs +267 -0
- package/dist/core/commands/serve.d.mts +2 -0
- package/dist/core/commands/serve.mjs +267 -0
- package/dist/core/commands/serve.mjs.map +1 -0
- package/dist/core/commands/stat.cjs +53 -0
- package/dist/core/commands/stat.d.cts +17 -0
- package/dist/core/commands/stat.d.cts.map +1 -0
- package/dist/core/commands/stat.d.mts +17 -0
- package/dist/core/commands/stat.d.mts.map +1 -0
- package/dist/core/commands/stat.mjs +54 -0
- package/dist/core/commands/stat.mjs.map +1 -0
- package/dist/core/commands/types.cjs +18 -0
- package/dist/core/commands/types.d.cts +54 -0
- package/dist/core/commands/types.d.cts.map +1 -0
- package/dist/core/commands/types.d.mts +54 -0
- package/dist/core/commands/types.d.mts.map +1 -0
- package/dist/core/commands/types.mjs +19 -0
- package/dist/core/commands/types.mjs.map +1 -0
- package/dist/core/commands/write.cjs +70 -0
- package/dist/core/commands/write.d.cts +20 -0
- package/dist/core/commands/write.d.cts.map +1 -0
- package/dist/core/commands/write.d.mts +20 -0
- package/dist/core/commands/write.d.mts.map +1 -0
- package/dist/core/commands/write.mjs +71 -0
- package/dist/core/commands/write.mjs.map +1 -0
- package/dist/core/executor/index.cjs +196 -0
- package/dist/core/executor/index.d.cts +77 -0
- package/dist/core/executor/index.d.cts.map +1 -0
- package/dist/core/executor/index.d.mts +77 -0
- package/dist/core/executor/index.d.mts.map +1 -0
- package/dist/core/executor/index.mjs +195 -0
- package/dist/core/executor/index.mjs.map +1 -0
- package/dist/core/formatters/delete.cjs +37 -0
- package/dist/core/formatters/delete.d.cts +18 -0
- package/dist/core/formatters/delete.d.cts.map +1 -0
- package/dist/core/formatters/delete.d.mts +18 -0
- package/dist/core/formatters/delete.d.mts.map +1 -0
- package/dist/core/formatters/delete.mjs +37 -0
- package/dist/core/formatters/delete.mjs.map +1 -0
- package/dist/core/formatters/exec.cjs +60 -0
- package/dist/core/formatters/exec.d.cts +18 -0
- package/dist/core/formatters/exec.d.cts.map +1 -0
- package/dist/core/formatters/exec.d.mts +18 -0
- package/dist/core/formatters/exec.d.mts.map +1 -0
- package/dist/core/formatters/exec.mjs +60 -0
- package/dist/core/formatters/exec.mjs.map +1 -0
- package/dist/core/formatters/explain.cjs +99 -0
- package/dist/core/formatters/explain.d.cts +11 -0
- package/dist/core/formatters/explain.d.cts.map +1 -0
- package/dist/core/formatters/explain.d.mts +11 -0
- package/dist/core/formatters/explain.d.mts.map +1 -0
- package/dist/core/formatters/explain.mjs +98 -0
- package/dist/core/formatters/explain.mjs.map +1 -0
- package/dist/core/formatters/index.d.mts +9 -0
- package/dist/core/formatters/ls.cjs +179 -0
- package/dist/core/formatters/ls.d.cts +20 -0
- package/dist/core/formatters/ls.d.cts.map +1 -0
- package/dist/core/formatters/ls.d.mts +20 -0
- package/dist/core/formatters/ls.d.mts.map +1 -0
- package/dist/core/formatters/ls.mjs +179 -0
- package/dist/core/formatters/ls.mjs.map +1 -0
- package/dist/core/formatters/mount.cjs +55 -0
- package/dist/core/formatters/mount.d.cts +15 -0
- package/dist/core/formatters/mount.d.cts.map +1 -0
- package/dist/core/formatters/mount.d.mts +15 -0
- package/dist/core/formatters/mount.d.mts.map +1 -0
- package/dist/core/formatters/mount.mjs +55 -0
- package/dist/core/formatters/mount.mjs.map +1 -0
- package/dist/core/formatters/read.cjs +100 -0
- package/dist/core/formatters/read.d.cts +22 -0
- package/dist/core/formatters/read.d.cts.map +1 -0
- package/dist/core/formatters/read.d.mts +22 -0
- package/dist/core/formatters/read.d.mts.map +1 -0
- package/dist/core/formatters/read.mjs +100 -0
- package/dist/core/formatters/read.mjs.map +1 -0
- package/dist/core/formatters/search.cjs +44 -0
- package/dist/core/formatters/search.d.mts +1 -0
- package/dist/core/formatters/search.mjs +44 -0
- package/dist/core/formatters/search.mjs.map +1 -0
- package/dist/core/formatters/stat.cjs +155 -0
- package/dist/core/formatters/stat.d.cts +15 -0
- package/dist/core/formatters/stat.d.cts.map +1 -0
- package/dist/core/formatters/stat.d.mts +15 -0
- package/dist/core/formatters/stat.d.mts.map +1 -0
- package/dist/core/formatters/stat.mjs +155 -0
- package/dist/core/formatters/stat.mjs.map +1 -0
- package/dist/core/formatters/write.cjs +51 -0
- package/dist/core/formatters/write.d.cts +22 -0
- package/dist/core/formatters/write.d.cts.map +1 -0
- package/dist/core/formatters/write.d.mts +22 -0
- package/dist/core/formatters/write.d.mts.map +1 -0
- package/dist/core/formatters/write.mjs +51 -0
- package/dist/core/formatters/write.mjs.map +1 -0
- package/dist/core/helpers/exec-args.cjs +142 -0
- package/dist/core/helpers/exec-args.d.cts +46 -0
- package/dist/core/helpers/exec-args.d.cts.map +1 -0
- package/dist/core/helpers/exec-args.d.mts +46 -0
- package/dist/core/helpers/exec-args.d.mts.map +1 -0
- package/dist/core/helpers/exec-args.mjs +139 -0
- package/dist/core/helpers/exec-args.mjs.map +1 -0
- package/dist/core/helpers/stdin.cjs +41 -0
- package/dist/core/helpers/stdin.d.cts +15 -0
- package/dist/core/helpers/stdin.d.cts.map +1 -0
- package/dist/core/helpers/stdin.d.mts +15 -0
- package/dist/core/helpers/stdin.d.mts.map +1 -0
- package/dist/core/helpers/stdin.mjs +41 -0
- package/dist/core/helpers/stdin.mjs.map +1 -0
- package/dist/core/index.cjs +49 -0
- package/dist/core/index.d.cts +24 -0
- package/dist/core/index.d.mts +25 -0
- package/dist/core/index.mjs +24 -0
- package/dist/core/path-utils.cjs +1 -0
- package/dist/core/path-utils.mjs +3 -0
- package/dist/core/types.d.cts +24 -0
- package/dist/core/types.d.cts.map +1 -0
- package/dist/core/types.d.mts +24 -0
- package/dist/core/types.d.mts.map +1 -0
- package/dist/credential/auth-server.cjs +247 -0
- package/dist/credential/auth-server.mjs +247 -0
- package/dist/credential/auth-server.mjs.map +1 -0
- package/dist/credential/cli-auth-context.cjs +86 -0
- package/dist/credential/cli-auth-context.d.mts +1 -0
- package/dist/credential/cli-auth-context.mjs +86 -0
- package/dist/credential/cli-auth-context.mjs.map +1 -0
- package/dist/credential/index.cjs +5 -0
- package/dist/credential/index.d.mts +4 -0
- package/dist/credential/index.mjs +7 -0
- package/dist/credential/mcp-auth-context.cjs +186 -0
- package/dist/credential/mcp-auth-context.d.mts +1 -0
- package/dist/credential/mcp-auth-context.mjs +186 -0
- package/dist/credential/mcp-auth-context.mjs.map +1 -0
- package/dist/credential/resolver.cjs +127 -0
- package/dist/credential/resolver.d.mts +1 -0
- package/dist/credential/resolver.mjs +127 -0
- package/dist/credential/resolver.mjs.map +1 -0
- package/dist/credential/store.cjs +106 -0
- package/dist/credential/store.d.cts +30 -0
- package/dist/credential/store.d.cts.map +1 -0
- package/dist/credential/store.d.mts +30 -0
- package/dist/credential/store.d.mts.map +1 -0
- package/dist/credential/store.mjs +106 -0
- package/dist/credential/store.mjs.map +1 -0
- package/dist/errors.cjs +18 -0
- package/dist/errors.mjs +18 -0
- package/dist/errors.mjs.map +1 -0
- package/dist/explorer/actions.cjs +311 -0
- package/dist/explorer/actions.mjs +305 -0
- package/dist/explorer/actions.mjs.map +1 -0
- package/dist/explorer/components/dialog.cjs +508 -0
- package/dist/explorer/components/dialog.mjs +509 -0
- package/dist/explorer/components/dialog.mjs.map +1 -0
- package/dist/explorer/components/file-list.cjs +107 -0
- package/dist/explorer/components/file-list.mjs +107 -0
- package/dist/explorer/components/file-list.mjs.map +1 -0
- package/dist/explorer/components/function-bar.cjs +55 -0
- package/dist/explorer/components/function-bar.mjs +55 -0
- package/dist/explorer/components/function-bar.mjs.map +1 -0
- package/dist/explorer/components/index.cjs +5 -0
- package/dist/explorer/components/index.mjs +7 -0
- package/dist/explorer/components/metadata-panel.cjs +219 -0
- package/dist/explorer/components/metadata-panel.mjs +219 -0
- package/dist/explorer/components/metadata-panel.mjs.map +1 -0
- package/dist/explorer/components/status-bar.cjs +53 -0
- package/dist/explorer/components/status-bar.mjs +54 -0
- package/dist/explorer/components/status-bar.mjs.map +1 -0
- package/dist/explorer/keybindings.cjs +214 -0
- package/dist/explorer/keybindings.mjs +213 -0
- package/dist/explorer/keybindings.mjs.map +1 -0
- package/dist/explorer/screen.cjs +251 -0
- package/dist/explorer/screen.d.cts +23 -0
- package/dist/explorer/screen.d.cts.map +1 -0
- package/dist/explorer/screen.d.mts +23 -0
- package/dist/explorer/screen.d.mts.map +1 -0
- package/dist/explorer/screen.mjs +250 -0
- package/dist/explorer/screen.mjs.map +1 -0
- package/dist/explorer/state.cjs +53 -0
- package/dist/explorer/state.mjs +53 -0
- package/dist/explorer/state.mjs.map +1 -0
- package/dist/explorer/theme.cjs +160 -0
- package/dist/explorer/theme.mjs +157 -0
- package/dist/explorer/theme.mjs.map +1 -0
- package/dist/index.cjs +12 -0
- package/dist/index.d.cts +6 -0
- package/dist/index.d.mts +7 -4
- package/dist/index.mjs +7 -2
- package/dist/mcp/http-transport.cjs +87 -0
- package/dist/mcp/http-transport.mjs +87 -0
- package/dist/mcp/http-transport.mjs.map +1 -0
- package/dist/mcp/prompts.cjs +48 -0
- package/dist/mcp/prompts.mjs +48 -0
- package/dist/mcp/prompts.mjs.map +1 -0
- package/dist/mcp/resources.cjs +25 -0
- package/dist/mcp/resources.mjs +25 -0
- package/dist/mcp/resources.mjs.map +1 -0
- package/dist/mcp/server.cjs +74 -0
- package/dist/mcp/server.mjs +73 -0
- package/dist/mcp/server.mjs.map +1 -0
- package/dist/mcp/tools.cjs +152 -0
- package/dist/mcp/tools.mjs +152 -0
- package/dist/mcp/tools.mjs.map +1 -0
- package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/dist/index.d.cts +10 -0
- package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/dist/index.d.cts.map +1 -0
- package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/dist/index.d.mts +10 -0
- package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/dist/index.d.mts.map +1 -0
- package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/dist/types.d.cts +46 -0
- package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/dist/types.d.cts.map +1 -0
- package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/dist/types.d.mts +46 -0
- package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/dist/types.d.mts.map +1 -0
- package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/dist/urlpattern.cjs +902 -0
- package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/dist/urlpattern.mjs +902 -0
- package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/dist/urlpattern.mjs.map +1 -0
- package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/index.cjs +6 -0
- package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/index.mjs +8 -0
- package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/index.mjs.map +1 -0
- package/dist/path-utils.cjs +105 -0
- package/dist/path-utils.d.cts +50 -0
- package/dist/path-utils.d.cts.map +1 -0
- package/dist/path-utils.d.mts +50 -0
- package/dist/path-utils.d.mts.map +1 -0
- package/dist/path-utils.mjs +104 -0
- package/dist/path-utils.mjs.map +1 -0
- package/dist/repl.cjs +491 -0
- package/dist/repl.d.cts +15 -0
- package/dist/repl.d.cts.map +1 -0
- package/dist/repl.d.mts +16 -0
- package/dist/repl.d.mts.map +1 -0
- package/dist/repl.mjs +491 -0
- package/dist/repl.mjs.map +1 -0
- package/dist/serve.cjs +146 -0
- package/dist/serve.d.cts +41 -0
- package/dist/serve.d.cts.map +1 -0
- package/dist/serve.d.mts +41 -0
- package/dist/serve.d.mts.map +1 -0
- package/dist/serve.mjs +146 -0
- package/dist/serve.mjs.map +1 -0
- package/dist/ui/header.cjs +12 -0
- package/dist/ui/header.mjs +13 -0
- package/dist/ui/header.mjs.map +1 -0
- package/dist/ui/index.cjs +8 -0
- package/dist/ui/index.mjs +9 -0
- package/dist/ui/index.mjs.map +1 -0
- package/dist/ui/terminal.cjs +88 -0
- package/dist/ui/terminal.mjs +88 -0
- package/dist/ui/terminal.mjs.map +1 -0
- package/dist/version.cjs +9 -0
- package/dist/version.d.cts +5 -0
- package/dist/version.d.cts.map +1 -0
- package/dist/version.d.mts +5 -0
- package/dist/version.d.mts.map +1 -0
- package/dist/version.mjs +9 -0
- package/dist/version.mjs.map +1 -0
- package/package.json +77 -11
- package/.turbo/turbo-build.log +0 -18
- package/.turbo/turbo-check-types.log +0 -4
- package/dist/version--p6A8sKX.mjs +0 -5
- package/src/cli.test.ts +0 -8
- package/src/cli.ts +0 -29
- package/src/index.ts +0 -7
- package/src/version.ts +0 -1
- package/tsconfig.json +0 -16
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadata-panel.mjs","names":[],"sources":["../../../src/explorer/components/metadata-panel.ts"],"sourcesContent":["/**\n * AFS Explorer Metadata Panel Component\n *\n * Right panel showing detailed metadata for selected entry.\n */\n\nimport type Blessed from \"blessed\";\nimport { Colors, formatSize, Icons } from \"../theme.js\";\nimport type { EntryMetadata, ExplorerEntry } from \"../types.js\";\n\nexport interface MetadataPanelOptions {\n parent: Blessed.Widgets.Node;\n width: string | number;\n height: string | number;\n top?: string | number;\n right?: string | number;\n}\n\n/**\n * Format metadata for display\n */\nexport function formatMetadata(entry: ExplorerEntry, metadata?: EntryMetadata): string[] {\n const lines: string[] = [];\n\n // Entry name with type indicator (only show icon for non-files)\n const icon = entry.type !== \"file\" ? Icons[entry.type] : \"\";\n const prefix = icon ? `${icon} ` : \"\";\n lines.push(`${prefix}${entry.name}`);\n lines.push(\"\");\n\n // Path\n lines.push(`Path: ${entry.path}`);\n\n // Size\n if (entry.size !== undefined || metadata?.size !== undefined) {\n const size = metadata?.size ?? entry.size;\n lines.push(`Size: ${formatSize(size!)}`);\n }\n\n // Children count\n if (entry.childrenCount !== undefined || metadata?.childrenCount !== undefined) {\n const count = metadata?.childrenCount ?? entry.childrenCount;\n lines.push(`Items: ${count}`);\n }\n\n // Modified date\n if (entry.modified || metadata?.modified) {\n const date = metadata?.modified ?? entry.modified;\n lines.push(`Modified: ${formatDateTime(date!)}`);\n }\n\n // Provider\n if (entry.provider || metadata?.provider) {\n lines.push(`Provider: ${metadata?.provider ?? entry.provider}`);\n }\n\n // Hash\n if (entry.hash || metadata?.hash) {\n const hash = metadata?.hash ?? entry.hash;\n // Truncate long hashes\n const display = hash!.length > 20 ? `${hash!.slice(0, 20)}...` : hash;\n lines.push(`Hash: ${display}`);\n }\n\n // Mount path\n if (metadata?.mountPath) {\n lines.push(`Mount: ${metadata.mountPath}`);\n }\n\n // URI\n if (metadata?.uri) {\n lines.push(`URI: ${metadata.uri}`);\n }\n\n // Kind/Kinds information (show one or the other, avoid redundancy)\n // Prefer entry.kinds/kind, fallback to metadata.extra.kinds/kind\n const kinds =\n entry.kinds && entry.kinds.length > 0\n ? entry.kinds\n : (metadata?.extra?.kinds as string[] | undefined);\n const kind = entry.kind ?? (metadata?.extra?.kind as string | undefined);\n\n if (kinds && kinds.length > 0) {\n lines.push(`Kinds: ${kinds.join(\" → \")}`);\n } else if (kind) {\n lines.push(`Kind: ${kind}`);\n }\n\n // Display all meta fields from extra (flat, same level as other fields)\n if (metadata?.extra && Object.keys(metadata.extra).length > 0) {\n // Filter out built-in fields that are already displayed above\n const builtInFields = new Set([\n \"size\",\n \"mimeType\",\n \"childrenCount\",\n \"hash\",\n \"provider\",\n \"mountPath\",\n \"uri\",\n \"permissions\",\n \"kind\",\n \"kinds\",\n ]);\n\n for (const [key, value] of Object.entries(metadata.extra)) {\n if (builtInFields.has(key) || value === undefined) continue;\n\n // Special handling for inputSchema - show properties nicely\n if (key === \"inputSchema\" && typeof value === \"object\" && value !== null) {\n const schema = value as Record<string, unknown>;\n if (schema.properties && typeof schema.properties === \"object\") {\n lines.push(\"\");\n lines.push(\"InputSchema:\");\n const props = schema.properties as Record<string, unknown>;\n for (const [propName, propSchema] of Object.entries(props)) {\n const ps = propSchema as Record<string, unknown>;\n const type = ps.type || \"any\";\n const desc = ps.description ? ` - ${ps.description}` : \"\";\n const req =\n Array.isArray(schema.required) && schema.required.includes(propName) ? \"*\" : \"\";\n lines.push(` • ${propName}${req}: ${type}${desc}`);\n }\n continue;\n }\n }\n\n // Capitalize first letter of key for display\n const displayKey = key.charAt(0).toUpperCase() + key.slice(1);\n const displayValue = formatValue(value);\n\n if (displayValue.includes(\"\\n\")) {\n lines.push(\"\");\n lines.push(`${displayKey}:`);\n for (const line of displayValue.split(\"\\n\")) {\n lines.push(` ${line}`);\n }\n } else {\n lines.push(`${displayKey}: ${displayValue}`);\n }\n }\n }\n\n // Actions section (prefer metadata.actions from stat, fallback to entry.actions)\n const actions = metadata?.actions ?? entry.actions;\n lines.push(\"\");\n lines.push(\"─────── Actions ───────\");\n if (actions && actions.length > 0) {\n for (let i = 0; i < actions.length; i++) {\n const action = actions[i];\n if (action) {\n lines.push(`[${i + 1}] ${action.name}`);\n }\n }\n lines.push(\"\");\n lines.push(\"(F4 to execute)\");\n } else {\n lines.push(\"(none)\");\n }\n\n return lines;\n}\n\n/**\n * Format a value for display\n */\nfunction formatValue(value: unknown): string {\n if (value === null || value === undefined) {\n return \"\";\n }\n if (typeof value === \"string\") {\n return value;\n }\n if (typeof value === \"number\" || typeof value === \"boolean\") {\n return String(value);\n }\n if (Array.isArray(value)) {\n if (value.length === 0) return \"[]\";\n // Simple arrays of primitives\n if (value.every((v) => typeof v === \"string\" || typeof v === \"number\")) {\n return value.join(\", \");\n }\n // Arrays of objects with name/type (like columns, fields, properties)\n if (value.every((v) => typeof v === \"object\" && v !== null && \"name\" in v)) {\n return formatNamedItems(\n value as Array<{ name: string; type?: string; description?: string }>,\n );\n }\n try {\n return JSON.stringify(value, null, 2);\n } catch {\n return \"[unable to display]\";\n }\n }\n if (typeof value === \"object\") {\n // Check if it's a JSON Schema properties object\n const obj = value as Record<string, unknown>;\n if (isSchemaProperties(obj)) {\n return formatSchemaProperties(obj);\n }\n try {\n return JSON.stringify(value, null, 2);\n } catch {\n return \"[unable to display]\";\n }\n }\n return String(value);\n}\n\n/**\n * Check if object looks like JSON Schema properties\n */\nfunction isSchemaProperties(obj: Record<string, unknown>): boolean {\n const values = Object.values(obj);\n if (values.length === 0) return false;\n // Check if values look like schema definitions (have type property)\n return values.every((v) => typeof v === \"object\" && v !== null && (\"type\" in v || \"$ref\" in v));\n}\n\n/**\n * Format JSON Schema properties object\n */\nfunction formatSchemaProperties(props: Record<string, unknown>): string {\n const lines: string[] = [];\n for (const [name, schema] of Object.entries(props)) {\n const s = schema as Record<string, unknown>;\n const type = s.type || s.$ref || \"any\";\n const desc = s.description ? ` - ${s.description}` : \"\";\n lines.push(`• ${name}: ${type}${desc}`);\n }\n return lines.join(\"\\n\");\n}\n\n/**\n * Format array of named items (columns, fields, etc.)\n */\nfunction formatNamedItems(\n items: Array<{\n name: string;\n type?: string;\n description?: string;\n nullable?: boolean;\n primaryKey?: boolean;\n }>,\n): string {\n const lines: string[] = [];\n for (const item of items) {\n const type = item.type ? `: ${item.type}` : \"\";\n const desc = item.description ? ` - ${item.description}` : \"\";\n // Add flags for nullable and primaryKey\n const flags: string[] = [];\n if (item.primaryKey) flags.push(\"PK\");\n if (item.nullable) flags.push(\"nullable\");\n const flagsStr = flags.length > 0 ? ` (${flags.join(\", \")})` : \"\";\n lines.push(`• ${item.name}${type}${flagsStr}${desc}`);\n }\n return lines.join(\"\\n\");\n}\n\n/**\n * Format date and time\n */\nfunction formatDateTime(date: Date): string {\n return date.toLocaleString(\"en\", {\n year: \"numeric\",\n month: \"short\",\n day: \"numeric\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n });\n}\n\n/**\n * Create metadata panel component\n */\nexport function createMetadataPanel(blessed: typeof Blessed, options: MetadataPanelOptions) {\n const { parent, width, height, top = 0, right = 0 } = options;\n\n // Create box for metadata panel\n const panel = blessed.box({\n parent,\n top,\n right,\n width,\n height,\n tags: true,\n scrollable: true,\n alwaysScroll: true,\n style: {\n fg: Colors.fg.normal,\n bg: Colors.bg.main,\n },\n border: {\n type: \"line\",\n },\n label: \" Details \",\n });\n\n let currentEntry: ExplorerEntry | undefined;\n let _currentMetadata: EntryMetadata | undefined;\n\n return {\n element: panel,\n\n /**\n * Update panel with entry info\n */\n update(entry: ExplorerEntry, metadata?: EntryMetadata): void {\n currentEntry = entry;\n _currentMetadata = metadata;\n\n if (entry.type === \"up\") {\n panel.setContent(\" Parent directory\");\n (panel.screen as Blessed.Widgets.Screen)?.render();\n return;\n }\n\n const lines = formatMetadata(entry, metadata);\n panel.setContent(lines.map((l) => ` ${l}`).join(\"\\n\"));\n (panel.screen as Blessed.Widgets.Screen)?.render();\n },\n\n /**\n * Clear the panel\n */\n clear(): void {\n currentEntry = undefined;\n _currentMetadata = undefined;\n panel.setContent(\"\");\n (panel.screen as Blessed.Widgets.Screen)?.render();\n },\n\n /**\n * Get current entry\n */\n getCurrentEntry(): ExplorerEntry | undefined {\n return currentEntry;\n },\n\n /**\n * Destroy the component\n */\n destroy(): void {\n panel.destroy();\n },\n };\n}\n\nexport type MetadataPanel = ReturnType<typeof createMetadataPanel>;\n"],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
const require_theme = require('../theme.cjs');
|
|
2
|
+
|
|
3
|
+
//#region src/explorer/components/status-bar.ts
|
|
4
|
+
/**
|
|
5
|
+
* Create status bar component
|
|
6
|
+
*/
|
|
7
|
+
function createStatusBar(blessed, options) {
|
|
8
|
+
const { parent, store, width, top = 0, left = 0 } = options;
|
|
9
|
+
const bar = blessed.box({
|
|
10
|
+
parent,
|
|
11
|
+
top,
|
|
12
|
+
left,
|
|
13
|
+
width,
|
|
14
|
+
height: 1,
|
|
15
|
+
tags: true,
|
|
16
|
+
style: {
|
|
17
|
+
fg: require_theme.Colors.fg.selected,
|
|
18
|
+
bg: require_theme.Colors.bg.functionKey
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
function updateContent(state) {
|
|
22
|
+
const path = state.currentPath || "/";
|
|
23
|
+
const count = state.entries.filter((e) => e.type !== "up").length;
|
|
24
|
+
const loading = state.loading ? " Loading..." : "";
|
|
25
|
+
const error = state.error ? ` ${require_theme.Symbols.error} ${state.error}` : "";
|
|
26
|
+
const left$1 = ` AFS Explorer | ${path}`;
|
|
27
|
+
const right = `${count} items${loading}${error} `;
|
|
28
|
+
const barWidth = typeof bar.width === "number" ? bar.width : 80;
|
|
29
|
+
const padding = Math.max(0, barWidth - left$1.length - right.length);
|
|
30
|
+
bar.setContent(`${left$1}${" ".repeat(padding)}${right}`);
|
|
31
|
+
}
|
|
32
|
+
store.subscribe((state) => {
|
|
33
|
+
updateContent(state);
|
|
34
|
+
bar.screen?.render();
|
|
35
|
+
});
|
|
36
|
+
updateContent(store.getState());
|
|
37
|
+
return {
|
|
38
|
+
element: bar,
|
|
39
|
+
setMessage(message) {
|
|
40
|
+
bar.setContent(` ${message}`);
|
|
41
|
+
bar.screen?.render();
|
|
42
|
+
},
|
|
43
|
+
restore() {
|
|
44
|
+
updateContent(store.getState());
|
|
45
|
+
},
|
|
46
|
+
destroy() {
|
|
47
|
+
bar.destroy();
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
//#endregion
|
|
53
|
+
exports.createStatusBar = createStatusBar;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Colors, Symbols } from "../theme.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/explorer/components/status-bar.ts
|
|
4
|
+
/**
|
|
5
|
+
* Create status bar component
|
|
6
|
+
*/
|
|
7
|
+
function createStatusBar(blessed, options) {
|
|
8
|
+
const { parent, store, width, top = 0, left = 0 } = options;
|
|
9
|
+
const bar = blessed.box({
|
|
10
|
+
parent,
|
|
11
|
+
top,
|
|
12
|
+
left,
|
|
13
|
+
width,
|
|
14
|
+
height: 1,
|
|
15
|
+
tags: true,
|
|
16
|
+
style: {
|
|
17
|
+
fg: Colors.fg.selected,
|
|
18
|
+
bg: Colors.bg.functionKey
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
function updateContent(state) {
|
|
22
|
+
const path = state.currentPath || "/";
|
|
23
|
+
const count = state.entries.filter((e) => e.type !== "up").length;
|
|
24
|
+
const loading = state.loading ? " Loading..." : "";
|
|
25
|
+
const error = state.error ? ` ${Symbols.error} ${state.error}` : "";
|
|
26
|
+
const left$1 = ` AFS Explorer | ${path}`;
|
|
27
|
+
const right = `${count} items${loading}${error} `;
|
|
28
|
+
const barWidth = typeof bar.width === "number" ? bar.width : 80;
|
|
29
|
+
const padding = Math.max(0, barWidth - left$1.length - right.length);
|
|
30
|
+
bar.setContent(`${left$1}${" ".repeat(padding)}${right}`);
|
|
31
|
+
}
|
|
32
|
+
store.subscribe((state) => {
|
|
33
|
+
updateContent(state);
|
|
34
|
+
bar.screen?.render();
|
|
35
|
+
});
|
|
36
|
+
updateContent(store.getState());
|
|
37
|
+
return {
|
|
38
|
+
element: bar,
|
|
39
|
+
setMessage(message) {
|
|
40
|
+
bar.setContent(` ${message}`);
|
|
41
|
+
bar.screen?.render();
|
|
42
|
+
},
|
|
43
|
+
restore() {
|
|
44
|
+
updateContent(store.getState());
|
|
45
|
+
},
|
|
46
|
+
destroy() {
|
|
47
|
+
bar.destroy();
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
//#endregion
|
|
53
|
+
export { createStatusBar };
|
|
54
|
+
//# sourceMappingURL=status-bar.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status-bar.mjs","names":["left"],"sources":["../../../src/explorer/components/status-bar.ts"],"sourcesContent":["/**\n * AFS Explorer Status Bar Component\n *\n * Top status bar showing current path and info.\n */\n\nimport type Blessed from \"blessed\";\nimport type { ExplorerStore } from \"../state.js\";\nimport { Colors, Symbols } from \"../theme.js\";\nimport type { ExplorerState } from \"../types.js\";\n\nexport interface StatusBarOptions {\n parent: Blessed.Widgets.Node;\n store: ExplorerStore;\n width: string | number;\n top?: string | number;\n left?: string | number;\n}\n\n/**\n * Create status bar component\n */\nexport function createStatusBar(blessed: typeof Blessed, options: StatusBarOptions) {\n const { parent, store, width, top = 0, left = 0 } = options;\n\n // Create box for status bar\n const bar = blessed.box({\n parent,\n top,\n left,\n width,\n height: 1,\n tags: true,\n style: {\n fg: Colors.fg.selected,\n bg: Colors.bg.functionKey,\n },\n });\n\n // Update content from state\n function updateContent(state: ExplorerState): void {\n const path = state.currentPath || \"/\";\n const count = state.entries.filter((e) => e.type !== \"up\").length;\n const loading = state.loading ? \" Loading...\" : \"\";\n const error = state.error ? ` ${Symbols.error} ${state.error}` : \"\";\n\n // Build status line: \"AFS Explorer | /path\"\n const left = ` AFS Explorer | ${path}`;\n const right = `${count} items${loading}${error} `;\n\n // Calculate padding to right-align\n const barWidth = typeof bar.width === \"number\" ? bar.width : 80;\n const padding = Math.max(0, barWidth - left.length - right.length);\n\n bar.setContent(`${left}${\" \".repeat(padding)}${right}`);\n }\n\n // Subscribe to state changes\n store.subscribe((state) => {\n updateContent(state);\n (bar.screen as Blessed.Widgets.Screen)?.render();\n });\n\n // Initial render\n updateContent(store.getState());\n\n return {\n element: bar,\n\n /**\n * Set temporary message\n */\n setMessage(message: string): void {\n bar.setContent(` ${message}`);\n (bar.screen as Blessed.Widgets.Screen)?.render();\n },\n\n /**\n * Restore normal status\n */\n restore(): void {\n updateContent(store.getState());\n },\n\n /**\n * Destroy the component\n */\n destroy(): void {\n bar.destroy();\n },\n };\n}\n\nexport type StatusBar = ReturnType<typeof createStatusBar>;\n"],"mappings":";;;;;;AAsBA,SAAgB,gBAAgB,SAAyB,SAA2B;CAClF,MAAM,EAAE,QAAQ,OAAO,OAAO,MAAM,GAAG,OAAO,MAAM;CAGpD,MAAM,MAAM,QAAQ,IAAI;EACtB;EACA;EACA;EACA;EACA,QAAQ;EACR,MAAM;EACN,OAAO;GACL,IAAI,OAAO,GAAG;GACd,IAAI,OAAO,GAAG;GACf;EACF,CAAC;CAGF,SAAS,cAAc,OAA4B;EACjD,MAAM,OAAO,MAAM,eAAe;EAClC,MAAM,QAAQ,MAAM,QAAQ,QAAQ,MAAM,EAAE,SAAS,KAAK,CAAC;EAC3D,MAAM,UAAU,MAAM,UAAU,gBAAgB;EAChD,MAAM,QAAQ,MAAM,QAAQ,IAAI,QAAQ,MAAM,GAAG,MAAM,UAAU;EAGjE,MAAMA,SAAO,mBAAmB;EAChC,MAAM,QAAQ,GAAG,MAAM,QAAQ,UAAU,MAAM;EAG/C,MAAM,WAAW,OAAO,IAAI,UAAU,WAAW,IAAI,QAAQ;EAC7D,MAAM,UAAU,KAAK,IAAI,GAAG,WAAWA,OAAK,SAAS,MAAM,OAAO;AAElE,MAAI,WAAW,GAAGA,SAAO,IAAI,OAAO,QAAQ,GAAG,QAAQ;;AAIzD,OAAM,WAAW,UAAU;AACzB,gBAAc,MAAM;AACpB,EAAC,IAAI,QAAmC,QAAQ;GAChD;AAGF,eAAc,MAAM,UAAU,CAAC;AAE/B,QAAO;EACL,SAAS;EAKT,WAAW,SAAuB;AAChC,OAAI,WAAW,IAAI,UAAU;AAC7B,GAAC,IAAI,QAAmC,QAAQ;;EAMlD,UAAgB;AACd,iBAAc,MAAM,UAAU,CAAC;;EAMjC,UAAgB;AACd,OAAI,SAAS;;EAEhB"}
|
|
@@ -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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"}
|