@travisennis/acai 0.0.9 → 0.0.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 +49 -762
- package/bin/acai +52 -0
- package/dist/agent/index.d.ts +12 -2
- package/dist/agent/index.d.ts.map +1 -1
- package/dist/agent/index.js +378 -199
- package/dist/agent/sub-agent.d.ts +23 -0
- package/dist/agent/sub-agent.d.ts.map +1 -0
- package/dist/agent/sub-agent.js +109 -0
- package/dist/cli/index.d.ts +26 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/{cli.js → cli/index.js} +84 -77
- package/dist/cli/stdin.d.ts.map +1 -0
- package/dist/{stdin.js → cli/stdin.js} +11 -0
- package/dist/commands/copy/index.js +2 -2
- package/dist/commands/copy/utils.d.ts.map +1 -1
- package/dist/commands/copy/utils.js +15 -13
- package/dist/commands/generate-rules/index.d.ts +1 -1
- package/dist/commands/generate-rules/index.d.ts.map +1 -1
- package/dist/commands/generate-rules/index.js +16 -101
- package/dist/commands/generate-rules/service.d.ts +21 -0
- package/dist/commands/generate-rules/service.d.ts.map +1 -0
- package/dist/commands/generate-rules/service.js +103 -0
- package/dist/commands/handoff/index.js +2 -2
- package/dist/commands/health/index.js +1 -1
- package/dist/commands/health/utils.d.ts.map +1 -1
- package/dist/commands/health/utils.js +6 -0
- package/dist/commands/history/index.d.ts +1 -1
- package/dist/commands/history/index.d.ts.map +1 -1
- package/dist/commands/history/index.js +17 -18
- package/dist/commands/history/types.d.ts +38 -0
- package/dist/commands/history/types.d.ts.map +1 -1
- package/dist/commands/history/utils.d.ts.map +1 -1
- package/dist/commands/history/utils.js +63 -58
- package/dist/commands/init/index.d.ts.map +1 -1
- package/dist/commands/init/index.js +3 -8
- package/dist/commands/init-project/index.d.ts.map +1 -1
- package/dist/commands/init-project/index.js +3 -3
- package/dist/commands/init-project/utils.d.ts.map +1 -1
- package/dist/commands/init-project/utils.js +10 -2
- package/dist/commands/list-tools/index.d.ts.map +1 -1
- package/dist/commands/list-tools/index.js +7 -31
- package/dist/commands/manager.d.ts +2 -2
- package/dist/commands/manager.d.ts.map +1 -1
- package/dist/commands/manager.js +55 -33
- package/dist/commands/model/index.d.ts.map +1 -1
- package/dist/commands/model/index.js +20 -151
- package/dist/commands/model/model-panel.d.ts +4 -0
- package/dist/commands/model/model-panel.d.ts.map +1 -0
- package/dist/commands/model/model-panel.js +144 -0
- package/dist/commands/paste/index.d.ts.map +1 -1
- package/dist/commands/paste/index.js +59 -62
- package/dist/commands/paste/utils.d.ts.map +1 -1
- package/dist/commands/paste/utils.js +88 -58
- package/dist/commands/pickup/index.d.ts.map +1 -1
- package/dist/commands/pickup/index.js +6 -3
- package/dist/commands/pickup/utils.js +3 -3
- package/dist/commands/resources/index.d.ts.map +1 -1
- package/dist/commands/resources/index.js +33 -50
- package/dist/commands/review/index.d.ts.map +1 -1
- package/dist/commands/review/index.js +3 -117
- package/dist/commands/review/review-panel.d.ts +3 -0
- package/dist/commands/review/review-panel.d.ts.map +1 -0
- package/dist/commands/review/review-panel.js +186 -0
- package/dist/commands/review/utils.d.ts +9 -0
- package/dist/commands/review/utils.d.ts.map +1 -1
- package/dist/commands/review/utils.js +127 -68
- package/dist/commands/session/index.d.ts +1 -1
- package/dist/commands/session/index.d.ts.map +1 -1
- package/dist/commands/session/index.js +124 -135
- package/dist/commands/shell/index.d.ts.map +1 -1
- package/dist/commands/shell/index.js +16 -1
- package/dist/commands/types.d.ts +2 -2
- package/dist/commands/types.d.ts.map +1 -1
- package/dist/{config.d.ts → config/index.d.ts} +20 -9
- package/dist/config/index.d.ts.map +1 -0
- package/dist/{config.js → config/index.js} +43 -42
- package/dist/execution/index.d.ts.map +1 -1
- package/dist/execution/index.js +75 -55
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +148 -141
- package/dist/middleware/cache.d.ts.map +1 -1
- package/dist/middleware/cache.js +18 -36
- package/dist/models/ai-config.d.ts +1 -0
- package/dist/models/ai-config.d.ts.map +1 -1
- package/dist/models/ai-config.js +4 -3
- package/dist/models/anthropic-provider.d.ts +2 -5
- package/dist/models/anthropic-provider.d.ts.map +1 -1
- package/dist/models/anthropic-provider.js +3 -70
- package/dist/models/deepseek-provider.d.ts +1 -0
- package/dist/models/deepseek-provider.d.ts.map +1 -1
- package/dist/models/google-provider.d.ts +2 -3
- package/dist/models/google-provider.d.ts.map +1 -1
- package/dist/models/google-provider.js +0 -26
- package/dist/models/groq-provider.d.ts +1 -0
- package/dist/models/groq-provider.d.ts.map +1 -1
- package/dist/models/manager.d.ts +13 -2
- package/dist/models/manager.d.ts.map +1 -1
- package/dist/models/manager.js +20 -8
- package/dist/models/openai-provider.d.ts +2 -5
- package/dist/models/openai-provider.d.ts.map +1 -1
- package/dist/models/openai-provider.js +0 -52
- package/dist/models/opencode-zen-provider.d.ts +7 -3
- package/dist/models/opencode-zen-provider.d.ts.map +1 -1
- package/dist/models/opencode-zen-provider.js +49 -10
- package/dist/models/openrouter-provider.d.ts +24 -31
- package/dist/models/openrouter-provider.d.ts.map +1 -1
- package/dist/models/openrouter-provider.js +84 -182
- package/dist/models/providers.d.ts +1 -1
- package/dist/models/providers.d.ts.map +1 -1
- package/dist/models/xai-provider.d.ts +4 -3
- package/dist/models/xai-provider.d.ts.map +1 -1
- package/dist/models/xai-provider.js +18 -18
- package/dist/modes/manager.d.ts +23 -0
- package/dist/modes/manager.d.ts.map +1 -0
- package/dist/modes/manager.js +77 -0
- package/dist/modes/prompts.d.ts +2 -0
- package/dist/modes/prompts.d.ts.map +1 -0
- package/dist/modes/prompts.js +143 -0
- package/dist/prompts/mentions.d.ts +11 -0
- package/dist/prompts/mentions.d.ts.map +1 -0
- package/dist/{mentions.js → prompts/mentions.js} +21 -80
- package/dist/{prompts.d.ts → prompts/system-prompt.d.ts} +7 -2
- package/dist/prompts/system-prompt.d.ts.map +1 -0
- package/dist/{prompts.js → prompts/system-prompt.js} +31 -16
- package/dist/repl/index.d.ts +174 -0
- package/dist/repl/index.d.ts.map +1 -0
- package/dist/{repl-new.js → repl/index.js} +389 -76
- package/dist/repl/project-status.d.ts +1 -0
- package/dist/repl/project-status.d.ts.map +1 -1
- package/dist/repl/project-status.js +4 -1
- package/dist/sessions/manager.d.ts +93 -1
- package/dist/sessions/manager.d.ts.map +1 -1
- package/dist/sessions/manager.js +262 -9
- package/dist/sessions/summary.d.ts +4 -0
- package/dist/sessions/summary.d.ts.map +1 -0
- package/dist/sessions/summary.js +30 -0
- package/dist/{skills.d.ts → skills/index.d.ts} +14 -2
- package/dist/skills/index.d.ts.map +1 -0
- package/dist/skills/index.js +294 -0
- package/dist/subagents/index.d.ts +15 -0
- package/dist/subagents/index.d.ts.map +1 -0
- package/dist/subagents/index.js +231 -0
- package/dist/terminal/control.d.ts +1 -1
- package/dist/terminal/control.d.ts.map +1 -1
- package/dist/terminal/control.js +3 -3
- package/dist/terminal/east-asian-width.d.ts.map +1 -1
- package/dist/terminal/east-asian-width.js +404 -351
- package/dist/terminal/keys.d.ts +17 -0
- package/dist/terminal/keys.d.ts.map +1 -1
- package/dist/terminal/keys.js +37 -0
- package/dist/terminal/select-prompt.d.ts.map +1 -1
- package/dist/terminal/select-prompt.js +24 -12
- package/dist/terminal/string-width.d.ts.map +1 -1
- package/dist/terminal/string-width.js +25 -27
- package/dist/terminal/style.d.ts.map +1 -1
- package/dist/terminal/style.js +4 -7
- package/dist/terminal/supports-color.d.ts.map +1 -1
- package/dist/terminal/supports-color.js +41 -27
- package/dist/terminal/table/cell.d.ts +12 -0
- package/dist/terminal/table/cell.d.ts.map +1 -1
- package/dist/terminal/table/cell.js +40 -25
- package/dist/terminal/table/layout-manager.d.ts.map +1 -1
- package/dist/terminal/table/layout-manager.js +100 -68
- package/dist/terminal/table/utils.d.ts.map +1 -1
- package/dist/terminal/table/utils.js +17 -10
- package/dist/terminal/wrap-ansi.d.ts.map +1 -1
- package/dist/terminal/wrap-ansi.js +172 -103
- package/dist/tokens/tracker.d.ts +1 -0
- package/dist/tokens/tracker.d.ts.map +1 -1
- package/dist/tokens/tracker.js +3 -0
- package/dist/tools/agent.d.ts +27 -0
- package/dist/tools/agent.d.ts.map +1 -0
- package/dist/tools/agent.js +81 -0
- package/dist/tools/bash.d.ts +4 -3
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/tools/bash.js +324 -137
- package/dist/tools/code-search.d.ts +41 -0
- package/dist/tools/code-search.d.ts.map +1 -0
- package/dist/tools/code-search.js +195 -0
- package/dist/tools/directory-tree.d.ts +3 -3
- package/dist/tools/directory-tree.d.ts.map +1 -1
- package/dist/tools/directory-tree.js +8 -5
- package/dist/tools/dynamic-tool-loader.d.ts +2 -5
- package/dist/tools/dynamic-tool-loader.d.ts.map +1 -1
- package/dist/tools/dynamic-tool-loader.js +20 -4
- package/dist/tools/edit-file.d.ts +7 -7
- package/dist/tools/edit-file.d.ts.map +1 -1
- package/dist/tools/edit-file.js +164 -66
- package/dist/tools/glob.d.ts +6 -6
- package/dist/tools/glob.d.ts.map +1 -1
- package/dist/tools/glob.js +95 -55
- package/dist/tools/grep.d.ts +15 -12
- package/dist/tools/grep.d.ts.map +1 -1
- package/dist/tools/grep.js +300 -192
- package/dist/tools/index.d.ts +143 -5
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +39 -24
- package/dist/tools/ls.d.ts +2 -2
- package/dist/tools/ls.d.ts.map +1 -1
- package/dist/tools/ls.js +7 -5
- package/dist/tools/read-file.d.ts +3 -3
- package/dist/tools/read-file.d.ts.map +1 -1
- package/dist/tools/read-file.js +74 -34
- package/dist/tools/save-file.d.ts +3 -3
- package/dist/tools/save-file.d.ts.map +1 -1
- package/dist/tools/save-file.js +11 -11
- package/dist/tools/skill.d.ts +23 -0
- package/dist/tools/skill.d.ts.map +1 -0
- package/dist/tools/skill.js +65 -0
- package/dist/tools/think.d.ts.map +1 -1
- package/dist/tools/think.js +2 -9
- package/dist/tools/utils.d.ts +2 -0
- package/dist/tools/utils.d.ts.map +1 -1
- package/dist/tools/utils.js +12 -0
- package/dist/tools/web-fetch.d.ts +62 -0
- package/dist/tools/web-fetch.d.ts.map +1 -0
- package/dist/tools/web-fetch.js +429 -0
- package/dist/tools/web-search.d.ts +62 -0
- package/dist/tools/web-search.d.ts.map +1 -0
- package/dist/tools/web-search.js +226 -0
- package/dist/tui/autocomplete/attachment-provider.d.ts +3 -6
- package/dist/tui/autocomplete/attachment-provider.d.ts.map +1 -1
- package/dist/tui/autocomplete/attachment-provider.js +25 -78
- package/dist/tui/autocomplete/base-provider.d.ts +1 -0
- package/dist/tui/autocomplete/base-provider.d.ts.map +1 -1
- package/dist/tui/autocomplete/combined-provider.d.ts +1 -4
- package/dist/tui/autocomplete/combined-provider.d.ts.map +1 -1
- package/dist/tui/autocomplete/combined-provider.js +3 -17
- package/dist/tui/autocomplete/command-provider.d.ts +1 -0
- package/dist/tui/autocomplete/command-provider.d.ts.map +1 -1
- package/dist/tui/autocomplete/command-provider.js +3 -0
- package/dist/tui/autocomplete/file-search-provider.d.ts +2 -1
- package/dist/tui/autocomplete/file-search-provider.d.ts.map +1 -1
- package/dist/tui/autocomplete/file-search-provider.js +36 -16
- package/dist/tui/autocomplete/skill-provider.d.ts +17 -0
- package/dist/tui/autocomplete/skill-provider.d.ts.map +1 -0
- package/dist/tui/autocomplete/skill-provider.js +49 -0
- package/dist/tui/autocomplete.d.ts +2 -2
- package/dist/tui/autocomplete.d.ts.map +1 -1
- package/dist/tui/autocomplete.js +3 -5
- package/dist/tui/components/assistant-message.d.ts.map +1 -1
- package/dist/tui/components/assistant-message.js +0 -4
- package/dist/tui/components/editor.d.ts +16 -2
- package/dist/tui/components/editor.d.ts.map +1 -1
- package/dist/tui/components/editor.js +211 -237
- package/dist/tui/components/footer.d.ts +6 -4
- package/dist/tui/components/footer.d.ts.map +1 -1
- package/dist/tui/components/footer.js +49 -25
- package/dist/tui/components/markdown.d.ts +8 -5
- package/dist/tui/components/markdown.d.ts.map +1 -1
- package/dist/tui/components/markdown.js +57 -39
- package/dist/tui/components/modal.d.ts.map +1 -1
- package/dist/tui/components/modal.js +35 -33
- package/dist/tui/components/notification.d.ts +13 -2
- package/dist/tui/components/notification.d.ts.map +1 -1
- package/dist/tui/components/notification.js +36 -2
- package/dist/tui/components/progress-bar.js +1 -1
- package/dist/tui/components/select-list.d.ts +1 -0
- package/dist/tui/components/select-list.d.ts.map +1 -1
- package/dist/tui/components/select-list.js +14 -11
- package/dist/tui/components/text.d.ts +16 -0
- package/dist/tui/components/text.d.ts.map +1 -1
- package/dist/tui/components/text.js +72 -57
- package/dist/tui/components/thinking-block.d.ts +9 -0
- package/dist/tui/components/thinking-block.d.ts.map +1 -1
- package/dist/tui/components/thinking-block.js +43 -11
- package/dist/tui/components/tool-execution.d.ts +5 -1
- package/dist/tui/components/tool-execution.d.ts.map +1 -1
- package/dist/tui/components/tool-execution.js +19 -10
- package/dist/tui/components/user-message.d.ts.map +1 -1
- package/dist/tui/components/user-message.js +0 -3
- package/dist/tui/components/welcome.js +2 -2
- package/dist/tui/terminal.d.ts.map +1 -1
- package/dist/tui/terminal.js +10 -2
- package/dist/tui/tui.d.ts +42 -0
- package/dist/tui/tui.d.ts.map +1 -1
- package/dist/tui/tui.js +157 -41
- package/dist/utils/bash/parse.d.ts +19 -0
- package/dist/utils/bash/parse.d.ts.map +1 -0
- package/dist/utils/bash/parse.js +223 -0
- package/dist/utils/bash/quote.d.ts +6 -0
- package/dist/utils/bash/quote.d.ts.map +1 -0
- package/dist/utils/bash/quote.js +23 -0
- package/dist/utils/bash.d.ts.map +1 -1
- package/dist/utils/bash.js +211 -126
- package/dist/utils/command-protection.d.ts +28 -0
- package/dist/utils/command-protection.d.ts.map +1 -0
- package/dist/utils/command-protection.js +324 -0
- package/dist/utils/dedent.d.ts.map +1 -0
- package/dist/utils/env-expand.d.ts +2 -0
- package/dist/utils/env-expand.d.ts.map +1 -0
- package/dist/utils/env-expand.js +8 -0
- package/dist/utils/filesystem/path-display.d.ts +11 -0
- package/dist/utils/filesystem/path-display.d.ts.map +1 -0
- package/dist/utils/filesystem/path-display.js +32 -0
- package/dist/utils/filesystem/security.d.ts +2 -2
- package/dist/utils/filesystem/security.d.ts.map +1 -1
- package/dist/utils/filesystem/security.js +28 -30
- package/dist/utils/formatting.d.ts.map +1 -0
- package/dist/{formatting.js → utils/formatting.js} +1 -1
- package/dist/utils/git.d.ts +4 -0
- package/dist/utils/git.d.ts.map +1 -1
- package/dist/utils/git.js +30 -0
- package/dist/utils/glob.d.ts +1 -1
- package/dist/utils/glob.d.ts.map +1 -1
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/{logger.js → utils/logger.js} +1 -1
- package/dist/utils/parsing.d.ts.map +1 -0
- package/dist/utils/process.d.ts.map +1 -1
- package/dist/utils/process.js +90 -37
- package/dist/utils/templates.d.ts +2 -0
- package/dist/utils/templates.d.ts.map +1 -0
- package/dist/utils/templates.js +24 -0
- package/dist/utils/version.d.ts.map +1 -0
- package/dist/{version.js → utils/version.js} +1 -1
- package/package.json +34 -25
- package/dist/cli.d.ts +0 -23
- package/dist/cli.d.ts.map +0 -1
- package/dist/commands/exit/index.d.ts +0 -10
- package/dist/commands/exit/index.d.ts.map +0 -1
- package/dist/commands/exit/index.js +0 -21
- package/dist/commands/exit/types.d.ts +0 -8
- package/dist/commands/exit/types.d.ts.map +0 -1
- package/dist/commands/exit/types.js +0 -1
- package/dist/commands/exit/utils.d.ts +0 -2
- package/dist/commands/exit/utils.d.ts.map +0 -1
- package/dist/commands/exit/utils.js +0 -13
- package/dist/commands/prompt/index.d.ts +0 -5
- package/dist/commands/prompt/index.d.ts.map +0 -1
- package/dist/commands/prompt/index.js +0 -122
- package/dist/commands/prompt/types.d.ts +0 -15
- package/dist/commands/prompt/types.d.ts.map +0 -1
- package/dist/commands/prompt/types.js +0 -1
- package/dist/commands/prompt/utils.d.ts +0 -12
- package/dist/commands/prompt/utils.d.ts.map +0 -1
- package/dist/commands/prompt/utils.js +0 -107
- package/dist/commands/reset/index.d.ts +0 -3
- package/dist/commands/reset/index.d.ts.map +0 -1
- package/dist/commands/reset/index.js +0 -25
- package/dist/commands/reset/types.d.ts +0 -1
- package/dist/commands/reset/types.d.ts.map +0 -1
- package/dist/commands/reset/types.js +0 -3
- package/dist/commands/save/index.d.ts +0 -3
- package/dist/commands/save/index.d.ts.map +0 -1
- package/dist/commands/save/index.js +0 -19
- package/dist/config.d.ts.map +0 -1
- package/dist/dedent.d.ts.map +0 -1
- package/dist/formatting.d.ts.map +0 -1
- package/dist/logger.d.ts.map +0 -1
- package/dist/mentions.d.ts +0 -14
- package/dist/mentions.d.ts.map +0 -1
- package/dist/parsing.d.ts.map +0 -1
- package/dist/prompts.d.ts.map +0 -1
- package/dist/repl-new.d.ts +0 -65
- package/dist/repl-new.d.ts.map +0 -1
- package/dist/skills.d.ts.map +0 -1
- package/dist/skills.js +0 -233
- package/dist/stdin.d.ts.map +0 -1
- package/dist/tui/autocomplete/path-provider.d.ts +0 -21
- package/dist/tui/autocomplete/path-provider.d.ts.map +0 -1
- package/dist/tui/autocomplete/path-provider.js +0 -164
- package/dist/version.d.ts.map +0 -1
- /package/dist/{stdin.d.ts → cli/stdin.d.ts} +0 -0
- /package/dist/{dedent.d.ts → utils/dedent.d.ts} +0 -0
- /package/dist/{dedent.js → utils/dedent.js} +0 -0
- /package/dist/{formatting.d.ts → utils/formatting.d.ts} +0 -0
- /package/dist/{logger.d.ts → utils/logger.d.ts} +0 -0
- /package/dist/{parsing.d.ts → utils/parsing.d.ts} +0 -0
- /package/dist/{parsing.js → utils/parsing.js} +0 -0
- /package/dist/{version.d.ts → utils/version.d.ts} +0 -0
package/dist/tui/tui.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Minimal TUI implementation with differential rendering
|
|
3
3
|
*/
|
|
4
|
-
import { getTerminalSize, isCtrlC, isCtrlZ, isEscape, } from "../terminal/control.js";
|
|
4
|
+
import { getTerminalSize, isCtrlC, isCtrlD, isCtrlM, isCtrlN, isCtrlO, isCtrlR, isCtrlZ, isEscape, } from "../terminal/control.js";
|
|
5
|
+
import { isShiftTab } from "../terminal/keys.js";
|
|
5
6
|
import style from "../terminal/style.js";
|
|
6
7
|
import { visibleWidth } from "./utils.js";
|
|
7
8
|
export { visibleWidth };
|
|
@@ -28,6 +29,14 @@ export class Container {
|
|
|
28
29
|
}
|
|
29
30
|
/**
|
|
30
31
|
* TUI - Main class for managing terminal UI with differential rendering
|
|
32
|
+
*
|
|
33
|
+
* The TUI splits its children into two regions:
|
|
34
|
+
* - Scrollable content: children added before setFixedFooterStart()
|
|
35
|
+
* - Fixed footer: children added after setFixedFooterStart()
|
|
36
|
+
*
|
|
37
|
+
* The scrollable content region supports virtual scrolling via trackpad/mouse
|
|
38
|
+
* wheel. The fixed footer (editor, footer bar, notifications) is always
|
|
39
|
+
* pinned to the bottom of the terminal.
|
|
31
40
|
*/
|
|
32
41
|
// biome-ignore lint/style/useNamingConvention: override
|
|
33
42
|
export class TUI extends Container {
|
|
@@ -37,14 +46,41 @@ export class TUI extends Container {
|
|
|
37
46
|
isRendering = false;
|
|
38
47
|
renderAgain = false;
|
|
39
48
|
activeModal = null;
|
|
49
|
+
scrollOffset = 0;
|
|
50
|
+
lastScrollableHeight = 0;
|
|
51
|
+
fixedFooterIndex = -1;
|
|
52
|
+
isUserScrolledUp = false;
|
|
40
53
|
onCtrlC;
|
|
54
|
+
onCtrlD;
|
|
55
|
+
onReconstructSession;
|
|
56
|
+
onCtrlN;
|
|
57
|
+
onCtrlO;
|
|
58
|
+
/** Callback invoked when Ctrl+M is pressed - opens model selector. */
|
|
59
|
+
onCtrlM;
|
|
60
|
+
onCtrlR;
|
|
61
|
+
onShiftTab;
|
|
41
62
|
constructor(terminal) {
|
|
42
63
|
super();
|
|
43
64
|
this.terminal = terminal;
|
|
44
65
|
}
|
|
66
|
+
/**
|
|
67
|
+
* Mark the boundary between scrollable content and fixed footer.
|
|
68
|
+
* All children added after this call will be rendered as fixed
|
|
69
|
+
* footer content pinned to the bottom of the terminal.
|
|
70
|
+
*/
|
|
71
|
+
setFixedFooterStart() {
|
|
72
|
+
this.fixedFooterIndex = this.children.length;
|
|
73
|
+
}
|
|
45
74
|
setFocus(component) {
|
|
46
75
|
this.focusedComponent = component;
|
|
47
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* Get the underlying terminal instance for external mode operations.
|
|
79
|
+
* Used primarily for spawning external editors.
|
|
80
|
+
*/
|
|
81
|
+
getTerminal() {
|
|
82
|
+
return this.terminal;
|
|
83
|
+
}
|
|
48
84
|
start() {
|
|
49
85
|
this.terminal.start((data) => this.handleInput(data), () => this.requestRender());
|
|
50
86
|
this.terminal.onResume(() => this.requestRender());
|
|
@@ -69,7 +105,15 @@ export class TUI extends Container {
|
|
|
69
105
|
});
|
|
70
106
|
}
|
|
71
107
|
inBracketedPaste = false;
|
|
108
|
+
focusedComponentWantsNavigation() {
|
|
109
|
+
return this.focusedComponent?.wantsNavigationKeys?.() ?? false;
|
|
110
|
+
}
|
|
72
111
|
handleInput(data) {
|
|
112
|
+
// Handle mouse tracking events (SGR format: \x1b[<button;x;yM)
|
|
113
|
+
if (data.startsWith("\x1b[<")) {
|
|
114
|
+
this.handleMouseEvent(data);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
73
117
|
if (data.includes("\x1b[200~")) {
|
|
74
118
|
this.inBracketedPaste = true;
|
|
75
119
|
}
|
|
@@ -94,6 +138,36 @@ export class TUI extends Container {
|
|
|
94
138
|
process.exit(0);
|
|
95
139
|
}
|
|
96
140
|
}
|
|
141
|
+
// Handle Ctrl+D - exit only if editor is empty (handled by Repl)
|
|
142
|
+
if (isCtrlD(data)) {
|
|
143
|
+
if (this.onCtrlD) {
|
|
144
|
+
this.onCtrlD();
|
|
145
|
+
}
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
const keyBindings = [
|
|
149
|
+
{ check: isCtrlO, handler: this.onCtrlO },
|
|
150
|
+
{ check: isCtrlR, handler: this.onCtrlR },
|
|
151
|
+
{ check: isCtrlN, handler: this.onCtrlN },
|
|
152
|
+
{ check: isCtrlM, handler: this.onCtrlM },
|
|
153
|
+
];
|
|
154
|
+
for (const binding of keyBindings) {
|
|
155
|
+
if (binding.check(data)) {
|
|
156
|
+
binding.handler?.();
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
// Handle Shift+Tab - cycle mode only when no modal is active,
|
|
161
|
+
// the focused component won't handle navigation (e.g., model selector),
|
|
162
|
+
// and the editor isn't showing autocomplete
|
|
163
|
+
if (isShiftTab(data) && !this.inBracketedPaste) {
|
|
164
|
+
if (!this.activeModal && !this.focusedComponentWantsNavigation()) {
|
|
165
|
+
if (this.onShiftTab) {
|
|
166
|
+
this.onShiftTab();
|
|
167
|
+
}
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
97
171
|
// Handle Escape key to close modal if one is active
|
|
98
172
|
if (isEscape(data) && this.activeModal) {
|
|
99
173
|
this.hideModal();
|
|
@@ -106,9 +180,69 @@ export class TUI extends Container {
|
|
|
106
180
|
}
|
|
107
181
|
else if (this.focusedComponent?.handleInput) {
|
|
108
182
|
this.focusedComponent.handleInput(data);
|
|
183
|
+
this.scrollToBottom();
|
|
184
|
+
this.requestRender();
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
handleMouseEvent(data) {
|
|
188
|
+
// SGR mouse format: \x1b[<button;x;yM (press) or \x1b[<button;x;ym (release)
|
|
189
|
+
// Extract button code between "<" and first ";"
|
|
190
|
+
const start = data.indexOf("<");
|
|
191
|
+
const semi = data.indexOf(";", start);
|
|
192
|
+
if (start === -1 || semi === -1)
|
|
193
|
+
return;
|
|
194
|
+
const button = Number.parseInt(data.slice(start + 1, semi), 10);
|
|
195
|
+
const scrollLines = 3;
|
|
196
|
+
const { rows } = getTerminalSize();
|
|
197
|
+
const fixedHeight = this.getFixedFooterHeight(this.terminal.columns);
|
|
198
|
+
const scrollableViewport = rows - fixedHeight;
|
|
199
|
+
// Button 64 = scroll up, button 65 = scroll down
|
|
200
|
+
if (button === 64) {
|
|
201
|
+
this.scrollOffset = Math.max(0, this.scrollOffset - scrollLines);
|
|
202
|
+
const maxOffset = Math.max(0, this.lastScrollableHeight - scrollableViewport);
|
|
203
|
+
this.isUserScrolledUp = this.scrollOffset < maxOffset;
|
|
204
|
+
this.requestRender();
|
|
205
|
+
}
|
|
206
|
+
else if (button === 65) {
|
|
207
|
+
const maxOffset = Math.max(0, this.lastScrollableHeight - scrollableViewport);
|
|
208
|
+
this.scrollOffset = Math.min(maxOffset, this.scrollOffset + scrollLines);
|
|
209
|
+
this.isUserScrolledUp = this.scrollOffset < maxOffset;
|
|
109
210
|
this.requestRender();
|
|
110
211
|
}
|
|
111
212
|
}
|
|
213
|
+
scrollToBottom() {
|
|
214
|
+
const { rows } = getTerminalSize();
|
|
215
|
+
const fixedHeight = this.getFixedFooterHeight(this.terminal.columns);
|
|
216
|
+
const scrollableViewport = rows - fixedHeight;
|
|
217
|
+
this.scrollOffset = Math.max(0, this.lastScrollableHeight - scrollableViewport);
|
|
218
|
+
this.isUserScrolledUp = false;
|
|
219
|
+
}
|
|
220
|
+
getFixedFooterHeight(width) {
|
|
221
|
+
if (this.fixedFooterIndex < 0)
|
|
222
|
+
return 0;
|
|
223
|
+
let height = 0;
|
|
224
|
+
for (let i = this.fixedFooterIndex; i < this.children.length; i++) {
|
|
225
|
+
height += this.children[i].render(width).length;
|
|
226
|
+
}
|
|
227
|
+
return height;
|
|
228
|
+
}
|
|
229
|
+
renderScrollableContent(width) {
|
|
230
|
+
const end = this.fixedFooterIndex >= 0 ? this.fixedFooterIndex : this.children.length;
|
|
231
|
+
const lines = [];
|
|
232
|
+
for (let i = 0; i < end; i++) {
|
|
233
|
+
lines.push(...this.children[i].render(width));
|
|
234
|
+
}
|
|
235
|
+
return lines;
|
|
236
|
+
}
|
|
237
|
+
renderFixedFooter(width) {
|
|
238
|
+
if (this.fixedFooterIndex < 0)
|
|
239
|
+
return [];
|
|
240
|
+
const lines = [];
|
|
241
|
+
for (let i = this.fixedFooterIndex; i < this.children.length; i++) {
|
|
242
|
+
lines.push(...this.children[i].render(width));
|
|
243
|
+
}
|
|
244
|
+
return lines;
|
|
245
|
+
}
|
|
112
246
|
doRender() {
|
|
113
247
|
if (this.isRendering) {
|
|
114
248
|
this.renderAgain = true;
|
|
@@ -117,13 +251,32 @@ export class TUI extends Container {
|
|
|
117
251
|
this.isRendering = true;
|
|
118
252
|
try {
|
|
119
253
|
const width = this.terminal.columns;
|
|
120
|
-
|
|
121
|
-
|
|
254
|
+
const { rows } = getTerminalSize();
|
|
255
|
+
// Render fixed footer and scrollable content separately
|
|
256
|
+
const fixedLines = this.renderFixedFooter(width);
|
|
257
|
+
const scrollableLines = this.renderScrollableContent(width);
|
|
258
|
+
this.lastScrollableHeight = scrollableLines.length;
|
|
259
|
+
const fixedHeight = fixedLines.length;
|
|
260
|
+
const scrollableViewport = rows - fixedHeight;
|
|
261
|
+
// Auto-scroll to bottom when new content arrives,
|
|
262
|
+
// unless the user has explicitly scrolled up
|
|
263
|
+
if (!this.isUserScrolledUp) {
|
|
264
|
+
this.scrollOffset = Math.max(0, scrollableLines.length - scrollableViewport);
|
|
265
|
+
}
|
|
266
|
+
// Clamp scroll offset
|
|
267
|
+
const maxOffset = Math.max(0, scrollableLines.length - scrollableViewport);
|
|
268
|
+
if (this.scrollOffset > maxOffset) {
|
|
269
|
+
this.scrollOffset = maxOffset;
|
|
270
|
+
}
|
|
271
|
+
// Apply scroll offset to get visible scrollable lines
|
|
272
|
+
const visibleScrollable = scrollableLines.slice(this.scrollOffset, this.scrollOffset + scrollableViewport);
|
|
273
|
+
// Combine visible scrollable content with fixed footer
|
|
274
|
+
const visibleLines = [...visibleScrollable, ...fixedLines];
|
|
122
275
|
// Build output buffer using array join (more efficient than string concat)
|
|
123
276
|
const bufferParts = [
|
|
124
277
|
"\x1b[?2026h", // Begin synchronized output
|
|
125
278
|
"\x1b[3J\x1b[2J\x1b[H", // Clear scrollback, screen, and home
|
|
126
|
-
|
|
279
|
+
visibleLines.join("\r\n"),
|
|
127
280
|
];
|
|
128
281
|
// Render modal on top if active
|
|
129
282
|
if (this.activeModal) {
|
|
@@ -154,43 +307,6 @@ export class TUI extends Container {
|
|
|
154
307
|
}
|
|
155
308
|
}
|
|
156
309
|
}
|
|
157
|
-
// private positionCursor(
|
|
158
|
-
// componentCursorPos: [number, number] | null,
|
|
159
|
-
// ): void {
|
|
160
|
-
// if (!componentCursorPos) {
|
|
161
|
-
// // No cursor position from component, hide cursor
|
|
162
|
-
// this.terminal.hideCursor();
|
|
163
|
-
// return;
|
|
164
|
-
// }
|
|
165
|
-
// const [cursorRow, cursorCol] = componentCursorPos;
|
|
166
|
-
//
|
|
167
|
-
// // Calculate absolute cursor position in the terminal
|
|
168
|
-
// // We need to find which line in newLines corresponds to the component's cursor row
|
|
169
|
-
// // and then position the cursor at that line and column
|
|
170
|
-
//
|
|
171
|
-
// // Find the line offset for the focused component
|
|
172
|
-
// let componentStartLine = 0;
|
|
173
|
-
// if (this.focusedComponent) {
|
|
174
|
-
// // Find the line where this component starts by summing heights of previous components
|
|
175
|
-
// for (const child of this.children) {
|
|
176
|
-
// if (child === this.focusedComponent) {
|
|
177
|
-
// break;
|
|
178
|
-
// }
|
|
179
|
-
// // Use the already-rendered lines to calculate height, not re-render
|
|
180
|
-
// const childLines = child.render(this.terminal.columns);
|
|
181
|
-
// componentStartLine += childLines.length;
|
|
182
|
-
// }
|
|
183
|
-
// }
|
|
184
|
-
//
|
|
185
|
-
// const absoluteRow = componentStartLine + cursorRow;
|
|
186
|
-
// const absoluteCol = cursorCol;
|
|
187
|
-
//
|
|
188
|
-
// // Position cursor using absolute positioning
|
|
189
|
-
// // Move to home position first, then move down to row, then right to column
|
|
190
|
-
// // Note: terminal rows/columns are 1-indexed, so we add 1
|
|
191
|
-
// this.terminal.write(`\x1b[H\x1b[${absoluteRow + 1}B\x1b[${absoluteCol + 1}G`);
|
|
192
|
-
// this.terminal.showCursor();
|
|
193
|
-
// }
|
|
194
310
|
/**
|
|
195
311
|
* Show a modal dialog
|
|
196
312
|
*/
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
interface ControlOperator {
|
|
2
|
+
op: "||" | "&&" | ";;" | "|&" | "<(" | "<<<" | ">>" | ">&" | "&" | ";" | "(" | ")" | "|" | "<" | ">";
|
|
3
|
+
}
|
|
4
|
+
interface GlobOperator {
|
|
5
|
+
op: "glob";
|
|
6
|
+
pattern: string;
|
|
7
|
+
}
|
|
8
|
+
interface CommentOperator {
|
|
9
|
+
comment: string;
|
|
10
|
+
}
|
|
11
|
+
type ParseEntry = string | ControlOperator | GlobOperator | CommentOperator;
|
|
12
|
+
interface ParseOptions {
|
|
13
|
+
escape?: string;
|
|
14
|
+
}
|
|
15
|
+
type EnvFunction = (key: string) => unknown;
|
|
16
|
+
export declare function parse(s: string, env?: Record<string, string | undefined> | EnvFunction, opts?: ParseOptions): ParseEntry[];
|
|
17
|
+
export declare function parse<T extends object | string>(s: string, env: (key: string) => T | undefined, opts?: ParseOptions): (ParseEntry | T)[];
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=parse.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../../source/utils/bash/parse.ts"],"names":[],"mappings":"AA+BA,UAAU,eAAe;IACvB,EAAE,EACE,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,KAAK,GACL,IAAI,GACJ,IAAI,GACJ,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,CAAC;CACT;AAED,UAAU,YAAY;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,eAAe;IACvB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,KAAK,UAAU,GAAG,MAAM,GAAG,eAAe,GAAG,YAAY,GAAG,eAAe,CAAC;AAE5E,UAAU,YAAY;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,KAAK,WAAW,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;AA8L5C,wBAAgB,KAAK,CACnB,CAAC,EAAE,MAAM,EACT,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GAAG,WAAW,EACtD,IAAI,CAAC,EAAE,YAAY,GAClB,UAAU,EAAE,CAAC;AAChB,wBAAgB,KAAK,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAC7C,CAAC,EAAE,MAAM,EACT,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,CAAC,GAAG,SAAS,EACnC,IAAI,CAAC,EAAE,YAAY,GAClB,CAAC,UAAU,GAAG,CAAC,CAAC,EAAE,CAAC"}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
// '<(' is process substitution operator and
|
|
2
|
+
// can be parsed the same as control operator
|
|
3
|
+
const CONTROL = `(?:${[
|
|
4
|
+
"\\|\\|",
|
|
5
|
+
"\\&\\&",
|
|
6
|
+
";;",
|
|
7
|
+
"\\|\\&",
|
|
8
|
+
"\\<\\(",
|
|
9
|
+
"\\<\\<\\<",
|
|
10
|
+
">>",
|
|
11
|
+
">\\&",
|
|
12
|
+
"<\\&",
|
|
13
|
+
"[&;()|<>]",
|
|
14
|
+
].join("|")})`;
|
|
15
|
+
const controlRe = new RegExp(`^${CONTROL}$`);
|
|
16
|
+
const META = "|&;()<> \t";
|
|
17
|
+
const SINGLE_QUOTE = '"((\\\\"|[^"])*?)"';
|
|
18
|
+
const DOUBLE_QUOTE = "'((\\\\'|[^'])*?)'";
|
|
19
|
+
const hash = /^#$/;
|
|
20
|
+
const SQ = "'";
|
|
21
|
+
const DQ = '"';
|
|
22
|
+
const DS = "$";
|
|
23
|
+
let Token = "";
|
|
24
|
+
const mult = 0x100000000; // Math.pow(16, 8);
|
|
25
|
+
for (let i = 0; i < 4; i++) {
|
|
26
|
+
Token += (mult * Math.random()).toString(16);
|
|
27
|
+
}
|
|
28
|
+
const startsWithToken = new RegExp(`^${Token}`);
|
|
29
|
+
function matchAll(s, r) {
|
|
30
|
+
const origIndex = r.lastIndex;
|
|
31
|
+
const matches = [];
|
|
32
|
+
let matchObj = r.exec(s);
|
|
33
|
+
while (matchObj !== null) {
|
|
34
|
+
matches.push(matchObj);
|
|
35
|
+
if (r.lastIndex === matchObj.index) {
|
|
36
|
+
r.lastIndex += 1;
|
|
37
|
+
}
|
|
38
|
+
matchObj = r.exec(s);
|
|
39
|
+
}
|
|
40
|
+
r.lastIndex = origIndex;
|
|
41
|
+
return matches;
|
|
42
|
+
}
|
|
43
|
+
function getVar(env, pre, key) {
|
|
44
|
+
let r = typeof env === "function" ? env(key) : env[key];
|
|
45
|
+
if (typeof r === "undefined" && key !== "") {
|
|
46
|
+
r = "";
|
|
47
|
+
}
|
|
48
|
+
else if (typeof r === "undefined") {
|
|
49
|
+
r = "$";
|
|
50
|
+
}
|
|
51
|
+
if (typeof r === "object") {
|
|
52
|
+
return pre + Token + JSON.stringify(r) + Token;
|
|
53
|
+
}
|
|
54
|
+
return pre + String(r);
|
|
55
|
+
}
|
|
56
|
+
function parseInternal(string, env, opts = {}) {
|
|
57
|
+
const Bs = opts.escape || "\\";
|
|
58
|
+
const Bareword = `(\\${Bs}["'${META}]|[^\\s'""${META}])+`;
|
|
59
|
+
const chunker = new RegExp([
|
|
60
|
+
`(${CONTROL})`, // control chars
|
|
61
|
+
`(${Bareword}|${SINGLE_QUOTE}|${DOUBLE_QUOTE})+`,
|
|
62
|
+
].join("|"), "g");
|
|
63
|
+
const matches = matchAll(string, chunker);
|
|
64
|
+
if (matches.length === 0) {
|
|
65
|
+
return [];
|
|
66
|
+
}
|
|
67
|
+
const envToUse = env ?? {};
|
|
68
|
+
let commented = false;
|
|
69
|
+
return matches
|
|
70
|
+
.map(
|
|
71
|
+
// biome-ignore lint:noExcessiveCognitiveComplexity
|
|
72
|
+
(match) => {
|
|
73
|
+
const s = match[0];
|
|
74
|
+
if (!s || commented) {
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
if (controlRe.test(s)) {
|
|
78
|
+
return { op: s };
|
|
79
|
+
}
|
|
80
|
+
// Hand-written scanner/parser for Bash quoting rules:
|
|
81
|
+
//
|
|
82
|
+
// 1. inside single quotes, all characters are printed literally.
|
|
83
|
+
// 2. inside double quotes, all characters are printed literally
|
|
84
|
+
// except variables prefixed by '$' and backslashes followed by
|
|
85
|
+
// either a double quote or another backslash.
|
|
86
|
+
// 3. outside of any quotes, backslashes are treated as escape
|
|
87
|
+
// characters and not printed (unless they are themselves escaped)
|
|
88
|
+
// 4. quote context can switch mid-token if there is no whitespace
|
|
89
|
+
// between the two quote contexts (e.g. all'one'"token" parses as
|
|
90
|
+
// "allonetoken")
|
|
91
|
+
let quote = false;
|
|
92
|
+
let esc = false;
|
|
93
|
+
let out = "";
|
|
94
|
+
let isGlob = false;
|
|
95
|
+
let i = 0;
|
|
96
|
+
function parseEnvVar() {
|
|
97
|
+
i += 1;
|
|
98
|
+
let varend;
|
|
99
|
+
let varname;
|
|
100
|
+
const char = s.charAt(i);
|
|
101
|
+
if (char === "{") {
|
|
102
|
+
i += 1;
|
|
103
|
+
if (s.charAt(i) === "}") {
|
|
104
|
+
throw new Error(`Bad substitution: ${s.slice(i - 2, i + 1)}`);
|
|
105
|
+
}
|
|
106
|
+
varend = s.indexOf("}", i);
|
|
107
|
+
if (varend < 0) {
|
|
108
|
+
throw new Error(`Bad substitution: ${s.slice(i)}`);
|
|
109
|
+
}
|
|
110
|
+
varname = s.slice(i, varend);
|
|
111
|
+
i = varend;
|
|
112
|
+
}
|
|
113
|
+
else if (/[*@#?$!_-]/.test(char)) {
|
|
114
|
+
varname = char;
|
|
115
|
+
i += 1;
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
const slicedFromI = s.slice(i);
|
|
119
|
+
const varendMatch = slicedFromI.match(/[^\w\d_]/);
|
|
120
|
+
if (!varendMatch) {
|
|
121
|
+
varname = slicedFromI;
|
|
122
|
+
i = s.length;
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
varname = slicedFromI.slice(0, varendMatch.index);
|
|
126
|
+
i += (varendMatch.index ?? 0) - 1;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return getVar(envToUse, "", varname);
|
|
130
|
+
}
|
|
131
|
+
for (i = 0; i < s.length; i++) {
|
|
132
|
+
const c = s.charAt(i);
|
|
133
|
+
isGlob = isGlob || (!quote && (c === "*" || c === "?"));
|
|
134
|
+
if (esc) {
|
|
135
|
+
out += c;
|
|
136
|
+
esc = false;
|
|
137
|
+
}
|
|
138
|
+
else if (quote) {
|
|
139
|
+
if (c === quote) {
|
|
140
|
+
quote = false;
|
|
141
|
+
}
|
|
142
|
+
else if (quote === SQ) {
|
|
143
|
+
out += c;
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
// Double quote
|
|
147
|
+
if (c === Bs) {
|
|
148
|
+
i += 1;
|
|
149
|
+
const charAtI = s.charAt(i);
|
|
150
|
+
if (charAtI === DQ || charAtI === Bs || charAtI === DS) {
|
|
151
|
+
out += charAtI;
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
out += Bs + charAtI;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
else if (c === DS) {
|
|
158
|
+
out += parseEnvVar();
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
out += c;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
else if (c === DQ || c === SQ) {
|
|
166
|
+
quote = c;
|
|
167
|
+
}
|
|
168
|
+
else if (controlRe.test(c)) {
|
|
169
|
+
return { op: s };
|
|
170
|
+
}
|
|
171
|
+
else if (hash.test(c)) {
|
|
172
|
+
commented = true;
|
|
173
|
+
const matchIndex = match.index;
|
|
174
|
+
const commentObj = {
|
|
175
|
+
comment: string.slice((matchIndex ?? 0) + i + 1),
|
|
176
|
+
};
|
|
177
|
+
if (out.length) {
|
|
178
|
+
return [out, commentObj];
|
|
179
|
+
}
|
|
180
|
+
return [commentObj];
|
|
181
|
+
}
|
|
182
|
+
else if (c === Bs) {
|
|
183
|
+
esc = true;
|
|
184
|
+
}
|
|
185
|
+
else if (c === DS) {
|
|
186
|
+
out += parseEnvVar();
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
out += c;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
if (isGlob) {
|
|
193
|
+
return { op: "glob", pattern: out };
|
|
194
|
+
}
|
|
195
|
+
return out;
|
|
196
|
+
})
|
|
197
|
+
.reduce((prev, arg) => {
|
|
198
|
+
// TODO: replace this whole reduce with a concat
|
|
199
|
+
return typeof arg === "undefined" ? prev : prev.concat(arg);
|
|
200
|
+
}, []);
|
|
201
|
+
}
|
|
202
|
+
export function parse(s, env = {}, opts) {
|
|
203
|
+
const mapped = parseInternal(s, env, opts);
|
|
204
|
+
if (typeof env !== "function") {
|
|
205
|
+
return mapped;
|
|
206
|
+
}
|
|
207
|
+
return mapped.reduce((acc, s) => {
|
|
208
|
+
if (typeof s === "object") {
|
|
209
|
+
return acc.concat(s);
|
|
210
|
+
}
|
|
211
|
+
const xs = s.split(RegExp(`(${Token}.*?${Token})`, "g"));
|
|
212
|
+
if (xs.length === 1) {
|
|
213
|
+
return acc.concat(xs[0]);
|
|
214
|
+
}
|
|
215
|
+
return acc.concat(xs.filter(Boolean).map((x) => {
|
|
216
|
+
if (startsWithToken.test(x)) {
|
|
217
|
+
const parts = x.split(Token);
|
|
218
|
+
return JSON.parse(parts[1]);
|
|
219
|
+
}
|
|
220
|
+
return x;
|
|
221
|
+
}));
|
|
222
|
+
}, []);
|
|
223
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quote.d.ts","sourceRoot":"","sources":["../../../source/utils/bash/quote.ts"],"names":[],"mappings":"AAAA,KAAK,QAAQ,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,GAAG,SAAS,CAAC;AAE9E,wBAAgB,KAAK,CAAC,EAAE,EAAE,SAAS,QAAQ,EAAE,GAAG,MAAM,CAyBrD"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export function quote(xs) {
|
|
2
|
+
return xs
|
|
3
|
+
.map((s) => {
|
|
4
|
+
if (s === null || s === undefined) {
|
|
5
|
+
return String(s);
|
|
6
|
+
}
|
|
7
|
+
const str = String(s);
|
|
8
|
+
if (str === "") {
|
|
9
|
+
return "''";
|
|
10
|
+
}
|
|
11
|
+
if (s && typeof s === "object") {
|
|
12
|
+
return s.op.replace(/(.)/g, "\\$1");
|
|
13
|
+
}
|
|
14
|
+
if (/["\s\\]/.test(str) && !/'/.test(str)) {
|
|
15
|
+
return `'${str.replace(/(['])/g, "\\$1")}'`;
|
|
16
|
+
}
|
|
17
|
+
if (/["'\s]/.test(str)) {
|
|
18
|
+
return `"${str.replace(/(["\\$`!])/g, "\\$1")}"`;
|
|
19
|
+
}
|
|
20
|
+
return str.replace(/([A-Za-z]:)?([#!"$&'()*,:;<=>?@[\\\]^`{|}])/g, "$1\\$2");
|
|
21
|
+
})
|
|
22
|
+
.join(" ");
|
|
23
|
+
}
|
package/dist/utils/bash.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bash.d.ts","sourceRoot":"","sources":["../../source/utils/bash.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"bash.d.ts","sourceRoot":"","sources":["../../source/utils/bash.ts"],"names":[],"mappings":"AAuJA,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,EAAE,EACrB,GAAG,EAAE,MAAM,GACV;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAiDtC;AAED,eAAO,MAAM,UAAU,GACrB,UAAU,MAAM,GAAG,IAAI,GAAG,SAAS,EACnC,YAAY,MAAM,EAClB,cAAc,MAAM,EAAE,KACrB,MAkEF,CAAC;AA6FF,eAAO,MAAM,iBAAiB,GAAI,YAAY,MAAM,KAAG,OAetD,CAAC"}
|