@oh-my-pi/pi-tui 18.2.3 → 18.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +29 -0
- package/README.md +43 -0
- package/dist/types/app-keybindings.d.ts +395 -0
- package/dist/types/apps/autoresearch-dashboard.d.ts +43 -0
- package/dist/types/apps/autoresearch-data.d.ts +15 -0
- package/dist/types/apps/cleanse-board.d.ts +66 -0
- package/dist/types/apps/cleanse-picker.d.ts +23 -0
- package/dist/types/apps/debug/log-formatting.d.ts +6 -0
- package/dist/types/apps/debug/log-viewer.d.ts +81 -0
- package/dist/types/apps/debug/protocol-probe.d.ts +42 -0
- package/dist/types/apps/debug/raw-sse-buffer.d.ts +58 -0
- package/dist/types/apps/debug/raw-sse.d.ts +26 -0
- package/dist/types/apps/debug/terminal-info.d.ts +34 -0
- package/dist/types/apps/debug/viewer-frame.d.ts +52 -0
- package/dist/types/apps/git/avatar.d.ts +9 -0
- package/dist/types/apps/git/colors.d.ts +49 -0
- package/dist/types/apps/git/diff-pane.d.ts +188 -0
- package/dist/types/apps/git/git-tui.d.ts +66 -0
- package/dist/types/apps/git/sidebar.d.ts +149 -0
- package/dist/types/apps/git/state.d.ts +117 -0
- package/dist/types/apps/if-bench-board.d.ts +75 -0
- package/dist/types/apps/live-visualizer.d.ts +33 -0
- package/dist/types/apps/ps-data.d.ts +51 -0
- package/dist/types/apps/ps-top.d.ts +33 -0
- package/dist/types/apps/session-picker.d.ts +26 -0
- package/dist/types/apps/setup-model-picker.d.ts +13 -0
- package/dist/types/apps/standalone-picker.d.ts +42 -0
- package/dist/types/autocomplete.d.ts +4 -0
- package/dist/types/chat/advisor-message.d.ts +11 -0
- package/dist/types/chat/assistant-message.d.ts +106 -0
- package/dist/types/chat/background-tan-message.d.ts +9 -0
- package/dist/types/chat/bash-execution.d.ts +47 -0
- package/dist/types/chat/cache-invalidation-marker.d.ts +50 -0
- package/dist/types/chat/chat-transcript-builder.d.ts +50 -0
- package/dist/types/chat/collab-prompt-message.d.ts +10 -0
- package/dist/types/chat/compaction-summary-message.d.ts +54 -0
- package/dist/types/chat/custom-message.d.ts +10 -0
- package/dist/types/chat/display-preferences.d.ts +13 -0
- package/dist/types/chat/eval-execution.d.ts +29 -0
- package/dist/types/chat/execution-shared.d.ts +51 -0
- package/dist/types/chat/extension-types.d.ts +28 -0
- package/dist/types/chat/hook-message.d.ts +10 -0
- package/dist/types/chat/image-loading.d.ts +46 -0
- package/dist/types/chat/late-diagnostics-message.d.ts +21 -0
- package/dist/types/chat/messages.d.ts +189 -0
- package/dist/types/chat/reaction.d.ts +30 -0
- package/dist/types/chat/read-target.d.ts +4 -0
- package/dist/types/chat/read-tool-group.d.ts +67 -0
- package/dist/types/chat/served-model-marker.d.ts +47 -0
- package/dist/types/chat/skill-message.d.ts +33 -0
- package/dist/types/chat/skill-title-input.d.ts +14 -0
- package/dist/types/chat/stripped-tool-calls-placeholder.d.ts +12 -0
- package/dist/types/chat/thinking-display.d.ts +12 -0
- package/dist/types/chat/todo-reminder.d.ts +13 -0
- package/dist/types/chat/tool-execution.d.ts +138 -0
- package/dist/types/chat/transcript-browser.d.ts +93 -0
- package/dist/types/chat/transcript-entry.d.ts +45 -0
- package/dist/types/chat/transcript-outline.d.ts +86 -0
- package/dist/types/chat/transcript-render-helpers.d.ts +92 -0
- package/dist/types/chat/ttsr-notification.d.ts +23 -0
- package/dist/types/chat/user-message.d.ts +52 -0
- package/dist/types/chrome/chat-block.d.ts +64 -0
- package/dist/types/chrome/collab-qrcode.d.ts +28 -0
- package/dist/types/chrome/context-thresholds.d.ts +10 -0
- package/dist/types/chrome/countdown-timer.d.ts +14 -0
- package/dist/types/chrome/diff.d.ts +14 -0
- package/dist/types/chrome/dynamic-border.d.ts +16 -0
- package/dist/types/chrome/error-block.d.ts +17 -0
- package/dist/types/chrome/form-theme.d.ts +3 -0
- package/dist/types/chrome/format.d.ts +12 -0
- package/dist/types/chrome/index.d.ts +20 -0
- package/dist/types/chrome/keybinding-hints.d.ts +40 -0
- package/dist/types/chrome/live-board.d.ts +23 -0
- package/dist/types/chrome/local-date.d.ts +4 -0
- package/dist/types/chrome/message-divider.d.ts +22 -0
- package/dist/types/chrome/message-frame.d.ts +52 -0
- package/dist/types/chrome/message-notice.d.ts +35 -0
- package/dist/types/chrome/overlay-box.d.ts +74 -0
- package/dist/types/chrome/qrcode.d.ts +48 -0
- package/dist/types/chrome/segment-track.d.ts +27 -0
- package/dist/types/chrome/select-list-mouse-routing.d.ts +4 -0
- package/dist/types/chrome/selector-helpers.d.ts +52 -0
- package/dist/types/chrome/shared.d.ts +5 -0
- package/dist/types/chrome/streaming-panel.d.ts +19 -0
- package/dist/types/chrome/tool-activity.d.ts +17 -0
- package/dist/types/chrome/transcript-container.d.ts +129 -0
- package/dist/types/chrome/transcript-status.d.ts +12 -0
- package/dist/types/chrome/visual-truncate.d.ts +19 -0
- package/dist/types/components/disclosure.d.ts +42 -0
- package/dist/types/components/form.d.ts +130 -0
- package/dist/types/components/image.d.ts +18 -16
- package/dist/types/components/key-value-list.d.ts +24 -0
- package/dist/types/components/layout/geometry.d.ts +73 -0
- package/dist/types/components/layout/row.d.ts +55 -0
- package/dist/types/components/layout/split-pane.d.ts +80 -0
- package/dist/types/components/layout/stack.d.ts +50 -0
- package/dist/types/components/menu-selection.d.ts +71 -0
- package/dist/types/components/metric.d.ts +44 -0
- package/dist/types/components/progress-bar.d.ts +36 -0
- package/dist/types/components/scroll-view.d.ts +53 -19
- package/dist/types/components/scroll-viewport.d.ts +46 -0
- package/dist/types/components/section.d.ts +19 -0
- package/dist/types/components/select-list.d.ts +46 -2
- package/dist/types/components/settings-list.d.ts +20 -0
- package/dist/types/components/table.d.ts +32 -0
- package/dist/types/components/tree-view.d.ts +130 -0
- package/dist/types/components/wizard-step.d.ts +60 -0
- package/dist/types/hotkeys-markdown.d.ts +7 -0
- package/dist/types/index.d.ts +17 -0
- package/dist/types/keybinding-matchers.d.ts +35 -0
- package/dist/types/keys.d.ts +2 -2
- package/dist/types/lang-from-path.d.ts +9 -0
- package/dist/types/overlays/advisor-config.d.ts +114 -0
- package/dist/types/overlays/agent-activity.d.ts +41 -0
- package/dist/types/overlays/agent-hub-projection.d.ts +33 -0
- package/dist/types/overlays/agent-hub-renderer.d.ts +53 -0
- package/dist/types/overlays/agent-hub-types.d.ts +99 -0
- package/dist/types/overlays/agent-hub.d.ts +126 -0
- package/dist/types/overlays/agent-transcript-viewer.d.ts +71 -0
- package/dist/types/overlays/agents-hub.d.ts +72 -0
- package/dist/types/overlays/ask-dialog.d.ts +88 -0
- package/dist/types/overlays/bordered-loader.d.ts +11 -0
- package/dist/types/overlays/btw-history-panel.d.ts +29 -0
- package/dist/types/overlays/btw-history.d.ts +17 -0
- package/dist/types/overlays/btw-panel.d.ts +26 -0
- package/dist/types/overlays/cleanse-panel.d.ts +36 -0
- package/dist/types/overlays/codex-reset-fireworks.d.ts +52 -0
- package/dist/types/overlays/composer-shape-preview.d.ts +47 -0
- package/dist/types/overlays/composer-shape-registry.d.ts +50 -0
- package/dist/types/overlays/copy-selector.d.ts +48 -0
- package/dist/types/overlays/copy-targets.d.ts +63 -0
- package/dist/types/overlays/error-banner.d.ts +13 -0
- package/dist/types/overlays/extensions/display-text.d.ts +10 -0
- package/dist/types/overlays/extensions/extension-dashboard.d.ts +63 -0
- package/dist/types/overlays/extensions/extension-list.d.ts +54 -0
- package/dist/types/overlays/extensions/inspector-model.d.ts +109 -0
- package/dist/types/overlays/extensions/inspector-panel.d.ts +17 -0
- package/dist/types/overlays/extensions/live-tool-session.d.ts +28 -0
- package/dist/types/overlays/extensions/mcp-runtime.d.ts +107 -0
- package/dist/types/overlays/extensions/state-manager.d.ts +42 -0
- package/dist/types/overlays/extensions/types.d.ts +165 -0
- package/dist/types/overlays/history-search.d.ts +16 -0
- package/dist/types/overlays/hook-editor.d.ts +44 -0
- package/dist/types/overlays/hook-input.d.ts +20 -0
- package/dist/types/overlays/hook-selector.d.ts +71 -0
- package/dist/types/overlays/hub-frame.d.ts +77 -0
- package/dist/types/overlays/login-dialog.d.ts +43 -0
- package/dist/types/overlays/logout-account-selector.d.ts +15 -0
- package/dist/types/overlays/mcp-add-wizard.d.ts +87 -0
- package/dist/types/overlays/model-browser.d.ts +213 -0
- package/dist/types/overlays/model-hub.d.ts +72 -0
- package/dist/types/overlays/model-picker.d.ts +74 -0
- package/dist/types/overlays/model-selector.d.ts +52 -0
- package/dist/types/overlays/move-overlay.d.ts +39 -0
- package/dist/types/overlays/oauth-selector.d.ts +41 -0
- package/dist/types/overlays/omfg-panel.d.ts +20 -0
- package/dist/types/overlays/pause-screen.d.ts +43 -0
- package/dist/types/overlays/plan-review-overlay.d.ts +89 -0
- package/dist/types/overlays/plan-save-overlay.d.ts +19 -0
- package/dist/types/overlays/plan-toc.d.ts +41 -0
- package/dist/types/overlays/plugin-selector.d.ts +28 -0
- package/dist/types/overlays/plugin-settings.d.ts +180 -0
- package/dist/types/overlays/queue-mode-selector.d.ts +11 -0
- package/dist/types/overlays/reset-usage-selector.d.ts +23 -0
- package/dist/types/overlays/rewind-selector.d.ts +61 -0
- package/dist/types/overlays/running-subagent-badge.d.ts +6 -0
- package/dist/types/overlays/session-account-selector.d.ts +24 -0
- package/dist/types/overlays/session-info-overlay.d.ts +17 -0
- package/dist/types/overlays/session-observer-registry.d.ts +77 -0
- package/dist/types/overlays/session-selector.d.ts +131 -0
- package/dist/types/overlays/settings-defs.d.ts +119 -0
- package/dist/types/overlays/settings-selector.d.ts +73 -0
- package/dist/types/overlays/show-images-selector.d.ts +11 -0
- package/dist/types/overlays/snapcompact-shape-preview.d.ts +31 -0
- package/dist/types/overlays/theme-selector.d.ts +12 -0
- package/dist/types/overlays/thinking-selector.d.ts +12 -0
- package/dist/types/overlays/tiny-title-download-progress.d.ts +21 -0
- package/dist/types/overlays/tree-selector.d.ts +92 -0
- package/dist/types/overlays/usage-dashboard.d.ts +94 -0
- package/dist/types/overlays/usage-display.d.ts +5 -0
- package/dist/types/overlays/usage-row.d.ts +17 -0
- package/dist/types/prompt/attachment-chips.d.ts +19 -0
- package/dist/types/prompt/composer-attachments.d.ts +71 -0
- package/dist/types/prompt/composer-cache.d.ts +37 -0
- package/dist/types/prompt/composer.d.ts +159 -0
- package/dist/types/prompt/custom-editor.d.ts +261 -0
- package/dist/types/prompt/editor-top-gap.d.ts +18 -0
- package/dist/types/prompt/emoji-autocomplete.d.ts +16 -0
- package/dist/types/prompt/github-ref-autocomplete.d.ts +35 -0
- package/dist/types/prompt/gradient-highlight.d.ts +32 -0
- package/dist/types/prompt/image-format.d.ts +4 -0
- package/dist/types/prompt/image-references.d.ts +26 -0
- package/dist/types/prompt/interactive-context-helpers.d.ts +43 -0
- package/dist/types/prompt/internal-url-autocomplete.d.ts +56 -0
- package/dist/types/prompt/macos-spelling.d.ts +44 -0
- package/dist/types/prompt/magic-keyword-boundary.d.ts +9 -0
- package/dist/types/prompt/magic-keywords.d.ts +26 -0
- package/dist/types/prompt/markdown-prose.d.ts +15 -0
- package/dist/types/prompt/model-mention-autocomplete.d.ts +25 -0
- package/dist/types/prompt/model-mention-syntax.d.ts +24 -0
- package/dist/types/prompt/orchestrate.d.ts +13 -0
- package/dist/types/prompt/prompt-action-autocomplete.d.ts +56 -0
- package/dist/types/prompt/queue-input.d.ts +8 -0
- package/dist/types/prompt/skill-tokens.d.ts +13 -0
- package/dist/types/prompt/tools-markdown.d.ts +12 -0
- package/dist/types/prompt/ultrathink.d.ts +13 -0
- package/dist/types/prompt/usage-amounts.d.ts +26 -0
- package/dist/types/prompt/video.d.ts +18 -0
- package/dist/types/prompt/welcome.d.ts +83 -0
- package/dist/types/prompt/workflow.d.ts +13 -0
- package/dist/types/render/code-cell.d.ts +51 -0
- package/dist/types/render/file-list.d.ts +22 -0
- package/dist/types/render/hyperlink.d.ts +80 -0
- package/dist/types/render/index.d.ts +16 -0
- package/dist/types/render/output-block.d.ts +54 -0
- package/dist/types/render/output-pane.d.ts +80 -0
- package/dist/types/render/render-utils.d.ts +312 -0
- package/dist/types/render/sixel.d.ts +21 -0
- package/dist/types/render/status-line.d.ts +23 -0
- package/dist/types/render/tool-card.d.ts +71 -0
- package/dist/types/render/tree-list.d.ts +29 -0
- package/dist/types/render/types.d.ts +17 -0
- package/dist/types/render/utils.d.ts +43 -0
- package/dist/types/render/width-aware-text.d.ts +23 -0
- package/dist/types/setup/lazy.d.ts +3 -0
- package/dist/types/setup/scenes/composer.d.ts +3 -0
- package/dist/types/setup/scenes/glyph.d.ts +3 -0
- package/dist/types/setup/scenes/model.d.ts +3 -0
- package/dist/types/setup/scenes/outro.d.ts +2 -0
- package/dist/types/setup/scenes/providers.d.ts +3 -0
- package/dist/types/setup/scenes/sign-in.d.ts +21 -0
- package/dist/types/setup/scenes/splash.d.ts +11 -0
- package/dist/types/setup/scenes/theme.d.ts +3 -0
- package/dist/types/setup/scenes/types.d.ts +110 -0
- package/dist/types/setup/scenes/web-search.d.ts +22 -0
- package/dist/types/setup/setup-version.d.ts +11 -0
- package/dist/types/setup/startup-splash.d.ts +9 -0
- package/dist/types/setup/wizard-overlay.d.ts +16 -0
- package/dist/types/setup/wizard.d.ts +25 -0
- package/dist/types/status-line/component.d.ts +182 -0
- package/dist/types/status-line/context-usage.d.ts +156 -0
- package/dist/types/status-line/footer.d.ts +30 -0
- package/dist/types/status-line/git-utils.d.ts +22 -0
- package/dist/types/status-line/host.d.ts +129 -0
- package/dist/types/status-line/index.d.ts +6 -0
- package/dist/types/status-line/loop.d.ts +18 -0
- package/dist/types/status-line/metrics.d.ts +21 -0
- package/dist/types/status-line/presets.d.ts +3 -0
- package/dist/types/status-line/schema.d.ts +15 -0
- package/dist/types/status-line/segments.d.ts +5 -0
- package/dist/types/status-line/separators.d.ts +3 -0
- package/dist/types/status-line/types.d.ts +236 -0
- package/dist/types/stdin-buffer.d.ts +4 -0
- package/dist/types/theme/color.d.ts +24 -0
- package/dist/types/theme/defaults/index.d.ts +9489 -0
- package/dist/types/theme/index.d.ts +4 -0
- package/dist/types/theme/loader.d.ts +23 -0
- package/dist/types/theme/mermaid-cache.d.ts +26 -0
- package/dist/types/theme/schema-validation.d.ts +3 -0
- package/dist/types/theme/schema.d.ts +25 -0
- package/dist/types/theme/session-color.d.ts +43 -0
- package/dist/types/theme/shimmer.d.ts +44 -0
- package/dist/types/theme/symbols.d.ts +34 -0
- package/dist/types/theme/theme-class.d.ts +299 -0
- package/dist/types/theme/theme.d.ts +111 -0
- package/dist/types/theme/tui-adapters.d.ts +30 -0
- package/dist/types/thinking.d.ts +165 -0
- package/dist/types/tools/agent-tree.d.ts +36 -0
- package/dist/types/tools/ask.d.ts +67 -0
- package/dist/types/tools/ast-edit.d.ts +53 -0
- package/dist/types/tools/ast-grep.d.ts +52 -0
- package/dist/types/tools/autoresearch.d.ts +156 -0
- package/dist/types/tools/bash-interactive.d.ts +28 -0
- package/dist/types/tools/bash.d.ts +103 -0
- package/dist/types/tools/conflict-detect.d.ts +43 -0
- package/dist/types/tools/debug.d.ts +60 -0
- package/dist/types/tools/default-renderer.d.ts +24 -0
- package/dist/types/tools/edit.d.ts +158 -0
- package/dist/types/tools/eval-format/code-mode-declarations.d.ts +5 -0
- package/dist/types/tools/eval-format/index.d.ts +5 -0
- package/dist/types/tools/eval-format/javascript.d.ts +2 -0
- package/dist/types/tools/eval-format/python.d.ts +2 -0
- package/dist/types/tools/eval.d.ts +94 -0
- package/dist/types/tools/fetch.d.ts +42 -0
- package/dist/types/tools/gh-format.d.ts +8 -0
- package/dist/types/tools/github.d.ts +144 -0
- package/dist/types/tools/glob.d.ts +44 -0
- package/dist/types/tools/goal.d.ts +42 -0
- package/dist/types/tools/grep.d.ts +64 -0
- package/dist/types/tools/grouped-file-output.d.ts +71 -0
- package/dist/types/tools/hashline-format.d.ts +28 -0
- package/dist/types/tools/hub.d.ts +340 -0
- package/dist/types/tools/index.d.ts +4 -0
- package/dist/types/tools/json-tree.d.ts +59 -0
- package/dist/types/tools/line-ranges.d.ts +29 -0
- package/dist/types/tools/list-limit.d.ts +15 -0
- package/dist/types/tools/lsp.d.ts +72 -0
- package/dist/types/tools/match-line-format.d.ts +11 -0
- package/dist/types/tools/mcp.d.ts +81 -0
- package/dist/types/tools/memory.d.ts +67 -0
- package/dist/types/tools/output-meta.d.ts +151 -0
- package/dist/types/tools/read.d.ts +139 -0
- package/dist/types/tools/renderer.d.ts +98 -0
- package/dist/types/tools/report-tool-issue.d.ts +8 -0
- package/dist/types/tools/resolve.d.ts +47 -0
- package/dist/types/tools/streaming-output.d.ts +282 -0
- package/dist/types/tools/subprocess.d.ts +24 -0
- package/dist/types/tools/task-repair-args.d.ts +53 -0
- package/dist/types/tools/task-yield-assembly.d.ts +20 -0
- package/dist/types/tools/task.d.ts +425 -0
- package/dist/types/tools/terminal-output.d.ts +8 -0
- package/dist/types/tools/think.d.ts +13 -0
- package/dist/types/tools/todo.d.ts +118 -0
- package/dist/types/tools/tool-errors.d.ts +7 -0
- package/dist/types/tools/vibe.d.ts +120 -0
- package/dist/types/tools/web-search.d.ts +195 -0
- package/dist/types/tools/write.d.ts +76 -0
- package/dist/types/tools/xd-url.d.ts +13 -0
- package/dist/types/tools/xdev.d.ts +52 -0
- package/dist/types/tui.d.ts +18 -0
- package/dist/types/utils.d.ts +2 -0
- package/package.json +37 -3
- package/src/app-keybindings.ts +760 -0
- package/src/apps/autoresearch-dashboard.ts +500 -0
- package/src/apps/autoresearch-data.ts +64 -0
- package/src/apps/cleanse-board.ts +341 -0
- package/src/apps/cleanse-picker.ts +57 -0
- package/src/apps/debug/log-formatting.ts +53 -0
- package/src/apps/debug/log-viewer.ts +868 -0
- package/src/apps/debug/protocol-probe.ts +267 -0
- package/src/apps/debug/raw-sse-buffer.ts +449 -0
- package/src/apps/debug/raw-sse.ts +282 -0
- package/src/apps/debug/terminal-info.ts +115 -0
- package/src/apps/debug/viewer-frame.ts +174 -0
- package/src/apps/git/avatar.ts +52 -0
- package/src/apps/git/colors.ts +109 -0
- package/src/apps/git/diff-pane.ts +1512 -0
- package/src/apps/git/git-tui.ts +889 -0
- package/src/apps/git/sidebar.ts +1204 -0
- package/src/apps/git/state.ts +113 -0
- package/src/apps/if-bench-board.ts +324 -0
- package/src/apps/live-visualizer.ts +238 -0
- package/src/apps/ps-data.ts +116 -0
- package/src/apps/ps-top.ts +422 -0
- package/src/apps/session-picker.ts +95 -0
- package/src/apps/setup-model-picker.ts +21 -0
- package/src/apps/standalone-picker.ts +111 -0
- package/src/autocomplete.ts +9 -13
- package/src/chat/advisor-message.ts +175 -0
- package/src/chat/assistant-message.ts +1214 -0
- package/src/chat/background-tan-message.ts +35 -0
- package/src/chat/bash-execution.ts +394 -0
- package/src/chat/cache-invalidation-marker.ts +94 -0
- package/src/chat/chat-transcript-builder.ts +593 -0
- package/src/chat/collab-prompt-message.ts +34 -0
- package/src/chat/compaction-summary-message.ts +261 -0
- package/src/chat/custom-message.ts +23 -0
- package/src/chat/display-preferences.ts +24 -0
- package/src/chat/eval-execution.ts +172 -0
- package/src/chat/execution-shared.ts +113 -0
- package/src/chat/extension-types.ts +46 -0
- package/src/chat/hook-message.ts +20 -0
- package/src/chat/image-loading.ts +122 -0
- package/src/chat/late-diagnostics-message.ts +92 -0
- package/src/chat/messages.ts +305 -0
- package/src/chat/reaction.ts +65 -0
- package/src/chat/read-target.ts +7 -0
- package/src/chat/read-tool-group.ts +873 -0
- package/src/chat/served-model-marker.ts +91 -0
- package/src/chat/skill-message.ts +220 -0
- package/src/chat/skill-title-input.ts +41 -0
- package/src/chat/stripped-tool-calls-placeholder.ts +35 -0
- package/src/chat/thinking-display.ts +312 -0
- package/src/chat/todo-reminder.ts +33 -0
- package/src/chat/tool-execution.ts +1395 -0
- package/src/chat/transcript-browser.ts +268 -0
- package/src/chat/transcript-entry.ts +96 -0
- package/src/chat/transcript-outline.ts +260 -0
- package/src/chat/transcript-render-helpers.ts +315 -0
- package/src/chat/ttsr-notification.ts +123 -0
- package/src/chat/user-message.ts +287 -0
- package/src/chrome/chat-block.ts +110 -0
- package/src/chrome/collab-qrcode.ts +74 -0
- package/src/chrome/context-thresholds.ts +85 -0
- package/src/chrome/countdown-timer.ts +74 -0
- package/src/chrome/diff.ts +266 -0
- package/src/chrome/dynamic-border.ts +36 -0
- package/src/chrome/error-block.ts +63 -0
- package/src/chrome/form-theme.ts +10 -0
- package/src/chrome/format.ts +66 -0
- package/src/chrome/index.ts +21 -0
- package/src/chrome/keybinding-hints.ts +55 -0
- package/src/chrome/live-board.ts +123 -0
- package/src/chrome/local-date.ts +20 -0
- package/src/chrome/message-divider.ts +51 -0
- package/src/chrome/message-frame.ts +164 -0
- package/src/chrome/message-notice.ts +103 -0
- package/src/chrome/overlay-box.ts +301 -0
- package/src/chrome/qrcode.ts +539 -0
- package/src/chrome/segment-track.ts +86 -0
- package/src/chrome/select-list-mouse-routing.ts +11 -0
- package/src/chrome/selector-helpers.ts +119 -0
- package/src/chrome/shared.ts +27 -0
- package/src/chrome/streaming-panel.ts +72 -0
- package/src/chrome/tool-activity.ts +44 -0
- package/src/chrome/transcript-container.ts +902 -0
- package/src/chrome/transcript-status.ts +27 -0
- package/src/chrome/visual-truncate.ts +70 -0
- package/src/components/disclosure.ts +235 -0
- package/src/components/editor.ts +10 -12
- package/src/components/form.ts +566 -0
- package/src/components/image.ts +80 -53
- package/src/components/input.ts +6 -27
- package/src/components/key-value-list.ts +88 -0
- package/src/components/layout/geometry.ts +202 -0
- package/src/components/layout/row.ts +283 -0
- package/src/components/layout/split-pane.ts +349 -0
- package/src/components/layout/stack.ts +261 -0
- package/src/components/markdown.ts +16 -12
- package/src/components/menu-selection.ts +248 -0
- package/src/components/metric.ts +132 -0
- package/src/components/progress-bar.ts +140 -0
- package/src/components/scroll-view.ts +372 -70
- package/src/components/scroll-viewport.ts +154 -0
- package/src/components/section.ts +77 -0
- package/src/components/select-list.ts +238 -159
- package/src/components/settings-list.ts +103 -80
- package/src/components/table.ts +127 -0
- package/src/components/tree-view.ts +481 -0
- package/src/components/wizard-step.ts +229 -0
- package/src/deccara.ts +1 -3
- package/src/hotkeys-markdown.ts +100 -0
- package/src/index.ts +18 -0
- package/src/keybinding-matchers.ts +99 -0
- package/src/keys.ts +2 -2
- package/src/lang-from-path.ts +252 -0
- package/src/overlays/advisor-config.ts +761 -0
- package/src/overlays/agent-activity.ts +113 -0
- package/src/overlays/agent-hub-projection.ts +250 -0
- package/src/overlays/agent-hub-renderer.ts +281 -0
- package/src/overlays/agent-hub-types.ts +74 -0
- package/src/overlays/agent-hub.ts +1562 -0
- package/src/overlays/agent-transcript-viewer.ts +669 -0
- package/src/overlays/agents-hub.ts +1203 -0
- package/src/overlays/ask-dialog.ts +1202 -0
- package/src/overlays/bordered-loader.ts +41 -0
- package/src/overlays/btw-history-panel.ts +591 -0
- package/src/overlays/btw-history.ts +33 -0
- package/src/overlays/btw-panel.ts +167 -0
- package/src/overlays/cleanse-panel.ts +167 -0
- package/src/overlays/codex-reset-fireworks.ts +375 -0
- package/src/overlays/composer-shape-preview.ts +137 -0
- package/src/overlays/composer-shape-registry.ts +82 -0
- package/src/overlays/copy-selector.ts +618 -0
- package/src/overlays/copy-targets.ts +210 -0
- package/src/overlays/error-banner.ts +39 -0
- package/src/overlays/extensions/display-text.ts +39 -0
- package/src/overlays/extensions/extension-dashboard.ts +645 -0
- package/src/overlays/extensions/extension-list.ts +667 -0
- package/src/overlays/extensions/inspector-model.ts +484 -0
- package/src/overlays/extensions/inspector-panel.ts +669 -0
- package/src/overlays/extensions/live-tool-session.ts +67 -0
- package/src/overlays/extensions/mcp-runtime.ts +289 -0
- package/src/overlays/extensions/state-manager.ts +337 -0
- package/src/overlays/extensions/types.ts +208 -0
- package/src/overlays/history-search.ts +268 -0
- package/src/overlays/hook-editor.ts +272 -0
- package/src/overlays/hook-input.ts +84 -0
- package/src/overlays/hook-selector.ts +635 -0
- package/src/overlays/hub-frame.ts +262 -0
- package/src/overlays/login-dialog.ts +231 -0
- package/src/overlays/logout-account-selector.ts +115 -0
- package/src/overlays/mcp-add-wizard.ts +1436 -0
- package/src/overlays/model-browser.ts +1176 -0
- package/src/overlays/model-hub.ts +2279 -0
- package/src/overlays/model-picker.ts +285 -0
- package/src/overlays/model-selector.ts +107 -0
- package/src/overlays/move-overlay.ts +197 -0
- package/src/overlays/oauth-selector.ts +446 -0
- package/src/overlays/omfg-panel.ts +136 -0
- package/src/overlays/pause-screen.ts +198 -0
- package/src/overlays/plan-review-overlay.ts +1227 -0
- package/src/overlays/plan-save-overlay.ts +74 -0
- package/src/overlays/plan-toc.ts +139 -0
- package/src/overlays/plugin-selector.ts +97 -0
- package/src/overlays/plugin-settings.ts +839 -0
- package/src/overlays/queue-mode-selector.ts +55 -0
- package/src/overlays/reset-usage-selector.ts +170 -0
- package/src/overlays/rewind-selector.ts +499 -0
- package/src/overlays/running-subagent-badge.ts +19 -0
- package/src/overlays/session-account-selector.ts +68 -0
- package/src/overlays/session-info-overlay.ts +96 -0
- package/src/overlays/session-observer-registry.ts +289 -0
- package/src/overlays/session-selector.ts +1137 -0
- package/src/overlays/settings-defs.ts +315 -0
- package/src/overlays/settings-selector.ts +1415 -0
- package/src/overlays/show-images-selector.ts +44 -0
- package/src/overlays/snapcompact-shape-preview-doc.md +14 -0
- package/src/overlays/snapcompact-shape-preview.ts +192 -0
- package/src/overlays/theme-selector.ts +62 -0
- package/src/overlays/thinking-selector.ts +51 -0
- package/src/overlays/tiny-title-download-progress.ts +102 -0
- package/src/overlays/tree-selector.ts +1121 -0
- package/src/overlays/usage-dashboard.ts +629 -0
- package/src/overlays/usage-display.ts +45 -0
- package/src/overlays/usage-row.ts +118 -0
- package/src/prompt/attachment-chips.ts +201 -0
- package/src/prompt/composer-attachments.ts +280 -0
- package/src/prompt/composer-cache.ts +304 -0
- package/src/prompt/composer.ts +934 -0
- package/src/prompt/custom-editor.ts +1392 -0
- package/src/prompt/data/emojis.json +1 -0
- package/src/prompt/editor-top-gap.ts +28 -0
- package/src/prompt/emoji-autocomplete.ts +285 -0
- package/src/prompt/github-ref-autocomplete.ts +75 -0
- package/src/prompt/gradient-highlight.ts +101 -0
- package/src/prompt/image-format.ts +28 -0
- package/src/prompt/image-references.ts +102 -0
- package/src/prompt/interactive-context-helpers.ts +126 -0
- package/src/prompt/internal-url-autocomplete.ts +155 -0
- package/src/prompt/macos-spelling.ts +456 -0
- package/src/prompt/magic-keyword-boundary.ts +23 -0
- package/src/prompt/magic-keywords.ts +42 -0
- package/src/prompt/markdown-prose.ts +245 -0
- package/src/prompt/model-mention-autocomplete.ts +94 -0
- package/src/prompt/model-mention-syntax.ts +41 -0
- package/src/prompt/orchestrate.ts +26 -0
- package/src/prompt/prompt-action-autocomplete.ts +337 -0
- package/src/prompt/queue-input.ts +132 -0
- package/src/prompt/skill-tokens.ts +36 -0
- package/src/prompt/tips.txt +27 -0
- package/src/prompt/tools-markdown.ts +29 -0
- package/src/prompt/ultrathink.ts +26 -0
- package/src/prompt/usage-amounts.ts +99 -0
- package/src/prompt/video.ts +47 -0
- package/src/prompt/welcome.ts +605 -0
- package/src/prompt/workflow.ts +26 -0
- package/src/render/code-cell.ts +244 -0
- package/src/render/file-list.ts +58 -0
- package/src/render/hyperlink.ts +192 -0
- package/src/render/index.ts +17 -0
- package/src/render/output-block.ts +267 -0
- package/src/render/output-pane.ts +299 -0
- package/src/render/render-utils.ts +1182 -0
- package/src/render/sixel.ts +69 -0
- package/src/render/status-line.ts +55 -0
- package/src/render/tool-card.ts +272 -0
- package/src/render/tree-list.ts +188 -0
- package/src/render/types.ts +19 -0
- package/src/render/utils.ts +109 -0
- package/src/render/width-aware-text.ts +60 -0
- package/src/setup/lazy.ts +17 -0
- package/src/setup/scenes/composer.ts +127 -0
- package/src/setup/scenes/glyph.ts +120 -0
- package/src/setup/scenes/model.ts +138 -0
- package/src/setup/scenes/outro.ts +24 -0
- package/src/setup/scenes/providers.ts +107 -0
- package/src/setup/scenes/sign-in.ts +373 -0
- package/src/setup/scenes/splash.ts +192 -0
- package/src/setup/scenes/theme.ts +343 -0
- package/src/setup/scenes/types.ts +111 -0
- package/src/setup/scenes/web-search.ts +165 -0
- package/src/setup/setup-version.ts +11 -0
- package/src/setup/startup-splash.ts +107 -0
- package/src/setup/wizard-overlay.ts +319 -0
- package/src/setup/wizard.ts +101 -0
- package/src/status-line/component.ts +3003 -0
- package/src/status-line/context-usage.ts +688 -0
- package/src/status-line/footer.ts +323 -0
- package/src/status-line/git-utils.ts +42 -0
- package/src/status-line/host.ts +97 -0
- package/src/status-line/index.ts +6 -0
- package/src/status-line/loop.ts +28 -0
- package/src/status-line/metrics.ts +94 -0
- package/src/status-line/presets.ts +107 -0
- package/src/status-line/schema.ts +57 -0
- package/src/status-line/segments.ts +934 -0
- package/src/status-line/separators.ts +55 -0
- package/src/status-line/types.ts +227 -0
- package/src/stdin-buffer.ts +4 -2
- package/src/theme/color.ts +95 -0
- package/src/theme/dark.json +95 -0
- package/src/theme/defaults/alabaster.json +93 -0
- package/src/theme/defaults/amethyst.json +96 -0
- package/src/theme/defaults/anthracite.json +93 -0
- package/src/theme/defaults/basalt.json +91 -0
- package/src/theme/defaults/birch.json +95 -0
- package/src/theme/defaults/dark-abyss.json +91 -0
- package/src/theme/defaults/dark-arctic.json +104 -0
- package/src/theme/defaults/dark-aurora.json +95 -0
- package/src/theme/defaults/dark-catppuccin.json +107 -0
- package/src/theme/defaults/dark-cavern.json +91 -0
- package/src/theme/defaults/dark-celestial.json +106 -0
- package/src/theme/defaults/dark-copper.json +95 -0
- package/src/theme/defaults/dark-cosmos.json +90 -0
- package/src/theme/defaults/dark-cyberpunk.json +102 -0
- package/src/theme/defaults/dark-dracula.json +98 -0
- package/src/theme/defaults/dark-eclipse.json +91 -0
- package/src/theme/defaults/dark-ember.json +95 -0
- package/src/theme/defaults/dark-equinox.json +90 -0
- package/src/theme/defaults/dark-forest.json +96 -0
- package/src/theme/defaults/dark-github.json +105 -0
- package/src/theme/defaults/dark-gruvbox.json +112 -0
- package/src/theme/defaults/dark-lavender.json +95 -0
- package/src/theme/defaults/dark-lunar.json +89 -0
- package/src/theme/defaults/dark-midnight.json +95 -0
- package/src/theme/defaults/dark-monochrome.json +94 -0
- package/src/theme/defaults/dark-monokai.json +98 -0
- package/src/theme/defaults/dark-nebula.json +90 -0
- package/src/theme/defaults/dark-nord.json +98 -0
- package/src/theme/defaults/dark-ocean.json +101 -0
- package/src/theme/defaults/dark-one.json +100 -0
- package/src/theme/defaults/dark-poimandres.json +115 -0
- package/src/theme/defaults/dark-rainforest.json +91 -0
- package/src/theme/defaults/dark-reef.json +91 -0
- package/src/theme/defaults/dark-retro.json +92 -0
- package/src/theme/defaults/dark-rose-pine.json +96 -0
- package/src/theme/defaults/dark-sakura.json +95 -0
- package/src/theme/defaults/dark-slate.json +95 -0
- package/src/theme/defaults/dark-solarized.json +97 -0
- package/src/theme/defaults/dark-solstice.json +90 -0
- package/src/theme/defaults/dark-starfall.json +91 -0
- package/src/theme/defaults/dark-sunset.json +99 -0
- package/src/theme/defaults/dark-swamp.json +90 -0
- package/src/theme/defaults/dark-synthwave.json +103 -0
- package/src/theme/defaults/dark-taiga.json +91 -0
- package/src/theme/defaults/dark-terminal.json +95 -0
- package/src/theme/defaults/dark-tokyo-night.json +101 -0
- package/src/theme/defaults/dark-tundra.json +91 -0
- package/src/theme/defaults/dark-twilight.json +91 -0
- package/src/theme/defaults/dark-volcanic.json +91 -0
- package/src/theme/defaults/graphite.json +92 -0
- package/src/theme/defaults/index.ts +201 -0
- package/src/theme/defaults/light-arctic.json +107 -0
- package/src/theme/defaults/light-aurora-day.json +91 -0
- package/src/theme/defaults/light-canyon.json +91 -0
- package/src/theme/defaults/light-catppuccin.json +106 -0
- package/src/theme/defaults/light-cirrus.json +90 -0
- package/src/theme/defaults/light-coral.json +95 -0
- package/src/theme/defaults/light-cyberpunk.json +96 -0
- package/src/theme/defaults/light-dawn.json +90 -0
- package/src/theme/defaults/light-dunes.json +91 -0
- package/src/theme/defaults/light-eucalyptus.json +95 -0
- package/src/theme/defaults/light-forest.json +100 -0
- package/src/theme/defaults/light-frost.json +95 -0
- package/src/theme/defaults/light-github.json +115 -0
- package/src/theme/defaults/light-glacier.json +91 -0
- package/src/theme/defaults/light-gruvbox.json +108 -0
- package/src/theme/defaults/light-haze.json +90 -0
- package/src/theme/defaults/light-honeycomb.json +95 -0
- package/src/theme/defaults/light-lagoon.json +91 -0
- package/src/theme/defaults/light-lavender.json +95 -0
- package/src/theme/defaults/light-meadow.json +91 -0
- package/src/theme/defaults/light-mint.json +95 -0
- package/src/theme/defaults/light-monochrome.json +101 -0
- package/src/theme/defaults/light-ocean.json +99 -0
- package/src/theme/defaults/light-one.json +99 -0
- package/src/theme/defaults/light-opal.json +91 -0
- package/src/theme/defaults/light-orchard.json +91 -0
- package/src/theme/defaults/light-paper.json +95 -0
- package/src/theme/defaults/light-poimandres.json +115 -0
- package/src/theme/defaults/light-prism.json +90 -0
- package/src/theme/defaults/light-retro.json +98 -0
- package/src/theme/defaults/light-sand.json +95 -0
- package/src/theme/defaults/light-savanna.json +91 -0
- package/src/theme/defaults/light-solarized.json +102 -0
- package/src/theme/defaults/light-soleil.json +90 -0
- package/src/theme/defaults/light-sunset.json +99 -0
- package/src/theme/defaults/light-synthwave.json +98 -0
- package/src/theme/defaults/light-tokyo-night.json +111 -0
- package/src/theme/defaults/light-wetland.json +91 -0
- package/src/theme/defaults/light-zenith.json +89 -0
- package/src/theme/defaults/limestone.json +94 -0
- package/src/theme/defaults/mahogany.json +97 -0
- package/src/theme/defaults/marble.json +93 -0
- package/src/theme/defaults/obsidian.json +91 -0
- package/src/theme/defaults/onyx.json +91 -0
- package/src/theme/defaults/pearl.json +93 -0
- package/src/theme/defaults/porcelain.json +91 -0
- package/src/theme/defaults/quartz.json +96 -0
- package/src/theme/defaults/sandstone.json +95 -0
- package/src/theme/defaults/titanium.json +90 -0
- package/src/theme/index.ts +5 -0
- package/src/theme/light.json +93 -0
- package/src/theme/loader.ts +200 -0
- package/src/theme/mermaid-cache.ts +92 -0
- package/src/theme/schema-validation.ts +119 -0
- package/src/theme/schema.ts +168 -0
- package/src/theme/session-color.ts +253 -0
- package/src/theme/shimmer.ts +307 -0
- package/src/theme/symbols.ts +1433 -0
- package/src/theme/theme-class.ts +787 -0
- package/src/theme/theme-schema.json +463 -0
- package/src/theme/theme.ts +810 -0
- package/src/theme/tui-adapters.ts +339 -0
- package/src/thinking.ts +380 -0
- package/src/tools/agent-tree.ts +128 -0
- package/src/tools/ask.ts +482 -0
- package/src/tools/ast-edit.ts +210 -0
- package/src/tools/ast-grep.ts +171 -0
- package/src/tools/autoresearch.ts +287 -0
- package/src/tools/bash-interactive.ts +295 -0
- package/src/tools/bash.ts +468 -0
- package/src/tools/conflict-detect.ts +77 -0
- package/src/tools/debug.ts +167 -0
- package/src/tools/default-renderer.ts +172 -0
- package/src/tools/edit.ts +1258 -0
- package/src/tools/eval-format/code-mode-declarations.ts +61 -0
- package/src/tools/eval-format/index.ts +16 -0
- package/src/tools/eval-format/javascript.ts +952 -0
- package/src/tools/eval-format/python.ts +544 -0
- package/src/tools/eval.ts +835 -0
- package/src/tools/fetch.ts +226 -0
- package/src/tools/gh-format.ts +18 -0
- package/src/tools/github.ts +686 -0
- package/src/tools/glob.ts +213 -0
- package/src/tools/goal.ts +153 -0
- package/src/tools/grep.ts +385 -0
- package/src/tools/grouped-file-output.ts +211 -0
- package/src/tools/hashline-format.ts +59 -0
- package/src/tools/hub.ts +1488 -0
- package/src/tools/index.ts +71 -0
- package/src/tools/json-tree.ts +388 -0
- package/src/tools/line-ranges.ts +98 -0
- package/src/tools/list-limit.ts +43 -0
- package/src/tools/lsp.ts +702 -0
- package/src/tools/match-line-format.ts +20 -0
- package/src/tools/mcp.ts +309 -0
- package/src/tools/memory.ts +220 -0
- package/src/tools/output-meta.ts +367 -0
- package/src/tools/read.ts +628 -0
- package/src/tools/renderer.ts +107 -0
- package/src/tools/report-tool-issue.ts +13 -0
- package/src/tools/resolve.ts +139 -0
- package/src/tools/streaming-output.ts +1576 -0
- package/src/tools/subprocess.ts +39 -0
- package/src/tools/task-repair-args.ts +118 -0
- package/src/tools/task-yield-assembly.ts +147 -0
- package/src/tools/task.ts +2110 -0
- package/src/tools/terminal-output.ts +153 -0
- package/src/tools/think.ts +28 -0
- package/src/tools/todo.ts +580 -0
- package/src/tools/tool-errors.ts +15 -0
- package/src/tools/vibe.ts +420 -0
- package/src/tools/web-search.ts +409 -0
- package/src/tools/write.ts +511 -0
- package/src/tools/xd-url.ts +28 -0
- package/src/tools/xdev.ts +201 -0
- package/src/tui.ts +70 -8
- package/src/utils.ts +8 -0
package/src/components/image.ts
CHANGED
|
@@ -108,10 +108,10 @@ function nextImageIdSeed(): number {
|
|
|
108
108
|
* Bounds how many inline images render as live terminal graphics at once.
|
|
109
109
|
*
|
|
110
110
|
* Terminal graphics protocols — Kitty especially — keep every transmitted image
|
|
111
|
-
* in a per-
|
|
112
|
-
*
|
|
113
|
-
* shows many images piles up placements plus store memory and
|
|
114
|
-
* scrollback.
|
|
111
|
+
* in a per-screen store and re-draw placements as content scrolls; placements
|
|
112
|
+
* that left the viewport survive text-clear escapes (`CSI 2 J`). Unbounded, a
|
|
113
|
+
* session that shows many images piles up placements plus store memory and
|
|
114
|
+
* leaves ghosts in scrollback.
|
|
115
115
|
*
|
|
116
116
|
* The budget keeps the most recent `cap` images live and demotes older ones to
|
|
117
117
|
* their text fallback. Demotion needs a full redraw (so off-screen rows are
|
|
@@ -165,10 +165,16 @@ export class ImageBudget {
|
|
|
165
165
|
* {@link forgetTransmitted}.
|
|
166
166
|
*/
|
|
167
167
|
#resetPurgeIds: number[] = [];
|
|
168
|
-
/**
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
168
|
+
/**
|
|
169
|
+
* Image ids whose data is believed to be loaded in each screen's store.
|
|
170
|
+
* kitty and Ghostty keep the normal and alternate buffers' graphics apart
|
|
171
|
+
* and wipe the alternate store on every `?1049h`, so data sent while one
|
|
172
|
+
* buffer was active is unknown to the other: a placement there resolves
|
|
173
|
+
* only after its own transmit.
|
|
174
|
+
*/
|
|
175
|
+
#transmitted: Record<Surface, Set<number>> = { screen: new Set(), alt: new Set() };
|
|
176
|
+
/** Transmit sequences (full base64) to write once per surface, before that frame's placements. */
|
|
177
|
+
#pendingTransmits: Record<Surface, Map<number, string>> = { screen: new Map(), alt: new Map() };
|
|
172
178
|
// True while the in-flight pass is a partial/throwaway pass (the
|
|
173
179
|
// non-multiplexer resize viewport fast path) that walks only the visible
|
|
174
180
|
// tail, bottom-up. Such a pass cannot derive display order from observe()
|
|
@@ -258,6 +264,8 @@ export class ImageBudget {
|
|
|
258
264
|
beginAltScreenLifecycle(): void {
|
|
259
265
|
resetSurfaceSplit(this.#altSplit);
|
|
260
266
|
this.#liveIds.alt.clear();
|
|
267
|
+
// `?1049h` hands over an empty graphics store as well as a cleared grid.
|
|
268
|
+
this.#transmitted.alt.clear();
|
|
261
269
|
}
|
|
262
270
|
|
|
263
271
|
/**
|
|
@@ -354,9 +362,10 @@ export class ImageBudget {
|
|
|
354
362
|
*/
|
|
355
363
|
limitResidentImages(): void {
|
|
356
364
|
this.#liveIds[this.#surface] = new Set(this.#passIds.filter(id => this.#passShowsLive(id)));
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
365
|
+
const transmitted = this.#transmitted[this.#surface];
|
|
366
|
+
if (this.#cap <= 0 || transmitted.size <= this.#cap) return;
|
|
367
|
+
for (const id of transmitted) {
|
|
368
|
+
if (transmitted.size <= this.#cap) break;
|
|
360
369
|
this.#retire(id);
|
|
361
370
|
}
|
|
362
371
|
}
|
|
@@ -384,15 +393,17 @@ export class ImageBudget {
|
|
|
384
393
|
}
|
|
385
394
|
|
|
386
395
|
/**
|
|
387
|
-
* Drop `imageId` from the
|
|
388
|
-
* a transmit that never went out) and
|
|
396
|
+
* Drop `imageId` from the painted surface's image store: queue its `d=I` (or
|
|
397
|
+
* cancel a transmit that never went out) and, once no surface holds its data,
|
|
398
|
+
* forget its placement ledger and key.
|
|
389
399
|
*
|
|
390
400
|
* The single gate on every destruction path. `d=I` removes an image's
|
|
391
|
-
* placements everywhere, scrollback included, and a frame diff
|
|
392
|
-
* rows whose text changed — so a graphic some standing frame
|
|
393
|
-
* cannot be repaired once deleted, and must never be a
|
|
394
|
-
* when the in-flight pass renders the image live, or when
|
|
395
|
-
* surface this pass is not repainting does. Returns whether
|
|
401
|
+
* placements everywhere on its screen, scrollback included, and a frame diff
|
|
402
|
+
* only rewrites rows whose text changed — so a graphic some standing frame
|
|
403
|
+
* still shows cannot be repaired once deleted, and must never be a
|
|
404
|
+
* candidate. Refuses when the in-flight pass renders the image live, or when
|
|
405
|
+
* the frame on any surface this pass is not repainting does. Returns whether
|
|
406
|
+
* it was retired.
|
|
396
407
|
*/
|
|
397
408
|
#retire(imageId: number): boolean {
|
|
398
409
|
if (this.#passShowsLive(imageId)) return false;
|
|
@@ -401,13 +412,19 @@ export class ImageBudget {
|
|
|
401
412
|
}
|
|
402
413
|
// A transmit queued by a discarded discovery pass never reached the
|
|
403
414
|
// terminal, so cancel it instead of transmitting then purging.
|
|
404
|
-
if (!this.#pendingTransmits.delete(imageId)) this.#purgeIds.push(imageId);
|
|
405
|
-
this.#transmitted.delete(imageId);
|
|
406
|
-
this.#deletePlacementState(imageId);
|
|
415
|
+
if (!this.#pendingTransmits[this.#surface].delete(imageId)) this.#purgeIds.push(imageId);
|
|
416
|
+
this.#transmitted[this.#surface].delete(imageId);
|
|
417
|
+
if (!this.#isTransmitted(imageId)) this.#deletePlacementState(imageId);
|
|
407
418
|
this.#forgetKeyForId(imageId);
|
|
408
419
|
return true;
|
|
409
420
|
}
|
|
410
421
|
|
|
422
|
+
/** Whether any screen's store is believed to hold `imageId`'s data. */
|
|
423
|
+
#isTransmitted(imageId: number): boolean {
|
|
424
|
+
for (const surface of SURFACES) if (this.#transmitted[surface].has(imageId)) return true;
|
|
425
|
+
return false;
|
|
426
|
+
}
|
|
427
|
+
|
|
411
428
|
/**
|
|
412
429
|
* Image ids a destructive reset must delete explicitly, alongside its `d=A`.
|
|
413
430
|
* Emit only from that reset's repaint; clears the queue.
|
|
@@ -427,25 +444,28 @@ export class ImageBudget {
|
|
|
427
444
|
return ids;
|
|
428
445
|
}
|
|
429
446
|
|
|
430
|
-
/** All image ids believed to be loaded in
|
|
447
|
+
/** All image ids believed to be loaded in any screen's store; clears tracking. */
|
|
431
448
|
takeAllTransmittedIds(): readonly number[] {
|
|
432
|
-
|
|
433
|
-
const
|
|
434
|
-
|
|
449
|
+
const ids = new Set<number>();
|
|
450
|
+
for (const surface of SURFACES) {
|
|
451
|
+
for (const id of this.#transmitted[surface]) ids.add(id);
|
|
452
|
+
this.#transmitted[surface].clear();
|
|
453
|
+
this.#pendingTransmits[surface].clear();
|
|
454
|
+
}
|
|
455
|
+
if (ids.size === 0) return EMPTY_IDS;
|
|
435
456
|
this.#purgeIds = [];
|
|
436
457
|
this.#resetPurgeIds = [];
|
|
437
|
-
this.#pendingTransmits.clear();
|
|
438
458
|
this.#keyToId.clear();
|
|
439
459
|
this.#idToKey.clear();
|
|
440
460
|
this.#placementState.clear();
|
|
441
461
|
this.#watchedPlacements.clear();
|
|
442
462
|
for (const surface of SURFACES) this.#liveIds[surface].clear();
|
|
443
|
-
return ids;
|
|
463
|
+
return [...ids];
|
|
444
464
|
}
|
|
445
465
|
|
|
446
|
-
/** Whether `imageId`'s data still needs to be transmitted to the
|
|
466
|
+
/** Whether `imageId`'s data still needs to be transmitted to the surface the in-flight pass paints. */
|
|
447
467
|
shouldTransmit(imageId: number): boolean {
|
|
448
|
-
return !this.#transmitted.has(imageId);
|
|
468
|
+
return !this.#transmitted[this.#surface].has(imageId);
|
|
449
469
|
}
|
|
450
470
|
|
|
451
471
|
/**
|
|
@@ -566,18 +586,20 @@ export class ImageBudget {
|
|
|
566
586
|
}
|
|
567
587
|
|
|
568
588
|
/**
|
|
569
|
-
* Queue a one-time transmit for `imageId
|
|
570
|
-
*
|
|
589
|
+
* Queue a one-time transmit for `imageId` on the surface the in-flight pass
|
|
590
|
+
* paints. No-op if that surface already holds the data, so a repeated call
|
|
591
|
+
* (e.g. a width-change re-render) never re-sends it.
|
|
571
592
|
*/
|
|
572
593
|
enqueueTransmit(imageId: number, sequence: string): void {
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
594
|
+
const transmitted = this.#transmitted[this.#surface];
|
|
595
|
+
if (transmitted.has(imageId)) return;
|
|
596
|
+
transmitted.add(imageId);
|
|
597
|
+
this.#pendingTransmits[this.#surface].set(imageId, sequence);
|
|
576
598
|
}
|
|
577
599
|
|
|
578
|
-
/** Whether
|
|
600
|
+
/** Whether the in-flight pass's surface has image data queued but not yet written. */
|
|
579
601
|
hasPendingTransmits(): boolean {
|
|
580
|
-
return this.#pendingTransmits.size > 0;
|
|
602
|
+
return this.#pendingTransmits[this.#surface].size > 0;
|
|
581
603
|
}
|
|
582
604
|
|
|
583
605
|
/**
|
|
@@ -587,33 +609,38 @@ export class ImageBudget {
|
|
|
587
609
|
* observe pass only then — a partial tree walk would under-count display order.
|
|
588
610
|
*/
|
|
589
611
|
get quiescent(): boolean {
|
|
590
|
-
if (this.#
|
|
612
|
+
if (this.#purgeIds.length > 0) return false;
|
|
613
|
+
for (const surface of SURFACES) if (this.#pendingTransmits[surface].size > 0) return false;
|
|
591
614
|
for (const split of [this.#screenSplit, this.#altSplit]) {
|
|
592
615
|
if (split.lastTotal !== 0 || split.planned !== split.onTerminal) return false;
|
|
593
616
|
}
|
|
594
617
|
return true;
|
|
595
618
|
}
|
|
596
619
|
|
|
597
|
-
/** Transmit sequences to write before this frame's placements; clears
|
|
620
|
+
/** Transmit sequences to write before this frame's placements on its surface; clears that queue. */
|
|
598
621
|
takeTransmits(): readonly string[] {
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
622
|
+
const pending = this.#pendingTransmits[this.#surface];
|
|
623
|
+
if (pending.size === 0) return EMPTY_TRANSMITS;
|
|
624
|
+
const sequences = [...pending.values()];
|
|
625
|
+
pending.clear();
|
|
602
626
|
return sequences;
|
|
603
627
|
}
|
|
604
628
|
|
|
605
629
|
/**
|
|
606
|
-
* Drop transmit tracking so every still-live image
|
|
607
|
-
* (`a=t`) on the next render. Recovers when the terminal
|
|
608
|
-
* transmit — e.g. Ghostty discarding graphics sent during
|
|
609
|
-
* window — where a placement-only replay can never bind a
|
|
610
|
-
* Pair with a component invalidate + forced repaint so
|
|
611
|
-
* re-emit together; keeps no base64 in budget state
|
|
630
|
+
* Drop the normal screen's transmit tracking so every still-live image
|
|
631
|
+
* re-enqueues its data (`a=t`) on the next render. Recovers when the terminal
|
|
632
|
+
* dropped the original transmit — e.g. Ghostty discarding graphics sent during
|
|
633
|
+
* its post-startup window — where a placement-only replay can never bind a
|
|
634
|
+
* Unicode placeholder. Pair with a component invalidate + forced repaint so
|
|
635
|
+
* the data and placement re-emit together; keeps no base64 in budget state
|
|
636
|
+
* (the transmit-once design).
|
|
612
637
|
*/
|
|
613
638
|
forgetTransmitted(): void {
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
639
|
+
const transmitted = this.#transmitted.screen;
|
|
640
|
+
const pending = this.#pendingTransmits.screen;
|
|
641
|
+
if (transmitted.size === 0 && pending.size === 0) return;
|
|
642
|
+
for (const id of transmitted) {
|
|
643
|
+
if (!pending.has(id)) this.#resetPurgeIds.push(id);
|
|
617
644
|
}
|
|
618
645
|
// The ids go to #resetPurgeIds, drained only by the destructive repaint
|
|
619
646
|
// itself — never to #purgeIds, which any frame drains. That is how a
|
|
@@ -624,8 +651,8 @@ export class ImageBudget {
|
|
|
624
651
|
// placements from it, and erasing placeholder text does not remove the
|
|
625
652
|
// prototype either. Forgetting drops the id from tracking, so without an
|
|
626
653
|
// explicit `d=I` no later sweep can ever find that placement again.
|
|
627
|
-
|
|
628
|
-
|
|
654
|
+
transmitted.clear();
|
|
655
|
+
pending.clear();
|
|
629
656
|
}
|
|
630
657
|
|
|
631
658
|
/**
|
|
@@ -641,7 +668,7 @@ export class ImageBudget {
|
|
|
641
668
|
* deleting every placement it ever made including scrollback copies.
|
|
642
669
|
*/
|
|
643
670
|
#forgetKeyForId(id: number): void {
|
|
644
|
-
if (this.#
|
|
671
|
+
if (this.#isTransmitted(id)) return;
|
|
645
672
|
const key = this.#idToKey.get(id);
|
|
646
673
|
if (key === undefined) return;
|
|
647
674
|
this.#idToKey.delete(id);
|
package/src/components/input.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { getKeybindings } from "../keybindings";
|
|
|
3
3
|
import { extractPrintableText } from "../keys";
|
|
4
4
|
import { KillRing } from "../kill-ring";
|
|
5
5
|
import { type Component, CURSOR_MARKER, type Focusable } from "../tui";
|
|
6
|
+
import { cursorColumnWindow } from "./scroll-viewport";
|
|
6
7
|
import {
|
|
7
8
|
getSegmenter,
|
|
8
9
|
getWordNavKind,
|
|
@@ -422,12 +423,13 @@ export class Input implements Component, Focusable {
|
|
|
422
423
|
}
|
|
423
424
|
|
|
424
425
|
render(width: number): readonly string[] {
|
|
426
|
+
width = Number.isFinite(width) ? Math.max(0, Math.trunc(width)) : 0;
|
|
425
427
|
// Calculate visible window
|
|
426
428
|
const prompt = this.prompt;
|
|
427
429
|
const availableWidth = width - visibleWidth(prompt);
|
|
428
430
|
|
|
429
431
|
if (availableWidth <= 0) {
|
|
430
|
-
return [prompt];
|
|
432
|
+
return [sliceWithWidth(prompt, 0, width, true).text];
|
|
431
433
|
}
|
|
432
434
|
|
|
433
435
|
let cursorIndex = this.#cursor;
|
|
@@ -440,32 +442,9 @@ export class Input implements Component, Focusable {
|
|
|
440
442
|
}
|
|
441
443
|
const displayValue = this.#cursor >= this.#value.length ? `${visibleValue} ` : visibleValue;
|
|
442
444
|
|
|
443
|
-
const
|
|
444
|
-
const
|
|
445
|
-
|
|
446
|
-
// Width of the grapheme at the cursor, for ensuring it fits in the viewport.
|
|
447
|
-
const cursorIter = segmenter.segment(displayValue.slice(cursorIndex))[Symbol.iterator]();
|
|
448
|
-
const cursorG = cursorIter.next().value?.segment ?? " ";
|
|
449
|
-
const cursorGWidth = visibleWidth(cursorG);
|
|
450
|
-
|
|
451
|
-
const maxStart = Math.max(0, totalCols - availableWidth);
|
|
452
|
-
let startCol = 0;
|
|
453
|
-
if (totalCols > availableWidth) {
|
|
454
|
-
const half = Math.floor(availableWidth / 2);
|
|
455
|
-
startCol = Math.max(0, Math.min(maxStart, cursorCols - half));
|
|
456
|
-
|
|
457
|
-
// Ensure the cursor grapheme is inside the viewport (and fits fully if wide).
|
|
458
|
-
const maxCursorRel = Math.max(0, availableWidth - cursorGWidth);
|
|
459
|
-
const cursorRel = cursorCols - startCol;
|
|
460
|
-
if (cursorRel > maxCursorRel) {
|
|
461
|
-
startCol = Math.max(0, Math.min(maxStart, cursorCols - maxCursorRel));
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
const visibleText = sliceWithWidth(displayValue, startCol, availableWidth, true).text;
|
|
466
|
-
const prefixText = sliceWithWidth(displayValue, startCol, Math.max(0, cursorCols - startCol), true).text;
|
|
467
|
-
let cursorDisplay = prefixText.length;
|
|
468
|
-
cursorDisplay = Math.max(0, Math.min(cursorDisplay, visibleText.length));
|
|
445
|
+
const window = cursorColumnWindow(displayValue, cursorIndex, availableWidth);
|
|
446
|
+
const visibleText = window.text;
|
|
447
|
+
const cursorDisplay = window.cursorIndex;
|
|
469
448
|
|
|
470
449
|
// Build the visible line and insert the cursor marker at the buffer cursor.
|
|
471
450
|
const graphemes = [...segmenter.segment(visibleText.slice(cursorDisplay))];
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import type { Component } from "../tui";
|
|
2
|
+
import { Ellipsis, getWidthConfigEpoch, replaceTabs, truncateToWidth, visibleWidth, wrapTextWithAnsi } from "../utils";
|
|
3
|
+
|
|
4
|
+
/** One label/value entry in a {@link KeyValueList}. */
|
|
5
|
+
export interface KeyValueRow {
|
|
6
|
+
readonly label: string;
|
|
7
|
+
readonly value: string;
|
|
8
|
+
readonly labelStyle?: (text: string) => string;
|
|
9
|
+
readonly valueStyle?: (text: string) => string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/** Explicit sizing and wrapping policy for a key/value list. */
|
|
13
|
+
export interface KeyValueListOptions {
|
|
14
|
+
readonly indent?: string;
|
|
15
|
+
readonly labelWidth: number;
|
|
16
|
+
readonly gap?: string;
|
|
17
|
+
readonly minValueWidth?: number;
|
|
18
|
+
readonly labelOverflow?: "allow" | "truncate";
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function finiteWidth(width: number): number {
|
|
22
|
+
return Number.isFinite(width) ? Math.max(0, Math.trunc(width)) : 0;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function singleLine(text: string): string {
|
|
26
|
+
return replaceTabs(text).replace(/[\r\n]+/g, " ");
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** A bounded ANSI-aware label/value list with replaceable rows and aligned wrapped continuations. */
|
|
30
|
+
export class KeyValueList implements Component {
|
|
31
|
+
#rows: readonly KeyValueRow[];
|
|
32
|
+
readonly #options: KeyValueListOptions;
|
|
33
|
+
#cache: { width: number; epoch: number; lines: readonly string[] } | undefined;
|
|
34
|
+
|
|
35
|
+
constructor(rows: readonly KeyValueRow[], options: KeyValueListOptions) {
|
|
36
|
+
this.#rows = rows;
|
|
37
|
+
this.#options = options;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
setRows(rows: readonly KeyValueRow[]): boolean {
|
|
41
|
+
if (this.#rows === rows) return false;
|
|
42
|
+
this.#rows = rows;
|
|
43
|
+
this.#cache = undefined;
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
invalidate(): void {
|
|
48
|
+
this.#cache = undefined;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
render(width: number): readonly string[] {
|
|
52
|
+
const renderWidth = finiteWidth(width);
|
|
53
|
+
const epoch = getWidthConfigEpoch();
|
|
54
|
+
if (this.#cache?.width === renderWidth && this.#cache.epoch === epoch) return this.#cache.lines;
|
|
55
|
+
const indent = singleLine(this.#options.indent ?? "");
|
|
56
|
+
const gap = singleLine(this.#options.gap ?? " ");
|
|
57
|
+
const labelWidth = finiteWidth(this.#options.labelWidth);
|
|
58
|
+
const minimumValueWidth = Math.max(1, finiteWidth(this.#options.minValueWidth ?? 1));
|
|
59
|
+
const lines: string[] = [];
|
|
60
|
+
for (const row of this.#rows) {
|
|
61
|
+
let label = singleLine(row.label);
|
|
62
|
+
const indentAndGapWidth = visibleWidth(indent) + visibleWidth(gap);
|
|
63
|
+
const constrainedLabelWidth = Math.max(0, renderWidth - indentAndGapWidth - minimumValueWidth);
|
|
64
|
+
const renderedLabelWidth = Math.min(labelWidth, constrainedLabelWidth);
|
|
65
|
+
if (
|
|
66
|
+
visibleWidth(label) > renderedLabelWidth &&
|
|
67
|
+
(this.#options.labelOverflow === "truncate" || renderedLabelWidth < labelWidth)
|
|
68
|
+
) {
|
|
69
|
+
label = truncateToWidth(label, renderedLabelWidth);
|
|
70
|
+
}
|
|
71
|
+
const labelPadding = " ".repeat(Math.max(0, renderedLabelWidth - visibleWidth(label)));
|
|
72
|
+
const rawLabelCell = `${label}${labelPadding}`;
|
|
73
|
+
const labelCell = row.labelStyle?.(rawLabelCell) ?? rawLabelCell;
|
|
74
|
+
const prefixWidth = visibleWidth(indent) + visibleWidth(rawLabelCell) + visibleWidth(gap);
|
|
75
|
+
const valueWidth = Math.max(1, renderWidth - prefixWidth);
|
|
76
|
+
const rawValue = singleLine(row.value);
|
|
77
|
+
const value = row.valueStyle?.(rawValue) ?? rawValue;
|
|
78
|
+
const wrapped = wrapTextWithAnsi(value, valueWidth);
|
|
79
|
+
const continuation = " ".repeat(prefixWidth);
|
|
80
|
+
lines.push(truncateToWidth(`${indent}${labelCell}${gap}${wrapped[0] ?? ""}`, renderWidth, Ellipsis.Omit));
|
|
81
|
+
for (const extra of wrapped.slice(1)) {
|
|
82
|
+
lines.push(truncateToWidth(`${continuation}${extra}`, renderWidth, Ellipsis.Omit));
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
this.#cache = { width: renderWidth, epoch, lines };
|
|
86
|
+
return lines;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import type { MouseRoutable } from "../../mouse";
|
|
2
|
+
import type { Component } from "../../tui";
|
|
3
|
+
import { padding, truncateToWidth, visibleWidth } from "../../utils";
|
|
4
|
+
|
|
5
|
+
/** Alignment within space allocated by a layout component. */
|
|
6
|
+
export type LayoutAlignment = "start" | "center" | "end";
|
|
7
|
+
|
|
8
|
+
/** Insets reserved inside a layout child's allocated rectangle. */
|
|
9
|
+
export interface LayoutInsets {
|
|
10
|
+
top?: number;
|
|
11
|
+
right?: number;
|
|
12
|
+
bottom?: number;
|
|
13
|
+
left?: number;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** Insets normalized to finite, non-negative terminal-cell counts. */
|
|
17
|
+
export interface NormalizedLayoutInsets {
|
|
18
|
+
top: number;
|
|
19
|
+
right: number;
|
|
20
|
+
bottom: number;
|
|
21
|
+
left: number;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** Rectangle in coordinates local to a layout component. */
|
|
25
|
+
export interface LayoutRect {
|
|
26
|
+
row: number;
|
|
27
|
+
col: number;
|
|
28
|
+
width: number;
|
|
29
|
+
height: number;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Lazy layout child, evaluated only when the child is visible. */
|
|
33
|
+
export type LayoutRenderer = (width: number, height: number | undefined) => readonly string[];
|
|
34
|
+
|
|
35
|
+
/** A concrete component or a lazy renderer used as a layout child. */
|
|
36
|
+
export type LayoutContent = Component | LayoutRenderer;
|
|
37
|
+
|
|
38
|
+
/** Static text or a late-bound layout decoration, useful for theme-colored rules. */
|
|
39
|
+
export type LayoutDecoration = string | (() => string);
|
|
40
|
+
|
|
41
|
+
/** A component whose parent may assign a local row budget before rendering. */
|
|
42
|
+
export interface HeightConstrainedComponent extends Component {
|
|
43
|
+
setHeight(height: number | undefined): void;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** One fixed or growing constraint consumed by {@link allocateLayoutSpace}. */
|
|
47
|
+
export interface LayoutAllocation {
|
|
48
|
+
fixed?: number;
|
|
49
|
+
grow?: number;
|
|
50
|
+
min?: number;
|
|
51
|
+
max?: number;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Clamp an external size to a finite, non-negative integer cell count. */
|
|
55
|
+
export function layoutSize(value: number | undefined, fallback = 0): number {
|
|
56
|
+
const resolved = value === undefined || !Number.isFinite(value) ? fallback : value;
|
|
57
|
+
return Number.isFinite(resolved) ? Math.max(0, Math.floor(resolved)) : 0;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Normalize an optional external size while preserving `undefined`. */
|
|
61
|
+
export function optionalLayoutSize(value: number | undefined): number | undefined {
|
|
62
|
+
return value === undefined ? undefined : layoutSize(value);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** Clamp a proportional layout input to a finite, non-negative number. */
|
|
66
|
+
export function layoutRatio(value: number | undefined, fallback: number): number {
|
|
67
|
+
const resolved = value === undefined || !Number.isFinite(value) ? fallback : value;
|
|
68
|
+
return Number.isFinite(resolved) ? Math.max(0, resolved) : 0;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** Resolve static or late-bound layout decoration text. */
|
|
72
|
+
export function layoutDecorationText(decoration: LayoutDecoration | undefined): string {
|
|
73
|
+
return typeof decoration === "function" ? decoration() : (decoration ?? "");
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function allocationMaximum(item: LayoutAllocation): number {
|
|
77
|
+
return item.max === undefined ? Number.MAX_SAFE_INTEGER : Math.max(layoutSize(item.min), layoutSize(item.max));
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Allocate bounded integer cells across fixed and growing children. When the
|
|
82
|
+
* minimums cannot fit, later children collapse first so output stays bounded.
|
|
83
|
+
*/
|
|
84
|
+
export function allocateLayoutSpace(items: readonly LayoutAllocation[], available: number): number[] {
|
|
85
|
+
available = layoutSize(available);
|
|
86
|
+
const sizes = items.map(item => {
|
|
87
|
+
const minimum = layoutSize(item.min);
|
|
88
|
+
const maximum = allocationMaximum(item);
|
|
89
|
+
return item.fixed === undefined ? minimum : Math.max(minimum, Math.min(maximum, layoutSize(item.fixed)));
|
|
90
|
+
});
|
|
91
|
+
const used = sizes.reduce((sum, size) => sum + size, 0);
|
|
92
|
+
if (used > available) {
|
|
93
|
+
let overflow = used - available;
|
|
94
|
+
for (let index = sizes.length - 1; index >= 0 && overflow > 0; index--) {
|
|
95
|
+
const reduction = Math.min(sizes[index] ?? 0, overflow);
|
|
96
|
+
sizes[index] = (sizes[index] ?? 0) - reduction;
|
|
97
|
+
overflow -= reduction;
|
|
98
|
+
}
|
|
99
|
+
return sizes;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
let remaining = available - used;
|
|
103
|
+
let flexible = items
|
|
104
|
+
.map((item, index) => ({ item, index }))
|
|
105
|
+
.filter(({ item }) => item.fixed === undefined && layoutSize(item.grow) > 0);
|
|
106
|
+
while (remaining > 0 && flexible.length > 0) {
|
|
107
|
+
const totalWeight = flexible.reduce((sum, { item }) => sum + layoutSize(item.grow), 0);
|
|
108
|
+
let granted = 0;
|
|
109
|
+
for (const { item, index } of flexible) {
|
|
110
|
+
const maximum = allocationMaximum(item);
|
|
111
|
+
const capacity = maximum - (sizes[index] ?? 0);
|
|
112
|
+
if (capacity <= 0) continue;
|
|
113
|
+
const proportional = Math.floor((remaining * layoutSize(item.grow)) / totalWeight);
|
|
114
|
+
const share = Math.min(capacity, Math.max(1, proportional), remaining - granted);
|
|
115
|
+
if (share <= 0) continue;
|
|
116
|
+
sizes[index] = (sizes[index] ?? 0) + share;
|
|
117
|
+
granted += share;
|
|
118
|
+
if (granted === remaining) break;
|
|
119
|
+
}
|
|
120
|
+
if (granted === 0) break;
|
|
121
|
+
remaining -= granted;
|
|
122
|
+
flexible = flexible.filter(({ item, index }) => {
|
|
123
|
+
const maximum = allocationMaximum(item);
|
|
124
|
+
return (sizes[index] ?? 0) < maximum;
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
return sizes;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/** Normalize every inset to a finite, non-negative integer cell count. */
|
|
131
|
+
export function layoutInsets(insets: LayoutInsets | undefined): NormalizedLayoutInsets {
|
|
132
|
+
return {
|
|
133
|
+
top: layoutSize(insets?.top),
|
|
134
|
+
right: layoutSize(insets?.right),
|
|
135
|
+
bottom: layoutSize(insets?.bottom),
|
|
136
|
+
left: layoutSize(insets?.left),
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/** Compare optional inset objects by their normalized terminal geometry. */
|
|
141
|
+
export function equalLayoutInsets(left: LayoutInsets | undefined, right: LayoutInsets | undefined): boolean {
|
|
142
|
+
return (
|
|
143
|
+
layoutSize(left?.top) === layoutSize(right?.top) &&
|
|
144
|
+
layoutSize(left?.right) === layoutSize(right?.right) &&
|
|
145
|
+
layoutSize(left?.bottom) === layoutSize(right?.bottom) &&
|
|
146
|
+
layoutSize(left?.left) === layoutSize(right?.left)
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/** Offset content within spare cells according to an alignment. */
|
|
151
|
+
export function layoutAlignmentOffset(space: number, alignment: LayoutAlignment): number {
|
|
152
|
+
if (space <= 0 || alignment === "start") return 0;
|
|
153
|
+
return alignment === "end" ? space : Math.floor(space / 2);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/** Narrow a concrete-or-lazy child to a concrete component. */
|
|
157
|
+
export function isLayoutComponent(content: LayoutContent): content is Component {
|
|
158
|
+
return typeof content !== "function";
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/** Narrow a layout child to a component accepting a row budget. */
|
|
162
|
+
export function isHeightConstrainedComponent(content: LayoutContent): content is HeightConstrainedComponent {
|
|
163
|
+
return isLayoutComponent(content) && "setHeight" in content && typeof content.setHeight === "function";
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/** Narrow a layout child to a mouse-routable component. */
|
|
167
|
+
export function isLayoutMouseRoutable(content: LayoutContent): content is Component & MouseRoutable {
|
|
168
|
+
return isLayoutComponent(content) && "routeMouse" in content && typeof content.routeMouse === "function";
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/** Return concrete children once each, preserving their first layout order. */
|
|
172
|
+
export function uniqueLayoutComponents(contents: readonly LayoutContent[]): readonly Component[] {
|
|
173
|
+
const seen = new Set<Component>();
|
|
174
|
+
const components: Component[] = [];
|
|
175
|
+
for (const content of contents) {
|
|
176
|
+
if (!isLayoutComponent(content) || seen.has(content)) continue;
|
|
177
|
+
seen.add(content);
|
|
178
|
+
components.push(content);
|
|
179
|
+
}
|
|
180
|
+
return components;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/** Fit one ANSI-styled row to an exact terminal-cell width. */
|
|
184
|
+
export function fitLayoutLine(line: string, width: number): string {
|
|
185
|
+
width = layoutSize(width);
|
|
186
|
+
if (width === 0) return "";
|
|
187
|
+
const lineWidth = visibleWidth(line);
|
|
188
|
+
const clipped = lineWidth > width ? truncateToWidth(line, width) : line;
|
|
189
|
+
const clippedWidth = lineWidth > width ? visibleWidth(clipped) : lineWidth;
|
|
190
|
+
return clipped + padding(Math.max(0, width - clippedWidth));
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/** Render a concrete or lazy child with an optional local height budget. */
|
|
194
|
+
export function renderLayoutContent(
|
|
195
|
+
content: LayoutContent,
|
|
196
|
+
width: number,
|
|
197
|
+
height: number | undefined,
|
|
198
|
+
): readonly string[] {
|
|
199
|
+
if (typeof content === "function") return content(layoutSize(width), optionalLayoutSize(height));
|
|
200
|
+
if (isHeightConstrainedComponent(content)) content.setHeight(optionalLayoutSize(height));
|
|
201
|
+
return content.render(layoutSize(width));
|
|
202
|
+
}
|