codebase-onboarder 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +196 -47
- package/bin/build-if-source.js +23 -0
- package/cli/commands.d.ts +26 -0
- package/cli/commands.js +836 -811
- package/cli/commands.js.map +1 -0
- package/cli/explorer/advanced.d.ts +14 -0
- package/cli/explorer/advanced.js +449 -0
- package/cli/explorer/advanced.js.map +1 -0
- package/cli/explorer/app.d.ts +1 -0
- package/cli/explorer/app.js +396 -229
- package/cli/explorer/app.js.map +1 -0
- package/cli/explorer/assistant.d.ts +9 -0
- package/cli/explorer/assistant.js +58 -0
- package/cli/explorer/assistant.js.map +1 -0
- package/cli/explorer/commands.d.ts +17 -0
- package/cli/explorer/commands.js +400 -162
- package/cli/explorer/commands.js.map +1 -0
- package/cli/explorer/featureViews.d.ts +124 -0
- package/cli/explorer/featureViews.js +179 -0
- package/cli/explorer/featureViews.js.map +1 -0
- package/cli/explorer/github.d.ts +21 -0
- package/cli/explorer/github.js +73 -0
- package/cli/explorer/github.js.map +1 -0
- package/cli/explorer/graphs.d.ts +7 -0
- package/cli/explorer/graphs.js +173 -0
- package/cli/explorer/graphs.js.map +1 -0
- package/cli/explorer/picker.d.ts +22 -0
- package/cli/explorer/picker.js +150 -0
- package/cli/explorer/picker.js.map +1 -0
- package/cli/explorer/report.d.ts +85 -0
- package/cli/explorer/report.js +60 -0
- package/cli/explorer/report.js.map +1 -0
- package/cli/explorer/session.d.ts +449 -0
- package/cli/explorer/session.js +184 -95
- package/cli/explorer/session.js.map +1 -0
- package/cli/explorer/views.d.ts +19 -0
- package/cli/explorer/views.js +496 -412
- package/cli/explorer/views.js.map +1 -0
- package/cli/explorer/wrap.d.ts +1 -0
- package/cli/explorer/wrap.js +33 -0
- package/cli/explorer/wrap.js.map +1 -0
- package/cli/main.d.ts +1 -0
- package/cli/main.js +235 -138
- package/cli/main.js.map +1 -0
- package/cli/prompt.d.ts +5 -0
- package/cli/prompt.js +84 -80
- package/cli/prompt.js.map +1 -0
- package/cli/scanOptions.d.ts +2 -0
- package/cli/scanOptions.js +11 -0
- package/cli/scanOptions.js.map +1 -0
- package/cli/ui.d.ts +33 -0
- package/cli/ui.js +55 -35
- package/cli/ui.js.map +1 -0
- package/cli/wizard.d.ts +187 -0
- package/cli/wizard.js +304 -284
- package/cli/wizard.js.map +1 -0
- package/package.json +15 -4
- package/public/app.d.ts +1 -0
- package/public/app.js +1057 -1009
- package/public/app.js.map +1 -0
- package/public/browser.d.ts +68 -0
- package/public/browser.js +2 -0
- package/public/browser.js.map +1 -0
- package/public/index.html +30 -13
- package/public/js/about.d.ts +6 -0
- package/public/js/about.js +165 -172
- package/public/js/about.js.map +1 -0
- package/public/js/aiDraft.d.ts +3 -0
- package/public/js/aiDraft.js +116 -124
- package/public/js/aiDraft.js.map +1 -0
- package/public/js/analysisPanel.d.ts +7 -0
- package/public/js/analysisPanel.js +166 -166
- package/public/js/analysisPanel.js.map +1 -0
- package/public/js/analysisReport.d.ts +38 -0
- package/public/js/analysisReport.js +105 -110
- package/public/js/analysisReport.js.map +1 -0
- package/public/js/api.d.ts +26 -0
- package/public/js/api.js +176 -167
- package/public/js/api.js.map +1 -0
- package/public/js/atlas.d.ts +6 -0
- package/public/js/atlas.js +50 -58
- package/public/js/atlas.js.map +1 -0
- package/public/js/blameView.d.ts +2 -0
- package/public/js/blameView.js +36 -37
- package/public/js/blameView.js.map +1 -0
- package/public/js/codeTab.d.ts +3 -0
- package/public/js/codeTab.js +175 -180
- package/public/js/codeTab.js.map +1 -0
- package/public/js/codeViewer.d.ts +5 -0
- package/public/js/codeViewer.js +162 -150
- package/public/js/codeViewer.js.map +1 -0
- package/public/js/components/FileChip.d.ts +9 -0
- package/public/js/components/FileChip.js +45 -49
- package/public/js/components/FileChip.js.map +1 -0
- package/public/js/components/MetricSparkline.d.ts +7 -0
- package/public/js/components/MetricSparkline.js +35 -44
- package/public/js/components/MetricSparkline.js.map +1 -0
- package/public/js/components/RiskBadge.d.ts +9 -0
- package/public/js/components/RiskBadge.js +55 -63
- package/public/js/components/RiskBadge.js.map +1 -0
- package/public/js/deepAnalysisView.d.ts +99 -0
- package/public/js/deepAnalysisView.js +282 -302
- package/public/js/deepAnalysisView.js.map +1 -0
- package/public/js/diagramPane.d.ts +8 -0
- package/public/js/diagramPane.js +133 -135
- package/public/js/diagramPane.js.map +1 -0
- package/public/js/diffView.d.ts +6 -0
- package/public/js/diffView.js +222 -209
- package/public/js/diffView.js.map +1 -0
- package/public/js/docsView.d.ts +2 -0
- package/public/js/docsView.js +441 -442
- package/public/js/docsView.js.map +1 -0
- package/public/js/dom.d.ts +189 -0
- package/public/js/dom.js +5 -0
- package/public/js/dom.js.map +1 -0
- package/public/js/fileSourceBrowser.d.ts +5 -0
- package/public/js/fileSourceBrowser.js +33 -41
- package/public/js/fileSourceBrowser.js.map +1 -0
- package/public/js/flameGraph.d.ts +5 -0
- package/public/js/flameGraph.js +62 -72
- package/public/js/flameGraph.js.map +1 -0
- package/public/js/forceGraph.d.ts +10 -0
- package/public/js/forceGraph.js +581 -556
- package/public/js/forceGraph.js.map +1 -0
- package/public/js/heatmap.d.ts +4 -0
- package/public/js/heatmap.js +142 -164
- package/public/js/heatmap.js.map +1 -0
- package/public/js/highlight.d.ts +2 -0
- package/public/js/highlight.js +116 -107
- package/public/js/highlight.js.map +1 -0
- package/public/js/html.d.ts +2 -0
- package/public/js/html.js +14 -44
- package/public/js/html.js.map +1 -0
- package/public/js/insightsView.d.ts +5 -0
- package/public/js/insightsView.js +93 -111
- package/public/js/insightsView.js.map +1 -0
- package/public/js/inspector.d.ts +37 -0
- package/public/js/inspector.js +416 -445
- package/public/js/inspector.js.map +1 -0
- package/public/js/llm.d.ts +113 -0
- package/public/js/llm.js +233 -272
- package/public/js/llm.js.map +1 -0
- package/public/js/mapView.d.ts +3 -0
- package/public/js/mapView.js +121 -120
- package/public/js/mapView.js.map +1 -0
- package/public/js/markdown.d.ts +3 -0
- package/public/js/markdown.js +84 -91
- package/public/js/markdown.js.map +1 -0
- package/public/js/mindmap.d.ts +32 -0
- package/public/js/mindmap.js +244 -259
- package/public/js/mindmap.js.map +1 -0
- package/public/js/mobilePanels.d.ts +5 -0
- package/public/js/mobilePanels.js +50 -0
- package/public/js/mobilePanels.js.map +1 -0
- package/public/js/repoFiles.d.ts +12 -0
- package/public/js/repoFiles.js +28 -27
- package/public/js/repoFiles.js.map +1 -0
- package/public/js/reviewView.d.ts +28 -0
- package/public/js/reviewView.js +256 -0
- package/public/js/reviewView.js.map +1 -0
- package/public/js/sbomView.d.ts +3 -0
- package/public/js/sbomView.js +59 -67
- package/public/js/sbomView.js.map +1 -0
- package/public/js/scanCache.d.ts +16 -0
- package/public/js/scanCache.js +67 -65
- package/public/js/scanCache.js.map +1 -0
- package/public/js/search.d.ts +7 -0
- package/public/js/search.js +868 -800
- package/public/js/search.js.map +1 -0
- package/public/js/searchLocal.d.ts +42 -0
- package/public/js/searchLocal.js +87 -0
- package/public/js/searchLocal.js.map +1 -0
- package/public/js/serverSettings.d.ts +5 -0
- package/public/js/serverSettings.js +153 -164
- package/public/js/serverSettings.js.map +1 -0
- package/public/js/state.d.ts +798 -0
- package/public/js/state.js +114 -122
- package/public/js/state.js.map +1 -0
- package/public/js/tour.d.ts +6 -0
- package/public/js/tour.js +5 -7
- package/public/js/tour.js.map +1 -0
- package/public/js/transitions.d.ts +2 -0
- package/public/js/transitions.js +9 -10
- package/public/js/transitions.js.map +1 -0
- package/public/js/tree.d.ts +12 -0
- package/public/js/tree.js +157 -154
- package/public/js/tree.js.map +1 -0
- package/public/js/workflowsView.d.ts +3 -0
- package/public/js/workflowsView.js +15 -22
- package/public/js/workflowsView.js.map +1 -0
- package/public/search.css +495 -0
- package/public/styles.css +163 -346
- package/public/workbench.css +166 -0
- package/server/apiAuth.d.ts +3 -0
- package/server/apiAuth.js +18 -20
- package/server/apiAuth.js.map +1 -0
- package/server/apiDiff.d.ts +2 -0
- package/server/apiDiff.js +20 -18
- package/server/apiDiff.js.map +1 -0
- package/server/apiDocs.d.ts +2 -0
- package/server/apiDocs.js +38 -40
- package/server/apiDocs.js.map +1 -0
- package/server/apiFile.d.ts +1 -0
- package/server/apiFile.js +14 -17
- package/server/apiFile.js.map +1 -0
- package/server/apiGitBlame.d.ts +2 -0
- package/server/apiGitBlame.js +50 -51
- package/server/apiGitBlame.js.map +1 -0
- package/server/apiMcp.d.ts +4 -0
- package/server/apiMcp.js +64 -66
- package/server/apiMcp.js.map +1 -0
- package/server/apiReview.d.ts +2 -0
- package/server/apiReview.js +45 -0
- package/server/apiReview.js.map +1 -0
- package/server/apiScan.d.ts +5 -0
- package/server/apiScan.js +90 -71
- package/server/apiScan.js.map +1 -0
- package/server/apiSearch.d.ts +33 -0
- package/server/apiSearch.js +184 -200
- package/server/apiSearch.js.map +1 -0
- package/server/apiSettings.d.ts +4 -0
- package/server/apiSettings.js +84 -85
- package/server/apiSettings.js.map +1 -0
- package/server/apiTools.d.ts +3 -0
- package/server/apiTools.js +55 -56
- package/server/apiTools.js.map +1 -0
- package/server/auth.d.ts +5 -0
- package/server/auth.js +54 -51
- package/server/auth.js.map +1 -0
- package/server/config.d.ts +42 -0
- package/server/config.js +189 -194
- package/server/config.js.map +1 -0
- package/server/daemon.d.ts +12 -0
- package/server/daemon.js +124 -114
- package/server/daemon.js.map +1 -0
- package/server/fileSourceNode.d.ts +2 -0
- package/server/fileSourceNode.js +34 -36
- package/server/fileSourceNode.js.map +1 -0
- package/server/gitClone.d.ts +9 -0
- package/server/gitClone.js +59 -61
- package/server/gitClone.js.map +1 -0
- package/server/gitDiff.d.ts +36 -0
- package/server/gitDiff.js +271 -169
- package/server/gitDiff.js.map +1 -0
- package/server/gitHistory.d.ts +12 -0
- package/server/gitHistory.js +80 -80
- package/server/gitHistory.js.map +1 -0
- package/server/gitRemote.d.ts +12 -0
- package/server/gitRemote.js +60 -0
- package/server/gitRemote.js.map +1 -0
- package/server/htmlText.d.ts +4 -0
- package/server/htmlText.js +16 -23
- package/server/htmlText.js.map +1 -0
- package/server/http.d.ts +5 -0
- package/server/http.js +27 -30
- package/server/http.js.map +1 -0
- package/server/httpGuards.d.ts +2 -0
- package/server/httpGuards.js +47 -43
- package/server/httpGuards.js.map +1 -0
- package/server/https.d.ts +34 -0
- package/server/https.js +121 -111
- package/server/https.js.map +1 -0
- package/server/index.d.ts +40 -0
- package/server/index.js +139 -147
- package/server/index.js.map +1 -0
- package/server/layout.d.ts +26 -0
- package/server/layout.js +59 -37
- package/server/layout.js.map +1 -0
- package/server/llmProxy.d.ts +3 -0
- package/server/llmProxy.js +137 -135
- package/server/llmProxy.js.map +1 -0
- package/server/logger.d.ts +38 -0
- package/server/logger.js +198 -211
- package/server/logger.js.map +1 -0
- package/server/mcp/analysis.d.ts +29 -0
- package/server/mcp/analysis.js +99 -120
- package/server/mcp/analysis.js.map +1 -0
- package/server/mcp/http.d.ts +9 -0
- package/server/mcp/http.js +128 -137
- package/server/mcp/http.js.map +1 -0
- package/server/mcp/runner.d.ts +68 -0
- package/server/mcp/runner.js +208 -218
- package/server/mcp/runner.js.map +1 -0
- package/server/mcp/server.d.ts +29 -0
- package/server/mcp/server.js +166 -179
- package/server/mcp/server.js.map +1 -0
- package/server/mcp/standalone.d.ts +1 -0
- package/server/mcp/standalone.js +8 -10
- package/server/mcp/standalone.js.map +1 -0
- package/server/mcp/tools.d.ts +2020 -0
- package/server/mcp/tools.js +523 -574
- package/server/mcp/tools.js.map +1 -0
- package/server/paths.d.ts +3 -0
- package/server/paths.js +17 -15
- package/server/paths.js.map +1 -0
- package/server/pidfile.d.ts +9 -0
- package/server/pidfile.js +43 -45
- package/server/pidfile.js.map +1 -0
- package/server/review.d.ts +5 -0
- package/server/review.js +35 -0
- package/server/review.js.map +1 -0
- package/server/router.d.ts +33 -0
- package/server/router.js +191 -197
- package/server/router.js.map +1 -0
- package/server/scanRequest.d.ts +3 -0
- package/server/scanRequest.js +36 -0
- package/server/scanRequest.js.map +1 -0
- package/server/searchIndex.d.ts +17 -0
- package/server/searchIndex.js +83 -80
- package/server/searchIndex.js.map +1 -0
- package/server/sessions.d.ts +14 -0
- package/server/sessions.js +62 -70
- package/server/sessions.js.map +1 -0
- package/server/startup.d.ts +118 -0
- package/server/startup.js +143 -148
- package/server/startup.js.map +1 -0
- package/server/static.d.ts +6 -0
- package/server/static.js +28 -31
- package/server/static.js.map +1 -0
- package/server/tools/install.d.ts +4 -0
- package/server/tools/install.js +176 -185
- package/server/tools/install.js.map +1 -0
- package/server/tools/parse.d.ts +8 -0
- package/server/tools/parse.js +112 -114
- package/server/tools/parse.js.map +1 -0
- package/server/tools/platform.d.ts +9 -0
- package/server/tools/platform.js +49 -47
- package/server/tools/platform.js.map +1 -0
- package/server/tools/registry.d.ts +137 -0
- package/server/tools/registry.js +173 -172
- package/server/tools/registry.js.map +1 -0
- package/server/tools/scan.d.ts +34 -0
- package/server/tools/scan.js +89 -98
- package/server/tools/scan.js.map +1 -0
- package/server/tools.d.ts +34 -0
- package/server/tools.js +94 -107
- package/server/tools.js.map +1 -0
- package/server/tunnel.d.ts +29 -0
- package/server/tunnel.js +61 -66
- package/server/tunnel.js.map +1 -0
- package/shared/analyzer/docs.d.ts +16 -0
- package/shared/analyzer/docs.js +99 -93
- package/shared/analyzer/docs.js.map +1 -0
- package/shared/analyzer/explainLocal.d.ts +4 -0
- package/shared/analyzer/explainLocal.js +122 -142
- package/shared/analyzer/explainLocal.js.map +1 -0
- package/shared/analyzer/github.d.ts +37 -0
- package/shared/analyzer/github.js +79 -0
- package/shared/analyzer/github.js.map +1 -0
- package/shared/analyzer/graph.d.ts +41 -0
- package/shared/analyzer/graph.js +393 -400
- package/shared/analyzer/graph.js.map +1 -0
- package/shared/analyzer/health.d.ts +33 -0
- package/shared/analyzer/health.js +197 -193
- package/shared/analyzer/health.js.map +1 -0
- package/shared/analyzer/history.d.ts +29 -0
- package/shared/analyzer/history.js +110 -111
- package/shared/analyzer/history.js.map +1 -0
- package/shared/analyzer/jsonConfig.d.ts +2 -0
- package/shared/analyzer/jsonConfig.js +61 -0
- package/shared/analyzer/jsonConfig.js.map +1 -0
- package/shared/analyzer/languages/csharp.d.ts +26 -0
- package/shared/analyzer/languages/csharp.js +83 -88
- package/shared/analyzer/languages/csharp.js.map +1 -0
- package/shared/analyzer/languages/generic.d.ts +23 -0
- package/shared/analyzer/languages/generic.js +94 -105
- package/shared/analyzer/languages/generic.js.map +1 -0
- package/shared/analyzer/languages/go.d.ts +24 -0
- package/shared/analyzer/languages/go.js +45 -54
- package/shared/analyzer/languages/go.js.map +1 -0
- package/shared/analyzer/languages/index.d.ts +6 -0
- package/shared/analyzer/languages/index.js +19 -20
- package/shared/analyzer/languages/index.js.map +1 -0
- package/shared/analyzer/languages/java.d.ts +20 -0
- package/shared/analyzer/languages/java.js +73 -78
- package/shared/analyzer/languages/java.js.map +1 -0
- package/shared/analyzer/languages/javascript.d.ts +12 -0
- package/shared/analyzer/languages/javascript.js +258 -209
- package/shared/analyzer/languages/javascript.js.map +1 -0
- package/shared/analyzer/languages/python.d.ts +23 -0
- package/shared/analyzer/languages/python.js +92 -100
- package/shared/analyzer/languages/python.js.map +1 -0
- package/shared/analyzer/languages/rust.d.ts +17 -0
- package/shared/analyzer/languages/rust.js +96 -98
- package/shared/analyzer/languages/rust.js.map +1 -0
- package/shared/analyzer/languages/typescript.d.ts +11 -0
- package/shared/analyzer/languages/typescript.js +117 -116
- package/shared/analyzer/languages/typescript.js.map +1 -0
- package/shared/analyzer/licenses.d.ts +18 -0
- package/shared/analyzer/licenses.js +130 -133
- package/shared/analyzer/licenses.js.map +1 -0
- package/shared/analyzer/metrics.d.ts +20 -0
- package/shared/analyzer/metrics.js +112 -104
- package/shared/analyzer/metrics.js.map +1 -0
- package/shared/analyzer/pathUtil.d.ts +10 -0
- package/shared/analyzer/pathUtil.js +29 -35
- package/shared/analyzer/pathUtil.js.map +1 -0
- package/shared/analyzer/patterns.d.ts +11 -0
- package/shared/analyzer/patterns.js +231 -253
- package/shared/analyzer/patterns.js.map +1 -0
- package/shared/analyzer/scan.d.ts +62 -0
- package/shared/analyzer/scan.js +451 -442
- package/shared/analyzer/scan.js.map +1 -0
- package/shared/analyzer/scanControl.d.ts +11 -0
- package/shared/analyzer/scanControl.js +62 -0
- package/shared/analyzer/scanControl.js.map +1 -0
- package/shared/analyzer/security.d.ts +18 -0
- package/shared/analyzer/security.js +159 -159
- package/shared/analyzer/security.js.map +1 -0
- package/shared/analyzer/services.d.ts +5 -0
- package/shared/analyzer/services.js +141 -138
- package/shared/analyzer/services.js.map +1 -0
- package/shared/analyzer/stack.d.ts +6 -0
- package/shared/analyzer/stack.js +134 -141
- package/shared/analyzer/stack.js.map +1 -0
- package/shared/analyzer/tour.d.ts +2 -0
- package/shared/analyzer/tour.js +45 -53
- package/shared/analyzer/tour.js.map +1 -0
- package/shared/analyzer/util.d.ts +8 -0
- package/shared/analyzer/util.js +130 -76
- package/shared/analyzer/util.js.map +1 -0
- package/shared/analyzer/workflows.d.ts +8 -0
- package/shared/analyzer/workflows.js +139 -134
- package/shared/analyzer/workflows.js.map +1 -0
- package/shared/contracts.d.ts +250 -0
- package/shared/contracts.js +2 -0
- package/shared/contracts.js.map +1 -0
- package/shared/diagram/aiFacts.d.ts +35 -0
- package/shared/diagram/aiFacts.js +102 -105
- package/shared/diagram/aiFacts.js.map +1 -0
- package/shared/diagram/aiMermaid.d.ts +5 -0
- package/shared/diagram/aiMermaid.js +46 -45
- package/shared/diagram/aiMermaid.js.map +1 -0
- package/shared/diagram/atlas.d.ts +16 -0
- package/shared/diagram/atlas.js +51 -60
- package/shared/diagram/atlas.js.map +1 -0
- package/shared/diagram/mermaid.d.ts +43 -0
- package/shared/diagram/mermaid.js +348 -370
- package/shared/diagram/mermaid.js.map +1 -0
- package/shared/review/contracts.d.ts +95 -0
- package/shared/review/contracts.js +2 -0
- package/shared/review/contracts.js.map +1 -0
- package/shared/review/review.d.ts +10 -0
- package/shared/review/review.js +184 -0
- package/shared/review/review.js.map +1 -0
- package/shared/search/query.d.ts +32 -0
- package/shared/search/query.js +395 -388
- package/shared/search/query.js.map +1 -0
package/cli/explorer/commands.js
CHANGED
|
@@ -9,189 +9,427 @@
|
|
|
9
9
|
// `run(ctx, args)` returns a string to print, or a marker the app layer acts on
|
|
10
10
|
// (`EXIT`, `CLEAR`). `args` is an array of already-parsed words, so quoting is
|
|
11
11
|
// handled once, in the tokenizer, and every command sees the same shape.
|
|
12
|
-
|
|
13
12
|
import * as V from './views.js';
|
|
14
|
-
|
|
13
|
+
import * as A from './advanced.js';
|
|
14
|
+
import { lineNumber, resolveTarget, fileFacts } from './session.js';
|
|
15
|
+
import { bold, cyan, dim, ok, fit, termWidth } from '../ui.js';
|
|
16
|
+
import { wrapText } from './wrap.js';
|
|
17
|
+
import { formatSbom, formatWorkflows, formatAtlas, formatInspector } from './featureViews.js';
|
|
18
|
+
import { execFile } from 'node:child_process';
|
|
19
|
+
import { promisify } from 'node:util';
|
|
20
|
+
const run = promisify(execFile);
|
|
15
21
|
export const EXIT = Symbol('exit');
|
|
16
22
|
export const CLEAR = Symbol('clear');
|
|
17
|
-
|
|
18
23
|
export const COMMANDS = [
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
24
|
+
{
|
|
25
|
+
name: 'help', aliases: ['?'], group: 'basics',
|
|
26
|
+
usage: 'help [command]', summary: 'This list, or everything about one command.',
|
|
27
|
+
// The topic is forwarded. `help find` used to ignore its argument and print
|
|
28
|
+
// the whole list, which reads as the command not working.
|
|
29
|
+
run: (ctx, args) => ctx.help(args.join(' ')),
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
name: 'map', aliases: ['overview', 'home'], group: 'basics',
|
|
33
|
+
usage: 'map', summary: 'What this repo is, and where to start.',
|
|
34
|
+
run: (ctx) => V.overview(ctx.repo),
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
name: 'tour', aliases: ['start', 'onboarding'], group: 'basics',
|
|
38
|
+
usage: 'tour', summary: 'The reading order a new teammate should follow.',
|
|
39
|
+
run: (ctx) => V.tour(ctx.repo),
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
name: 'explain', aliases: ['why', 'what'], group: 'basics',
|
|
43
|
+
usage: 'explain [file|folder]', summary: 'This repo, or one file/folder, in prose. No AI key needed.',
|
|
44
|
+
run: (ctx, args) => V.explain(ctx.repo, { target: args.join(' ') }),
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: 'tree', aliases: ['ls', 'files'], group: 'navigate',
|
|
48
|
+
usage: 'tree [folder] [depth]', summary: 'The file tree, with entries and hubs marked.',
|
|
49
|
+
run: (ctx, args) => {
|
|
50
|
+
// A lone number is the depth, not a folder called "2". `tree 3` is what
|
|
51
|
+
// everyone types when they want to see more; making them spell
|
|
52
|
+
// `tree . 3` would be pedantry in a tool built to be forgiving. `.` is the
|
|
53
|
+
// root, so it must not be taken as a folder name either.
|
|
54
|
+
const onlyDepth = args.length === 1 && /^\d+$/.test(args[0]);
|
|
55
|
+
const sub = onlyDepth ? '' : (args[0] || '');
|
|
56
|
+
return V.tree(ctx.repo, {
|
|
57
|
+
sub: sub === '.' ? '' : sub,
|
|
58
|
+
depth: onlyDepth ? Number(args[0]) : (Number(args[1]) || 2),
|
|
59
|
+
});
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
name: 'find', aliases: ['search', 'grep'], group: 'navigate',
|
|
64
|
+
usage: 'find <query>', summary: 'Search. Supports ext:js, -exclude, "phrases", /regex/.',
|
|
65
|
+
run: (ctx, args) => V.find(ctx.repo, { query: args.join(' ') }),
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
name: 'show', aliases: ['open', 'cat', 'read', 'code'], group: 'navigate',
|
|
69
|
+
usage: 'show <file> [from] [count]', summary: 'Read a file. Name it loosely: `show logger.js` works.',
|
|
70
|
+
run: (ctx, args) => V.show(ctx.repo, {
|
|
71
|
+
target: args[0] || '',
|
|
72
|
+
from: lineNumber(args[1], 0),
|
|
73
|
+
count: lineNumber(args[2], 0),
|
|
74
|
+
}),
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
name: 'deps', aliases: ['connections'], group: 'navigate',
|
|
78
|
+
usage: 'deps <file>', summary: 'What a file imports, and what imports it.',
|
|
79
|
+
run: (ctx, args) => V.deps(ctx.repo, { target: args.join(' ') }),
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
name: 'inspect', aliases: ['detail'], group: 'navigate',
|
|
83
|
+
usage: 'inspect <file>', summary: 'One file’s role, links, exports, and findings.',
|
|
84
|
+
run: (ctx, args) => {
|
|
85
|
+
const target = args.join(' ');
|
|
86
|
+
if (!target)
|
|
87
|
+
return ' Name a file: inspect path/to/file.js';
|
|
88
|
+
const found = resolveTarget(ctx.repo, target);
|
|
89
|
+
if (found.error)
|
|
90
|
+
return V.explain(ctx.repo, { target });
|
|
91
|
+
if (found.folder)
|
|
92
|
+
return V.explain(ctx.repo, { target });
|
|
93
|
+
const file = found.file;
|
|
94
|
+
return formatInspector({
|
|
95
|
+
path: file.path,
|
|
96
|
+
role: fileFacts(ctx.repo, file).role,
|
|
97
|
+
loc: file.loc || 0,
|
|
98
|
+
complexity: file.complexity || 0,
|
|
99
|
+
risk: ctx.repo.health.perFile.find((item) => item.path === file.path)?.risk || 0,
|
|
100
|
+
imports: ctx.repo.facts.importsOf[file.path] || [],
|
|
101
|
+
importers: ctx.repo.facts.importers[file.path] || [],
|
|
102
|
+
exports: file.exports || [],
|
|
103
|
+
findings: file.findings || [],
|
|
104
|
+
});
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
name: 'health', aliases: ['grade'], group: 'analyze',
|
|
109
|
+
usage: 'health', summary: 'Health grade, riskiest files, debt.',
|
|
110
|
+
run: (ctx) => V.health(ctx.repo),
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
name: 'hubs', aliases: ['core'], group: 'analyze',
|
|
114
|
+
usage: 'hubs', summary: 'The most depended-on files.',
|
|
115
|
+
run: (ctx) => V.hubs(ctx.repo),
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
name: 'layers', aliases: ['depth'], group: 'analyze',
|
|
119
|
+
usage: 'layers', summary: 'Import depth, shallowest first.',
|
|
120
|
+
run: (ctx) => V.layers(ctx.repo),
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
name: 'patterns', aliases: ['architecture'], group: 'analyze',
|
|
124
|
+
usage: 'patterns', summary: 'What the architecture looks like, in prose.',
|
|
125
|
+
run: (ctx) => V.patterns(ctx.repo),
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
name: 'stats', aliases: ['numbers'], group: 'analyze',
|
|
129
|
+
usage: 'stats', summary: 'Languages, biggest folders and files, complexity.',
|
|
130
|
+
run: (ctx) => V.stats(ctx.repo),
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
name: 'security', aliases: ['audit'], group: 'analyze',
|
|
134
|
+
usage: 'security', summary: 'Heuristic findings from the built-in rules.',
|
|
135
|
+
run: (ctx) => V.security(ctx.repo),
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
name: 'stack', aliases: ['packages', 'services'], group: 'analyze',
|
|
139
|
+
usage: 'stack', summary: 'Declared dependencies and frameworks.',
|
|
140
|
+
run: (ctx) => V.stack(ctx.repo),
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
name: 'entry', aliases: ['entries'], group: 'analyze',
|
|
144
|
+
usage: 'entry', summary: 'Recognized entry points and how far they reach.',
|
|
145
|
+
run: (ctx) => V.entry(ctx.repo),
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
name: 'externals', aliases: ['drift'], group: 'analyze',
|
|
149
|
+
usage: 'externals', summary: 'External packages, plus dependency drift.',
|
|
150
|
+
run: (ctx) => V.externals(ctx.repo),
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
name: 'graph', aliases: ['tree-graph'], group: 'navigate',
|
|
154
|
+
usage: 'graph <file> [depth]', summary: 'The dependency tree around a file, as arrows.',
|
|
155
|
+
run: (ctx, args) => A.graph(ctx.repo, { target: args[0] || '', depth: Number(args[1]) || 2 }),
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
name: 'blast', aliases: ['impact', 'radius'], group: 'navigate',
|
|
159
|
+
usage: 'blast <file>', summary: 'What breaks if this file breaks, transitively.',
|
|
160
|
+
run: (ctx, args) => A.blast(ctx.repo, { target: args.join(' ') }),
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
name: 'symbols', aliases: ['outline', 'functions'], group: 'navigate',
|
|
164
|
+
usage: 'symbols <file>', summary: 'Functions, classes and exports in a file.',
|
|
165
|
+
run: (ctx, args) => A.symbols(ctx.repo, { target: args.join(' ') }),
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
name: 'docs', aliases: ['document'], group: 'analyze',
|
|
169
|
+
usage: 'docs [file|folder] | docs --write', summary: 'Prose docs for a file, or write ONBOARDER.md.',
|
|
170
|
+
run: async (ctx, args) => {
|
|
171
|
+
// `--write` is the one command here that touches the filesystem. It is
|
|
172
|
+
// opt-in, explicit, and prints where it wrote — a map tool should never
|
|
173
|
+
// leave a file behind just because someone asked what the docs say.
|
|
174
|
+
if (args[0] === '--write') {
|
|
175
|
+
const abs = await A.writeDocs(ctx.repo, args[1] || 'ONBOARDER.md');
|
|
176
|
+
return ' ' + ok('Wrote ') + cyan(abs);
|
|
177
|
+
}
|
|
178
|
+
return A.docs(ctx.repo, { target: args.filter((a) => a !== '--write').join(' ') });
|
|
179
|
+
},
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
name: 'log', aliases: ['history', 'commits'], group: 'git',
|
|
183
|
+
usage: 'log [count]', summary: 'Recent commits, and who wrote them.',
|
|
184
|
+
run: (ctx, args) => A.log(ctx.repo, { limit: Number(args[0]) || 15 }),
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
name: 'hotspots', aliases: ['churn'], group: 'git',
|
|
188
|
+
usage: 'hotspots [count]', summary: 'Files that are both complex and frequently changed.',
|
|
189
|
+
run: (ctx, args) => A.hotspots(ctx.repo, { limit: Number(args[0]) || 12 }),
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
name: 'blame', aliases: ['authors'], group: 'git',
|
|
193
|
+
usage: 'blame <file>', summary: 'Who wrote each line of a file.',
|
|
194
|
+
run: (ctx, args) => A.blame(ctx.repo, { target: args.join(' ') }),
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
name: 'coupling', aliases: ['matrix', 'heatmap'], group: 'analyze',
|
|
198
|
+
usage: 'coupling', summary: 'Folder-to-folder import traffic, as a heat grid.',
|
|
199
|
+
run: (ctx) => A.coupling(ctx.repo),
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
name: 'clusters', aliases: ['communities', 'modules'], group: 'analyze',
|
|
203
|
+
usage: 'clusters', summary: 'Groups of files that import each other more than the rest.',
|
|
204
|
+
run: (ctx) => A.clusters(ctx.repo),
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
name: 'diagram', aliases: ['mermaid'], group: 'analyze',
|
|
208
|
+
usage: 'diagram [file]', summary: 'Mermaid source for the repo, or one file.',
|
|
209
|
+
run: (ctx, args) => A.diagram(ctx.repo, { target: args.join(' ') }),
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
name: 'layers-diagram', aliases: [], group: 'analyze',
|
|
213
|
+
usage: 'layers-diagram', summary: 'Mermaid source for the layer stack.',
|
|
214
|
+
run: (ctx) => A.layerDiagram(ctx.repo),
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
name: 'risks', aliases: ['problems', 'smells', 'insights'], group: 'analyze',
|
|
218
|
+
usage: 'risks', summary: 'Cycles, orphans, dead exports, drift — in one list.',
|
|
219
|
+
run: (ctx) => A.risks(ctx.repo),
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
name: 'workflows', aliases: ['ci', 'pipelines'], group: 'analyze',
|
|
223
|
+
usage: 'workflows', summary: 'GitHub Actions triggers, jobs, and steps.',
|
|
224
|
+
run: (ctx) => formatWorkflows(ctx.repo.scan.workflows || []),
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
name: 'atlas', aliases: ['diagrams'], group: 'analyze',
|
|
228
|
+
usage: 'atlas', summary: 'An index of useful repository and file diagrams.',
|
|
229
|
+
run: (ctx) => formatAtlas(ctx.repo.facts.entries, ctx.repo.facts.hubs, ctx.repo.scan.folders),
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
name: 'sbom', aliases: ['licenses', 'inventory'], group: 'analyze',
|
|
233
|
+
usage: 'sbom [filter]', summary: 'Declared dependencies and inferred license inventory.',
|
|
234
|
+
run: (ctx, args) => formatSbom(ctx.repo.scan.licenseReport, args.join(' ')),
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
name: 'diff', aliases: ['changes'], group: 'git',
|
|
238
|
+
usage: 'diff [base] [head] [file]', summary: 'Git changes, patch, and dependent-file impact.',
|
|
239
|
+
run: (ctx, args) => ctx.diff(args[0] || 'HEAD', args[1] || '', args[2] || ''),
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
name: 'engines', aliases: ['analyzers'], group: 'analyze',
|
|
243
|
+
usage: 'engines', summary: 'Show available external analyzers and how to install them.',
|
|
244
|
+
run: (ctx) => ctx.engines(),
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
name: 'deep', aliases: ['deep-analysis'], group: 'analyze',
|
|
248
|
+
usage: 'deep <engine|all>', summary: 'Run an optional analyzer and show its findings.',
|
|
249
|
+
run: (ctx, args) => args[0] ? ctx.deep(args[0]) : ctx.engines(),
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
name: 'ask', aliases: ['ai'], group: 'basics',
|
|
253
|
+
usage: 'ask <question>', summary: 'Ask an optional OpenAI-compatible model about this repo.',
|
|
254
|
+
run: (ctx, args) => ctx.ask(args.join(' ')),
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
name: 'about', aliases: ['version'], group: 'session',
|
|
258
|
+
usage: 'about', summary: 'Version, repo path, and what is indexed.',
|
|
259
|
+
run: (ctx) => V.about(ctx.repo, ctx.version),
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
name: 'rescan', aliases: ['reload'], group: 'session',
|
|
263
|
+
usage: 'rescan', summary: 'Re-read the repo from disk.',
|
|
264
|
+
run: (ctx) => ctx.rescan(),
|
|
265
|
+
},
|
|
266
|
+
{
|
|
267
|
+
name: 'github', aliases: ['remote', 'repo'], group: 'session',
|
|
268
|
+
usage: 'github', summary: "What GitHub says about this repo — stars, issues, license.",
|
|
269
|
+
run: (ctx) => ctx.github(),
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
name: 'cd', aliases: ['open-repo', 'use'], group: 'session',
|
|
273
|
+
usage: 'cd [folder|url]', summary: 'Choose a folder, or load one by path or Git URL.',
|
|
274
|
+
run: (ctx, args) => args.length ? ctx.loadRepo(args.join(' ')) : ctx.selectSource(),
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
name: 'pick', aliases: ['browse'], group: 'session',
|
|
278
|
+
usage: 'pick', summary: 'Browse device folders or paste a Git URL.',
|
|
279
|
+
run: (ctx) => ctx.selectSource(),
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
name: 'web', aliases: ['site', 'serve'], group: 'session',
|
|
283
|
+
usage: 'web', summary: 'Start the web UI and print its URL.',
|
|
284
|
+
run: (ctx) => ctx.web(),
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
name: 'clear', aliases: ['cls'], group: 'session',
|
|
288
|
+
usage: 'clear', summary: 'Clear the screen.',
|
|
289
|
+
run: () => CLEAR,
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
name: 'exit', aliases: ['quit', 'q'], group: 'session',
|
|
293
|
+
usage: 'exit', summary: 'Leave. Ctrl-D does the same.',
|
|
294
|
+
run: () => EXIT,
|
|
295
|
+
},
|
|
143
296
|
];
|
|
144
|
-
|
|
145
297
|
// One lookup for every spelling a person might type, built once at import.
|
|
146
298
|
const BY_NAME = new Map();
|
|
147
299
|
for (const cmd of COMMANDS) {
|
|
148
|
-
|
|
149
|
-
|
|
300
|
+
BY_NAME.set(cmd.name, cmd);
|
|
301
|
+
for (const a of cmd.aliases)
|
|
302
|
+
BY_NAME.set(a, cmd);
|
|
150
303
|
}
|
|
151
|
-
|
|
152
304
|
export function lookup(word) {
|
|
153
|
-
|
|
305
|
+
return BY_NAME.get(String(word || '').toLowerCase());
|
|
154
306
|
}
|
|
155
|
-
|
|
156
307
|
// Every canonical name, for "did you mean" matching. Aliases are deliberately
|
|
157
308
|
// excluded: suggesting `open` when someone typed `sho` is less useful than
|
|
158
309
|
// suggesting `show`, which is the word they were reaching for.
|
|
159
310
|
export function commandNames() {
|
|
160
|
-
|
|
311
|
+
return COMMANDS.map((c) => c.name);
|
|
161
312
|
}
|
|
162
|
-
|
|
163
313
|
// `help <command>` answers about one command; bare `help` lists them, grouped so
|
|
164
|
-
// the shape of the tool is visible rather than alphabetical.
|
|
314
|
+
// the shape of the tool is visible rather than alphabetical. Every row is
|
|
315
|
+
// fitted, because a long summary on a narrow terminal used to wrap into the
|
|
316
|
+
// next row and make the list unreadable.
|
|
165
317
|
export function helpText(ctx, topic = '') {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
318
|
+
const w = termWidth();
|
|
319
|
+
if (topic) {
|
|
320
|
+
const cmd = lookup(topic);
|
|
321
|
+
if (!cmd)
|
|
322
|
+
return fit(` No command called "${topic}". Try \`help\`.`, Math.max(10, w - 2));
|
|
323
|
+
const also = cmd.aliases.length ? ` (also: ${cmd.aliases.join(', ')})` : '';
|
|
324
|
+
return [
|
|
325
|
+
fit(' ' + cmd.usage + also, Math.max(10, w - 2)),
|
|
326
|
+
wrapText(cmd.summary, ' '),
|
|
327
|
+
].join('\n');
|
|
328
|
+
}
|
|
329
|
+
const groups = new Map();
|
|
330
|
+
for (const cmd of COMMANDS) {
|
|
331
|
+
if (!groups.has(cmd.group))
|
|
332
|
+
groups.set(cmd.group, []);
|
|
333
|
+
groups.get(cmd.group).push(cmd);
|
|
334
|
+
}
|
|
335
|
+
// Two cells of indent, two of gap, and the summary gets whatever is left. The
|
|
336
|
+
// usage column shrinks with the terminal rather than pushing the text off it.
|
|
337
|
+
const longest = Math.max(...COMMANDS.map((c) => c.usage.length));
|
|
338
|
+
const usageRoom = Math.max(8, Math.min(longest, Math.floor(w * 0.4)));
|
|
339
|
+
const out = [];
|
|
340
|
+
for (const [group, list] of groups) {
|
|
341
|
+
out.push(fit(' ' + group.toUpperCase(), Math.max(10, w - 2)));
|
|
342
|
+
for (const c of list) {
|
|
343
|
+
const left = ' ' + fit(c.usage, usageRoom);
|
|
344
|
+
const room = w - left.length - 2;
|
|
345
|
+
out.push(room > 8 ? left + ' ' + fit(c.summary, room, { tail: false }) : left);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
out.push('');
|
|
349
|
+
out.push(fit(' ' + (ctx?.repo ? ctx.repo.name : 'onboarder')
|
|
350
|
+
+ ' · Ctrl-D or `exit` to leave · Ctrl-C twice to quit', Math.max(10, w - 2)));
|
|
351
|
+
return out.join('\n');
|
|
186
352
|
}
|
|
187
|
-
|
|
188
353
|
// Split a typed line into words, honoring quotes so `find "exact phrase"` and
|
|
189
354
|
// `show "my file.js"` arrive as one argument each. Done once, here, so no
|
|
190
355
|
// command has to re-implement it.
|
|
191
356
|
export function tokenize(line) {
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
357
|
+
const out = [];
|
|
358
|
+
const re = /"([^"]*)"|'([^']*)'|(\S+)/g;
|
|
359
|
+
let m;
|
|
360
|
+
while ((m = re.exec(String(line || ''))))
|
|
361
|
+
out.push(m[1] ?? m[2] ?? m[3]);
|
|
362
|
+
return out;
|
|
363
|
+
}
|
|
364
|
+
// Tab completion, because a REPL where you retype `shared/analyzer/graph.js` one
|
|
365
|
+
// letter at a time is not a REPL, it is a punishment.
|
|
366
|
+
//
|
|
367
|
+
// Two contexts, chosen by what is already typed. Before the first space, the line
|
|
368
|
+
// is a command name, so it completes against the command table — including
|
|
369
|
+
// aliases, because a person who types `ls` wants `tree` to finish. After a space,
|
|
370
|
+
// it is an argument, so it completes against real file paths in the loaded repo,
|
|
371
|
+
// which is the thing that is tedious to type and impossible to remember.
|
|
372
|
+
//
|
|
373
|
+
// `shellEscape` is the other half of a good REPL: `!git status` runs a shell
|
|
374
|
+
// command and hands the output back, so nobody has to leave the session to run
|
|
375
|
+
// one thing. It is deliberately the *only* way out to a shell, so the set of
|
|
376
|
+
// things that can happen in a session stays legible.
|
|
377
|
+
function completer(repo) {
|
|
378
|
+
return function complete(line) {
|
|
379
|
+
const trailingSpace = /\s$/.test(line);
|
|
380
|
+
const parts = line.split(/\s+/);
|
|
381
|
+
// Completing a command (no space yet, or trailing space after one word).
|
|
382
|
+
if (parts.length <= 1 || (parts.length === 2 && trailingSpace)) {
|
|
383
|
+
const hits = [...BY_NAME.keys()].filter((n) => n.startsWith(parts[0] || '')).sort();
|
|
384
|
+
return [hits.length ? hits : parts, parts[0] || ''];
|
|
385
|
+
}
|
|
386
|
+
// Completing a path argument against the loaded repo. Matches at any depth,
|
|
387
|
+
// not just from the root: `show rend` should find `src/render.js`, which is
|
|
388
|
+
// the case the resolver's forgiving path lookup already handles — the
|
|
389
|
+
// completer has to agree with it or Tab contradicts what the command does.
|
|
390
|
+
const frag = parts[parts.length - 1] || '';
|
|
391
|
+
const slash = frag.lastIndexOf('/');
|
|
392
|
+
const dir = slash === -1 ? '' : frag.slice(0, slash + 1);
|
|
393
|
+
const base = slash === -1 ? frag : frag.slice(slash + 1);
|
|
394
|
+
const seen = new Set();
|
|
395
|
+
const hits = [];
|
|
396
|
+
for (const f of repo.scan.allFiles || repo.scan.files) {
|
|
397
|
+
if (dir && !f.startsWith(dir))
|
|
398
|
+
continue;
|
|
399
|
+
// With no directory typed, match the *last* segment so `rend` finds
|
|
400
|
+
// `src/render.js`; with one typed, match the segment being completed.
|
|
401
|
+
const name = dir ? f.slice(dir.length) : f.slice(f.lastIndexOf('/') + 1);
|
|
402
|
+
if (!name.startsWith(base))
|
|
403
|
+
continue;
|
|
404
|
+
if (seen.has(name))
|
|
405
|
+
continue;
|
|
406
|
+
seen.add(name);
|
|
407
|
+
hits.push(name);
|
|
408
|
+
if (hits.length >= 200)
|
|
409
|
+
break;
|
|
410
|
+
}
|
|
411
|
+
return [hits.length ? hits : [frag], frag];
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
// Run a shell command and capture its output. A non-zero exit is not a crash —
|
|
415
|
+
// `grep` that finds nothing is a normal answer — so the code is reported, not
|
|
416
|
+
// thrown. There is no `shell: true`: the whole line is the argument vector, so
|
|
417
|
+
// nothing in a filename can be interpreted as a second command.
|
|
418
|
+
async function shellEscape(line, cwd) {
|
|
419
|
+
const parts = tokenize(line);
|
|
420
|
+
if (!parts.length)
|
|
421
|
+
return null;
|
|
422
|
+
try {
|
|
423
|
+
const { stdout, stderr } = await run(parts[0], parts.slice(1), { cwd, maxBuffer: 8 * 1024 * 1024 });
|
|
424
|
+
const out = String(stdout || '').trimEnd();
|
|
425
|
+
const err = String(stderr || '').trimEnd();
|
|
426
|
+
return [out, err].filter(Boolean).join('\n') || dim(' (no output)');
|
|
427
|
+
}
|
|
428
|
+
catch (e) {
|
|
429
|
+
const code = e.code ?? e.status;
|
|
430
|
+
const err = String(e.stderr || '').trimEnd() || String(e.message || '').trimEnd();
|
|
431
|
+
return dim(' exit ' + (code ?? '?') + (err ? '\n ' + err : ''));
|
|
432
|
+
}
|
|
197
433
|
}
|
|
434
|
+
export { completer, shellEscape };
|
|
435
|
+
//# sourceMappingURL=commands.js.map
|