gloomberb 0.18.3 → 0.18.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/README.md +8 -8
- package/README.zh-CN.md +11 -11
- package/bin/{gloomberb → gloom} +3 -1
- package/package.json +6 -2
- package/src/account/checkout-handoff.tsx +225 -0
- package/src/account/device-signin-dialog.tsx +2 -2
- package/src/account/device-signin.ts +2 -2
- package/src/account/upgrade-dialog.tsx +1 -1
- package/src/api-client/askg.ts +2 -2
- package/src/api-client/auth.ts +2 -2
- package/src/api-client/central-bank-rates.ts +6 -0
- package/src/api-client/collections.ts +5 -1
- package/src/api-client/cot.ts +2 -0
- package/src/api-client/crypto-etf-flows.ts +37 -0
- package/src/api-client/crypto-markets.ts +60 -0
- package/src/api-client/data.ts +84 -5
- package/src/api-client/doe.ts +15 -0
- package/src/api-client/equity-screener.ts +28 -0
- package/src/api-client/exchange-announcements.ts +38 -0
- package/src/api-client/fund-facts.ts +39 -0
- package/src/api-client/futures-curve.ts +9 -1
- package/src/api-client/hiring.ts +301 -0
- package/src/api-client/index.ts +22 -5
- package/src/api-client/market-discovery.ts +14 -0
- package/src/api-client/members.ts +6 -0
- package/src/api-client/mna.ts +6 -0
- package/src/api-client/paths.ts +18 -1
- package/src/api-client/request.ts +21 -4
- package/src/api-client/short-side-publications.ts +37 -0
- package/src/api-client/socket.ts +64 -4
- package/src/api-client/swap-curve.ts +35 -0
- package/src/api-client/themes.ts +7 -1
- package/src/api-client/types.ts +90 -2
- package/src/app/pane-runtime/plugin-bindings.ts +9 -2
- package/src/app/runtime/desktop-deeplink.ts +5 -5
- package/src/app/runtime/plugin-bindings.ts +2 -2
- package/src/app/runtime/startup.ts +13 -0
- package/src/app/star-prompt/status-line.tsx +2 -2
- package/src/architecture/core-builtin-allowlist.json +5 -2
- package/src/architecture/ui-literals-allowlist.json +3 -3
- package/src/architecture/ui-tokens-allowlist.json +1 -1
- package/src/brokers/broker-portfolio-sync.ts +37 -0
- package/src/brokers/directory.ts +11 -0
- package/src/brokers/logos.ts +3 -1
- package/src/brokers/signed-in/adapter.ts +304 -26
- package/src/brokers/signed-in/client.ts +14 -2
- package/src/brokers/signed-in/connect.ts +10 -2
- package/src/brokers/sync-broker-instance.ts +9 -1
- package/src/capabilities/chart-series.ts +22 -6
- package/src/cli/bank-section.ts +1 -1
- package/src/cli/base-converter.ts +23 -14
- package/src/cli/central-bank-events.ts +1 -1
- package/src/cli/command-options.ts +59 -4
- package/src/cli/commands/api.ts +9 -6
- package/src/cli/commands/broker.ts +2 -2
- package/src/cli/commands/command-utils.ts +2 -2
- package/src/cli/commands/crypto-hints.ts +7 -20
- package/src/cli/commands/fred-series.ts +4 -2
- package/src/cli/commands/keybindings.ts +2 -2
- package/src/cli/commands/market.ts +1117 -264
- package/src/cli/commands/news-hints.ts +2 -2
- package/src/cli/commands/news-search.ts +59 -6
- package/src/cli/commands/options-leaps.ts +41 -26
- package/src/cli/commands/overview.ts +121 -48
- package/src/cli/commands/plugins.ts +9 -9
- package/src/cli/commands/remote.ts +13 -10
- package/src/cli/commands/search.ts +64 -44
- package/src/cli/commands/system.ts +27 -19
- package/src/cli/commands/themes.ts +1 -1
- package/src/cli/commands/ticker.ts +192 -47
- package/src/cli/context.ts +3 -2
- package/src/cli/desktop-pane-shot-view.ts +2 -2
- package/src/cli/desktop-pane-shot.ts +1 -1
- package/src/cli/earnings-calendar.ts +4 -4
- package/src/cli/entry.ts +18 -1
- package/src/cli/errors.ts +20 -2
- package/src/cli/exit-codes.ts +1 -1
- package/src/cli/export-source.ts +10 -4
- package/src/cli/freshness.ts +2 -8
- package/src/cli/fx-forward.ts +130 -0
- package/src/cli/fx-pair.ts +10 -9
- package/src/cli/glossary.ts +64 -20
- package/src/cli/help.ts +19 -13
- package/src/cli/history-export.ts +126 -0
- package/src/cli/history-rows.ts +196 -43
- package/src/cli/index-roots.ts +5 -45
- package/src/cli/index.ts +24 -18
- package/src/cli/known-gaps.ts +118 -25
- package/src/cli/listing-arg.ts +300 -41
- package/src/cli/name-entries.ts +30 -18
- package/src/cli/native-smoke.ts +2 -0
- package/src/cli/not-a-ticker.ts +19 -9
- package/src/cli/opentui-libc.ts +5 -0
- package/src/cli/options.ts +12 -0
- package/src/cli/pane-functions/capabilities.ts +75 -20
- package/src/cli/pane-functions/catalog.ts +24 -23
- package/src/cli/pane-functions/discovery.ts +1 -1
- package/src/cli/pane-functions/dom.ts +10 -7
- package/src/cli/pane-functions/financial-ratio-shot.ts +2 -2
- package/src/cli/pane-functions/freshness.ts +174 -23
- package/src/cli/pane-functions/function-help.ts +66 -27
- package/src/cli/pane-functions/headless.ts +24 -11
- package/src/cli/pane-functions/index.ts +18 -16
- package/src/cli/pane-functions/options.ts +22 -2
- package/src/cli/pane-functions/report-notices.ts +12 -4
- package/src/cli/pane-functions/report.ts +5 -5
- package/src/cli/pane-functions/resolver.ts +47 -10
- package/src/cli/pane-functions/screenshot-assessment.ts +322 -0
- package/src/cli/pane-functions/screenshot-bridge.ts +152 -0
- package/src/cli/pane-functions/screenshot-chart-evidence.ts +396 -0
- package/src/cli/pane-functions/screenshot-data-evidence.ts +383 -0
- package/src/cli/pane-functions/screenshot-evidence.ts +1 -1
- package/src/cli/pane-functions/screenshot-payload.ts +453 -0
- package/src/cli/pane-functions/screenshot-render.ts +316 -0
- package/src/cli/pane-functions/screenshot-types.ts +162 -0
- package/src/cli/pane-functions/shot-options.ts +8 -3
- package/src/cli/peso-dollar-rates.ts +79 -0
- package/src/cli/quote-answer.ts +38 -3
- package/src/cli/report-tables.ts +61 -16
- package/src/cli/restore-plugins.ts +29 -14
- package/src/cli/result.ts +111 -22
- package/src/cli/series-search.ts +5 -5
- package/src/cli/statement-filings.ts +19 -0
- package/src/cli/suffixed-listing-rows.ts +49 -0
- package/src/cli/symbol-args.ts +50 -15
- package/src/cli/symbol-cells.ts +120 -0
- package/src/cli/symbol-list.ts +198 -68
- package/src/cli/symbol-rows.ts +131 -25
- package/src/cli/ticker-resolution.ts +108 -11
- package/src/cli/treasury-yields.ts +5 -5
- package/src/cli/types.ts +2 -0
- package/src/cli/uncovered-instrument.ts +3 -3
- package/src/cli/unknown-command.ts +6 -6
- package/src/components/chart/composite/chart-layout.ts +131 -0
- package/src/components/chart/composite/composite-chart.tsx +373 -16
- package/src/components/chart/composite/interactions.ts +7 -2
- package/src/components/chart/composite/legend.tsx +75 -3
- package/src/components/chart/composite/levels.ts +5 -0
- package/src/components/chart/composite/panel-gestures.ts +41 -0
- package/src/components/chart/composite/panel-labels.ts +2 -1
- package/src/components/chart/composite/panel-surface.tsx +305 -11
- package/src/components/chart/composite/price-axis-labels.tsx +27 -3
- package/src/components/chart/composite/rasterizer.ts +44 -19
- package/src/components/chart/composite/scene.ts +16 -4
- package/src/components/chart/composite/text-renderer.ts +48 -21
- package/src/components/chart/composite/toolbar.tsx +52 -5
- package/src/components/chart/composite/types.ts +13 -0
- package/src/components/chart/composite/use-composite-chart-keyboard.ts +120 -13
- package/src/components/chart/composite/use-composite-value-scales.ts +44 -0
- package/src/components/chart/composite/use-composite-viewport.ts +12 -3
- package/src/components/chart/composite/value-scale.ts +149 -0
- package/src/components/chart/composite/volume-profile-paint.ts +6 -3
- package/src/components/chart/core/pointer.ts +2 -0
- package/src/components/chart-table/index.ts +2 -0
- package/src/components/chart-table/read.tsx +74 -0
- package/src/components/command-bar/commands/collection-list.ts +41 -19
- package/src/components/command-bar/commands/collection.ts +9 -3
- package/src/components/command-bar/commands/direct/index.ts +1 -1
- package/src/components/command-bar/commands/direct/runtime.ts +3 -2
- package/src/components/command-bar/pane-templates/items.ts +59 -6
- package/src/components/command-bar/pane-templates/workflow.ts +10 -1
- package/src/components/command-bar/routes/root/plugin-install.ts +1 -1
- package/src/components/command-bar/routes/root/provider-search.ts +42 -11
- package/src/components/command-bar/routes/root/results.ts +18 -4
- package/src/components/command-bar/routes/root/runtime.ts +15 -3
- package/src/components/command-bar/routes/root/search-providers.ts +25 -2
- package/src/components/command-bar/routes/root/selection.ts +6 -1
- package/src/components/command-bar/routes/root/shortcut-feedback.ts +4 -1
- package/src/components/command-bar/routes/root/shortcuts.ts +30 -3
- package/src/components/command-bar/routes/ticker-search/results.ts +73 -4
- package/src/components/command-bar/selection-runtime.ts +50 -10
- package/src/components/command-bar/surface/index.tsx +24 -2
- package/src/components/command-bar/view-model.ts +7 -0
- package/src/components/command-bar/workflow/broker.ts +2 -2
- package/src/components/command-bar/workflow/collection-actions.ts +46 -7
- package/src/components/command-bar/workflow/collection-ticker.ts +32 -4
- package/src/components/command-bar/workflow/fields.ts +8 -2
- package/src/components/command-bar/workflow/ops.ts +18 -4
- package/src/components/command-bar/workflow/portfolio-position.ts +53 -4
- package/src/components/command-bar/workflow/submit.ts +3 -2
- package/src/components/command-bar/workflow/tickers.ts +5 -1
- package/src/components/company-logo.tsx +39 -0
- package/src/components/data-table/sections.ts +4 -2
- package/src/components/form-modal/confirm.tsx +2 -1
- package/src/components/form-modal/request.ts +5 -0
- package/src/components/form-modal/routes.ts +4 -1
- package/src/components/index.ts +12 -6
- package/src/components/layout/header.tsx +7 -6
- package/src/components/layout/market-summary.ts +9 -6
- package/src/components/layout/pane/capture-status.ts +1 -1
- package/src/components/layout/pane/footer/model.ts +11 -5
- package/src/components/layout/shell/chrome.ts +19 -6
- package/src/components/layout/shell/index.tsx +2 -1
- package/src/components/layout/shell/pane/layers.tsx +19 -1
- package/src/components/layout/status-bar.tsx +2 -2
- package/src/components/market-board/index.tsx +11 -3
- package/src/components/onboarding/onboarding-wizard.tsx +1 -0
- package/src/components/onboarding/portfolio-step/broker-setup-panel.tsx +2 -2
- package/src/components/onboarding/wizard-broker-sync.ts +4 -1
- package/src/components/pane-settings-dialog/desktop.tsx +20 -7
- package/src/components/pane-settings-dialog/tui.tsx +17 -9
- package/src/components/pane-settings-dialog/value.ts +8 -1
- package/src/components/pane-settings-dialog.tsx +44 -13
- package/src/components/sign-in-code-panel.tsx +27 -19
- package/src/components/ui/column-grid.tsx +48 -4
- package/src/components/ui/country-flag-art.tsx +180 -0
- package/src/components/ui/country-flag.tsx +118 -12
- package/src/components/ui/data-table/opentui/index.tsx +61 -2
- package/src/components/ui/data-table/opentui/model.ts +109 -2
- package/src/components/ui/data-table/types.ts +1 -1
- package/src/components/ui/display.tsx +5 -1
- package/src/components/ui/index.ts +3 -1
- package/src/components/ui/logo-mark.tsx +11 -2
- package/src/components/ui/query-bar.tsx +1 -1
- package/src/components/ui/row-notes.ts +79 -0
- package/src/core/state/app/layout.ts +4 -4
- package/src/data/cached-query.ts +8 -1
- package/src/data/config/chart-settings.ts +3 -3
- package/src/data/config/home.ts +10 -2
- package/src/data/config/layout.ts +4 -1
- package/src/data/config/store/node.ts +4 -0
- package/src/data/config/store/normalize.ts +13 -3
- package/src/data/config/store/portfolio-as-of-column.ts +2 -2
- package/src/data/json-storage.ts +2 -0
- package/src/data/saved-copies.ts +84 -0
- package/src/docs/snapshot.json +65 -32
- package/src/i18n/es.ts +29 -12
- package/src/i18n/ja.ts +29 -12
- package/src/i18n/ko.ts +29 -12
- package/src/i18n/zh-cn.ts +29 -12
- package/src/i18n/zh-tw.ts +29 -12
- package/src/layout/desks.ts +1 -1
- package/src/layout/launch-layout.ts +1 -1
- package/src/layout/pane-manager/floating-actions.ts +5 -3
- package/src/layout/pane-manager/floating.ts +43 -1
- package/src/layout/pane-manager/index.ts +2 -0
- package/src/layout/selected-ticker.ts +74 -0
- package/src/market-data/depositary-pair.ts +251 -0
- package/src/market-data/futures-board.ts +1 -1
- package/src/market-data/futures-contract.ts +124 -40
- package/src/market-data/fx-closes.ts +17 -2
- package/src/market-data/hooks.tsx +19 -11
- package/src/market-data/market/change-basis.ts +49 -7
- package/src/market-data/market/freshness.ts +34 -5
- package/src/market-data/market/period-return.ts +163 -0
- package/src/market-data/market/trading-sessions.ts +13 -0
- package/src/market-data/market/year-to-date.ts +8 -13
- package/src/market-data/performance.ts +20 -14
- package/src/market-data/perpetual-premium.ts +32 -0
- package/src/market-data/published-apac-sessions.ts +2 -1
- package/src/market-data/published-futures-sessions.ts +69 -0
- package/src/market-data/quotes/contributions.ts +5 -1
- package/src/market-data/quotes/freshness.ts +42 -0
- package/src/market-data/quotes/intraday-bar.ts +37 -0
- package/src/market-data/quotes/regular-session-valuation.ts +13 -8
- package/src/market-data/quotes/resolution.ts +4 -2
- package/src/market-data/tax-equivalent.ts +1 -1
- package/src/market-data/ticker-price-returns.ts +3 -1
- package/src/news/aggregator.ts +5 -1
- package/src/news/news-model.ts +4 -0
- package/src/news/types.ts +11 -0
- package/src/notifications/app-notifier.ts +1 -1
- package/src/plugins/auto-update.ts +2 -2
- package/src/plugins/builtin/account-management/index.tsx +1 -0
- package/src/plugins/builtin/account-management/pane.tsx +9 -8
- package/src/plugins/builtin/alerts/alert-engine.ts +29 -19
- package/src/plugins/builtin/alerts/calendar-events.ts +378 -0
- package/src/plugins/builtin/alerts/cli.ts +485 -76
- package/src/plugins/builtin/alerts/command.ts +5 -10
- package/src/plugins/builtin/alerts/event-rows.ts +9 -5
- package/src/plugins/builtin/alerts/events-pane.tsx +71 -56
- package/src/plugins/builtin/alerts/events.ts +107 -5
- package/src/plugins/builtin/alerts/fired-log.ts +78 -0
- package/src/plugins/builtin/alerts/format.ts +2 -1
- package/src/plugins/builtin/alerts/headless.ts +100 -39
- package/src/plugins/builtin/alerts/history-pane.tsx +105 -62
- package/src/plugins/builtin/alerts/history-rows.ts +89 -0
- package/src/plugins/builtin/alerts/index.tsx +45 -18
- package/src/plugins/builtin/alerts/iv-level.ts +365 -0
- package/src/plugins/builtin/alerts/levels.ts +3 -3
- package/src/plugins/builtin/alerts/pane.tsx +97 -29
- package/src/plugins/builtin/alerts/price.ts +35 -0
- package/src/plugins/builtin/alerts/quotes.ts +24 -0
- package/src/plugins/builtin/alerts/research-builder.ts +84 -11
- package/src/plugins/builtin/alerts/research-rules.ts +76 -3
- package/src/plugins/builtin/alerts/scheduled-check.ts +206 -32
- package/src/plugins/builtin/alerts/scheduled-sources.ts +26 -3
- package/src/plugins/builtin/alerts/scheduled.ts +188 -29
- package/src/plugins/builtin/alerts/storage.ts +13 -10
- package/src/plugins/builtin/alerts/targets.ts +12 -3
- package/src/plugins/builtin/analytics/index.tsx +8 -2
- package/src/plugins/builtin/analytics/metrics.ts +1 -1
- package/src/plugins/builtin/analytics/risk-book.ts +215 -0
- package/src/plugins/builtin/analytics/risk-client.ts +13 -6
- package/src/plugins/builtin/analytics/risk-headless.ts +55 -21
- package/src/plugins/builtin/analytics/risk-math.ts +6 -3
- package/src/plugins/builtin/analytics/risk-model.ts +297 -104
- package/src/plugins/builtin/analytics/risk-options.ts +17 -2
- package/src/plugins/builtin/analytics/risk-pane.tsx +97 -36
- package/src/plugins/builtin/attention/pane.tsx +6 -2
- package/src/plugins/builtin/awards/headless.ts +7 -3
- package/src/plugins/builtin/awards/model.ts +18 -0
- package/src/plugins/builtin/awards/pane.tsx +6 -3
- package/src/plugins/builtin/backtest/headless.ts +3 -3
- package/src/plugins/builtin/backtest/rules.ts +41 -5
- package/src/plugins/builtin/broker-manager/add-flow.tsx +12 -7
- package/src/plugins/builtin/broker-manager/detail.tsx +47 -19
- package/src/plugins/builtin/broker-manager/footer.ts +27 -11
- package/src/plugins/builtin/broker-manager/index.tsx +21 -12
- package/src/plugins/builtin/broker-manager/keyboard.ts +1 -1
- package/src/plugins/builtin/broker-manager/model.ts +12 -2
- package/src/plugins/builtin/broker-manager/pane-actions.tsx +183 -57
- package/src/plugins/builtin/broker-manager/table.ts +28 -12
- package/src/plugins/builtin/broker-trading/account-picker.tsx +2 -1
- package/src/plugins/builtin/broker-trading/chart-levels.ts +82 -13
- package/src/plugins/builtin/broker-trading/controller.ts +45 -13
- package/src/plugins/builtin/broker-trading/dock.tsx +22 -4
- package/src/plugins/builtin/broker-trading/headless.ts +2 -1
- package/src/plugins/builtin/broker-trading/index.tsx +7 -1
- package/src/plugins/builtin/broker-trading/linked-orders.ts +148 -0
- package/src/plugins/builtin/broker-trading/order-feed.ts +75 -7
- package/src/plugins/builtin/broker-trading/orders.tsx +109 -31
- package/src/plugins/builtin/broker-trading/overview-orders.tsx +9 -3
- package/src/plugins/builtin/broker-trading/pane-model.ts +30 -2
- package/src/plugins/builtin/broker-trading/pane.tsx +110 -23
- package/src/plugins/builtin/broker-trading/ticket-parts.tsx +36 -7
- package/src/plugins/builtin/broker-trading/ticket.tsx +112 -31
- package/src/plugins/builtin/buildout/cells.tsx +4 -0
- package/src/plugins/builtin/buildout/detail/index.tsx +5 -1
- package/src/plugins/builtin/buildout/detail/ui.tsx +7 -4
- package/src/plugins/builtin/buildout/pane/index.tsx +25 -12
- package/src/plugins/builtin/buildout/pane/status.tsx +0 -4
- package/src/plugins/builtin/builtin-plugin-meta.ts +1 -1
- package/src/plugins/builtin/catalysts/detail.tsx +3 -2
- package/src/plugins/builtin/catalysts/index.tsx +1 -1
- package/src/plugins/builtin/catalysts/model.ts +49 -4
- package/src/plugins/builtin/catalysts/pane.tsx +6 -8
- package/src/plugins/builtin/central-bank-rates/client.ts +5 -0
- package/src/plugins/builtin/central-bank-rates/headless.ts +36 -10
- package/src/plugins/builtin/central-bank-rates/model.ts +33 -8
- package/src/plugins/builtin/changelog/index.tsx +1 -0
- package/src/plugins/builtin/chart-composer/catalog-inventory.ts +1 -0
- package/src/plugins/builtin/chart-composer/chart-spec-edit.ts +2 -1
- package/src/plugins/builtin/chart-composer/chart-spec.ts +7 -0
- package/src/plugins/builtin/chart-composer/cli-options.ts +2 -5
- package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +2 -1
- package/src/plugins/builtin/chart-composer/editor/controller.ts +2 -0
- package/src/plugins/builtin/chart-composer/editor.tsx +4 -1
- package/src/plugins/builtin/chart-composer/headless-schema.ts +28 -26
- package/src/plugins/builtin/chart-composer/headless.ts +253 -35
- package/src/plugins/builtin/chart-composer/index.tsx +12 -2
- package/src/plugins/builtin/chart-composer/leverage-overlay.ts +142 -0
- package/src/plugins/builtin/chart-composer/pane.tsx +127 -28
- package/src/plugins/builtin/chart-composer/series-catalog.ts +1 -0
- package/src/plugins/builtin/chart-composer/series-expression.ts +65 -6
- package/src/plugins/builtin/chart-composer/session-history.ts +15 -21
- package/src/plugins/builtin/chart-composer/session-range.ts +4 -2
- package/src/plugins/builtin/chart-composer/settings.ts +31 -19
- package/src/plugins/builtin/chart-composer/use-series-catalog.ts +5 -6
- package/src/plugins/builtin/chart-composer/viewport-labels.ts +18 -8
- package/src/plugins/builtin/chat/attachments/model.ts +3 -1
- package/src/plugins/builtin/chat/content/index.tsx +1 -1
- package/src/plugins/builtin/chat/pane-links/open.ts +1 -1
- package/src/plugins/builtin/chat/people.ts +1 -1
- package/src/plugins/builtin/clinical-trials/client.ts +5 -2
- package/src/plugins/builtin/clinical-trials/model.ts +13 -4
- package/src/plugins/builtin/clinical-trials/pane.tsx +32 -12
- package/src/plugins/builtin/clinical-trials/ticker-sponsor.ts +17 -0
- package/src/plugins/builtin/cloud/askg/controller.ts +1 -1
- package/src/plugins/builtin/cloud/askg/lock-note.ts +1 -1
- package/src/plugins/builtin/cloud/askg/tool-display.ts +1 -1
- package/src/plugins/builtin/cloud/auth-commands.ts +3 -3
- package/src/plugins/builtin/cloud/team/pane-sections.tsx +105 -47
- package/src/plugins/builtin/cloud/team/pane-ui.tsx +42 -4
- package/src/plugins/builtin/cloud/team/pane.tsx +204 -64
- package/src/plugins/builtin/cloud/thesis/store.ts +45 -22
- package/src/plugins/builtin/cloud-tweets/registration.ts +1 -0
- package/src/plugins/builtin/commodities-energy/index.tsx +29 -2
- package/src/plugins/builtin/commodities-energy/view-state.ts +2 -0
- package/src/plugins/builtin/commodity-balances/pane.tsx +11 -4
- package/src/plugins/builtin/company-attention/app-rank.tsx +7 -5
- package/src/plugins/builtin/company-attention/building-model.ts +222 -0
- package/src/plugins/builtin/company-attention/building.tsx +172 -0
- package/src/plugins/builtin/company-attention/client.ts +117 -1
- package/src/plugins/builtin/company-attention/evidence.ts +16 -3
- package/src/plugins/builtin/company-attention/headless.ts +101 -5
- package/src/plugins/builtin/company-attention/index.tsx +6 -3
- package/src/plugins/builtin/company-attention/model.ts +33 -7
- package/src/plugins/builtin/company-attention/moves-model.ts +253 -0
- package/src/plugins/builtin/company-attention/moves.tsx +159 -0
- package/src/plugins/builtin/company-attention/pane.tsx +79 -23
- package/src/plugins/builtin/company-attention/signals-model.ts +229 -0
- package/src/plugins/builtin/company-attention/signals.tsx +160 -0
- package/src/plugins/builtin/company-kpis/headless.ts +3 -2
- package/src/plugins/builtin/company-kpis/model.ts +2 -2
- package/src/plugins/builtin/company-kpis/pane.tsx +1 -1
- package/src/plugins/builtin/composite-plugins.ts +2 -1
- package/src/plugins/builtin/congress-trades/headless.ts +1 -1
- package/src/plugins/builtin/connections/index.ts +1 -0
- package/src/plugins/builtin/correlation/headless-schema.ts +3 -2
- package/src/plugins/builtin/correlation/headless.ts +5 -3
- package/src/plugins/builtin/cot/headless.ts +28 -6
- package/src/plugins/builtin/cot/model.ts +12 -0
- package/src/plugins/builtin/cot/pane.tsx +3 -2
- package/src/plugins/builtin/cpi/headless.ts +5 -1
- package/src/plugins/builtin/cpi/pane.tsx +11 -9
- package/src/plugins/builtin/credit-boards/model.ts +2 -0
- package/src/plugins/builtin/credit-documents/headless.ts +1 -1
- package/src/plugins/builtin/crypto-board/client.ts +86 -0
- package/src/plugins/builtin/crypto-board/defi-view.tsx +218 -0
- package/src/plugins/builtin/crypto-board/defi.ts +239 -0
- package/src/plugins/builtin/crypto-board/headless.ts +117 -6
- package/src/plugins/builtin/crypto-board/index.tsx +8 -3
- package/src/plugins/builtin/crypto-board/model.ts +40 -8
- package/src/plugins/builtin/crypto-board/pane.tsx +55 -21
- package/src/plugins/builtin/crypto-board/series.ts +19 -1
- package/src/plugins/builtin/crypto-etf-flows/client.ts +60 -0
- package/src/plugins/builtin/crypto-etf-flows/headless.ts +132 -0
- package/src/plugins/builtin/crypto-etf-flows/index.tsx +44 -0
- package/src/plugins/builtin/crypto-etf-flows/model.ts +121 -0
- package/src/plugins/builtin/crypto-etf-flows/pane.tsx +193 -0
- package/src/plugins/builtin/debug/index.tsx +1 -0
- package/src/plugins/builtin/dividend-yield/index.tsx +1 -1
- package/src/plugins/builtin/docs/index.tsx +1 -1
- package/src/plugins/builtin/docs/pane.tsx +2 -2
- package/src/plugins/builtin/docs/targets.ts +1 -1
- package/src/plugins/builtin/doe/client.ts +5 -1
- package/src/plugins/builtin/doe/headless.ts +12 -6
- package/src/plugins/builtin/doe/model.ts +43 -6
- package/src/plugins/builtin/doe/pane.tsx +18 -11
- package/src/plugins/builtin/earnings/board-model.ts +13 -6
- package/src/plugins/builtin/earnings/board-table.ts +4 -1
- package/src/plugins/builtin/earnings/board.tsx +253 -50
- package/src/plugins/builtin/earnings/calendar-model.ts +188 -0
- package/src/plugins/builtin/earnings/calendar.tsx +338 -0
- package/src/plugins/builtin/earnings/client.ts +4 -3
- package/src/plugins/builtin/earnings/headless.ts +53 -15
- package/src/plugins/builtin/earnings/history-model.ts +53 -36
- package/src/plugins/builtin/earnings/index.tsx +15 -22
- package/src/plugins/builtin/earnings/model.ts +17 -12
- package/src/plugins/builtin/earnings/scope.ts +89 -0
- package/src/plugins/builtin/earnings-calls/calendar.tsx +310 -0
- package/src/plugins/builtin/earnings-calls/data.ts +146 -2
- package/src/plugins/builtin/earnings-calls/headless.ts +151 -9
- package/src/plugins/builtin/earnings-calls/index.tsx +3 -3
- package/src/plugins/builtin/earnings-calls/lock-note.ts +1 -1
- package/src/plugins/builtin/earnings-calls/pane.tsx +149 -31
- package/src/plugins/builtin/earnings-calls/upcoming.ts +195 -0
- package/src/plugins/builtin/earnings-ripple/pane.tsx +10 -5
- package/src/plugins/builtin/econ/calendar-model.ts +132 -20
- package/src/plugins/builtin/econ/detail-view.tsx +48 -10
- package/src/plugins/builtin/econ/fred-catalog.ts +23 -6
- package/src/plugins/builtin/econ/fred-series-map.ts +4 -0
- package/src/plugins/builtin/econ/index.tsx +112 -25
- package/src/plugins/builtin/econ/print-watch.ts +2 -1
- package/src/plugins/builtin/econ/types.ts +32 -1
- package/src/plugins/builtin/econ-statistics/client.ts +16 -3
- package/src/plugins/builtin/econ-statistics/defs.ts +4 -0
- package/src/plugins/builtin/econ-statistics/detail.tsx +2 -2
- package/src/plugins/builtin/econ-statistics/headless.ts +13 -2
- package/src/plugins/builtin/econ-statistics/index.tsx +3 -3
- package/src/plugins/builtin/econ-statistics/pane.tsx +2 -1
- package/src/plugins/builtin/econ-statistics/stats.ts +103 -0
- package/src/plugins/builtin/econ-statistics/view.ts +16 -1
- package/src/plugins/builtin/equity-screener/client.ts +21 -3
- package/src/plugins/builtin/equity-screener/headless.ts +68 -6
- package/src/plugins/builtin/equity-screener/live.ts +1 -1
- package/src/plugins/builtin/equity-screener/model.ts +6 -0
- package/src/plugins/builtin/equity-screener/pane.tsx +45 -10
- package/src/plugins/builtin/equity-screener/screen-check.ts +90 -0
- package/src/plugins/builtin/equity-screener/ticker-check.tsx +148 -0
- package/src/plugins/builtin/estimate-revisions/headless.ts +3 -1
- package/src/plugins/builtin/estimate-revisions/lock-note.ts +3 -3
- package/src/plugins/builtin/estimate-revisions/model.ts +8 -10
- package/src/plugins/builtin/exposure/headless.ts +51 -6
- package/src/plugins/builtin/exposure/index.tsx +28 -2
- package/src/plugins/builtin/exposure/model.ts +7 -0
- package/src/plugins/builtin/exposure/pane.tsx +6 -1
- package/src/plugins/builtin/fear-greed/index.tsx +1 -1
- package/src/plugins/builtin/filing-events/index.tsx +1 -1
- package/src/plugins/builtin/futures/model.ts +10 -9
- package/src/plugins/builtin/futures/returns.ts +8 -36
- package/src/plugins/builtin/futures/table.tsx +1 -1
- package/src/plugins/builtin/futures-curve/client.ts +40 -9
- package/src/plugins/builtin/futures-curve/headless.ts +39 -17
- package/src/plugins/builtin/futures-curve/model.ts +258 -69
- package/src/plugins/builtin/futures-curve/pane.tsx +46 -17
- package/src/plugins/builtin/fx-matrix/client.ts +15 -8
- package/src/plugins/builtin/fx-matrix/headless.ts +32 -14
- package/src/plugins/builtin/fx-matrix/index.tsx +13 -11
- package/src/plugins/builtin/fx-matrix/live-legs.ts +22 -0
- package/src/plugins/builtin/fx-matrix/settings.ts +2 -1
- package/src/plugins/builtin/gpu/headless.ts +9 -4
- package/src/plugins/builtin/help/index.tsx +13 -3
- package/src/plugins/builtin/holders/beneficial-model.ts +8 -11
- package/src/plugins/builtin/holders/beneficial-report.ts +6 -5
- package/src/plugins/builtin/holders/beneficial-view.tsx +7 -3
- package/src/plugins/builtin/holders/client.ts +13 -1
- package/src/plugins/builtin/holders/format.ts +28 -17
- package/src/plugins/builtin/holders/headless.ts +46 -7
- package/src/plugins/builtin/holders/index-holders.ts +264 -0
- package/src/plugins/builtin/holders/pane.tsx +79 -15
- package/src/plugins/builtin/holders/report-rows.ts +35 -7
- package/src/plugins/builtin/holders/table-model.ts +2 -1
- package/src/plugins/builtin/holders/treemap.tsx +2 -2
- package/src/plugins/builtin/insider/headless.ts +1 -1
- package/src/plugins/builtin/insider/signals-client.ts +1 -1
- package/src/plugins/builtin/insider/signals.tsx +1 -1
- package/src/plugins/builtin/ipo-calendar/pane.tsx +7 -4
- package/src/plugins/builtin/iv-history/client.ts +20 -0
- package/src/plugins/builtin/iv-history/headless.ts +4 -4
- package/src/plugins/builtin/iv-history/index.tsx +1 -1
- package/src/plugins/builtin/iv-history/model.ts +13 -4
- package/src/plugins/builtin/iv-history/series.ts +3 -1
- package/src/plugins/builtin/jobs/lock-note.ts +1 -1
- package/src/plugins/builtin/jobs/model.ts +4 -15
- package/src/plugins/builtin/jobs/pane.tsx +7 -5
- package/src/plugins/builtin/jobs/share-bars.tsx +11 -5
- package/src/plugins/builtin/jodi/pane.tsx +10 -4
- package/src/plugins/builtin/layout-manager/index.tsx +1 -0
- package/src/plugins/builtin/macro-day/headless.ts +20 -7
- package/src/plugins/builtin/macro-day/index.tsx +3 -2
- package/src/plugins/builtin/macro-day/model.ts +29 -8
- package/src/plugins/builtin/macro-day/pane.tsx +46 -10
- package/src/plugins/builtin/macro-day/releases.ts +55 -13
- package/src/plugins/builtin/market-heatmap/data.ts +9 -2
- package/src/plugins/builtin/market-heatmap/evidence.ts +1 -1
- package/src/plugins/builtin/market-heatmap/headless.ts +9 -6
- package/src/plugins/builtin/market-heatmap/index.tsx +3 -3
- package/src/plugins/builtin/market-heatmap/model.ts +10 -7
- package/src/plugins/builtin/market-movers/client.ts +33 -19
- package/src/plugins/builtin/market-movers/headless.ts +8 -2
- package/src/plugins/builtin/market-movers/index.tsx +16 -10
- package/src/plugins/builtin/market-movers/screener.ts +29 -8
- package/src/plugins/builtin/market-movers/session-body.tsx +4 -2
- package/src/plugins/builtin/market-movers/session-table.ts +4 -2
- package/src/plugins/builtin/market-movers/table.ts +4 -1
- package/src/plugins/builtin/market-valuation/headless.ts +2 -0
- package/src/plugins/builtin/market-valuation/view.ts +5 -0
- package/src/plugins/builtin/members/headless.ts +6 -5
- package/src/plugins/builtin/members/pane.tsx +11 -4
- package/src/plugins/builtin/mna/client.ts +1 -0
- package/src/plugins/builtin/mna/detail.tsx +20 -32
- package/src/plugins/builtin/mna/distress/detail.tsx +16 -4
- package/src/plugins/builtin/mna/distress/model.ts +3 -2
- package/src/plugins/builtin/mna/distress/pane.tsx +7 -4
- package/src/plugins/builtin/mna/headless.ts +6 -13
- package/src/plugins/builtin/mna/model.ts +93 -15
- package/src/plugins/builtin/mna/pane.tsx +5 -4
- package/src/plugins/builtin/news/headless.ts +12 -6
- package/src/plugins/builtin/news/index.tsx +10 -1
- package/src/plugins/builtin/news/wire/index.tsx +3 -2
- package/src/plugins/builtin/news/wire/news/command-bar-search.ts +26 -10
- package/src/plugins/builtin/news/wire/news/query-presets.ts +6 -2
- package/src/plugins/builtin/news/wire/rss/cli.ts +3 -3
- package/src/plugins/builtin/notes/cli.ts +49 -14
- package/src/plugins/builtin/openfda/pane.tsx +1 -1
- package/src/plugins/builtin/options/carry.ts +2 -2
- package/src/plugins/builtin/options/index.tsx +1 -1
- package/src/plugins/builtin/options/view.tsx +10 -10
- package/src/plugins/builtin/options-calculator/headless.ts +46 -7
- package/src/plugins/builtin/options-scenario/client.ts +123 -28
- package/src/plugins/builtin/options-scenario/collar.ts +8 -6
- package/src/plugins/builtin/options-scenario/csp-screen-headless.ts +127 -0
- package/src/plugins/builtin/options-scenario/csp-screen-pane.tsx +165 -0
- package/src/plugins/builtin/options-scenario/csp-screen.ts +258 -0
- package/src/plugins/builtin/options-scenario/csp.ts +101 -21
- package/src/plugins/builtin/options-scenario/headless.ts +36 -15
- package/src/plugins/builtin/options-scenario/hedge.ts +20 -14
- package/src/plugins/builtin/options-scenario/index.tsx +28 -3
- package/src/plugins/builtin/options-scenario/model.ts +13 -0
- package/src/plugins/builtin/options-scenario/pane.tsx +9 -5
- package/src/plugins/builtin/perps/equity-row.tsx +11 -3
- package/src/plugins/builtin/perps/freshness.ts +8 -5
- package/src/plugins/builtin/perps/headless.ts +3 -1
- package/src/plugins/builtin/perps/list-perpetuals.ts +25 -4
- package/src/plugins/builtin/perps/live-rows.ts +161 -0
- package/src/plugins/builtin/perps/markets-section.tsx +154 -0
- package/src/plugins/builtin/perps/pane.tsx +36 -17
- package/src/plugins/builtin/perps/venue-markets.ts +96 -0
- package/src/plugins/builtin/plugin-marketplace/index.tsx +2 -1
- package/src/plugins/builtin/plugin-marketplace/pane.tsx +143 -59
- package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +72 -24
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +158 -141
- package/src/plugins/builtin/portfolio-list/cli/render.ts +49 -20
- package/src/plugins/builtin/portfolio-list/cli/shared.ts +3 -3
- package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +29 -24
- package/src/plugins/builtin/portfolio-list/headless.ts +6 -3
- package/src/plugins/builtin/portfolio-list/income.ts +13 -2
- package/src/plugins/builtin/portfolio-list/index.tsx +9 -2
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +21 -8
- package/src/plugins/builtin/portfolio-list/pane/purchase-date-fx.ts +46 -0
- package/src/plugins/builtin/portfolio-list/summary/live-accounts.ts +16 -9
- package/src/plugins/builtin/portfolio-list/summary/totals.ts +2 -15
- package/src/plugins/builtin/power/client.ts +4 -1
- package/src/plugins/builtin/power/evidence.ts +22 -7
- package/src/plugins/builtin/power/gas.tsx +5 -1
- package/src/plugins/builtin/power/pane.tsx +8 -1
- package/src/plugins/builtin/power/prices.tsx +10 -3
- package/src/plugins/builtin/research/analyst-headless.ts +25 -8
- package/src/plugins/builtin/research/analyst-model.ts +68 -3
- package/src/plugins/builtin/research/corporate-actions-pane.tsx +63 -14
- package/src/plugins/builtin/research/event-model.ts +3 -1
- package/src/plugins/builtin/research/event-sources.ts +12 -4
- package/src/plugins/builtin/research/index.tsx +2 -1
- package/src/plugins/builtin/research/relative-valuation-basis.ts +58 -0
- package/src/plugins/builtin/research/relative-valuation-columns.ts +31 -2
- package/src/plugins/builtin/research/relative-valuation-currency.ts +12 -5
- package/src/plugins/builtin/research/relative-valuation-headless.ts +84 -26
- package/src/plugins/builtin/research/relative-valuation-model.ts +88 -19
- package/src/plugins/builtin/research/relative-valuation-pane.tsx +76 -9
- package/src/plugins/builtin/research/relative-valuation-peers.ts +1 -1
- package/src/plugins/builtin/reverse-dcf/model.ts +6 -2
- package/src/plugins/builtin/risk-factors/index.tsx +2 -2
- package/src/plugins/builtin/scanner/lock-note.ts +1 -1
- package/src/plugins/builtin/sec/forms.ts +13 -0
- package/src/plugins/builtin/sec/fund-abroad.ts +32 -0
- package/src/plugins/builtin/sec/fund-facts.ts +68 -8
- package/src/plugins/builtin/sec/headless.ts +85 -8
- package/src/plugins/builtin/sec/index.tsx +58 -12
- package/src/plugins/builtin/sectors/client.ts +2 -1
- package/src/plugins/builtin/sectors/sector-model.ts +11 -15
- package/src/plugins/builtin/series-inventory.ts +2 -0
- package/src/plugins/builtin/shared/broker-reconnect.ts +107 -22
- package/src/plugins/builtin/shared/cloud-upgrade.ts +34 -6
- package/src/plugins/builtin/shared/earnings-calendar.ts +375 -0
- package/src/plugins/builtin/{earnings/estimate-basis.ts → shared/earnings-estimate-basis.ts} +1 -1
- package/src/plugins/builtin/shared/earnings-report.ts +3 -3
- package/src/plugins/builtin/shared/fx-rate-freshness.ts +23 -1
- package/src/plugins/builtin/shared/job-posting.ts +129 -0
- package/src/plugins/builtin/shared/pro-lock-note.ts +3 -3
- package/src/plugins/builtin/shared/report-freshness.ts +3 -0
- package/src/plugins/builtin/shared/research-trading.tsx +21 -0
- package/src/plugins/builtin/shared/series-cache.ts +2 -0
- package/src/plugins/builtin/shared/ticker-surface.ts +2 -1
- package/src/plugins/builtin/short-interest/client.ts +2 -0
- package/src/plugins/builtin/short-interest/headless.ts +41 -12
- package/src/plugins/builtin/short-interest/index.tsx +23 -1
- package/src/plugins/builtin/short-interest/model.ts +70 -19
- package/src/plugins/builtin/short-interest/pane.tsx +19 -2
- package/src/plugins/builtin/short-interest/publications-client.ts +82 -0
- package/src/plugins/builtin/short-interest/publications-headless.ts +29 -0
- package/src/plugins/builtin/short-interest/publications-model.ts +50 -0
- package/src/plugins/builtin/short-interest/publications-pane.tsx +66 -0
- package/src/plugins/builtin/short-interest/schedule.ts +35 -2
- package/src/plugins/builtin/short-interest/surface.tsx +11 -4
- package/src/plugins/builtin/short-interest/types.ts +9 -0
- package/src/plugins/builtin/short-interest/watch-client.ts +14 -8
- package/src/plugins/builtin/short-interest/watch-model.ts +12 -25
- package/src/plugins/builtin/short-interest/watch-pane.tsx +5 -1
- package/src/plugins/builtin/supply-chain/flow.tsx +33 -9
- package/src/plugins/builtin/supply-chain/model.ts +51 -3
- package/src/plugins/builtin/supply-chain/pane.tsx +78 -39
- package/src/plugins/builtin/supply-chain/row-evidence.tsx +1 -1
- package/src/plugins/builtin/themes/headless.ts +8 -5
- package/src/plugins/builtin/themes/model.ts +14 -4
- package/src/plugins/builtin/themes/pane.tsx +24 -5
- package/src/plugins/builtin/thirteenf/headless.ts +5 -5
- package/src/plugins/builtin/thirteenf/signals.ts +3 -1
- package/src/plugins/builtin/ticker-detail/adr-pair/headless.ts +123 -0
- package/src/plugins/builtin/ticker-detail/adr-pair/model.ts +132 -0
- package/src/plugins/builtin/ticker-detail/adr-pair/tab.tsx +87 -0
- package/src/plugins/builtin/ticker-detail/data-panes/historical-prices.tsx +40 -26
- package/src/plugins/builtin/ticker-detail/data-panes/history-bars.ts +8 -4
- package/src/plugins/builtin/ticker-detail/data-panes/returns-history.ts +67 -3
- package/src/plugins/builtin/ticker-detail/data-panes/returns-model.ts +112 -5
- package/src/plugins/builtin/ticker-detail/data-panes/returns-pane.tsx +17 -2
- package/src/plugins/builtin/ticker-detail/financials/aggregation.ts +21 -7
- package/src/plugins/builtin/ticker-detail/financials/model.ts +36 -1
- package/src/plugins/builtin/ticker-detail/financials/offerings.ts +56 -0
- package/src/plugins/builtin/ticker-detail/financials/ratios.ts +62 -13
- package/src/plugins/builtin/ticker-detail/financials/tab.tsx +30 -4
- package/src/plugins/builtin/ticker-detail/headless-schema.ts +14 -2
- package/src/plugins/builtin/ticker-detail/headless.ts +148 -35
- package/src/plugins/builtin/ticker-detail/index.tsx +37 -5
- package/src/plugins/builtin/ticker-detail/overview/model.ts +65 -10
- package/src/plugins/builtin/ticker-detail/overview/pane.tsx +9 -1
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +68 -11
- package/src/plugins/builtin/ticker-detail/pane.tsx +11 -0
- package/src/plugins/builtin/ticker-detail/quote-footer.ts +8 -3
- package/src/plugins/builtin/ticker-detail/research-tabs.ts +11 -0
- package/src/plugins/builtin/vol-surface/client.ts +5 -4
- package/src/plugins/builtin/vol-surface/headless.ts +12 -3
- package/src/plugins/builtin/vol-surface/model.ts +4 -2
- package/src/plugins/builtin/volatility/model.ts +5 -10
- package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +4 -3
- package/src/plugins/builtin/world-venue-map/basemap.ts +3 -1
- package/src/plugins/builtin/world-venue-map/chokepoint-chart.ts +40 -0
- package/src/plugins/builtin/world-venue-map/evidence.ts +1 -1
- package/src/plugins/builtin/world-venue-map/geo-series.ts +90 -11
- package/src/plugins/builtin/world-venue-map/headless.ts +1 -1
- package/src/plugins/builtin/world-venue-map/index.ts +3 -26
- package/src/plugins/builtin/world-venue-map/layers.ts +1 -1
- package/src/plugins/builtin/world-venue-map/map.tsx +2 -1
- package/src/plugins/builtin/world-venue-map/pane.tsx +4 -2
- package/src/plugins/builtin/world-venue-map/venue-header.tsx +15 -4
- package/src/plugins/builtin/yield-curve/client.ts +25 -0
- package/src/plugins/builtin/yield-curve/curves.ts +7 -4
- package/src/plugins/builtin/yield-curve/headless.ts +38 -4
- package/src/plugins/builtin/yield-curve/history.ts +4 -3
- package/src/plugins/builtin/yield-curve/index.tsx +12 -6
- package/src/plugins/builtin/yield-curve/swaps-model.ts +93 -0
- package/src/plugins/builtin/yield-curve/swaps.tsx +99 -0
- package/src/plugins/bundle.ts +1 -1
- package/src/plugins/catalog-browser.ts +2 -1
- package/src/plugins/compat.ts +3 -3
- package/src/plugins/dependencies.ts +75 -14
- package/src/plugins/extracted-plugins.ts +132 -34
- package/src/plugins/host-link.ts +149 -34
- package/src/plugins/installer.ts +35 -10
- package/src/plugins/loader.ts +206 -38
- package/src/plugins/manager-node.ts +2 -2
- package/src/plugins/marketplace/deactivation.ts +22 -0
- package/src/plugins/marketplace/model.ts +2 -2
- package/src/plugins/marketplace/packs.ts +1 -1
- package/src/plugins/ownership.ts +1 -1
- package/src/plugins/peer-retry.ts +155 -0
- package/src/plugins/registry/contributions.ts +3 -1
- package/src/plugins/registry/index.ts +4 -3
- package/src/plugins/registry/plugin-state.ts +3 -0
- package/src/plugins/seed-notice.ts +20 -0
- package/src/plugins/shortcut-argument.ts +39 -0
- package/src/portfolio/allocation.ts +1 -1
- package/src/portfolio/collection-name.ts +31 -0
- package/src/portfolio/column-values.ts +10 -8
- package/src/portfolio/cost-fx.ts +296 -19
- package/src/portfolio/manual-lots.ts +75 -0
- package/src/portfolio/mutations.ts +60 -22
- package/src/portfolio/suffixed-listings.ts +209 -0
- package/src/portfolio/totals-currency.ts +24 -0
- package/src/public/__snapshots__/public-api.test.ts.snap +14 -0
- package/src/public/time-series.ts +11 -8
- package/src/remote/schema.ts +1 -1
- package/src/renderers/browser/config-host.ts +3 -0
- package/src/renderers/browser/main.tsx +23 -3
- package/src/renderers/dom/boot-frame-page.ts +187 -0
- package/src/renderers/dom/boot-frame.ts +237 -0
- package/src/renderers/dom/build-assets.ts +46 -8
- package/src/renderers/dom/dom-ui-host.tsx +4 -29
- package/src/renderers/dom/host/ascii-text.ts +16 -2
- package/src/renderers/dom/host/box.tsx +43 -2
- package/src/renderers/dom/host/chart-surface.tsx +2 -0
- package/src/renderers/dom/host/hls.chunk.ts +3 -0
- package/src/renderers/dom/host/image-surface.tsx +49 -0
- package/src/renderers/dom/host/media-surface.tsx +24 -18
- package/src/renderers/dom/host/mouse.ts +30 -0
- package/src/renderers/dom/host/size-observer.ts +1 -1
- package/src/renderers/dom/host/style.ts +1 -1
- package/src/renderers/dom/styles.css +76 -0
- package/src/renderers/dom/test-utils.tsx +2 -1
- package/src/renderers/electrobun/bun/application-menu/index.ts +3 -3
- package/src/renderers/electrobun/bun/desktop/backend-requests.ts +3 -0
- package/src/renderers/electrobun/bun/desktop/backend.ts +46 -3
- package/src/renderers/electrobun/bun/desktop/detached-windows.ts +1 -1
- package/src/renderers/electrobun/bun/desktop/host-requests.ts +9 -3
- package/src/renderers/electrobun/bun/desktop/initialization.ts +81 -18
- package/src/renderers/electrobun/bun/external-plugins.ts +29 -7
- package/src/renderers/electrobun/bun/index.ts +11 -1
- package/src/renderers/electrobun/bun/window/boot-frame.ts +67 -0
- package/src/renderers/electrobun/bun/window/create.ts +4 -1
- package/src/renderers/electrobun/shared/boot-frame.ts +7 -0
- package/src/renderers/electrobun/shared/protocol.ts +6 -1
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +1 -1
- package/src/renderers/electrobun/view/config-host.ts +3 -0
- package/src/renderers/electrobun/view/fatal-screen.tsx +1 -1
- package/src/renderers/electrobun/view/main.tsx +30 -4
- package/src/renderers/electrobun/view/news-source.ts +5 -5
- package/src/renderers/electrobun/view/remote/asset-data-client.ts +1 -1
- package/src/renderers/electrobun/view/ui-host.tsx +1 -1
- package/src/renderers/opentui/browser-open.ts +88 -0
- package/src/renderers/opentui/host.tsx +5 -14
- package/src/renderers/opentui/image/loader.ts +3 -2
- package/src/renderers/opentui/native-smoke.ts +10 -1
- package/src/renderers/opentui/pane-image/index.ts +2 -1
- package/src/renderers/opentui/render-lib.ts +253 -0
- package/src/renderers/opentui/render-timing-smoke.ts +1 -1
- package/src/renderers/opentui/start.tsx +1 -1
- package/src/renderers/share/layout-view.tsx +2 -2
- package/src/renderers/share/main.tsx +4 -4
- package/src/renderers/share/view.tsx +1 -1
- package/src/series/resolve.ts +22 -6
- package/src/series/standalone.ts +30 -2
- package/src/series/types.ts +8 -1
- package/src/shares/api.ts +4 -1
- package/src/shares/pane.ts +1 -1
- package/src/sources/gloomberb-cloud/fred-series.ts +46 -1
- package/src/sources/gloomberb-cloud/index.ts +32 -16
- package/src/sources/gloomberb-cloud/news.ts +39 -0
- package/src/sources/gloomberb-cloud/normalizers.ts +14 -1
- package/src/sources/gloomberb-cloud/perpetuals.ts +49 -1
- package/src/sources/listing-symbols.ts +37 -0
- package/src/sources/provider-errors.ts +16 -2
- package/src/sources/provider-router/financial-routes.ts +21 -3
- package/src/sources/provider-router/financials.ts +15 -2
- package/src/sources/provider-router/history.ts +30 -8
- package/src/sources/provider-router/primary.ts +1 -1
- package/src/state/app/bootstrap.ts +23 -0
- package/src/state/hooks/inline-tickers.ts +30 -5
- package/src/sync/controller.ts +1 -1
- package/src/sync/core-contributors.ts +46 -14
- package/src/team/collections-sync.ts +2 -1
- package/src/team/collections.ts +178 -17
- package/src/telemetry/crash-reports.ts +17 -4
- package/src/test-support/builtin-panes.ts +1 -1
- package/src/theme/colors.ts +3 -30
- package/src/theme/ui-tokens.ts +37 -1
- package/src/tickers/company-name-listing.ts +210 -33
- package/src/tickers/index-roots.ts +47 -0
- package/src/tickers/instrument-label.ts +5 -1
- package/src/tickers/metadata.ts +10 -0
- package/src/tickers/perpetual-listing.ts +5 -2
- package/src/tickers/search/home-listing.ts +75 -0
- package/src/tickers/search/index.ts +76 -27
- package/src/tickers/search/ranking.ts +54 -4
- package/src/tickers/search/upsert.ts +29 -0
- package/src/tickers/terminal-codes.ts +416 -40
- package/src/time-series/bar-aggregation.ts +243 -0
- package/src/time-series/base-series.ts +307 -0
- package/src/time-series/chart-bounds.ts +349 -0
- package/src/time-series/chart-seed.ts +142 -0
- package/src/time-series/economic.ts +5 -0
- package/src/time-series/fundamentals.ts +18 -3
- package/src/time-series/history-acquisition.ts +499 -0
- package/src/time-series/leverage.ts +100 -0
- package/src/time-series/market-resolution.ts +4 -2
- package/src/time-series/market.ts +2 -1
- package/src/time-series/price-comparison.ts +175 -30
- package/src/time-series/range.ts +9 -1
- package/src/time-series/resolution.ts +174 -16
- package/src/time-series/resolve-context.ts +157 -0
- package/src/time-series/resolve.ts +126 -1577
- package/src/time-series/series-name.ts +38 -0
- package/src/time-series/series-presentation.ts +208 -0
- package/src/time-series/spec.ts +11 -6
- package/src/time-series/studies.ts +109 -12
- package/src/time-series/tail-reconcile.ts +121 -0
- package/src/time-series/types.ts +29 -2
- package/src/time-series/use-chart-resolution.ts +4 -5
- package/src/types/broker.ts +10 -0
- package/src/types/config.ts +14 -0
- package/src/types/data-provider.ts +14 -0
- package/src/types/exchange-rate.ts +6 -0
- package/src/types/financials.ts +104 -7
- package/src/types/headless.ts +76 -6
- package/src/types/instrument.ts +3 -0
- package/src/types/plugin.ts +65 -8
- package/src/types/price-history.ts +2 -0
- package/src/types/ticker.ts +13 -0
- package/src/types/trading.ts +59 -1
- package/src/ui/ascii-font.ts +13 -1
- package/src/ui/host.tsx +6 -1
- package/src/updater/command-names.ts +175 -0
- package/src/updater/index.ts +10 -5
- package/src/utils/calendar-date.ts +32 -15
- package/src/utils/cash-runway.ts +241 -0
- package/src/utils/central-banks.ts +42 -0
- package/src/utils/cli-output.ts +259 -80
- package/src/utils/contract-month.ts +16 -0
- package/src/utils/crypto-pair.ts +61 -3
- package/src/utils/currency-units.ts +29 -0
- package/src/utils/datetime-format.ts +10 -0
- package/src/utils/debug-log.ts +1 -1
- package/src/utils/decimal-comma.ts +39 -6
- package/src/utils/exchange-announcements.ts +71 -0
- package/src/utils/exchange-rate-snapshot.ts +10 -0
- package/src/utils/financial-statements.ts +83 -4
- package/src/utils/format.ts +34 -16
- package/src/utils/fundamentals.ts +150 -34
- package/src/utils/fx-market-hours.ts +10 -1
- package/src/utils/latest-financial-period.ts +8 -0
- package/src/utils/linux-libc.ts +54 -0
- package/src/utils/market-capitalization.ts +111 -15
- package/src/utils/max-drawdown.ts +64 -0
- package/src/utils/network-failure.ts +83 -0
- package/src/utils/option-expiry.ts +139 -7
- package/src/utils/price-earnings.ts +11 -5
- package/src/utils/price-history.ts +18 -8
- package/src/utils/price-window.ts +131 -0
- package/src/utils/release-date.ts +47 -0
- package/src/utils/sec.ts +3 -0
- package/src/utils/throttled-fetch.ts +11 -4
- package/src/utils/trailing-eps.ts +67 -0
- package/src/utils/typed-text.ts +21 -0
- package/src/utils/utc-time.ts +24 -1
- package/src/version.ts +6 -0
- package/src/cli/pane-functions/screenshot.ts +0 -2122
package/src/cli/symbol-args.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { isFigure, isNumberCell, protectFigureCommas, restoreFigureCommas } from "./symbol-cells";
|
|
2
|
+
import { readTerminalListingCode, unknownBloombergMarket } from "../tickers/terminal-codes";
|
|
3
|
+
|
|
1
4
|
/** The quote marks a pasted list wraps its entries in: "AAPL", 'MSFT', “NVDA”. */
|
|
2
5
|
const QUOTE_MARKS = "\"'`\u2018\u2019\u201C\u201D";
|
|
3
6
|
const QUOTE_EDGES = new RegExp(`^[${QUOTE_MARKS}]+|[${QUOTE_MARKS}]+$`, "g");
|
|
@@ -12,18 +15,37 @@ const LIST_SEPARATOR = /[,;\t\r\n]/;
|
|
|
12
15
|
* in it is split on those, so an entry may be a company's name (`WHR,
|
|
13
16
|
* Whirlpool Corporation, BRK.B`) or several symbols with spaces between them
|
|
14
17
|
* (`brk.b bf-b` on a pasted line); one without them is split on spaces (`JNK
|
|
15
|
-
* EMB BRK.B`)
|
|
18
|
+
* EMB BRK.B`), or with `phrases` kept whole (`splitSymbolArgLines`). Which an
|
|
19
|
+
* entry with a space is takes a search: a command that
|
|
16
20
|
* resolves its symbols reads them with `readNameEntries`, and a parser that
|
|
17
|
-
* looks nothing up takes `splitSymbolWords`.
|
|
21
|
+
* looks nothing up takes `splitSymbolWords`. A comma inside a figure
|
|
22
|
+
* (`2.582,52`, `1,899.21`) is no separator: the figure stays one entry. One
|
|
23
|
+
* between plain digits is a decimal comma only on a line with another
|
|
24
|
+
* separator (`ED 2,5`); alone it splits codes (`9988,5`, `700,388`).
|
|
18
25
|
*/
|
|
19
|
-
export function splitSymbolArgs(args: readonly string[]): string[] {
|
|
20
|
-
return args
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
export function splitSymbolArgs(args: readonly string[], options: { phrases?: boolean } = {}): string[] {
|
|
27
|
+
return args.flatMap((arg) => splitSymbolArgLines(arg, options).flat());
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* `splitSymbolArgs` of one argument, its entries kept by the line they are
|
|
32
|
+
* on, so a figure can be told to sit beside the symbol on its line. With
|
|
33
|
+
* `phrases`, an argument with spaces and no list separator is one entry, as
|
|
34
|
+
* an entry between commas is: a company's name (`"Beyond Meat"`) or symbols
|
|
35
|
+
* typed on one line (`"GME AMC"`), which `readNameEntries` tells apart.
|
|
36
|
+
*/
|
|
37
|
+
export function splitSymbolArgLines(arg: string, { phrases = false }: { phrases?: boolean } = {}): string[][] {
|
|
38
|
+
const lines = arg.replace(/^\uFEFF/, "").split(/\r\n?|\n/).map((line) => protectFigureCommas(line));
|
|
39
|
+
const separated = lines.length > 1 || lines.some((line) => LIST_SEPARATOR.test(line));
|
|
40
|
+
// A terminal's code (`VOD LN`, `JPM US Equity`), or words written as one (`AAPL GP`), is one entry.
|
|
41
|
+
return lines.map((line) => (separated ? line.split(/[,;\t]/) : phrases || isTerminalCodeLine(line) ? [line] : line.split(/\s+/))
|
|
42
|
+
.map((entry) => restoreFigureCommas(entry).trim().replace(QUOTE_EDGES, "").trim().replace(/\s+/g, " "))
|
|
43
|
+
.filter(Boolean));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function isTerminalCodeLine(line: string): boolean {
|
|
47
|
+
const text = line.trim().replace(QUOTE_EDGES, "").trim();
|
|
48
|
+
return /\s/.test(text) && (readTerminalListingCode(text) != null || unknownBloombergMarket(text) != null);
|
|
27
49
|
}
|
|
28
50
|
|
|
29
51
|
/**
|
|
@@ -31,15 +53,28 @@ export function splitSymbolArgs(args: readonly string[]): string[] {
|
|
|
31
53
|
* spaces and no list separator into it: `quote "10 year yield"`, `quote
|
|
32
54
|
* "Apple Inc"` or a pasted line `quote "AAPL MSFT"`. Which of those it is
|
|
33
55
|
* takes a lookup (`readPhraseArgument`); `splitSymbolArgs` would split it
|
|
34
|
-
* into words, each a symbol (10, YEAR, YIELD).
|
|
35
|
-
*
|
|
56
|
+
* into words, each a symbol (10, YEAR, YIELD). A figure in it is part of
|
|
57
|
+
* the phrase (`"10.5 year yield"`, `"fed funds rate 5.25%"`). Null for
|
|
58
|
+
* anything else: several arguments, one word, a list with commas, or a
|
|
59
|
+
* pasted row of symbols each followed by its prices (`ED 2.582,52`, `AAPL
|
|
60
|
+
* 150.00 MSFT 300.00`), which is read as a list is.
|
|
36
61
|
*/
|
|
37
62
|
export function quotedPhrase(args: readonly string[]): string | null {
|
|
38
63
|
if (args.length !== 1) return null;
|
|
39
64
|
const text = args[0]!.replace(/^\uFEFF/, "");
|
|
40
|
-
if (LIST_SEPARATOR.test(text)) return null;
|
|
65
|
+
if (LIST_SEPARATOR.test(protectFigureCommas(text))) return null;
|
|
41
66
|
const phrase = text.trim().replace(QUOTE_EDGES, "").trim().replace(/\s+/g, " ");
|
|
42
|
-
return phrase.includes(" ") ? phrase : null;
|
|
67
|
+
return phrase.includes(" ") && !isPricedRow(phrase.split(" ")) ? phrase : null;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Words that are a sheet's row rather than a phrase: a number (`2.582,52`)
|
|
72
|
+
* among them, and each word that is no figure followed by one (`ED
|
|
73
|
+
* 2.582,52`), so no two words of a name or a phrase sit side by side.
|
|
74
|
+
*/
|
|
75
|
+
function isPricedRow(words: readonly string[]): boolean {
|
|
76
|
+
if (!words.some(isNumberCell) || isFigure(words[0]!)) return false;
|
|
77
|
+
return words.every((word, index) => isFigure(word) || (index + 1 < words.length && isFigure(words[index + 1]!)));
|
|
43
78
|
}
|
|
44
79
|
|
|
45
80
|
/**
|
|
@@ -50,7 +85,7 @@ export function quotedPhrase(args: readonly string[]): string | null {
|
|
|
50
85
|
*/
|
|
51
86
|
export function splitSymbolWords(args: readonly string[]): string[] {
|
|
52
87
|
return splitSymbolArgs(args)
|
|
53
|
-
.flatMap((entry) => entry.split(" "))
|
|
88
|
+
.flatMap((entry) => isTerminalCodeLine(entry) ? [entry] : entry.split(" "))
|
|
54
89
|
.map((word) => word.replace(QUOTE_EDGES, ""))
|
|
55
90
|
.filter(Boolean);
|
|
56
91
|
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What one cell of a pasted list or a typed argument is before anything is
|
|
3
|
+
* looked up: a symbol, a figure (a price, a weight, a share count) or junk
|
|
4
|
+
* a sheet leaves where a value is missing (`N/A`, `--`, `$$$`). Every list
|
|
5
|
+
* reader and every lookup of a list's symbols decide it here, so a price
|
|
6
|
+
* from a European sheet (`2.582,52`) is never searched for as a ticker.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/** A sign before a figure: plus, hyphen-minus or the minus sign. */
|
|
10
|
+
const SIGN = "[+\\-\u2212]";
|
|
11
|
+
/** The currency marks a sheet writes beside an amount. */
|
|
12
|
+
const CURRENCY = "[$\u20ac\u00a3\u00a5\u20b9\u20a9\u20bd\u20ba\u20aa\u0e3f\u20ab\u00a2]";
|
|
13
|
+
/** Thousands written with an apostrophe (1'234.50) or a no-break or thin space (1 234,50). */
|
|
14
|
+
const GROUP_MARK = "['\u2019\u00a0\u202f\u2009]";
|
|
15
|
+
const FIGURE_BODY = [
|
|
16
|
+
// 1,899.21 and 1,899: commas between thousands.
|
|
17
|
+
"\\d{1,3}(?:,\\d{3})+(?:\\.\\d+)?",
|
|
18
|
+
// 2.582,52, 1.899 and 1.234.567: dots between thousands, a decimal comma.
|
|
19
|
+
"\\d{1,3}(?:\\.\\d{3})+(?:,\\d+)?",
|
|
20
|
+
`\\d{1,3}(?:${GROUP_MARK}\\d{3})+(?:[.,]\\d+)?`,
|
|
21
|
+
// 2,5 and 12,345, and 1234,56: a decimal comma.
|
|
22
|
+
"\\d{1,3},\\d+",
|
|
23
|
+
"\\d+,\\d{1,2}",
|
|
24
|
+
"\\d*\\.\\d+",
|
|
25
|
+
"\\d+",
|
|
26
|
+
].join("|");
|
|
27
|
+
const FIGURE = new RegExp(
|
|
28
|
+
`^(?:${SIGN}?${CURRENCY}?${SIGN}?(?:${FIGURE_BODY})(?:%|\u2030|${CURRENCY})?|\\(${CURRENCY}?(?:${FIGURE_BODY})%?\\))$`,
|
|
29
|
+
"u",
|
|
30
|
+
);
|
|
31
|
+
/** A run of digits and the marks between them, where a comma may be a decimal comma rather than a list's separator. */
|
|
32
|
+
const FIGURE_RUN = new RegExp(`(?<![\\p{L}\\p{N}.])(?:${SIGN}|${CURRENCY})*\\d[\\d.,'\u2019\u00a0\u202f\u2009]*(?:%|\u2030|${CURRENCY})?`, "gu");
|
|
33
|
+
/** Placeholders a sheet writes for a missing value, and its error values: N/A, n.a., #N/A, #VALUE!. */
|
|
34
|
+
const PLACEHOLDER = /^(?:#?n\/a|n\.a\.?|#(?:value!|ref!|div\/0!|name\?|num!|null!|spill!|calc!|getting_data))$/i;
|
|
35
|
+
/** Stands in for a comma inside a figure while a line is split on its separators. */
|
|
36
|
+
const FIGURE_COMMA = "\u0000";
|
|
37
|
+
/** Plain digits split by commas (`7203,10`, `5,700`): a decimal comma, or the line's separator between two codes. */
|
|
38
|
+
const PLAIN_COMMA_RUN = /^\d+(?:,\d+)+$/;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* A figure as a sheet or a keyboard writes it, a bare whole number (7203)
|
|
42
|
+
* included: `2.582,52`, `1,899.21`, `-3.2%`, `€1.234,56`, `(1,234.56)`.
|
|
43
|
+
*/
|
|
44
|
+
export function isFigure(cell: string): boolean {
|
|
45
|
+
return FIGURE.test(cell.trim());
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* A figure that is never a symbol: one with a decimal or thousands mark, a
|
|
50
|
+
* sign, a percent or a currency mark (`1.899`, `2,5`, `+4`, `12%`, `$12`). A
|
|
51
|
+
* bare whole number is not one, as `7203` and `0700` are tickers on their own.
|
|
52
|
+
*/
|
|
53
|
+
export function isNumberCell(cell: string): boolean {
|
|
54
|
+
const text = cell.trim();
|
|
55
|
+
return FIGURE.test(text) && !/^\d+$/.test(text);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** A cell that names nothing: no letter or digit (`$$$`, `--`, `-`, `…`), or a placeholder for a missing value (`N/A`, `#N/A`). */
|
|
59
|
+
export function isJunkCell(cell: string): boolean {
|
|
60
|
+
const text = cell.trim();
|
|
61
|
+
return !/[\p{L}\p{N}]/u.test(text) || PLACEHOLDER.test(text);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** Why a cell is not a symbol, as a lookup refuses it without asking anything; null for one that may be. */
|
|
65
|
+
function notASymbolReason(cell: string): string | null {
|
|
66
|
+
if (isJunkCell(cell)) return "not a symbol";
|
|
67
|
+
if (isNumberCell(cell)) return "a number, not a symbol";
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** An entry of a list that cannot be a symbol, refused before any lookup and never looked up again. */
|
|
72
|
+
export class NotASymbolError extends Error {
|
|
73
|
+
constructor(readonly input: string, readonly reason: string) {
|
|
74
|
+
super(`${input.trim()} is ${reason}.`);
|
|
75
|
+
this.name = "NotASymbolError";
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** `NotASymbolError` for a cell that is not a symbol, else null. */
|
|
80
|
+
export function notASymbolError(cell: string): NotASymbolError | null {
|
|
81
|
+
const reason = notASymbolReason(cell);
|
|
82
|
+
return reason ? new NotASymbolError(cell, reason) : null;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Whether a comma between plain digits on a line is a decimal comma (`ED
|
|
87
|
+
* 2,5`, `CNX;1899,21`): the line has another separator, a tab, a semicolon or
|
|
88
|
+
* spaces between its cells. Otherwise the comma is the line's only separator
|
|
89
|
+
* and splits the digits into cells, as a sheet of codes exports them
|
|
90
|
+
* (`0700,25`, `7203,10`). Quoted cells and separators at the ends are not
|
|
91
|
+
* counted.
|
|
92
|
+
*/
|
|
93
|
+
export function hasDecimalCommas(line: string): boolean {
|
|
94
|
+
const bare = line.replace(/"(?:[^"]|"")*"/g, "\"\"").replace(/^[\s,;]+|[\s,;]+$/g, "");
|
|
95
|
+
return /[\t;]/.test(bare) || /[^\s,;]\s+[^\s,;]/.test(bare);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* The text with each comma inside a figure swapped for a stand-in, so
|
|
100
|
+
* splitting on commas leaves the figure whole; `restoreFigureCommas` puts
|
|
101
|
+
* them back. A figure only a number can be (`2.582,52`, `1,899.21`, `2,5%`)
|
|
102
|
+
* keeps its comma. One of plain digits (`7203,10`) keeps it only where its
|
|
103
|
+
* comma is a decimal comma: `decimalCommas`, else `hasDecimalCommas` of each
|
|
104
|
+
* line. A run that is no figure keeps its commas as separators.
|
|
105
|
+
*/
|
|
106
|
+
export function protectFigureCommas(text: string, decimalCommas?: boolean): string {
|
|
107
|
+
if (decimalCommas == null) {
|
|
108
|
+
return text.split(/(\r\n?|\n)/).map((part, index) => index % 2 === 1 ? part : protectFigureCommas(part, hasDecimalCommas(part))).join("");
|
|
109
|
+
}
|
|
110
|
+
return text.replace(FIGURE_RUN, (run) => {
|
|
111
|
+
const body = run.replace(/[.,'\u2019]+$/, "");
|
|
112
|
+
const tail = run.slice(body.length);
|
|
113
|
+
const figure = body.includes(",") && isFigure(body) && (decimalCommas || !PLAIN_COMMA_RUN.test(body));
|
|
114
|
+
return figure ? `${body.replaceAll(",", FIGURE_COMMA)}${tail}` : run;
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export function restoreFigureCommas(text: string): string {
|
|
119
|
+
return text.replaceAll(FIGURE_COMMA, ",");
|
|
120
|
+
}
|
package/src/cli/symbol-list.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { readFile } from "fs/promises";
|
|
2
2
|
import { fstatSync } from "fs";
|
|
3
|
-
import {
|
|
3
|
+
import { splitSymbolArgLines, splitSymbolWords, stripStrayEdges, uniqueSymbols } from "./symbol-args";
|
|
4
|
+
import { foldTypedText } from "../utils/typed-text";
|
|
5
|
+
import { hasDecimalCommas, isFigure, isJunkCell, isNumberCell, protectFigureCommas, restoreFigureCommas } from "./symbol-cells";
|
|
4
6
|
|
|
5
7
|
/** Header cells that name a spreadsheet's symbol column, compared without case, spaces or punctuation. */
|
|
6
8
|
const SYMBOL_HEADERS = new Set(["symbol", "symbols", "ticker", "tickers", "code", "stockcode", "securitycode", "instrument"]);
|
|
@@ -9,8 +11,6 @@ const NAME_HEADERS = new Set(["name", "names", "company", "companies", "companyn
|
|
|
9
11
|
|
|
10
12
|
/** One symbol as it can be typed: AAPL, $nvda, TTF.AS, SAN:EPA, BRK-B, 7203.T, ^GSPC, ES=F. */
|
|
11
13
|
const SYMBOL_TOKEN = /^\$?[\p{L}\p{N}^][\p{L}\p{N}.:\-^=/&]{0,23}$/u;
|
|
12
|
-
/** A plain number: a price, a weight or a share count in a spreadsheet's other columns. */
|
|
13
|
-
const NUMBER_CELL = /^[+-]?(?:\d{1,3}(?:,\d{3})+|\d*)(?:\.\d+)?%?$/;
|
|
14
14
|
|
|
15
15
|
function headerKey(cell: string): string {
|
|
16
16
|
return cell.toLowerCase().replace(/[^\p{L}\p{N}]/gu, "");
|
|
@@ -20,21 +20,61 @@ function isComment(cell: string): boolean {
|
|
|
20
20
|
return cell.startsWith("#") || cell.startsWith("//");
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
/**
|
|
24
|
-
function
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
23
|
+
/** Whether a quote mark at `index` closes a quoted cell: it is followed by a separator, a line end or the end. */
|
|
24
|
+
function closesCell(text: string, index: number): boolean {
|
|
25
|
+
return /^[^\S\n]*(?:[\t,;\n]|$)/.test(text.slice(index + 1, index + 40));
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Where the quoted cell opened at `index` ends, or -1 when no quote mark closes it, so the mark is only a stray. */
|
|
29
|
+
function closingQuote(text: string, index: number): number {
|
|
30
|
+
for (let at = text.indexOf("\"", index + 1); at >= 0; at = text.indexOf("\"", at + 1)) {
|
|
31
|
+
if (text[at + 1] === "\"") {
|
|
32
|
+
at += 1;
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
if (closesCell(text, at)) return at;
|
|
30
36
|
}
|
|
31
|
-
return
|
|
37
|
+
return -1;
|
|
32
38
|
}
|
|
33
39
|
|
|
34
|
-
/**
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
40
|
+
/**
|
|
41
|
+
* The records of a text: its lines, except that a quoted cell (RFC 4180)
|
|
42
|
+
* may hold a line break. A quote mark opens a cell only at the start of
|
|
43
|
+
* one and when a mark closes it, so a stray one never swallows the lines after it.
|
|
44
|
+
*/
|
|
45
|
+
function splitRecords(text: string): string[] {
|
|
46
|
+
const records: string[] = [];
|
|
47
|
+
let start = 0;
|
|
48
|
+
for (let index = 0; index < text.length; index += 1) {
|
|
49
|
+
const char = text[index]!;
|
|
50
|
+
if (char === "\"" && /(?:^|[\t,;])[^\S\n]*$/.test(text.slice(start, index))) {
|
|
51
|
+
const end = closingQuote(text, index);
|
|
52
|
+
if (end >= 0) index = end;
|
|
53
|
+
} else if (char === "\n") {
|
|
54
|
+
records.push(text.slice(start, index));
|
|
55
|
+
start = index + 1;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
records.push(text.slice(start));
|
|
59
|
+
return records;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* The separator of one line: a tab, else a semicolon, else a comma that
|
|
64
|
+
* splits cells, not one inside a figure (`ED 2.582,52` is split by its space,
|
|
65
|
+
* `CNX;1.899,21` by its semicolon). Null for a line split by spaces. A
|
|
66
|
+
* separator at either end is a stray (`UPST;`), named when the cell is read.
|
|
67
|
+
* `decimalCommas` says whether a comma between plain digits is a decimal one.
|
|
68
|
+
*/
|
|
69
|
+
function lineDelimiter(record: string, decimalCommas: boolean): string | null {
|
|
70
|
+
const bare = protectFigureCommas(record, decimalCommas).replace(/^[\s,;]+|[\s,;]+$/g, "").replace(/"(?:[^"]|"")*"/g, "");
|
|
71
|
+
return ["\t", ";", ","].find((delimiter) => bare.includes(delimiter)) ?? null;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** The cells of a line split by `delimiter`; a quoted cell may hold the delimiter and doubled quotes. */
|
|
75
|
+
function splitCells(record: string, delimiter: string, decimalCommas: boolean): string[] {
|
|
76
|
+
const text = protectFigureCommas(record, decimalCommas);
|
|
77
|
+
const cells: string[] = [];
|
|
38
78
|
let cell = "";
|
|
39
79
|
let quoted = false;
|
|
40
80
|
for (let index = 0; index < text.length; index += 1) {
|
|
@@ -50,30 +90,58 @@ function parseDelimited(text: string, delimiter: string): string[][] {
|
|
|
50
90
|
}
|
|
51
91
|
continue;
|
|
52
92
|
}
|
|
53
|
-
if (char === "\"" && !cell.trim()) {
|
|
93
|
+
if (char === "\"" && !cell.trim() && closingQuote(text, index) >= 0) {
|
|
54
94
|
quoted = true;
|
|
55
95
|
cell = "";
|
|
56
96
|
} else if (char === delimiter) {
|
|
57
|
-
|
|
58
|
-
cell = "";
|
|
59
|
-
} else if (char === "\n") {
|
|
60
|
-
record.push(cell);
|
|
61
|
-
records.push(record);
|
|
62
|
-
record = [];
|
|
97
|
+
cells.push(cell);
|
|
63
98
|
cell = "";
|
|
64
99
|
} else {
|
|
65
100
|
cell += char;
|
|
66
101
|
}
|
|
67
102
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
103
|
+
cells.push(cell);
|
|
104
|
+
return cells.map((value) => restoreFigureCommas(value).trim());
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* The cells of each line, each line split by its own separator
|
|
109
|
+
* (`lineDelimiter`), as a list pasted from several sheets mixes them. A line
|
|
110
|
+
* with no separator in a list whose other lines have one is one cell (a
|
|
111
|
+
* company's name), unless a figure follows its first word (`ED 2.582,52`).
|
|
112
|
+
* A comma between plain digits is a decimal comma on a line with another
|
|
113
|
+
* separator, or under a header split by tabs or semicolons; otherwise it
|
|
114
|
+
* splits the line (`0700,25` is a code and a weight). `delimited` says
|
|
115
|
+
* whether any line had a separator.
|
|
116
|
+
*/
|
|
117
|
+
function readRecords(text: string): { records: string[][]; delimited: boolean } {
|
|
118
|
+
const kept = splitRecords(text).filter((record) => record.replace(/[\s,;"']/g, ""));
|
|
119
|
+
const sheetDecimals = headerSplitsOnTabsOrSemicolons(kept[0]);
|
|
120
|
+
const lines = kept.map((record) => {
|
|
121
|
+
const decimalCommas = sheetDecimals || hasDecimalCommas(record);
|
|
122
|
+
const delimiter = lineDelimiter(record, decimalCommas);
|
|
123
|
+
return delimiter
|
|
124
|
+
? { cells: splitCells(record, delimiter, decimalCommas), delimited: true }
|
|
125
|
+
: { cells: record.trim().split(/\s+/), delimited: false };
|
|
126
|
+
});
|
|
127
|
+
const delimited = lines.some((line) => line.delimited);
|
|
128
|
+
const records = lines.map(({ cells, delimited: own }) => (
|
|
129
|
+
own || !delimited || cells.slice(1).some(isFigure) ? cells : [cells.join(" ")]
|
|
130
|
+
));
|
|
131
|
+
return { records: records.filter((cells) => cells.some(Boolean) && !isComment(cells[0] ?? "")), delimited };
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/** Whether a header line (one with a Symbol, Ticker, Code or Name cell) splits its cells on tabs or semicolons. */
|
|
135
|
+
function headerSplitsOnTabsOrSemicolons(record: string | undefined): boolean {
|
|
136
|
+
if (!record) return false;
|
|
137
|
+
const delimiter = lineDelimiter(record, false);
|
|
138
|
+
if (delimiter !== "\t" && delimiter !== ";") return false;
|
|
139
|
+
return splitCells(record, delimiter, false).map(headerKey)
|
|
140
|
+
.some((key) => SYMBOL_HEADERS.has(key) || NAME_HEADERS.has(key) || key.includes("symbol") || key.includes("ticker"));
|
|
73
141
|
}
|
|
74
142
|
|
|
75
143
|
function looksLikeSymbol(cell: string): boolean {
|
|
76
|
-
return SYMBOL_TOKEN.test(cell) && !(
|
|
144
|
+
return SYMBOL_TOKEN.test(cell) && !isNumberCell(cell);
|
|
77
145
|
}
|
|
78
146
|
|
|
79
147
|
/** How many cells a table's ignored-cells note names before it counts the rest. */
|
|
@@ -94,43 +162,45 @@ interface SymbolText {
|
|
|
94
162
|
}
|
|
95
163
|
|
|
96
164
|
/**
|
|
97
|
-
* The symbols in a file or piped text, in order.
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
* or
|
|
165
|
+
* The symbols in a file or piped text, in order. Each line is split by its
|
|
166
|
+
* own separator (`readRecords`): a tab, a semicolon, a comma that is not a
|
|
167
|
+
* decimal comma, or spaces. A figure (`2.582,52`, `1,899.21`, `12%`) is never
|
|
168
|
+
* a symbol, and a bare whole number beside a symbol is a value: such a cell
|
|
169
|
+
* makes the list a table. A spreadsheet export reads from the column its
|
|
170
|
+
* header names (Symbol, Ticker, Code), else from its Name or Company column,
|
|
171
|
+
* as `entries`. Without a header, every cell is a symbol unless some column
|
|
172
|
+
* after the first holds a name, a price or a weight: that table is read by
|
|
173
|
+
* its first column, and the cells beside it are returned as `ignored` so the
|
|
174
|
+
* command can name them. A list split by commas, spaces or newlines gives
|
|
175
|
+
* every entry, even when a line of it is ragged or carries a stray separator
|
|
176
|
+
* (`"BIMAS ,"`); a cell that names nothing (`N/A`, `$$$`) does not make it a
|
|
177
|
+
* table, and is refused by the lookup. A list of lines gives each line whole,
|
|
178
|
+
* and a list of names split by semicolons or commas (one line, or one name a
|
|
179
|
+
* line) each cell, as `entries`: a line with spaces is a company's name
|
|
180
|
+
* (`Altria Group`) or symbols on one line, which reading the entries tells
|
|
181
|
+
* apart. Names beside other text (`Apple Inc,Technology`) are a table read by
|
|
182
|
+
* its first column, its names as `entries`. A byte order mark, Windows line
|
|
183
|
+
* ends, blank lines and lines starting with # or // are ignored.
|
|
113
184
|
*/
|
|
114
185
|
export function parseSymbolText(text: string): SymbolText {
|
|
115
186
|
const normalized = text.replace(/^\uFEFF/, "").replace(/\r\n?/g, "\n");
|
|
116
|
-
const
|
|
117
|
-
const delimiter = detectDelimiter(lines);
|
|
118
|
-
const records = (delimiter ? parseDelimited(normalized, delimiter) : lines.map((line) => line.trim().split(/\s+/)))
|
|
119
|
-
.filter((cells) => cells.some(Boolean) && !isComment(cells[0] ?? ""));
|
|
187
|
+
const { records, delimited } = readRecords(normalized);
|
|
120
188
|
if (records.length === 0) return { symbols: [], ignored: [] };
|
|
121
189
|
const header = records[0]!.map(headerKey);
|
|
122
190
|
const exact = header.findIndex((cell) => SYMBOL_HEADERS.has(cell));
|
|
123
191
|
const column = exact >= 0 ? exact : header.findIndex((cell) => cell.includes("symbol") || cell.includes("ticker"));
|
|
124
192
|
if (column >= 0) return { symbols: records.slice(1).map((cells) => cells[column] ?? "").filter(Boolean), ignored: [] };
|
|
125
193
|
// Without one, a delimited export's Name or Company column holds the companies, read as typed names are.
|
|
126
|
-
const nameColumn =
|
|
194
|
+
const nameColumn = delimited ? header.findIndex((cell) => NAME_HEADERS.has(cell)) : -1;
|
|
127
195
|
if (nameColumn >= 0) return { symbols: records.slice(1).map((cells) => cells[nameColumn] ?? "").filter(Boolean), ignored: [], entries: true };
|
|
128
196
|
// A separator or quote mark stuck to a cell is dropped (and named) when it is read, so it does not make the list a table.
|
|
129
197
|
const cleaned = records.map((cells) => cells.map((cell) => stripStrayEdges(cell).text));
|
|
130
|
-
const figures = cleaned.some((cells) => cells.some((cell, index) => index > 0 &&
|
|
198
|
+
const figures = cleaned.some((cells) => cells.some((cell, index) => index > 0 && isFigure(cell)));
|
|
131
199
|
// Lines split by spaces alone are entries, unless figures sit beside the symbols.
|
|
132
|
-
if (!
|
|
133
|
-
const grid = cleaned.every((cells) => cells.every((cell, index) =>
|
|
200
|
+
if (!delimited && !figures) return { symbols: records.map((cells) => cells.join(" ")), ignored: [], entries: true };
|
|
201
|
+
const grid = cleaned.every((cells) => cells.every((cell, index) => (
|
|
202
|
+
!cell || isJunkCell(cell) || (looksLikeSymbol(cell) && (index === 0 || !isFigure(cell)))
|
|
203
|
+
)));
|
|
134
204
|
if (grid) return { symbols: records.flat().filter(Boolean), ignored: [] };
|
|
135
205
|
// Names split by semicolons or commas, with no figures: one pasted line, or one name a line with a separator left
|
|
136
206
|
// on it, is a list. A name beside a sector or any other text is a table, read by its first column below.
|
|
@@ -146,6 +216,19 @@ export function parseSymbolText(text: string): SymbolText {
|
|
|
146
216
|
};
|
|
147
217
|
}
|
|
148
218
|
|
|
219
|
+
/** Cells named in a note, split by semicolons when one of them has a comma of its own (`2.582,52; 1.899,21`). */
|
|
220
|
+
function listCells(cells: readonly string[]): string {
|
|
221
|
+
const named = cells.slice(0, IGNORED_PREVIEW);
|
|
222
|
+
const more = cells.length - IGNORED_PREVIEW;
|
|
223
|
+
return `${named.join(named.some((cell) => cell.includes(",")) ? "; " : ", ")}${more > 0 ? ` and ${more} more` : ""}`;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/** "the cell", "the 3 number cells": number when every one is a figure. */
|
|
227
|
+
function cellsNoun(cells: readonly string[]): string {
|
|
228
|
+
const kind = cells.every(isFigure) ? "number cell" : "cell";
|
|
229
|
+
return cells.length === 1 ? `the ${kind}` : `the ${cells.length} ${kind}s`;
|
|
230
|
+
}
|
|
231
|
+
|
|
149
232
|
/**
|
|
150
233
|
* The note a table read by its first column gets, naming what was left out:
|
|
151
234
|
* `Read the first column as symbols; ignored the 4 cells beside it: Apple
|
|
@@ -154,10 +237,47 @@ export function parseSymbolText(text: string): SymbolText {
|
|
|
154
237
|
*/
|
|
155
238
|
function ignoredCellsNote(ignored: readonly string[]): string | null {
|
|
156
239
|
if (ignored.length === 0) return null;
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
240
|
+
return `Read the first column as symbols; ignored ${cellsNoun(ignored)} beside it: ${listCells(ignored)}.`;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* The one note for the numbers read where a symbol goes, typed beside a
|
|
245
|
+
* symbol (`ED 2.582,52`) or on a line of their own: `Ignored 3 numbers, not
|
|
246
|
+
* symbols: 2.582,52; 1.899,21; 3.594,10.`
|
|
247
|
+
*/
|
|
248
|
+
function ignoredNumbersNote(numbers: readonly string[]): string | null {
|
|
249
|
+
if (numbers.length === 0) return null;
|
|
250
|
+
return numbers.length === 1
|
|
251
|
+
? `Ignored ${numbers[0]}, a number, not a symbol.`
|
|
252
|
+
: `Ignored ${numbers.length} numbers, not symbols: ${listCells(numbers)}.`;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* The entries of one line of what was typed, with the figures beside its
|
|
257
|
+
* symbols moved to `beside`: a number (`2.582,52`) on a line that has a
|
|
258
|
+
* symbol, and a bare whole number after a symbol when only figures follow it
|
|
259
|
+
* (`ED 2582`, `AAPL 150`). A bare whole number among symbols, or alone, is a
|
|
260
|
+
* code (`amd 2222 pltr`, `7203`).
|
|
261
|
+
*/
|
|
262
|
+
function withoutFigures(words: readonly string[], beside: string[]): string[] {
|
|
263
|
+
const symbolAt = words.findIndex((word) => !isFigure(word) && !isJunkCell(word));
|
|
264
|
+
if (symbolAt < 0) return [...words];
|
|
265
|
+
const row = symbolAt === 0 && words.length > 1 && words.slice(1).every(isFigure);
|
|
266
|
+
const value = (word: string, index: number) => index !== symbolAt && (isNumberCell(word) || (row && isFigure(word)));
|
|
267
|
+
beside.push(...words.filter(value));
|
|
268
|
+
return words.filter((word, index) => !value(word, index));
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* The entries of typed arguments (`splitSymbolArgs`), without the figures
|
|
273
|
+
* beside their symbols (`withoutFigures`), which go to `beside`. An entry with
|
|
274
|
+
* spaces (`ED 2.582,52` between semicolons) loses its figures the same way.
|
|
275
|
+
*/
|
|
276
|
+
function typedEntries(args: readonly string[], beside: string[]): string[] {
|
|
277
|
+
// An argument of words is one entry, read as a list's line is: `"Beyond Meat"` is a company, `"GME AMC"` two symbols.
|
|
278
|
+
return args.flatMap((arg) => splitSymbolArgLines(arg, { phrases: true }).flatMap((line) => withoutFigures(line, beside)
|
|
279
|
+
.map((entry) => withoutFigures(entry.split(" "), beside).join(" "))
|
|
280
|
+
.filter(Boolean)));
|
|
161
281
|
}
|
|
162
282
|
|
|
163
283
|
/** Whether standard input is a pipe or a file rather than a terminal, so a command may read its list from it. */
|
|
@@ -200,29 +320,37 @@ export class SymbolListError extends Error {
|
|
|
200
320
|
/**
|
|
201
321
|
* The symbols a command was given: as arguments, from `--file`, and from
|
|
202
322
|
* standard input when an argument is `-` or nothing else was given and input
|
|
203
|
-
* is piped in.
|
|
204
|
-
*
|
|
205
|
-
*
|
|
206
|
-
*
|
|
323
|
+
* is piped in. This is the one reader of `watchlist add`, `portfolio add`,
|
|
324
|
+
* `quote`, `compare` and the command bar's pasted list. Repeats are dropped. A
|
|
325
|
+
* separator stuck to a symbol in a file, or left on the end of what was typed
|
|
326
|
+
* (`UPST;`), is dropped with the quote marks around it, and the cells beside
|
|
327
|
+
* the symbols of a table read by its first column, or the figures typed beside
|
|
328
|
+
* a symbol, are left out; `notes` names each so the command can say so, the
|
|
329
|
+
* numbers in one line: a number (`2.582,52`, `1,899.21`, `12%`) is never a
|
|
330
|
+
* symbol, beside one or on its own. An entry that names nothing (`N/A`, `$$$`,
|
|
331
|
+
* `--`) stays in `symbols`, for the lookup to refuse without asking anything
|
|
332
|
+
* (`notASymbolError`) and the command to name.
|
|
207
333
|
*/
|
|
208
334
|
export async function readSymbolList(source: SymbolListSource): Promise<{ symbols: string[]; repeated: number; notes: string[] }> {
|
|
209
335
|
const readStdin = source.readStdin ?? (() => Bun.stdin.text());
|
|
210
336
|
const wantsStdin = source.args.includes("-") || source.file === "-";
|
|
211
337
|
const typedArgs = source.args.filter((arg) => arg !== "-");
|
|
212
|
-
const
|
|
213
|
-
const
|
|
338
|
+
const figures: string[] = [];
|
|
339
|
+
const entries = typedEntries(typedArgs, figures);
|
|
340
|
+
const readEntries = (read: string[]) => source.readEntries ? source.readEntries(read) : Promise.resolve(splitSymbolWords(read));
|
|
341
|
+
const typed = source.readEntries ? await source.readEntries(entries) : splitSymbolWords(entries);
|
|
214
342
|
const collected = [...typed];
|
|
215
343
|
// A separator left on the end of what was typed: `UPST;`, or a list that ends in a comma.
|
|
216
344
|
const strays = new Set<string>(stripStrayEdges(typedArgs.join(" ")).notes);
|
|
217
345
|
const ignored: string[] = [];
|
|
218
|
-
const addCells = async ({ symbols, ignored: beside, entries }: SymbolText) => {
|
|
346
|
+
const addCells = async ({ symbols, ignored: beside, entries: whole }: SymbolText) => {
|
|
219
347
|
const cells = symbols.map((cell) => {
|
|
220
348
|
const cleaned = stripStrayEdges(cell);
|
|
221
349
|
cleaned.notes.forEach((note) => strays.add(note));
|
|
222
350
|
return cleaned.text;
|
|
223
351
|
}).filter(Boolean);
|
|
224
352
|
// A list's lines and names are read as typed entries are: `Altria Group` stays one company.
|
|
225
|
-
collected.push(...
|
|
353
|
+
collected.push(...whole ? await readEntries(cells) : cells);
|
|
226
354
|
ignored.push(...beside);
|
|
227
355
|
};
|
|
228
356
|
if (source.file != null && source.file !== "-") {
|
|
@@ -234,11 +362,13 @@ export async function readSymbolList(source: SymbolListSource): Promise<{ symbol
|
|
|
234
362
|
const code = (error as NodeJS.ErrnoException).code;
|
|
235
363
|
throw new SymbolListError(code === "ENOENT" ? `No file at ${source.file}.` : `Could not read ${source.file}: ${error instanceof Error ? error.message : String(error)}`);
|
|
236
364
|
}
|
|
237
|
-
await addCells(parseSymbolText(text));
|
|
365
|
+
await addCells(parseSymbolText(foldTypedText(text)));
|
|
238
366
|
}
|
|
239
367
|
if (wantsStdin || (typed.length === 0 && source.file == null && (source.stdinPiped ?? stdinIsPiped()))) {
|
|
240
|
-
await addCells(parseSymbolText(await readStdin()));
|
|
368
|
+
await addCells(parseSymbolText(foldTypedText(await readStdin())));
|
|
241
369
|
}
|
|
242
|
-
|
|
243
|
-
|
|
370
|
+
// A number where a symbol goes (a line of prices, a typed 1.899) is left out with those typed beside a symbol.
|
|
371
|
+
const numbers = [...figures, ...collected.filter(isNumberCell)];
|
|
372
|
+
const notes = [ignoredCellsNote(ignored), ignoredNumbersNote(numbers)].filter((note): note is string => !!note);
|
|
373
|
+
return { ...uniqueSymbols(collected.filter((symbol) => !isNumberCell(symbol))), notes: [...strays, ...notes] };
|
|
244
374
|
}
|