@oh-my-pi/pi-tui 18.4.3 → 18.4.4
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 +36 -0
- package/dist/types/apps/cleanse-board.d.ts +17 -0
- package/dist/types/apps/git/help.d.ts +16 -0
- package/dist/types/apps/git/sidebar.d.ts +18 -0
- package/dist/types/apps/live-visualizer.d.ts +10 -0
- package/dist/types/apps/ps-top.d.ts +15 -0
- package/dist/types/apps/standalone-picker.d.ts +3 -0
- package/dist/types/autocomplete.d.ts +8 -0
- package/dist/types/chat/advisor-message.d.ts +12 -2
- package/dist/types/chat/assistant-message.d.ts +20 -0
- package/dist/types/chat/bash-execution.d.ts +9 -0
- package/dist/types/chat/chat-transcript-builder.d.ts +6 -1
- package/dist/types/chat/collab-prompt-message.d.ts +4 -0
- package/dist/types/chat/compaction-summary-message.d.ts +15 -0
- package/dist/types/chat/eval-execution.d.ts +8 -0
- package/dist/types/chat/execution-shared.d.ts +58 -0
- package/dist/types/chat/late-diagnostics-message.d.ts +15 -1
- package/dist/types/chat/read-tool-group.d.ts +15 -0
- package/dist/types/chat/skill-message.d.ts +9 -0
- package/dist/types/chat/stripped-tool-calls-placeholder.d.ts +3 -0
- package/dist/types/chat/todo-reminder.d.ts +4 -1
- package/dist/types/chat/tool-execution.d.ts +25 -1
- package/dist/types/chat/transcript-actions.d.ts +37 -0
- package/dist/types/chat/transcript-entry.d.ts +3 -1
- package/dist/types/chat/user-message.d.ts +25 -0
- package/dist/types/chrome/collab-qrcode.d.ts +7 -0
- package/dist/types/chrome/context-thresholds.d.ts +11 -0
- package/dist/types/chrome/countdown-timer.d.ts +9 -3
- package/dist/types/chrome/diff.d.ts +12 -0
- package/dist/types/chrome/dynamic-border.d.ts +3 -0
- package/dist/types/chrome/format.d.ts +6 -0
- package/dist/types/chrome/message-divider.d.ts +13 -0
- package/dist/types/chrome/message-frame.d.ts +10 -0
- package/dist/types/chrome/message-notice.d.ts +23 -0
- package/dist/types/chrome/overlay-box.d.ts +11 -2
- package/dist/types/chrome/qrcode.d.ts +7 -0
- package/dist/types/chrome/segment-track.d.ts +7 -0
- package/dist/types/chrome/selector-helpers.d.ts +0 -6
- package/dist/types/chrome/status-notice.d.ts +14 -0
- package/dist/types/chrome/streaming-panel.d.ts +3 -0
- package/dist/types/chrome/tool-activity.d.ts +3 -0
- package/dist/types/chrome/transcript-container.d.ts +13 -0
- package/dist/types/chrome/transcript-status.d.ts +15 -3
- package/dist/types/components/box.d.ts +7 -0
- package/dist/types/components/disclosure.d.ts +9 -0
- package/dist/types/components/editor.d.ts +37 -0
- package/dist/types/components/form.d.ts +14 -0
- package/dist/types/components/image.d.ts +7 -0
- package/dist/types/components/input.d.ts +20 -1
- package/dist/types/components/key-value-list.d.ts +3 -0
- package/dist/types/components/layout/geometry.d.ts +16 -0
- package/dist/types/components/layout/row.d.ts +7 -0
- package/dist/types/components/layout/split-pane.d.ts +8 -0
- package/dist/types/components/layout/stack.d.ts +6 -0
- package/dist/types/components/loader.d.ts +48 -0
- package/dist/types/components/markdown.d.ts +8 -0
- package/dist/types/components/metric.d.ts +7 -0
- package/dist/types/components/progress-bar.d.ts +3 -0
- package/dist/types/components/scroll-view.d.ts +6 -0
- package/dist/types/components/section.d.ts +3 -0
- package/dist/types/components/select-list.d.ts +33 -0
- package/dist/types/components/settings-list.d.ts +68 -0
- package/dist/types/components/spacer.d.ts +4 -0
- package/dist/types/components/tab-bar.d.ts +9 -0
- package/dist/types/components/table.d.ts +7 -0
- package/dist/types/components/text.d.ts +6 -0
- package/dist/types/components/tree-view.d.ts +9 -0
- package/dist/types/components/truncated-text.d.ts +3 -0
- package/dist/types/components/wizard-step.d.ts +6 -0
- package/dist/types/hotkeys-markdown.d.ts +24 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/latex-block.d.ts +7 -0
- package/dist/types/native/apply.d.ts +39 -0
- package/dist/types/native/backend.d.ts +94 -0
- package/dist/types/native/blobs.d.ts +29 -0
- package/dist/types/native/describe.d.ts +56 -0
- package/dist/types/native/encode.d.ts +50 -0
- package/dist/types/native/icons.d.ts +18 -0
- package/dist/types/native/memo.d.ts +27 -0
- package/dist/types/native/node.d.ts +107 -0
- package/dist/types/native/overlay.d.ts +64 -0
- package/dist/types/native/picker.d.ts +124 -0
- package/dist/types/native/reconcile.d.ts +41 -0
- package/dist/types/native/settle.d.ts +11 -0
- package/dist/types/native/spans.d.ts +21 -0
- package/dist/types/native/state.d.ts +6 -0
- package/dist/types/native/tone.d.ts +24 -0
- package/dist/types/overlays/advisor-config.d.ts +20 -0
- package/dist/types/overlays/agent-hub-renderer.d.ts +27 -11
- package/dist/types/overlays/agent-hub.d.ts +10 -0
- package/dist/types/overlays/agent-transcript-viewer.d.ts +7 -0
- package/dist/types/overlays/agents-hub.d.ts +8 -0
- package/dist/types/overlays/annotation-overlay.d.ts +3 -0
- package/dist/types/overlays/ask-dialog.d.ts +23 -0
- package/dist/types/overlays/bordered-loader.d.ts +3 -0
- package/dist/types/overlays/btw-history-panel.d.ts +9 -0
- package/dist/types/overlays/btw-panel.d.ts +3 -0
- package/dist/types/overlays/cleanse-panel.d.ts +5 -2
- package/dist/types/overlays/composer-shape-preview.d.ts +7 -1
- package/dist/types/overlays/copy-selector.d.ts +38 -0
- package/dist/types/overlays/error-banner.d.ts +9 -0
- package/dist/types/overlays/extensions/extension-list.d.ts +1 -0
- package/dist/types/overlays/history-search.d.ts +18 -0
- package/dist/types/overlays/hook-editor.d.ts +28 -1
- package/dist/types/overlays/hook-input.d.ts +3 -0
- package/dist/types/overlays/hook-selector.d.ts +10 -0
- package/dist/types/overlays/hub-frame.d.ts +18 -0
- package/dist/types/overlays/jobs-panel.d.ts +24 -0
- package/dist/types/overlays/login-dialog.d.ts +10 -0
- package/dist/types/overlays/logout-account-selector.d.ts +4 -0
- package/dist/types/overlays/mcp-add-wizard.d.ts +4 -0
- package/dist/types/overlays/model-browser.d.ts +69 -0
- package/dist/types/overlays/model-hub.d.ts +7 -0
- package/dist/types/overlays/model-picker.d.ts +7 -0
- package/dist/types/overlays/move-overlay.d.ts +3 -0
- package/dist/types/overlays/oauth-selector.d.ts +4 -0
- package/dist/types/overlays/omfg-panel.d.ts +3 -0
- package/dist/types/overlays/pause-screen.d.ts +12 -0
- package/dist/types/overlays/plan-review-overlay.d.ts +5 -0
- package/dist/types/overlays/plan-save-overlay.d.ts +10 -0
- package/dist/types/overlays/plugin-selector.d.ts +4 -0
- package/dist/types/overlays/plugin-settings.d.ts +30 -0
- package/dist/types/overlays/queue-mode-selector.d.ts +4 -0
- package/dist/types/overlays/reset-usage-selector.d.ts +8 -0
- package/dist/types/overlays/rewind-selector.d.ts +5 -0
- package/dist/types/overlays/session-info-overlay.d.ts +19 -1
- package/dist/types/overlays/session-selector.d.ts +64 -1
- package/dist/types/overlays/settings-defs.d.ts +14 -0
- package/dist/types/overlays/settings-selector.d.ts +21 -0
- package/dist/types/overlays/show-images-selector.d.ts +4 -0
- package/dist/types/overlays/snapcompact-shape-preview.d.ts +2 -0
- package/dist/types/overlays/stats-notice.d.ts +8 -0
- package/dist/types/overlays/theme-selector.d.ts +11 -0
- package/dist/types/overlays/thinking-selector.d.ts +4 -0
- package/dist/types/overlays/tree-selector.d.ts +60 -2
- package/dist/types/overlays/usage-dashboard.d.ts +26 -3
- package/dist/types/overlays/usage-row.d.ts +36 -2
- package/dist/types/prompt/attachment-chips.d.ts +8 -0
- package/dist/types/prompt/composer-attachments.d.ts +15 -3
- package/dist/types/prompt/composer.d.ts +18 -1
- package/dist/types/prompt/custom-editor.d.ts +48 -2
- package/dist/types/prompt/editor-top-gap.d.ts +2 -0
- package/dist/types/prompt/macos-spelling.d.ts +6 -0
- package/dist/types/prompt/magic-keywords.d.ts +9 -0
- package/dist/types/prompt/queued-messages.d.ts +23 -0
- package/dist/types/prompt/skill-tokens.d.ts +4 -2
- package/dist/types/prompt/welcome.d.ts +16 -0
- package/dist/types/render/code-cell.d.ts +10 -0
- package/dist/types/render/file-list.d.ts +8 -0
- package/dist/types/render/hyperlink.d.ts +14 -0
- package/dist/types/render/output-block.d.ts +43 -0
- package/dist/types/render/output-pane.d.ts +17 -0
- package/dist/types/render/tool-card.d.ts +8 -0
- package/dist/types/render/tree-list.d.ts +8 -0
- package/dist/types/render/width-aware-text.d.ts +7 -0
- package/dist/types/setup/scenes/outro.d.ts +7 -0
- package/dist/types/setup/scenes/sign-in.d.ts +7 -0
- package/dist/types/setup/scenes/splash.d.ts +8 -0
- package/dist/types/setup/scenes/types.d.ts +6 -1
- package/dist/types/setup/wizard-overlay.d.ts +9 -0
- package/dist/types/status-line/component.d.ts +49 -5
- package/dist/types/status-line/context-usage.d.ts +20 -0
- package/dist/types/status-line/footer.d.ts +8 -0
- package/dist/types/status-line/metrics.d.ts +1 -2
- package/dist/types/status-line/segments.d.ts +10 -1
- package/dist/types/status-line/types.d.ts +40 -1
- package/dist/types/terminal-capabilities.d.ts +1 -1
- package/dist/types/terminal.d.ts +27 -0
- package/dist/types/theme/defaults/index.d.ts +100 -0
- package/dist/types/theme/schema.d.ts +2 -0
- package/dist/types/theme/shimmer.d.ts +8 -0
- package/dist/types/theme/theme-class.d.ts +2 -0
- package/dist/types/theme/theme.d.ts +33 -1
- package/dist/types/tools/ask.d.ts +3 -0
- package/dist/types/tools/ast-edit.d.ts +10 -1
- package/dist/types/tools/ast-grep.d.ts +10 -1
- package/dist/types/tools/autoresearch.d.ts +21 -4
- package/dist/types/tools/bash.d.ts +30 -1
- package/dist/types/tools/cfg-render.d.ts +5 -1
- package/dist/types/tools/debug.d.ts +3 -1
- package/dist/types/tools/default-renderer.d.ts +6 -1
- package/dist/types/tools/edit.d.ts +14 -1
- package/dist/types/tools/eval.d.ts +12 -1
- package/dist/types/tools/fetch.d.ts +16 -1
- package/dist/types/tools/find.d.ts +15 -1
- package/dist/types/tools/github.d.ts +3 -0
- package/dist/types/tools/glob.d.ts +14 -1
- package/dist/types/tools/goal.d.ts +3 -1
- package/dist/types/tools/grep.d.ts +14 -1
- package/dist/types/tools/grouped-file-output.d.ts +58 -0
- package/dist/types/tools/json-tree.d.ts +20 -0
- package/dist/types/tools/lsp.d.ts +3 -10
- package/dist/types/tools/mcp.d.ts +16 -1
- package/dist/types/tools/memory.d.ts +26 -0
- package/dist/types/tools/native-view.d.ts +90 -0
- package/dist/types/tools/proc-render.d.ts +7 -1
- package/dist/types/tools/read.d.ts +23 -1
- package/dist/types/tools/renderer.d.ts +57 -0
- package/dist/types/tools/report-tool-issue.d.ts +3 -0
- package/dist/types/tools/resolve.d.ts +14 -1
- package/dist/types/tools/task.d.ts +3 -0
- package/dist/types/tools/think.d.ts +3 -0
- package/dist/types/tools/todo.d.ts +12 -0
- package/dist/types/tools/vibe.d.ts +3 -1
- package/dist/types/tools/wait.d.ts +3 -0
- package/dist/types/tools/web-search.d.ts +8 -0
- package/dist/types/tools/write.d.ts +14 -1
- package/dist/types/tools/xdev.d.ts +13 -0
- package/dist/types/tui.d.ts +49 -0
- package/package.json +9 -9
- package/src/apps/autoresearch-dashboard.ts +362 -4
- package/src/apps/cleanse-board.ts +219 -1
- package/src/apps/cleanse-picker.ts +9 -1
- package/src/apps/debug/log-viewer.ts +15 -15
- package/src/apps/debug/protocol-probe.ts +2 -20
- package/src/apps/git/avatar.ts +2 -22
- package/src/apps/git/git-tui.ts +406 -59
- package/src/apps/git/help.ts +130 -0
- package/src/apps/git/sidebar.ts +491 -0
- package/src/apps/live-visualizer.ts +65 -0
- package/src/apps/ps-top.ts +448 -17
- package/src/apps/session-picker.ts +1 -0
- package/src/apps/setup-model-picker.ts +5 -1
- package/src/apps/standalone-picker.ts +55 -1
- package/src/autocomplete.ts +44 -1
- package/src/chat/advisor-message.ts +72 -3
- package/src/chat/assistant-message.ts +346 -11
- package/src/chat/background-tan-message.ts +4 -4
- package/src/chat/bash-execution.ts +81 -0
- package/src/chat/cache-invalidation-marker.ts +8 -0
- package/src/chat/chat-transcript-builder.ts +37 -6
- package/src/chat/collab-prompt-message.ts +15 -3
- package/src/chat/compaction-summary-message.ts +74 -1
- package/src/chat/custom-message.ts +3 -1
- package/src/chat/eval-execution.ts +57 -0
- package/src/chat/execution-shared.ts +153 -1
- package/src/chat/hook-message.ts +1 -0
- package/src/chat/late-diagnostics-message.ts +85 -2
- package/src/chat/read-tool-group.ts +341 -1
- package/src/chat/served-model-marker.ts +8 -0
- package/src/chat/skill-message.ts +63 -0
- package/src/chat/stripped-tool-calls-placeholder.ts +18 -10
- package/src/chat/todo-reminder.ts +34 -4
- package/src/chat/tool-execution.ts +385 -10
- package/src/chat/transcript-actions.ts +38 -0
- package/src/chat/transcript-browser.ts +2 -9
- package/src/chat/transcript-entry.ts +10 -1
- package/src/chat/transcript-render-helpers.ts +16 -15
- package/src/chat/ttsr-notification.ts +38 -1
- package/src/chat/user-message.ts +167 -4
- package/src/chrome/collab-qrcode.ts +27 -2
- package/src/chrome/context-thresholds.ts +34 -0
- package/src/chrome/countdown-timer.ts +24 -1
- package/src/chrome/diff.ts +60 -1
- package/src/chrome/dynamic-border.ts +7 -0
- package/src/chrome/format.ts +12 -0
- package/src/chrome/message-divider.ts +33 -1
- package/src/chrome/message-frame.ts +53 -10
- package/src/chrome/message-notice.ts +71 -0
- package/src/chrome/overlay-box.ts +45 -2
- package/src/chrome/qrcode.ts +28 -0
- package/src/chrome/segment-track.ts +26 -0
- package/src/chrome/selector-helpers.ts +1 -17
- package/src/chrome/status-notice.ts +46 -0
- package/src/chrome/streaming-panel.ts +25 -1
- package/src/chrome/tool-activity.ts +20 -0
- package/src/chrome/transcript-container.ts +37 -0
- package/src/chrome/transcript-status.ts +40 -11
- package/src/components/box.ts +51 -0
- package/src/components/disclosure.ts +33 -0
- package/src/components/editor.ts +216 -27
- package/src/components/form.ts +93 -9
- package/src/components/image.ts +30 -0
- package/src/components/input.ts +77 -26
- package/src/components/key-value-list.ts +18 -0
- package/src/components/layout/geometry.ts +44 -0
- package/src/components/layout/row.ts +30 -0
- package/src/components/layout/split-pane.ts +65 -0
- package/src/components/layout/stack.ts +27 -0
- package/src/components/loader.ts +183 -1
- package/src/components/markdown.ts +21 -0
- package/src/components/metric.ts +39 -0
- package/src/components/progress-bar.ts +28 -0
- package/src/components/scroll-view.ts +23 -0
- package/src/components/section.ts +16 -0
- package/src/components/select-list.ts +174 -25
- package/src/components/settings-list.ts +264 -7
- package/src/components/spacer.ts +17 -0
- package/src/components/tab-bar.ts +42 -0
- package/src/components/table.ts +34 -0
- package/src/components/text.ts +23 -0
- package/src/components/tree-view.ts +65 -0
- package/src/components/truncated-text.ts +14 -0
- package/src/components/wizard-step.ts +18 -9
- package/src/debug-server.ts +14 -7
- package/src/hotkeys-markdown.ts +251 -69
- package/src/index.ts +6 -0
- package/src/latex-block.ts +11 -0
- package/src/native/apply.ts +275 -0
- package/src/native/backend.ts +682 -0
- package/src/native/blobs.ts +70 -0
- package/src/native/describe.ts +124 -0
- package/src/native/encode.ts +233 -0
- package/src/native/icons.ts +184 -0
- package/src/native/memo.ts +64 -0
- package/src/native/node.ts +112 -0
- package/src/native/overlay.ts +131 -0
- package/src/native/picker.ts +333 -0
- package/src/native/reconcile.ts +1063 -0
- package/src/native/settle.ts +23 -0
- package/src/native/spans.ts +308 -0
- package/src/native/state.ts +28 -0
- package/src/native/tone.ts +79 -0
- package/src/overlays/advisor-config.ts +420 -0
- package/src/overlays/agent-hub-renderer.ts +155 -18
- package/src/overlays/agent-hub.ts +1037 -44
- package/src/overlays/agent-transcript-viewer.ts +129 -0
- package/src/overlays/agents-hub.ts +688 -53
- package/src/overlays/annotation-overlay.ts +391 -52
- package/src/overlays/ask-dialog.ts +435 -24
- package/src/overlays/bordered-loader.ts +17 -0
- package/src/overlays/btw-history-panel.ts +182 -0
- package/src/overlays/btw-panel.ts +68 -2
- package/src/overlays/cleanse-panel.ts +105 -15
- package/src/overlays/codex-reset-fireworks.ts +65 -5
- package/src/overlays/composer-shape-preview.ts +26 -1
- package/src/overlays/copy-selector.ts +545 -23
- package/src/overlays/error-banner.ts +44 -0
- package/src/overlays/extensions/extension-list.ts +23 -17
- package/src/overlays/history-search.ts +175 -33
- package/src/overlays/hook-editor.ts +113 -6
- package/src/overlays/hook-input.ts +22 -1
- package/src/overlays/hook-selector.ts +311 -22
- package/src/overlays/hub-frame.ts +80 -0
- package/src/overlays/jobs-panel.ts +112 -0
- package/src/overlays/login-dialog.ts +183 -1
- package/src/overlays/logout-account-selector.ts +102 -4
- package/src/overlays/mcp-add-wizard.ts +232 -53
- package/src/overlays/model-browser.ts +681 -22
- package/src/overlays/model-hub.ts +1402 -78
- package/src/overlays/model-picker.ts +175 -1
- package/src/overlays/move-overlay.ts +45 -0
- package/src/overlays/oauth-selector.ts +227 -23
- package/src/overlays/omfg-panel.ts +86 -2
- package/src/overlays/pause-screen.ts +55 -4
- package/src/overlays/plan-review-overlay.ts +352 -0
- package/src/overlays/plan-save-overlay.ts +45 -0
- package/src/overlays/plugin-selector.ts +21 -1
- package/src/overlays/plugin-settings.ts +195 -5
- package/src/overlays/queue-mode-selector.ts +19 -1
- package/src/overlays/reset-usage-selector.ts +110 -40
- package/src/overlays/rewind-selector.ts +458 -44
- package/src/overlays/session-account-selector.ts +1 -1
- package/src/overlays/session-info-overlay.ts +137 -1
- package/src/overlays/session-selector.ts +807 -46
- package/src/overlays/settings-defs.ts +41 -0
- package/src/overlays/settings-selector.ts +583 -23
- package/src/overlays/show-images-selector.ts +18 -1
- package/src/overlays/snapcompact-shape-preview.ts +48 -3
- package/src/overlays/stats-notice.ts +31 -0
- package/src/overlays/theme-selector.ts +31 -1
- package/src/overlays/thinking-selector.ts +22 -1
- package/src/overlays/tree-selector.ts +570 -110
- package/src/overlays/usage-dashboard.ts +587 -12
- package/src/overlays/usage-row.ts +161 -25
- package/src/prompt/attachment-chips.ts +60 -0
- package/src/prompt/composer-attachments.ts +31 -9
- package/src/prompt/composer.ts +55 -2
- package/src/prompt/custom-editor.ts +302 -4
- package/src/prompt/editor-top-gap.ts +8 -0
- package/src/prompt/macos-spelling.ts +24 -9
- package/src/prompt/magic-keywords.ts +22 -1
- package/src/prompt/model-mention-autocomplete.ts +1 -0
- package/src/prompt/queued-messages.ts +101 -0
- package/src/prompt/skill-tokens.ts +5 -3
- package/src/prompt/welcome.ts +213 -6
- package/src/render/code-cell.ts +103 -2
- package/src/render/file-list.ts +29 -0
- package/src/render/hyperlink.ts +32 -0
- package/src/render/output-block.ts +110 -0
- package/src/render/output-pane.ts +37 -0
- package/src/render/tool-card.ts +137 -0
- package/src/render/tree-list.ts +39 -0
- package/src/render/width-aware-text.ts +20 -0
- package/src/setup/scenes/composer.ts +29 -0
- package/src/setup/scenes/glyph.ts +15 -0
- package/src/setup/scenes/model.ts +36 -8
- package/src/setup/scenes/outro.ts +28 -1
- package/src/setup/scenes/sign-in.ts +122 -13
- package/src/setup/scenes/splash.ts +28 -1
- package/src/setup/scenes/theme.ts +88 -3
- package/src/setup/scenes/types.ts +7 -1
- package/src/setup/startup-splash.ts +46 -9
- package/src/setup/wizard-overlay.ts +140 -23
- package/src/status-line/component.ts +398 -16
- package/src/status-line/context-usage.ts +279 -50
- package/src/status-line/footer.ts +94 -1
- package/src/status-line/metrics.ts +3 -6
- package/src/status-line/segments.ts +463 -97
- package/src/status-line/separators.ts +3 -16
- package/src/status-line/types.ts +43 -1
- package/src/terminal-capabilities.ts +7 -0
- package/src/terminal.ts +130 -2
- package/src/theme/defaults/dark-neon-noir.json +100 -0
- package/src/theme/defaults/index.ts +2 -0
- package/src/theme/defaults/light-prism.json +5 -5
- package/src/theme/defaults/onyx.json +62 -62
- package/src/theme/schema.ts +15 -0
- package/src/theme/shimmer.ts +33 -0
- package/src/theme/theme-class.ts +24 -19
- package/src/theme/theme.ts +111 -9
- package/src/tools/ask.ts +157 -1
- package/src/tools/ast-edit.ts +174 -1
- package/src/tools/ast-grep.ts +82 -2
- package/src/tools/autoresearch.ts +149 -1
- package/src/tools/bash.ts +180 -49
- package/src/tools/cfg-render.ts +66 -1
- package/src/tools/debug.ts +78 -1
- package/src/tools/default-renderer.ts +35 -1
- package/src/tools/edit.ts +247 -2
- package/src/tools/eval.ts +257 -1
- package/src/tools/fetch.ts +102 -3
- package/src/tools/find.ts +127 -1
- package/src/tools/github.ts +119 -10
- package/src/tools/glob.ts +116 -1
- package/src/tools/goal.ts +56 -1
- package/src/tools/grep.ts +83 -2
- package/src/tools/grouped-file-output.ts +205 -0
- package/src/tools/json-tree.ts +116 -1
- package/src/tools/lsp.ts +318 -1
- package/src/tools/mcp.ts +80 -1
- package/src/tools/memory.ts +93 -11
- package/src/tools/native-view.ts +292 -0
- package/src/tools/proc-render.ts +221 -1
- package/src/tools/read.ts +199 -4
- package/src/tools/renderer.ts +61 -0
- package/src/tools/report-tool-issue.ts +7 -1
- package/src/tools/resolve.ts +63 -1
- package/src/tools/task.ts +406 -4
- package/src/tools/think.ts +19 -1
- package/src/tools/todo.ts +89 -0
- package/src/tools/vibe.ts +230 -2
- package/src/tools/wait.ts +181 -1
- package/src/tools/web-search.ts +113 -1
- package/src/tools/write.ts +144 -5
- package/src/tools/xdev.ts +64 -1
- package/src/tui.ts +294 -3
package/src/components/form.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { getKeybindings } from "../keybindings";
|
|
2
2
|
import { matchesKey } from "../keys";
|
|
3
3
|
import type { MouseRoutable, SgrMouseEvent } from "../mouse";
|
|
4
|
+
import { col, node, span } from "../native/describe";
|
|
5
|
+
import { plainText } from "../native/spans";
|
|
6
|
+
import type { DescribeContext, NativeChild, NativeNode, NativeUiEvent } from "../native/node";
|
|
7
|
+
import { type SelectPickerOptions, SelectListSheet } from "../native/picker";
|
|
4
8
|
import { Container, type Component, type Focusable } from "../tui";
|
|
5
9
|
import { replaceTabs, truncateToWidth } from "../utils";
|
|
6
10
|
import { Input } from "./input";
|
|
@@ -48,10 +52,13 @@ function hasMouseRouter(component: FormControl): component is FormControl & Mous
|
|
|
48
52
|
class StyledText implements Component {
|
|
49
53
|
readonly #text: Text;
|
|
50
54
|
#value: string;
|
|
55
|
+
#native: NativeNode | undefined;
|
|
51
56
|
|
|
52
57
|
constructor(
|
|
53
58
|
value: string,
|
|
54
59
|
private readonly style: (text: string) => string,
|
|
60
|
+
/** Span token standing in for `style` on a TSP terminal. */
|
|
61
|
+
private readonly token?: string,
|
|
55
62
|
) {
|
|
56
63
|
this.#value = value;
|
|
57
64
|
this.#text = new Text(this.style(value), 0, 0);
|
|
@@ -60,9 +67,15 @@ class StyledText implements Component {
|
|
|
60
67
|
setText(value: string): void {
|
|
61
68
|
if (value === this.#value) return;
|
|
62
69
|
this.#value = value;
|
|
70
|
+
this.#native = undefined;
|
|
63
71
|
this.#text.setText(this.style(value));
|
|
64
72
|
}
|
|
65
73
|
|
|
74
|
+
describe(_cx: DescribeContext): NativeNode {
|
|
75
|
+
this.#native ??= node("text", { spans: [span(plainText(this.#value), this.token)] });
|
|
76
|
+
return this.#native;
|
|
77
|
+
}
|
|
78
|
+
|
|
66
79
|
render(width: number): readonly string[] {
|
|
67
80
|
return this.#text.render(width);
|
|
68
81
|
}
|
|
@@ -77,9 +90,14 @@ class OptionalText implements Component {
|
|
|
77
90
|
readonly #text: StyledText;
|
|
78
91
|
#value = "";
|
|
79
92
|
readonly #empty: readonly string[] = [];
|
|
93
|
+
readonly #hidden = node("text", { text: "", hidden: true });
|
|
80
94
|
|
|
81
|
-
constructor(style: (text: string) => string) {
|
|
82
|
-
this.#text = new StyledText("", style);
|
|
95
|
+
constructor(style: (text: string) => string, token?: string) {
|
|
96
|
+
this.#text = new StyledText("", style, token);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
describe(cx: DescribeContext): NativeNode {
|
|
100
|
+
return this.#value ? this.#text.describe(cx) : this.#hidden;
|
|
83
101
|
}
|
|
84
102
|
|
|
85
103
|
setText(value: string): void {
|
|
@@ -114,37 +132,67 @@ export class FormField implements Component, Focusable, MouseRoutable {
|
|
|
114
132
|
#memoControl: readonly string[] | undefined;
|
|
115
133
|
#memoAfter: readonly string[] | undefined;
|
|
116
134
|
#memoLines: readonly string[] = [];
|
|
135
|
+
/** Fixed described structure: every child is a component or a static node, so it never changes. */
|
|
136
|
+
readonly #native: NativeNode;
|
|
117
137
|
|
|
118
138
|
constructor(control: FormControl, options: FormFieldOptions) {
|
|
119
139
|
this.control = control;
|
|
120
|
-
this.#error = new OptionalText(options.theme.error);
|
|
140
|
+
this.#error = new OptionalText(options.theme.error, "error");
|
|
141
|
+
// Spacing is the terminal's (`gap`); only content becomes native children.
|
|
142
|
+
const native: NativeChild[] = [];
|
|
121
143
|
|
|
122
144
|
if (options.leadingSpace) this.#beforeControl.addChild(new Spacer(1));
|
|
123
145
|
if (options.label) {
|
|
124
|
-
|
|
146
|
+
const label = new StyledText(options.label, options.theme.label, "strong");
|
|
147
|
+
this.#beforeControl.addChild(label);
|
|
148
|
+
native.push(label);
|
|
125
149
|
}
|
|
126
150
|
if (options.description) {
|
|
127
151
|
if (options.label) this.#beforeControl.addChild(new Spacer(1));
|
|
128
|
-
|
|
152
|
+
const description = new StyledText(options.description, options.theme.description, "muted");
|
|
153
|
+
this.#beforeControl.addChild(description);
|
|
154
|
+
native.push(description);
|
|
155
|
+
}
|
|
156
|
+
for (const detail of options.details ?? []) {
|
|
157
|
+
this.#beforeControl.addChild(detail);
|
|
158
|
+
native.push(detail);
|
|
129
159
|
}
|
|
130
|
-
for (const detail of options.details ?? []) this.#beforeControl.addChild(detail);
|
|
131
160
|
if (options.preview) {
|
|
132
161
|
this.#beforeControl.addChild(new Spacer(1));
|
|
133
162
|
if (options.previewLabel) {
|
|
134
|
-
|
|
163
|
+
const previewLabel = new StyledText(options.previewLabel, options.theme.description, "muted");
|
|
164
|
+
this.#beforeControl.addChild(previewLabel);
|
|
165
|
+
native.push(previewLabel);
|
|
135
166
|
}
|
|
136
167
|
this.#beforeControl.addChild(options.preview);
|
|
168
|
+
native.push(options.preview);
|
|
137
169
|
}
|
|
138
170
|
if (options.spaceBeforeControl !== false) this.#beforeControl.addChild(new Spacer(1));
|
|
171
|
+
native.push(control);
|
|
139
172
|
|
|
140
173
|
if (options.spaceAfterControl !== false) this.#afterControl.addChild(new Spacer(1));
|
|
141
174
|
this.#afterControl.addChild(this.#error);
|
|
142
|
-
|
|
143
|
-
|
|
175
|
+
native.push(this.#error);
|
|
176
|
+
for (const summary of options.summary ?? []) {
|
|
177
|
+
this.#afterControl.addChild(summary);
|
|
178
|
+
native.push(summary);
|
|
179
|
+
}
|
|
180
|
+
if (options.hint) {
|
|
181
|
+
const hint = new StyledText(options.hint, options.theme.hint, "muted");
|
|
182
|
+
this.#afterControl.addChild(hint);
|
|
183
|
+
native.push(hint);
|
|
184
|
+
}
|
|
144
185
|
if (options.footer) {
|
|
145
186
|
this.#afterControl.addChild(new Spacer(1));
|
|
146
187
|
this.#afterControl.addChild(options.footer);
|
|
188
|
+
native.push(options.footer);
|
|
147
189
|
}
|
|
190
|
+
this.#native = col(native, { gap: "sm", role: "omp.form.field" });
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/** Label, description, details, preview, the control, error, summary, hint and footer as one column. */
|
|
194
|
+
describe(_cx: DescribeContext): NativeNode {
|
|
195
|
+
return this.#native;
|
|
148
196
|
}
|
|
149
197
|
|
|
150
198
|
get focused(): boolean {
|
|
@@ -346,14 +394,22 @@ export interface SelectFormFieldOptions extends Omit<FormFieldOptions, "preview"
|
|
|
346
394
|
onCancel(): void;
|
|
347
395
|
/** Schedule a frame after an asynchronous preview update settles. */
|
|
348
396
|
requestRender?: () => void;
|
|
397
|
+
/** The picker sheet a long choice (> {@link PICKER_MIN_ITEMS} items) describes as; defaults to the label. */
|
|
398
|
+
picker?: SelectPickerOptions;
|
|
349
399
|
}
|
|
350
400
|
|
|
401
|
+
/** Choices longer than this describe as a `picker md` sheet where the terminal draws one (spec §5 controls). */
|
|
402
|
+
const PICKER_MIN_ITEMS = 12;
|
|
403
|
+
|
|
351
404
|
/** SelectList field that centralizes selection, cancellation, preview refresh, and mouse routing. */
|
|
352
405
|
export class SelectFormField extends FormField {
|
|
353
406
|
readonly selectList: SelectList;
|
|
354
407
|
readonly #previewText: StyledText | undefined;
|
|
355
408
|
readonly #getPreview: (() => string) | undefined;
|
|
356
409
|
readonly #requestRender: (() => void) | undefined;
|
|
410
|
+
readonly #sheet: SelectListSheet;
|
|
411
|
+
/** Number of choices (before filtering). */
|
|
412
|
+
readonly itemCount: number;
|
|
357
413
|
#previewRequestId = 0;
|
|
358
414
|
|
|
359
415
|
constructor(options: SelectFormFieldOptions) {
|
|
@@ -375,6 +431,16 @@ export class SelectFormField extends FormField {
|
|
|
375
431
|
this.#previewText = previewText;
|
|
376
432
|
this.#getPreview = options.getPreview;
|
|
377
433
|
this.#requestRender = options.requestRender;
|
|
434
|
+
this.itemCount = options.items.length;
|
|
435
|
+
this.#sheet = new SelectListSheet(
|
|
436
|
+
selectList,
|
|
437
|
+
options.picker ?? {
|
|
438
|
+
title: options.label ?? "Select",
|
|
439
|
+
...(options.description ? { subtitle: options.description } : {}),
|
|
440
|
+
searchable: true,
|
|
441
|
+
},
|
|
442
|
+
{ docked: false },
|
|
443
|
+
);
|
|
378
444
|
|
|
379
445
|
selectList.onSelect = item => {
|
|
380
446
|
try {
|
|
@@ -420,9 +486,20 @@ export class SelectFormField extends FormField {
|
|
|
420
486
|
|
|
421
487
|
override invalidate(): void {
|
|
422
488
|
this.#updatePreview();
|
|
489
|
+
this.#sheet.invalidate();
|
|
423
490
|
super.invalidate();
|
|
424
491
|
}
|
|
425
492
|
|
|
493
|
+
/** Long choices describe as a picker sheet where supported; the host places it (layer or prefs editor). */
|
|
494
|
+
override describe(cx: DescribeContext): NativeNode {
|
|
495
|
+
return this.itemCount > PICKER_MIN_ITEMS && cx.supports("picker") ? this.#sheet.describe() : super.describe(cx);
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/** Picker pointer events drive the list as its keys do (preview, pick, cancel). */
|
|
499
|
+
handleNativeEvent(event: NativeUiEvent): void {
|
|
500
|
+
this.#sheet.handle(event);
|
|
501
|
+
}
|
|
502
|
+
|
|
426
503
|
#finishPreview(requestId: number): void {
|
|
427
504
|
if (requestId !== this.#previewRequestId) return;
|
|
428
505
|
this.setError(undefined);
|
|
@@ -467,13 +544,20 @@ export class Form implements Component, Focusable, MouseRoutable {
|
|
|
467
544
|
#memoWidth = -1;
|
|
468
545
|
#memoFieldLines: (readonly string[])[] = [];
|
|
469
546
|
#memoLines: readonly string[] = [];
|
|
547
|
+
readonly #native: NativeNode;
|
|
470
548
|
|
|
471
549
|
constructor(options: FormOptions) {
|
|
472
550
|
this.#options = options;
|
|
473
551
|
this.#fields = options.fields;
|
|
552
|
+
this.#native = col(this.#fields, { gap: "md", role: "omp.form" });
|
|
474
553
|
this.#syncFocus();
|
|
475
554
|
}
|
|
476
555
|
|
|
556
|
+
/** The fields as one column; focus traversal stays keyboard-driven. */
|
|
557
|
+
describe(_cx: DescribeContext): NativeNode {
|
|
558
|
+
return this.#native;
|
|
559
|
+
}
|
|
560
|
+
|
|
477
561
|
get focused(): boolean {
|
|
478
562
|
return this.#focused;
|
|
479
563
|
}
|
package/src/components/image.ts
CHANGED
|
@@ -8,6 +8,9 @@ import {
|
|
|
8
8
|
renderImage,
|
|
9
9
|
TERMINAL,
|
|
10
10
|
} from "../terminal-capabilities";
|
|
11
|
+
import { registerNativeBlob } from "../native/blobs";
|
|
12
|
+
import { node } from "../native/describe";
|
|
13
|
+
import type { DescribeContext, NativeNode } from "../native/node";
|
|
11
14
|
import type { Component } from "../tui";
|
|
12
15
|
|
|
13
16
|
export interface ImageTheme {
|
|
@@ -731,6 +734,7 @@ export class Image implements Component {
|
|
|
731
734
|
// pads itself to this height so a budget demotion never shrinks the block
|
|
732
735
|
// (its rows may already be committed to native scrollback).
|
|
733
736
|
#renderedGraphicRows = 0;
|
|
737
|
+
#native?: NativeNode;
|
|
734
738
|
|
|
735
739
|
constructor(
|
|
736
740
|
base64Data: string,
|
|
@@ -764,6 +768,32 @@ export class Image implements Component {
|
|
|
764
768
|
this.#cachedWidth = undefined;
|
|
765
769
|
}
|
|
766
770
|
|
|
771
|
+
/**
|
|
772
|
+
* A native `image` backed by a content-addressed blob; the terminal fits
|
|
773
|
+
* it. Cell caps become `ch`/`lines` bounds. The inline-image budget and
|
|
774
|
+
* graphics protocols do not apply.
|
|
775
|
+
*/
|
|
776
|
+
describe(_cx: DescribeContext): NativeNode {
|
|
777
|
+
if (this.#native) return this.#native;
|
|
778
|
+
const blob = registerNativeBlob(Buffer.from(this.#base64Data, "base64"), this.#mimeType);
|
|
779
|
+
const maxW = this.#options.maxWidthCells;
|
|
780
|
+
const maxH = this.#options.maxHeightCells;
|
|
781
|
+
this.#native = node("image", {
|
|
782
|
+
blob,
|
|
783
|
+
alt: imageFallback(this.#mimeType, this.#dimensions, this.#options.filename),
|
|
784
|
+
w: this.#dimensions.widthPx,
|
|
785
|
+
h: this.#dimensions.heightPx,
|
|
786
|
+
max:
|
|
787
|
+
(maxW ?? 0) > 0 || (maxH ?? 0) > 0
|
|
788
|
+
? {
|
|
789
|
+
w: maxW && maxW > 0 ? `${maxW}ch` : undefined,
|
|
790
|
+
h: maxH && maxH > 0 ? `${maxH}lines` : undefined,
|
|
791
|
+
}
|
|
792
|
+
: undefined,
|
|
793
|
+
});
|
|
794
|
+
return this.#native;
|
|
795
|
+
}
|
|
796
|
+
|
|
767
797
|
render(width: number): readonly string[] {
|
|
768
798
|
const imageProtocol = TERMINAL.imageProtocol;
|
|
769
799
|
const hasProtocol = imageProtocol != null;
|
package/src/components/input.ts
CHANGED
|
@@ -2,6 +2,11 @@ import { BracketedPasteHandler, decodeReencodedPasteControls } from "../brackete
|
|
|
2
2
|
import { getKeybindings } from "../keybindings";
|
|
3
3
|
import { extractPrintableText, matchesKey } from "../keys";
|
|
4
4
|
import { KillRing } from "../kill-ring";
|
|
5
|
+
import type { TspInputProps } from "@oh-my-pi/pi-wire";
|
|
6
|
+
import { node } from "../native/describe";
|
|
7
|
+
import { sameProps } from "../native/memo";
|
|
8
|
+
import { plainText } from "../native/spans";
|
|
9
|
+
import type { DescribeContext, NativeNode } from "../native/node";
|
|
5
10
|
import { SpaceHoldGesture } from "../space-hold";
|
|
6
11
|
import { type Component, CURSOR_MARKER, type Focusable } from "../tui";
|
|
7
12
|
import { cursorColumnWindow } from "./scroll-viewport";
|
|
@@ -58,6 +63,8 @@ export class Input implements Component, Focusable {
|
|
|
58
63
|
prompt = "> ";
|
|
59
64
|
/** Render the editable value as bullets while retaining the real value internally. */
|
|
60
65
|
mask = false;
|
|
66
|
+
/** Dim hint a native terminal shows while the value is empty. */
|
|
67
|
+
placeholder: string | undefined;
|
|
61
68
|
onSubmit?: (value: string) => void;
|
|
62
69
|
onEscape?: () => void;
|
|
63
70
|
/** Space-bar push-to-talk; set its `handler` to enable it. */
|
|
@@ -81,9 +88,17 @@ export class Input implements Component, Focusable {
|
|
|
81
88
|
/** Code units of the current volatile speech-to-text preview (see {@link setVolatileText}). */
|
|
82
89
|
#volatileTextLen = 0;
|
|
83
90
|
|
|
91
|
+
#native?: { props: TspInputProps; node: NativeNode };
|
|
92
|
+
|
|
84
93
|
getValue(): string {
|
|
85
94
|
return this.#value;
|
|
86
95
|
}
|
|
96
|
+
|
|
97
|
+
/** The caret as a UTF-16 offset into {@link getValue}. */
|
|
98
|
+
getCursor(): number {
|
|
99
|
+
return this.#cursor;
|
|
100
|
+
}
|
|
101
|
+
|
|
87
102
|
/** Return bounded input content and cursor state for debug inspection. */
|
|
88
103
|
debugState(): Record<string, unknown> {
|
|
89
104
|
return {
|
|
@@ -112,7 +127,14 @@ export class Input implements Component, Focusable {
|
|
|
112
127
|
return this.#useTerminalCursor;
|
|
113
128
|
}
|
|
114
129
|
|
|
115
|
-
|
|
130
|
+
/**
|
|
131
|
+
* Apply one key: the editor's text bindings (motion, deletion, kill ring,
|
|
132
|
+
* undo), pastes and printable text. Returns whether the key was the
|
|
133
|
+
* field's: false for keys it has no binding for, and for cancel/submit
|
|
134
|
+
* without an `onEscape`/`onSubmit`, so a host (a list's search field) can
|
|
135
|
+
* route everything else on.
|
|
136
|
+
*/
|
|
137
|
+
handleInput(data: string): boolean {
|
|
116
138
|
// Handle bracketed paste mode
|
|
117
139
|
const paste = this.#pasteHandler.process(data);
|
|
118
140
|
if (paste.handled) {
|
|
@@ -122,77 +144,79 @@ export class Input implements Component, Focusable {
|
|
|
122
144
|
this.handleInput(paste.remaining);
|
|
123
145
|
}
|
|
124
146
|
}
|
|
125
|
-
return;
|
|
147
|
+
return true;
|
|
126
148
|
}
|
|
127
149
|
|
|
128
150
|
// Space-hold push-to-talk: a sustained space bar starts/stops STT instead of typing spaces.
|
|
129
151
|
switch (this.spaceHold.process(matchesKey(data, "space"))) {
|
|
130
152
|
case "type":
|
|
131
153
|
this.#insertCharacter(" ");
|
|
132
|
-
return;
|
|
154
|
+
return true;
|
|
133
155
|
case "swallow":
|
|
134
|
-
return;
|
|
156
|
+
return true;
|
|
135
157
|
}
|
|
136
158
|
|
|
137
159
|
const kb = getKeybindings();
|
|
138
160
|
|
|
139
161
|
// Escape/Cancel
|
|
140
162
|
if (kb.matches(data, "tui.select.cancel")) {
|
|
141
|
-
if (this.onEscape)
|
|
142
|
-
|
|
163
|
+
if (!this.onEscape) return false;
|
|
164
|
+
this.onEscape();
|
|
165
|
+
return true;
|
|
143
166
|
}
|
|
144
167
|
|
|
145
168
|
// Undo
|
|
146
169
|
if (kb.matches(data, "tui.editor.undo")) {
|
|
147
170
|
this.#undo();
|
|
148
|
-
return;
|
|
171
|
+
return true;
|
|
149
172
|
}
|
|
150
173
|
|
|
151
174
|
// Submit
|
|
152
175
|
if (kb.matches(data, "tui.input.submit") || data === "\n") {
|
|
153
|
-
if (this.onSubmit)
|
|
154
|
-
|
|
176
|
+
if (!this.onSubmit) return false;
|
|
177
|
+
this.onSubmit(this.#value);
|
|
178
|
+
return true;
|
|
155
179
|
}
|
|
156
180
|
|
|
157
181
|
// Deletion
|
|
158
182
|
if (kb.matches(data, "tui.editor.deleteCharBackward")) {
|
|
159
183
|
this.#handleBackspace();
|
|
160
|
-
return;
|
|
184
|
+
return true;
|
|
161
185
|
}
|
|
162
186
|
|
|
163
187
|
if (kb.matches(data, "tui.editor.deleteCharForward")) {
|
|
164
188
|
this.#handleForwardDelete();
|
|
165
|
-
return;
|
|
189
|
+
return true;
|
|
166
190
|
}
|
|
167
191
|
|
|
168
192
|
if (kb.matches(data, "tui.editor.deleteWordBackward")) {
|
|
169
193
|
this.#deleteWordBackwards();
|
|
170
|
-
return;
|
|
194
|
+
return true;
|
|
171
195
|
}
|
|
172
196
|
|
|
173
197
|
if (kb.matches(data, "tui.editor.deleteWordForward")) {
|
|
174
198
|
this.#deleteWordForward();
|
|
175
|
-
return;
|
|
199
|
+
return true;
|
|
176
200
|
}
|
|
177
201
|
|
|
178
202
|
if (kb.matches(data, "tui.editor.deleteToLineStart")) {
|
|
179
203
|
this.#deleteToLineStart();
|
|
180
|
-
return;
|
|
204
|
+
return true;
|
|
181
205
|
}
|
|
182
206
|
|
|
183
207
|
if (kb.matches(data, "tui.editor.deleteToLineEnd")) {
|
|
184
208
|
this.#deleteToLineEnd();
|
|
185
|
-
return;
|
|
209
|
+
return true;
|
|
186
210
|
}
|
|
187
211
|
|
|
188
212
|
// Kill ring actions
|
|
189
213
|
if (kb.matches(data, "tui.editor.yank")) {
|
|
190
214
|
this.#yank();
|
|
191
|
-
return;
|
|
215
|
+
return true;
|
|
192
216
|
}
|
|
193
217
|
if (kb.matches(data, "tui.editor.yankPop")) {
|
|
194
218
|
this.#yankPop();
|
|
195
|
-
return;
|
|
219
|
+
return true;
|
|
196
220
|
}
|
|
197
221
|
|
|
198
222
|
// Cursor movement
|
|
@@ -204,7 +228,7 @@ export class Input implements Component, Focusable {
|
|
|
204
228
|
const lastGrapheme = graphemes[graphemes.length - 1];
|
|
205
229
|
this.#cursor -= lastGrapheme ? lastGrapheme.segment.length : 1;
|
|
206
230
|
}
|
|
207
|
-
return;
|
|
231
|
+
return true;
|
|
208
232
|
}
|
|
209
233
|
|
|
210
234
|
if (kb.matches(data, "tui.editor.cursorRight")) {
|
|
@@ -215,36 +239,36 @@ export class Input implements Component, Focusable {
|
|
|
215
239
|
const firstGrapheme = graphemes[0];
|
|
216
240
|
this.#cursor += firstGrapheme ? firstGrapheme.segment.length : 1;
|
|
217
241
|
}
|
|
218
|
-
return;
|
|
242
|
+
return true;
|
|
219
243
|
}
|
|
220
244
|
|
|
221
245
|
if (kb.matches(data, "tui.editor.cursorLineStart")) {
|
|
222
246
|
this.#lastAction = null;
|
|
223
247
|
this.#cursor = 0;
|
|
224
|
-
return;
|
|
248
|
+
return true;
|
|
225
249
|
}
|
|
226
250
|
|
|
227
251
|
if (kb.matches(data, "tui.editor.cursorLineEnd")) {
|
|
228
252
|
this.#lastAction = null;
|
|
229
253
|
this.#cursor = this.#value.length;
|
|
230
|
-
return;
|
|
254
|
+
return true;
|
|
231
255
|
}
|
|
232
256
|
|
|
233
257
|
if (kb.matches(data, "tui.editor.cursorWordLeft")) {
|
|
234
258
|
this.#moveWordBackwards();
|
|
235
|
-
return;
|
|
259
|
+
return true;
|
|
236
260
|
}
|
|
237
261
|
|
|
238
262
|
if (kb.matches(data, "tui.editor.cursorWordRight")) {
|
|
239
263
|
this.#moveWordForwards();
|
|
240
|
-
return;
|
|
264
|
+
return true;
|
|
241
265
|
}
|
|
242
266
|
|
|
243
267
|
// Regular character input, including Kitty CSI-u text-producing sequences.
|
|
244
268
|
const printableText = extractPrintableText(data);
|
|
245
|
-
if (printableText)
|
|
246
|
-
|
|
247
|
-
|
|
269
|
+
if (!printableText) return false;
|
|
270
|
+
this.#insertCharacter(printableText);
|
|
271
|
+
return true;
|
|
248
272
|
}
|
|
249
273
|
|
|
250
274
|
/** Apply terminal paste semantics to text from non-bracketed paste transports
|
|
@@ -484,6 +508,33 @@ export class Input implements Component, Focusable {
|
|
|
484
508
|
// No cached state to invalidate currently
|
|
485
509
|
}
|
|
486
510
|
|
|
511
|
+
/**
|
|
512
|
+
* An `input` with the value, the caret as a UTF-16 offset and the prompt;
|
|
513
|
+
* the terminal draws the caret, scrolls horizontally and places the IME.
|
|
514
|
+
* A masked input sends one bullet per grapheme, with the caret mapped onto
|
|
515
|
+
* them, so the secret never leaves the process.
|
|
516
|
+
*/
|
|
517
|
+
describe(_cx: DescribeContext): NativeNode {
|
|
518
|
+
let value = this.#value;
|
|
519
|
+
let cursor = this.#cursor;
|
|
520
|
+
if (this.mask) {
|
|
521
|
+
const graphemes = [...segmenter.segment(this.#value)];
|
|
522
|
+
value = "•".repeat(graphemes.length);
|
|
523
|
+
cursor = graphemes.filter(grapheme => grapheme.index < this.#cursor).length;
|
|
524
|
+
}
|
|
525
|
+
const prompt = plainText(this.prompt);
|
|
526
|
+
const props: TspInputProps = {
|
|
527
|
+
text: value,
|
|
528
|
+
cursor,
|
|
529
|
+
prompt: prompt || undefined,
|
|
530
|
+
placeholder: this.placeholder,
|
|
531
|
+
};
|
|
532
|
+
if (this.#native && sameProps(this.#native.props, props)) return this.#native.node;
|
|
533
|
+
const described = node("input", props);
|
|
534
|
+
this.#native = { props, node: described };
|
|
535
|
+
return described;
|
|
536
|
+
}
|
|
537
|
+
|
|
487
538
|
render(width: number): readonly string[] {
|
|
488
539
|
width = Number.isFinite(width) ? Math.max(0, Math.trunc(width)) : 0;
|
|
489
540
|
// Calculate visible window
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { compactText, styleSpans } from "../native/spans";
|
|
2
|
+
import { node } from "../native/describe";
|
|
3
|
+
import type { DescribeContext, NativeNode } from "../native/node";
|
|
1
4
|
import type { Component } from "../tui";
|
|
2
5
|
import { Ellipsis, getWidthConfigEpoch, replaceTabs, truncateToWidth, visibleWidth, wrapTextWithAnsi } from "../utils";
|
|
3
6
|
|
|
@@ -31,6 +34,7 @@ export class KeyValueList implements Component {
|
|
|
31
34
|
#rows: readonly KeyValueRow[];
|
|
32
35
|
readonly #options: KeyValueListOptions;
|
|
33
36
|
#cache: { width: number; epoch: number; lines: readonly string[] } | undefined;
|
|
37
|
+
#native: NativeNode | undefined;
|
|
34
38
|
|
|
35
39
|
constructor(rows: readonly KeyValueRow[], options: KeyValueListOptions) {
|
|
36
40
|
this.#rows = rows;
|
|
@@ -41,11 +45,25 @@ export class KeyValueList implements Component {
|
|
|
41
45
|
if (this.#rows === rows) return false;
|
|
42
46
|
this.#rows = rows;
|
|
43
47
|
this.#cache = undefined;
|
|
48
|
+
this.#native = undefined;
|
|
44
49
|
return true;
|
|
45
50
|
}
|
|
46
51
|
|
|
47
52
|
invalidate(): void {
|
|
48
53
|
this.#cache = undefined;
|
|
54
|
+
this.#native = undefined;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** An aligned `kv` grid; label width and value wrapping are the terminal's. */
|
|
58
|
+
describe(_cx: DescribeContext): NativeNode {
|
|
59
|
+
this.#native ??= node("kv", {
|
|
60
|
+
layout: "grid",
|
|
61
|
+
items: this.#rows.map(row => ({
|
|
62
|
+
k: compactText(styleSpans(singleLine(row.label), row.labelStyle)),
|
|
63
|
+
v: compactText(styleSpans(singleLine(row.value), row.valueStyle)),
|
|
64
|
+
})),
|
|
65
|
+
});
|
|
66
|
+
return this.#native;
|
|
49
67
|
}
|
|
50
68
|
|
|
51
69
|
render(width: number): readonly string[] {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { TspProps, TspSpace } from "@oh-my-pi/pi-wire";
|
|
1
2
|
import type { MouseRoutable } from "../../mouse";
|
|
2
3
|
import type { Component } from "../../tui";
|
|
3
4
|
import { padding, truncateToWidth, visibleWidth } from "../../utils";
|
|
@@ -51,6 +52,49 @@ export interface LayoutAllocation {
|
|
|
51
52
|
max?: number;
|
|
52
53
|
}
|
|
53
54
|
|
|
55
|
+
const kNativeAdapter = Symbol("layout.nativeAdapter");
|
|
56
|
+
type AdaptedRenderer = LayoutRenderer & { [kNativeAdapter]?: Component };
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Describe child for layout content: components describe themselves; a lazy
|
|
60
|
+
* row renderer becomes a stable adapter component the native engine renders
|
|
61
|
+
* as a `rows` fallback (it can only produce width-bound rows).
|
|
62
|
+
*/
|
|
63
|
+
export function nativeLayoutChild(content: LayoutContent): Component {
|
|
64
|
+
if (typeof content !== "function") return content;
|
|
65
|
+
const adapted = content as AdaptedRenderer;
|
|
66
|
+
adapted[kNativeAdapter] ??= { render: width => content(width, undefined) };
|
|
67
|
+
return adapted[kNativeAdapter];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** Spacing step standing in for a textual gap decoration (the terminal draws no divider glyphs). */
|
|
71
|
+
export function nativeLayoutGap(decoration: LayoutDecoration | undefined): TspSpace | undefined {
|
|
72
|
+
const length = layoutDecorationText(decoration).length;
|
|
73
|
+
if (length === 0) return undefined;
|
|
74
|
+
if (length === 1) return "xs";
|
|
75
|
+
if (length === 2) return "sm";
|
|
76
|
+
return "md";
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** Flex props for one layout slot along `axis` (`w` for rows, `h` for stacks). */
|
|
80
|
+
export function nativeSlotProps(
|
|
81
|
+
axis: "w" | "h",
|
|
82
|
+
slot: { fixed?: number; grow?: number; min?: number; max?: number },
|
|
83
|
+
): TspProps<"col"> {
|
|
84
|
+
const bound = (cells: number): { w: `${number}ch` } | { h: `${number}lines` } =>
|
|
85
|
+
axis === "w" ? { w: `${cells}ch` } : { h: `${cells}lines` };
|
|
86
|
+
const fixed = optionalLayoutSize(slot.fixed);
|
|
87
|
+
if (fixed !== undefined) return { grow: 0, shrink: 0, min: bound(fixed), max: bound(fixed) };
|
|
88
|
+
const min = optionalLayoutSize(slot.min);
|
|
89
|
+
const max = optionalLayoutSize(slot.max);
|
|
90
|
+
return {
|
|
91
|
+
grow: slot.grow === undefined ? undefined : layoutSize(slot.grow),
|
|
92
|
+
basis: "content",
|
|
93
|
+
min: min === undefined || min === 0 ? undefined : bound(min),
|
|
94
|
+
max: max === undefined ? undefined : bound(max),
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
|
|
54
98
|
/** Clamp an external size to a finite, non-negative integer cell count. */
|
|
55
99
|
export function layoutSize(value: number | undefined, fallback = 0): number {
|
|
56
100
|
const resolved = value === undefined || !Number.isFinite(value) ? fallback : value;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { MouseRoutable, SgrMouseEvent } from "../../mouse";
|
|
2
|
+
import { col, row } from "../../native/describe";
|
|
3
|
+
import type { DescribeContext, NativeNode } from "../../native/node";
|
|
2
4
|
import type { Component } from "../../tui";
|
|
3
5
|
import { padding, visibleWidth } from "../../utils";
|
|
4
6
|
import {
|
|
@@ -15,6 +17,9 @@ import {
|
|
|
15
17
|
type LayoutInsets,
|
|
16
18
|
type LayoutRect,
|
|
17
19
|
layoutSize,
|
|
20
|
+
nativeLayoutChild,
|
|
21
|
+
nativeLayoutGap,
|
|
22
|
+
nativeSlotProps,
|
|
18
23
|
optionalLayoutSize,
|
|
19
24
|
renderLayoutContent,
|
|
20
25
|
uniqueLayoutComponents,
|
|
@@ -87,6 +92,7 @@ export class Row implements Component, MouseRoutable {
|
|
|
87
92
|
#frames: LayoutRect[] = [];
|
|
88
93
|
#memo: RowMemo | undefined;
|
|
89
94
|
#ignoreTight = false;
|
|
95
|
+
#native: { children: RowChild[]; gap: LayoutDecoration | undefined; node: NativeNode } | undefined;
|
|
90
96
|
|
|
91
97
|
constructor(options: RowOptions) {
|
|
92
98
|
this.#children = options.children.map(child => ({ ...child, padding: { ...child.padding } }));
|
|
@@ -168,6 +174,30 @@ export class Row implements Component, MouseRoutable {
|
|
|
168
174
|
}
|
|
169
175
|
}
|
|
170
176
|
|
|
177
|
+
/**
|
|
178
|
+
* A flex `row`: each child sits in a slot carrying its width bounds
|
|
179
|
+
* (fixed → min = max `ch`, else grow/min/max). Decorations become gap
|
|
180
|
+
* spacing; clipping and the exact row budget are the terminal's.
|
|
181
|
+
*/
|
|
182
|
+
describe(_cx: DescribeContext): NativeNode {
|
|
183
|
+
const cached = this.#native;
|
|
184
|
+
if (cached?.children === this.#children && cached.gap === this.#gap) return cached.node;
|
|
185
|
+
const slots = this.#children.map(child =>
|
|
186
|
+
col(
|
|
187
|
+
[nativeLayoutChild(child.content)],
|
|
188
|
+
nativeSlotProps("w", {
|
|
189
|
+
fixed: child.width,
|
|
190
|
+
grow: child.width === undefined ? layoutSize(child.grow, 1) : undefined,
|
|
191
|
+
min: child.minWidth,
|
|
192
|
+
max: child.maxWidth,
|
|
193
|
+
}),
|
|
194
|
+
),
|
|
195
|
+
);
|
|
196
|
+
const described = row(slots, { gap: nativeLayoutGap(this.#gap), align: this.#align });
|
|
197
|
+
this.#native = { children: this.#children, gap: this.#gap, node: described };
|
|
198
|
+
return described;
|
|
199
|
+
}
|
|
200
|
+
|
|
171
201
|
/** Translate a row-local point into a child's local coordinates. */
|
|
172
202
|
locate(line: number, col: number): RowHit | undefined {
|
|
173
203
|
for (let index = 0; index < this.#frames.length; index++) {
|