gloomberb 0.8.2 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -7
- package/package.json +14 -13
- package/patches/{@opentui%2Fcore@0.1.90.patch → @opentui%2Fcore@0.3.2.patch} +175 -90
- package/src/app/global-shortcuts.test.tsx +54 -4
- package/src/app/global-shortcuts.ts +11 -5
- package/src/components/command-bar/action-runtime.ts +1 -0
- package/src/components/command-bar/layout-items/current-layout.test.ts +115 -0
- package/src/components/command-bar/layout-items/current-layout.ts +33 -0
- package/src/components/command-bar/list/view.tsx +3 -1
- package/src/components/command-bar/pane-templates/items.ts +4 -1
- package/src/components/command-bar/panel/body.tsx +1 -0
- package/src/components/command-bar/routes/root/results.ts +0 -30
- package/src/components/command-bar/routes/root/runtime.ts +2 -20
- package/src/components/command-bar/routes/ticker-search/actions.ts +42 -4
- package/src/components/command-bar/routes/ticker-search/route.ts +4 -1
- package/src/components/command-bar/routing/launch-request.ts +14 -7
- package/src/components/command-bar/routing/list-state.ts +1 -3
- package/src/components/command-bar/surface/index.test.tsx +76 -4
- package/src/components/command-bar/surface/index.tsx +0 -2
- package/src/components/command-bar/surface/pane.test.tsx +1 -0
- package/src/components/command-bar/surface/test-harness.tsx +1 -0
- package/src/components/command-bar/view-model.ts +3 -3
- package/src/components/layout/shell/index.test.tsx +120 -2
- package/src/components/layout/shell/index.tsx +2 -0
- package/src/components/layout/shell/menu.ts +1 -7
- package/src/components/layout/shell/pane/actions.ts +8 -0
- package/src/components/layout/shell/pane/management-shortcuts.ts +12 -2
- package/src/components/layout/shell/shortcuts.ts +14 -6
- package/src/components/layout/shell/window-mode/index.ts +8 -3
- package/src/components/layout/window-edit/presentation.ts +4 -4
- package/src/components/onboarding/onboarding-steps.tsx +3 -2
- package/src/components/ticker/list-table-view.tsx +6 -0
- package/src/components/ui/remote-image.tsx +1 -14
- package/src/components/ui/tabs.tsx +95 -80
- package/src/components/ui/ui.test.tsx +54 -0
- package/src/core/state/app/types.ts +12 -4
- package/src/plugins/builtin/chat/content/channel-navigation.ts +44 -11
- package/src/plugins/builtin/chat/content/index.tsx +5 -4
- package/src/plugins/builtin/chat/content/shortcuts.ts +7 -0
- package/src/plugins/builtin/chat/sidebar.test.tsx +71 -0
- package/src/plugins/builtin/help/components.tsx +1 -1
- package/src/plugins/builtin/help/index.test.tsx +105 -30
- package/src/plugins/builtin/help/index.tsx +324 -168
- package/src/plugins/builtin/help/shortcut-model.ts +5 -6
- package/src/plugins/builtin/portfolio-list/column-values.ts +304 -1
- package/src/plugins/builtin/portfolio-list/metrics.test.ts +93 -0
- package/src/plugins/builtin/portfolio-list/pane/data.ts +7 -0
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +25 -2
- package/src/plugins/builtin/portfolio-list/pane/supplemental.ts +281 -0
- package/src/plugins/builtin/portfolio-list/settings.ts +27 -0
- package/src/plugins/builtin/portfolio-list/table.tsx +4 -2
- package/src/plugins/builtin/portfolio-list/use-throttled-cursor-symbol.ts +10 -68
- package/src/plugins/builtin/substack/api/auth.ts +185 -0
- package/src/plugins/builtin/substack/api/cache.ts +78 -0
- package/src/plugins/builtin/substack/api/loaders.ts +146 -0
- package/src/plugins/builtin/substack/api/store.ts +186 -0
- package/src/plugins/builtin/substack/api/types.ts +40 -0
- package/src/plugins/builtin/substack/api.test.ts +298 -0
- package/src/plugins/builtin/substack/article-detail.tsx +359 -0
- package/src/plugins/builtin/substack/article-stack.tsx +129 -0
- package/src/plugins/builtin/substack/content.ts +478 -0
- package/src/plugins/builtin/substack/feed-tabs.tsx +41 -0
- package/src/plugins/builtin/substack/index.tsx +49 -0
- package/src/plugins/builtin/substack/login-view.tsx +126 -0
- package/src/plugins/builtin/substack/model.test.ts +155 -0
- package/src/plugins/builtin/substack/normalize.ts +343 -0
- package/src/plugins/builtin/substack/pane-footer.ts +71 -0
- package/src/plugins/builtin/substack/pane-state.ts +170 -0
- package/src/plugins/builtin/substack/pane.tsx +500 -0
- package/src/plugins/builtin/substack/table.ts +111 -0
- package/src/plugins/builtin/substack/types.ts +71 -0
- package/src/plugins/builtin/substack/utils.ts +131 -0
- package/src/plugins/builtin/ticker-detail/index.test.tsx +16 -2
- package/src/plugins/builtin/ticker-detail/index.tsx +1 -0
- package/src/plugins/builtin/ticker-detail/pane.tsx +13 -1
- package/src/plugins/catalog-ui.ts +2 -0
- package/src/plugins/pane-manager/layout-state.ts +11 -0
- package/src/plugins/pane-manager.ts +1 -1
- package/src/react/use-throttled-commit-value.ts +116 -0
- package/src/renderers/electrobun/bun/desktop/http-fetch.test.ts +42 -0
- package/src/renderers/electrobun/bun/desktop/http-fetch.ts +5 -0
- package/src/renderers/electrobun/view/http-fetch.ts +10 -3
- package/src/state/app/context/index.test.tsx +16 -0
- package/src/tickers/search/index.ts +1 -0
- package/src/version.ts +1 -1
package/README.md
CHANGED
|
@@ -51,7 +51,7 @@ For the best terminal experience, use a [Kitty](https://sw.kovidgoyal.net/kitty/
|
|
|
51
51
|
|
|
52
52
|
## Start
|
|
53
53
|
|
|
54
|
-
Open
|
|
54
|
+
Open command mode with `Ctrl+P`, then type a command. Press `` ` `` to open ticker search directly.
|
|
55
55
|
|
|
56
56
|
| Try | Opens |
|
|
57
57
|
|-----|-------|
|
|
@@ -65,7 +65,7 @@ Open the command bar with `Ctrl+P` or `` ` ``, then type a command.
|
|
|
65
65
|
## What It Does
|
|
66
66
|
|
|
67
67
|
- Research companies with quotes, charts, financials, filings, holders, insiders, options, analyst ratings, events, and relative valuation.
|
|
68
|
-
- Follow markets with top stories, breaking news, sector feeds, global indices, FX, macro events, yield curves, market movers, and fear/greed.
|
|
68
|
+
- Follow markets with top stories, breaking news, sector feeds, Substack subscriptions, global indices, FX, macro events, yield curves, market movers, and fear/greed.
|
|
69
69
|
- Track portfolios and watchlists, connect brokers, set alerts, keep notes, run AI screens, browse prediction markets, and use Gloom Cloud chat.
|
|
70
70
|
|
|
71
71
|
## CLI
|
|
@@ -94,7 +94,7 @@ Core plugin areas include:
|
|
|
94
94
|
|
|
95
95
|
- Portfolios, watchlists, manual entry, and broker connections
|
|
96
96
|
- Ticker details, quotes, charts, options, filings, holders, insiders, and research
|
|
97
|
-
- News, market movers, global indices, sectors, FX, earnings, macro data, and yield curves
|
|
97
|
+
- News, Substack reader feeds, market movers, global indices, sectors, FX, earnings, macro data, and yield curves
|
|
98
98
|
- Prediction markets, alerts, notes, chat, AI screeners, and external plugins
|
|
99
99
|
|
|
100
100
|
See [PLUGINS.md](PLUGINS.md) for the plugin API and the shared UI surface available through `gloomberb/components`.
|
|
@@ -103,7 +103,8 @@ See [PLUGINS.md](PLUGINS.md) for the plugin API and the shared UI surface availa
|
|
|
103
103
|
|
|
104
104
|
| Key | Action |
|
|
105
105
|
|-----|--------|
|
|
106
|
-
| `Ctrl+P`
|
|
106
|
+
| `Ctrl+P` | Open command mode |
|
|
107
|
+
| `` ` `` | Open ticker search |
|
|
107
108
|
| `Ctrl+,` | Open focused pane settings |
|
|
108
109
|
| `Ctrl+W` | Close focused pane |
|
|
109
110
|
| `Ctrl+Shift+M` | Move focused window (`WIN resize` starts resize mode) |
|
|
@@ -155,11 +156,15 @@ Use `HELP` inside Gloomberb for the live shortcut list. The common command-bar p
|
|
|
155
156
|
|----------|----------|
|
|
156
157
|
| `TOP` | Ranked market stories |
|
|
157
158
|
| `MOST` | Top gainers, losers, most active, and trending tickers |
|
|
159
|
+
| `PM <query>` | Polymarket and Kalshi prediction data |
|
|
158
160
|
| `N` | News feed |
|
|
159
161
|
| `CN <ticker>` | Ticker news |
|
|
160
162
|
| `NI` | Sector news |
|
|
163
|
+
| `SUB` | Authenticated Substack reader feed |
|
|
161
164
|
| `FIRST` | Breaking news |
|
|
162
165
|
| `TWIT <query>` | Ticker-related market posts |
|
|
166
|
+
| `TBO` | TheBuildout infrastructure intelligence |
|
|
167
|
+
| `CG` | Congress trading disclosures |
|
|
163
168
|
| `WEI` | Global equity indices |
|
|
164
169
|
| `ECON` | Economic events and releases |
|
|
165
170
|
| `GC` | Yield curve |
|
|
@@ -176,13 +181,10 @@ Use `HELP` inside Gloomberb for the live shortcut list. The common command-bar p
|
|
|
176
181
|
| `PORT` | Portfolio risk and sector exposure |
|
|
177
182
|
| `ALRT` | Price alerts |
|
|
178
183
|
| `SA <symbol condition price>` | Create a price alert |
|
|
179
|
-
| `PM <query>` | Polymarket and Kalshi prediction data |
|
|
180
184
|
| `AI <prompt>` | AI screener |
|
|
181
185
|
| `CHAT [channel]` | Gloom Cloud chat |
|
|
182
186
|
| `DM @user [@user...]` | Open or start a direct or group chat |
|
|
183
187
|
| `ACM` | Gloom Cloud account settings |
|
|
184
|
-
| `TBO` | TheBuildout infrastructure intelligence |
|
|
185
|
-
| `CG` | Congress trading disclosures |
|
|
186
188
|
| `NOTE` | Notes |
|
|
187
189
|
| `IBKR` | IBKR trading pane |
|
|
188
190
|
| `BR` | Broker connections |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gloomberb",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "Market research and portfolio tracker for the terminal",
|
|
5
5
|
"module": "src/index.tsx",
|
|
6
6
|
"type": "module",
|
|
@@ -37,27 +37,28 @@
|
|
|
37
37
|
"finance"
|
|
38
38
|
],
|
|
39
39
|
"devDependencies": {
|
|
40
|
-
"@types/bun": "
|
|
40
|
+
"@types/bun": "^1.3.14",
|
|
41
41
|
"@types/react-dom": "^19.2.3",
|
|
42
|
-
"electrobun": "^1.
|
|
43
|
-
"react-dom": "19.2.
|
|
42
|
+
"electrobun": "^1.18.1",
|
|
43
|
+
"react-dom": "19.2.7"
|
|
44
44
|
},
|
|
45
45
|
"peerDependencies": {
|
|
46
|
-
"typescript": "^5"
|
|
46
|
+
"typescript": "^5.9.2"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
49
|
"@opentui-ui/dialog": "^0.1.2",
|
|
50
50
|
"@opentui-ui/toast": "^0.0.5",
|
|
51
|
-
"@opentui/core": "^0.
|
|
52
|
-
"@opentui/react": "^0.
|
|
53
|
-
"@stoqey/ib": "^1.5.
|
|
54
|
-
"@tanstack/react-virtual": "^3.
|
|
55
|
-
"jimp": "1.6.
|
|
51
|
+
"@opentui/core": "^0.3.2",
|
|
52
|
+
"@opentui/react": "^0.3.2",
|
|
53
|
+
"@stoqey/ib": "^1.5.6",
|
|
54
|
+
"@tanstack/react-virtual": "^3.14.2",
|
|
55
|
+
"jimp": "1.6.1",
|
|
56
56
|
"opentui-spinner": "^0.0.6",
|
|
57
|
-
"react": "19.2.
|
|
58
|
-
"rxjs": "^7.8.2"
|
|
57
|
+
"react": "19.2.7",
|
|
58
|
+
"rxjs": "^7.8.2",
|
|
59
|
+
"web-tree-sitter": "0.25.10"
|
|
59
60
|
},
|
|
60
61
|
"patchedDependencies": {
|
|
61
|
-
"@opentui/core@0.
|
|
62
|
+
"@opentui/core@0.3.2": "patches/@opentui%2Fcore@0.3.2.patch"
|
|
62
63
|
}
|
|
63
64
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
diff --git a/index-
|
|
2
|
-
index
|
|
3
|
-
--- a/index-
|
|
4
|
-
+++ b/index-
|
|
5
|
-
@@ -
|
|
1
|
+
diff --git a/index-218h9p3f.js b/index-218h9p3f.js
|
|
2
|
+
index b9445d2cca9477dfe06026da451b6d19268fcbdd..3efd05fa41eb713ac6e539764b15c346939bb068 100644
|
|
3
|
+
--- a/index-218h9p3f.js
|
|
4
|
+
+++ b/index-218h9p3f.js
|
|
5
|
+
@@ -6487,17 +6487,27 @@ class MouseParser {
|
|
6
6
|
const buf = Buffer.isBuffer(data) ? data : Buffer.from(data.buffer, data.byteOffset, data.byteLength);
|
|
7
7
|
return buf.toString("latin1");
|
|
8
8
|
}
|
|
@@ -17,14 +17,14 @@ index e3b6cf9f90b13698966eec991fa7a1b2e1e22d96..709940f3998e5cb1caa88642fa68fa9a
|
|
|
17
17
|
+ const projected = Math.floor(Math.max(pixel, 0) * cellCount / pixelExtent);
|
|
18
18
|
+ return Math.max(0, Math.min(projected, cellCount - 1));
|
|
19
19
|
+ }
|
|
20
|
-
+ parseMouseEvent(data, context =
|
|
20
|
+
+ parseMouseEvent(data, context = undefined) {
|
|
21
21
|
const str = this.decodeInput(data);
|
|
22
22
|
- const parsed = this.parseMouseSequenceAt(str, 0);
|
|
23
23
|
+ const parsed = this.parseMouseSequenceAt(str, 0, context);
|
|
24
24
|
return parsed?.event ?? null;
|
|
25
25
|
}
|
|
26
26
|
- parseAllMouseEvents(data) {
|
|
27
|
-
+ parseAllMouseEvents(data, context =
|
|
27
|
+
+ parseAllMouseEvents(data, context = undefined) {
|
|
28
28
|
const str = this.decodeInput(data);
|
|
29
29
|
const events = [];
|
|
30
30
|
let offset = 0;
|
|
@@ -34,12 +34,12 @@ index e3b6cf9f90b13698966eec991fa7a1b2e1e22d96..709940f3998e5cb1caa88642fa68fa9a
|
|
|
34
34
|
if (!parsed) {
|
|
35
35
|
break;
|
|
36
36
|
}
|
|
37
|
-
@@ -
|
|
37
|
+
@@ -6506,19 +6516,19 @@ class MouseParser {
|
|
38
38
|
}
|
|
39
39
|
return events;
|
|
40
40
|
}
|
|
41
41
|
- parseMouseSequenceAt(str, offset) {
|
|
42
|
-
+ parseMouseSequenceAt(str, offset, context =
|
|
42
|
+
+ parseMouseSequenceAt(str, offset, context = undefined) {
|
|
43
43
|
if (!str.startsWith("\x1B[", offset))
|
|
44
44
|
return null;
|
|
45
45
|
const introducer = str[offset + 2];
|
|
@@ -53,11 +53,11 @@ index e3b6cf9f90b13698966eec991fa7a1b2e1e22d96..709940f3998e5cb1caa88642fa68fa9a
|
|
|
53
53
|
return null;
|
|
54
54
|
}
|
|
55
55
|
- parseSgrSequence(str, offset) {
|
|
56
|
-
+ parseSgrSequence(str, offset, context =
|
|
56
|
+
+ parseSgrSequence(str, offset, context = undefined) {
|
|
57
57
|
let index = offset + 3;
|
|
58
58
|
const values = [0, 0, 0];
|
|
59
59
|
let part = 0;
|
|
60
|
-
@@ -
|
|
60
|
+
@@ -6546,7 +6556,7 @@ class MouseParser {
|
|
61
61
|
if (!hasDigit || part !== 2)
|
|
62
62
|
return null;
|
|
63
63
|
return {
|
|
@@ -66,13 +66,13 @@ index e3b6cf9f90b13698966eec991fa7a1b2e1e22d96..709940f3998e5cb1caa88642fa68fa9a
|
|
|
66
66
|
consumed: index - offset + 1
|
|
67
67
|
};
|
|
68
68
|
}
|
|
69
|
-
@@ -
|
|
69
|
+
@@ -6567,10 +6577,12 @@ class MouseParser {
|
|
70
70
|
consumed: 6
|
|
71
71
|
};
|
|
72
72
|
}
|
|
73
73
|
- decodeSgrEvent(rawButtonCode, wireX, wireY, pressRelease) {
|
|
74
74
|
- const button = rawButtonCode & 3;
|
|
75
|
-
+ decodeSgrEvent(rawButtonCode, wireX, wireY, pressRelease, context =
|
|
75
|
+
+ decodeSgrEvent(rawButtonCode, wireX, wireY, pressRelease, context = undefined) {
|
|
76
76
|
+ const encodedButton = rawButtonCode & 3;
|
|
77
77
|
+ const isExtendedButton = (rawButtonCode & 128) !== 0;
|
|
78
78
|
+ const button = isExtendedButton ? 8 + encodedButton : encodedButton;
|
|
@@ -82,7 +82,7 @@ index e3b6cf9f90b13698966eec991fa7a1b2e1e22d96..709940f3998e5cb1caa88642fa68fa9a
|
|
|
82
82
|
const isMotion = (rawButtonCode & 32) !== 0;
|
|
83
83
|
const modifiers = {
|
|
84
84
|
shift: (rawButtonCode & 4) !== 0,
|
|
85
|
-
@@ -
|
|
85
|
+
@@ -6581,7 +6593,7 @@ class MouseParser {
|
|
86
86
|
let scrollInfo;
|
|
87
87
|
if (isMotion) {
|
|
88
88
|
const isDragging = this.mouseButtonsPressed.size > 0;
|
|
@@ -91,7 +91,7 @@ index e3b6cf9f90b13698966eec991fa7a1b2e1e22d96..709940f3998e5cb1caa88642fa68fa9a
|
|
|
91
91
|
type = "move";
|
|
92
92
|
} else if (isDragging) {
|
|
93
93
|
type = "drag";
|
|
94
|
-
@@ -
|
|
94
|
+
@@ -6596,17 +6608,24 @@ class MouseParser {
|
|
95
95
|
};
|
|
96
96
|
} else {
|
|
97
97
|
type = pressRelease === "M" ? "down" : "up";
|
|
@@ -104,36 +104,28 @@ index e3b6cf9f90b13698966eec991fa7a1b2e1e22d96..709940f3998e5cb1caa88642fa68fa9a
|
|
|
104
104
|
}
|
|
105
105
|
+ const pixelModeRequested = context?.mouseUsesPixels === true;
|
|
106
106
|
+ const pixelModeConfirmed = context?.mousePixelsConfirmed === true;
|
|
107
|
-
+ const pixelModeDetected = pixelModeRequested && (
|
|
108
|
-
+
|
|
109
|
-
+
|
|
110
|
-
+ wireY > (context?.terminalHeight ?? Number.POSITIVE_INFINITY)
|
|
111
|
-
+ );
|
|
112
|
-
+ const pixelX = pixelModeDetected ? Math.max(wireX - 1, 0) : void 0;
|
|
113
|
-
+ const pixelY = pixelModeDetected ? Math.max(wireY - 1, 0) : void 0;
|
|
107
|
+
+ const pixelModeDetected = pixelModeRequested && (pixelModeConfirmed || wireX > (context?.terminalWidth ?? Number.POSITIVE_INFINITY) || wireY > (context?.terminalHeight ?? Number.POSITIVE_INFINITY));
|
|
108
|
+
+ const pixelX = pixelModeDetected ? Math.max(wireX - 1, 0) : undefined;
|
|
109
|
+
+ const pixelY = pixelModeDetected ? Math.max(wireY - 1, 0) : undefined;
|
|
114
110
|
return {
|
|
115
111
|
type,
|
|
116
112
|
- button: button === 3 ? 0 : button,
|
|
117
113
|
- x: wireX - 1,
|
|
118
114
|
- y: wireY - 1,
|
|
119
115
|
+ button: !isExtendedButton && encodedButton === 3 ? 0 : button,
|
|
120
|
-
+ x: pixelModeDetected && pixelX !==
|
|
121
|
-
+
|
|
122
|
-
+ : wireX - 1,
|
|
123
|
-
+ y: pixelModeDetected && pixelY !== void 0
|
|
124
|
-
+ ? this.projectPixelToCell(pixelY, context?.pixelHeight ?? 0, context?.terminalHeight ?? 0)
|
|
125
|
-
+ : wireY - 1,
|
|
116
|
+
+ x: pixelModeDetected && pixelX !== undefined ? this.projectPixelToCell(pixelX, context?.pixelWidth ?? 0, context?.terminalWidth ?? 0) : wireX - 1,
|
|
117
|
+
+ y: pixelModeDetected && pixelY !== undefined ? this.projectPixelToCell(pixelY, context?.pixelHeight ?? 0, context?.terminalHeight ?? 0) : wireY - 1,
|
|
126
118
|
+ pixelX,
|
|
127
119
|
+ pixelY,
|
|
128
120
|
modifiers,
|
|
129
121
|
scroll: scrollInfo
|
|
130
122
|
};
|
|
131
|
-
@@ -
|
|
132
|
-
kittyKeyboardEnabled: false,
|
|
123
|
+
@@ -7030,7 +7049,13 @@ var DEFAULT_PROTOCOL_CONTEXT = {
|
|
133
124
|
privateCapabilityRepliesActive: false,
|
|
134
125
|
pixelResolutionQueryActive: false,
|
|
135
|
-
|
|
136
|
-
|
|
126
|
+
explicitWidthCprActive: false,
|
|
127
|
+
- startupCursorCprActive: false
|
|
128
|
+
+ startupCursorCprActive: false,
|
|
137
129
|
+ mouseUsesPixels: false,
|
|
138
130
|
+ mousePixelsConfirmed: false,
|
|
139
131
|
+ terminalWidth: 0,
|
|
@@ -143,12 +135,12 @@ index e3b6cf9f90b13698966eec991fa7a1b2e1e22d96..709940f3998e5cb1caa88642fa68fa9a
|
|
|
143
135
|
};
|
|
144
136
|
var RXVT_DOLLAR_CSI_RE = /^\x1b\[\d+\$$/;
|
|
145
137
|
var SYSTEM_CLOCK = new SystemClock;
|
|
146
|
-
@@ -
|
|
147
|
-
kittyKeyboardEnabled: options.protocolContext?.kittyKeyboardEnabled ?? false,
|
|
138
|
+
@@ -7369,7 +7394,13 @@ class StdinParser {
|
|
148
139
|
privateCapabilityRepliesActive: options.protocolContext?.privateCapabilityRepliesActive ?? false,
|
|
149
140
|
pixelResolutionQueryActive: options.protocolContext?.pixelResolutionQueryActive ?? false,
|
|
150
|
-
|
|
151
|
-
|
|
141
|
+
explicitWidthCprActive: options.protocolContext?.explicitWidthCprActive ?? false,
|
|
142
|
+
- startupCursorCprActive: options.protocolContext?.startupCursorCprActive ?? false
|
|
143
|
+
+ startupCursorCprActive: options.protocolContext?.startupCursorCprActive ?? false,
|
|
152
144
|
+ mouseUsesPixels: options.protocolContext?.mouseUsesPixels ?? false,
|
|
153
145
|
+ mousePixelsConfirmed: options.protocolContext?.mousePixelsConfirmed ?? false,
|
|
154
146
|
+ terminalWidth: options.protocolContext?.terminalWidth ?? 0,
|
|
@@ -158,7 +150,7 @@ index e3b6cf9f90b13698966eec991fa7a1b2e1e22d96..709940f3998e5cb1caa88642fa68fa9a
|
|
|
158
150
|
};
|
|
159
151
|
}
|
|
160
152
|
get bufferCapacity() {
|
|
161
|
-
@@ -
|
|
153
|
+
@@ -8298,11 +8329,14 @@ class StdinParser {
|
|
162
154
|
});
|
|
163
155
|
}
|
|
164
156
|
emitMouse(rawBytes, encoding) {
|
|
@@ -168,13 +160,57 @@ index e3b6cf9f90b13698966eec991fa7a1b2e1e22d96..709940f3998e5cb1caa88642fa68fa9a
|
|
|
168
160
|
this.emitOpaqueResponse("unknown", rawBytes);
|
|
169
161
|
return;
|
|
170
162
|
}
|
|
171
|
-
+ if (event.pixelX !==
|
|
163
|
+
+ if (event.pixelX !== undefined && event.pixelY !== undefined && !this.protocolContext.mousePixelsConfirmed) {
|
|
172
164
|
+ this.updateProtocolContext({ mousePixelsConfirmed: true });
|
|
173
165
|
+ }
|
|
174
166
|
this.events.push({
|
|
175
167
|
type: "mouse",
|
|
176
168
|
raw: decodeLatin1(rawBytes),
|
|
177
|
-
@@ -
|
|
169
|
+
@@ -12538,34 +12572,35 @@ function validateLinuxLibcOverride() {
|
|
170
|
+
throw new Error(`OPENTUI_LIBC must be "glibc" or "musl", got "${libc}"`);
|
|
171
|
+
}
|
|
172
|
+
async function resolveNativePackage() {
|
|
173
|
+
+ const loadNativePackage = async (packageName) => await import(packageName);
|
|
174
|
+
if (process.platform === "darwin") {
|
|
175
|
+
if (process.arch === "x64")
|
|
176
|
+
- return await import("@opentui/core-darwin-x64");
|
|
177
|
+
+ return await loadNativePackage("@opentui/core-darwin-x64");
|
|
178
|
+
if (process.arch === "arm64")
|
|
179
|
+
- return await import("@opentui/core-darwin-arm64");
|
|
180
|
+
+ return await loadNativePackage("@opentui/core-darwin-arm64");
|
|
181
|
+
}
|
|
182
|
+
if (process.platform === "linux") {
|
|
183
|
+
validateLinuxLibcOverride();
|
|
184
|
+
if (process.arch === "x64") {
|
|
185
|
+
if (process.env.OPENTUI_LIBC === "musl") {
|
|
186
|
+
- return await import("@opentui/core-linux-x64-musl");
|
|
187
|
+
+ return await loadNativePackage("@opentui/core-linux-x64-musl");
|
|
188
|
+
} else {
|
|
189
|
+
- return await import("@opentui/core-linux-x64");
|
|
190
|
+
+ return await loadNativePackage("@opentui/core-linux-x64");
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
if (process.arch === "arm64") {
|
|
194
|
+
if (process.env.OPENTUI_LIBC === "musl") {
|
|
195
|
+
- return await import("@opentui/core-linux-arm64-musl");
|
|
196
|
+
+ return await loadNativePackage("@opentui/core-linux-arm64-musl");
|
|
197
|
+
} else {
|
|
198
|
+
- return await import("@opentui/core-linux-arm64");
|
|
199
|
+
+ return await loadNativePackage("@opentui/core-linux-arm64");
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
if (process.platform === "win32") {
|
|
204
|
+
if (process.arch === "x64")
|
|
205
|
+
- return await import("@opentui/core-win32-x64");
|
|
206
|
+
+ return await loadNativePackage("@opentui/core-win32-x64");
|
|
207
|
+
if (process.arch === "arm64")
|
|
208
|
+
- return await import("@opentui/core-win32-arm64");
|
|
209
|
+
+ return await loadNativePackage("@opentui/core-win32-arm64");
|
|
210
|
+
}
|
|
211
|
+
throw new Error(`opentui is not supported on the current platform: ${process.platform}-${process.arch}`);
|
|
212
|
+
}
|
|
213
|
+
@@ -22288,6 +22323,8 @@ class MouseEvent {
|
|
178
214
|
button;
|
|
179
215
|
x;
|
|
180
216
|
y;
|
|
@@ -183,7 +219,7 @@ index e3b6cf9f90b13698966eec991fa7a1b2e1e22d96..709940f3998e5cb1caa88642fa68fa9a
|
|
|
183
219
|
source;
|
|
184
220
|
modifiers;
|
|
185
221
|
scroll;
|
|
186
|
-
@@ -
|
|
222
|
+
@@ -22307,6 +22344,8 @@ class MouseEvent {
|
|
187
223
|
this.button = attributes.button;
|
|
188
224
|
this.x = attributes.x;
|
|
189
225
|
this.y = attributes.y;
|
|
@@ -192,30 +228,30 @@ index e3b6cf9f90b13698966eec991fa7a1b2e1e22d96..709940f3998e5cb1caa88642fa68fa9a
|
|
|
192
228
|
this.modifiers = attributes.modifiers;
|
|
193
229
|
this.scroll = attributes.scroll;
|
|
194
230
|
this.source = attributes.source;
|
|
195
|
-
@@ -
|
|
231
|
+
@@ -22457,6 +22496,8 @@ class CliRenderer extends EventEmitter9 {
|
|
196
232
|
resizeDebounceDelay = 100;
|
|
197
233
|
enableMouseMovement = false;
|
|
198
234
|
_useMouse = true;
|
|
199
235
|
+ _mouseProtocolSignature = "disabled";
|
|
200
236
|
+ _pixelMouseEnabled = false;
|
|
201
237
|
autoFocus = true;
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
@@ -
|
|
238
|
+
_screenMode = "alternate-screen";
|
|
239
|
+
_footerHeight = DEFAULT_FOOTER_HEIGHT;
|
|
240
|
+
@@ -22491,7 +22532,7 @@ class CliRenderer extends EventEmitter9 {
|
|
205
241
|
this.handleResize(width, height);
|
|
206
242
|
}).bind(this);
|
|
207
243
|
_capabilities = null;
|
|
208
244
|
- _latestPointer = { x: 0, y: 0 };
|
|
209
|
-
+ _latestPointer = { x: 0, y: 0, pixelX:
|
|
245
|
+
+ _latestPointer = { x: 0, y: 0, pixelX: undefined, pixelY: undefined };
|
|
210
246
|
_hasPointer = false;
|
|
211
|
-
_lastPointerModifiers = {
|
|
212
|
-
|
|
213
|
-
@@ -
|
|
214
|
-
kittyKeyboardEnabled: useKittyForParsing,
|
|
247
|
+
_lastPointerModifiers = {
|
|
248
|
+
shift: false,
|
|
249
|
+
@@ -22738,7 +22779,13 @@ Captured external output:
|
|
215
250
|
privateCapabilityRepliesActive: false,
|
|
216
251
|
pixelResolutionQueryActive: false,
|
|
217
|
-
|
|
218
|
-
|
|
252
|
+
explicitWidthCprActive: false,
|
|
253
|
+
- startupCursorCprActive: false
|
|
254
|
+
+ startupCursorCprActive: false,
|
|
219
255
|
+ mouseUsesPixels: false,
|
|
220
256
|
+ mousePixelsConfirmed: false,
|
|
221
257
|
+ terminalWidth: this._terminalWidth,
|
|
@@ -225,7 +261,7 @@ index e3b6cf9f90b13698966eec991fa7a1b2e1e22d96..709940f3998e5cb1caa88642fa68fa9a
|
|
|
225
261
|
},
|
|
226
262
|
clock: this.clock
|
|
227
263
|
});
|
|
228
|
-
@@ -
|
|
264
|
+
@@ -24021,12 +24068,14 @@ Captured external output:
|
|
229
265
|
enableMouse() {
|
|
230
266
|
this._useMouse = true;
|
|
231
267
|
this.lib.enableMouse(this.rendererPtr, this.enableMouseMovement);
|
|
@@ -240,7 +276,7 @@ index e3b6cf9f90b13698966eec991fa7a1b2e1e22d96..709940f3998e5cb1caa88642fa68fa9a
|
|
|
240
276
|
}
|
|
241
277
|
enableKittyKeyboard(flags = 3) {
|
|
242
278
|
this.lib.enableKittyKeyboard(this.rendererPtr, flags);
|
|
243
|
-
@@ -
|
|
279
|
+
@@ -24036,6 +24085,52 @@ Captured external output:
|
|
244
280
|
this.lib.disableKittyKeyboard(this.rendererPtr);
|
|
245
281
|
this.updateStdinParserProtocolContext({ kittyKeyboardEnabled: false }, true);
|
|
246
282
|
}
|
|
@@ -248,27 +284,15 @@ index e3b6cf9f90b13698966eec991fa7a1b2e1e22d96..709940f3998e5cb1caa88642fa68fa9a
|
|
|
248
284
|
+ return this.enableMouseMovement ? "any" : "press";
|
|
249
285
|
+ }
|
|
250
286
|
+ buildMouseProtocolSequence(pixelEnabled) {
|
|
251
|
-
+ const trackingSequence = this.enableMouseMovement
|
|
252
|
-
+ ? "\x1B[?1000l\x1B[?1002l\x1B[?1003h"
|
|
253
|
-
+ : "\x1B[?1003l\x1B[?1002l\x1B[?1000h";
|
|
287
|
+
+ const trackingSequence = this.enableMouseMovement ? "\x1B[?1000l\x1B[?1002l\x1B[?1003h" : "\x1B[?1003l\x1B[?1002l\x1B[?1000h";
|
|
254
288
|
+ return "\x1B[?1005l\x1B[?1015l\x1B[?1006h" + trackingSequence + (pixelEnabled ? "\x1B[?1016h" : "\x1B[?1016l");
|
|
255
289
|
+ }
|
|
256
290
|
+ syncPixelMouseMode(force = false) {
|
|
257
291
|
+ const nextEnabled = Boolean(this._useMouse);
|
|
258
|
-
+ const pixelMouseDisabled = typeof process !== "undefined" && process?.env?.GLOOMBERB_DISABLE_PIXEL_MOUSE === "1";
|
|
259
292
|
+ const hasPixelCapability = this._capabilities?.sgr_pixels === true;
|
|
260
293
|
+ const hasPixelResolution = (this._resolution?.width ?? 0) > 0 && (this._resolution?.height ?? 0) > 0;
|
|
261
|
-
+ const nextPixelEnabled = Boolean(
|
|
262
|
-
+
|
|
263
|
-
+ !pixelMouseDisabled &&
|
|
264
|
-
+ hasPixelCapability &&
|
|
265
|
-
+ hasPixelResolution &&
|
|
266
|
-
+ this._terminalWidth > 0 &&
|
|
267
|
-
+ this._terminalHeight > 0
|
|
268
|
-
+ );
|
|
269
|
-
+ const nextSignature = nextEnabled
|
|
270
|
-
+ ? `${this.getMouseProtocolTrackingMode()}:${nextPixelEnabled ? "pixel" : "cell"}`
|
|
271
|
-
+ : "disabled";
|
|
294
|
+
+ const nextPixelEnabled = Boolean(nextEnabled && hasPixelCapability && hasPixelResolution && this._terminalWidth > 0 && this._terminalHeight > 0);
|
|
295
|
+
+ const nextSignature = nextEnabled ? `${this.getMouseProtocolTrackingMode()}:${nextPixelEnabled ? "pixel" : "cell"}` : "disabled";
|
|
272
296
|
+ if (nextEnabled) {
|
|
273
297
|
+ if (force || this._mouseProtocolSignature !== nextSignature) {
|
|
274
298
|
+ this.writeOut(this.buildMouseProtocolSequence(nextPixelEnabled));
|
|
@@ -305,23 +329,15 @@ index e3b6cf9f90b13698966eec991fa7a1b2e1e22d96..709940f3998e5cb1caa88642fa68fa9a
|
|
|
305
329
|
set useThread(useThread) {
|
|
306
330
|
this._useThread = useThread;
|
|
307
331
|
this.lib.setUseThread(this.rendererPtr, useThread);
|
|
308
|
-
@@ -
|
|
309
|
-
if (this._useMouse) {
|
|
310
|
-
this.enableMouse();
|
|
332
|
+
@@ -24141,6 +24236,7 @@ Captured external output:
|
|
311
333
|
}
|
|
334
|
+
this.lib.processCapabilityResponse(this.rendererPtr, sequence);
|
|
335
|
+
this._capabilities = this.lib.getTerminalCapabilities(this.rendererPtr);
|
|
312
336
|
+ this.syncPixelMouseMode();
|
|
313
|
-
this.
|
|
314
|
-
|
|
315
|
-
stdinListener = ((chunk) => {
|
|
316
|
-
@@ -18070,6 +18185,7 @@ Captured output:
|
|
317
|
-
if (isCapabilityResponse(sequence)) {
|
|
318
|
-
this.lib.processCapabilityResponse(this.rendererPtr, sequence);
|
|
319
|
-
this._capabilities = this.lib.getTerminalCapabilities(this.rendererPtr);
|
|
320
|
-
+ this.syncPixelMouseMode();
|
|
321
|
-
this.emit("capabilities" /* CAPABILITIES */, this._capabilities);
|
|
322
|
-
return true;
|
|
337
|
+
if (this._capabilities?.terminal?.from_xtversion) {
|
|
338
|
+
this.resolveXtVersionWaiters();
|
|
323
339
|
}
|
|
324
|
-
@@ -
|
|
340
|
+
@@ -24170,6 +24266,7 @@ Captured external output:
|
|
325
341
|
if (sequence === "\x1B[I") {
|
|
326
342
|
if (this.shouldRestoreModesOnNextFocus) {
|
|
327
343
|
this.lib.restoreTerminalModes(this.rendererPtr);
|
|
@@ -329,7 +345,7 @@ index e3b6cf9f90b13698966eec991fa7a1b2e1e22d96..709940f3998e5cb1caa88642fa68fa9a
|
|
|
329
345
|
this.shouldRestoreModesOnNextFocus = false;
|
|
330
346
|
}
|
|
331
347
|
if (this._terminalFocusState !== true) {
|
|
332
|
-
@@ -
|
|
348
|
+
@@ -24264,6 +24361,7 @@ Captured external output:
|
|
333
349
|
}
|
|
334
350
|
this.waitingForPixelResolution = false;
|
|
335
351
|
this.updateStdinParserProtocolContext({ pixelResolutionQueryActive: false }, true);
|
|
@@ -337,11 +353,11 @@ index e3b6cf9f90b13698966eec991fa7a1b2e1e22d96..709940f3998e5cb1caa88642fa68fa9a
|
|
|
337
353
|
return true;
|
|
338
354
|
}
|
|
339
355
|
return false;
|
|
340
|
-
@@ -
|
|
356
|
+
@@ -24298,9 +24396,15 @@ Captured external output:
|
|
341
357
|
return false;
|
|
342
358
|
}
|
|
343
359
|
mouseEvent.y -= this.renderOffset;
|
|
344
|
-
+ if (mouseEvent.pixelY !==
|
|
360
|
+
+ if (mouseEvent.pixelY !== undefined && this._resolution) {
|
|
345
361
|
+ const cellHeight = this._resolution.height / Math.max(this._terminalHeight, 1);
|
|
346
362
|
+ mouseEvent.pixelY = Math.max(mouseEvent.pixelY - this.renderOffset * cellHeight, 0);
|
|
347
363
|
+ }
|
|
@@ -353,7 +369,7 @@ index e3b6cf9f90b13698966eec991fa7a1b2e1e22d96..709940f3998e5cb1caa88642fa68fa9a
|
|
|
353
369
|
this._hasPointer = true;
|
|
354
370
|
this._lastPointerModifiers = mouseEvent.modifiers;
|
|
355
371
|
if (this._console.visible) {
|
|
356
|
-
@@ -
|
|
372
|
+
@@ -24441,6 +24545,8 @@ Captured external output:
|
|
357
373
|
button: 0,
|
|
358
374
|
x: this._latestPointer.x,
|
|
359
375
|
y: this._latestPointer.y,
|
|
@@ -362,19 +378,88 @@ index e3b6cf9f90b13698966eec991fa7a1b2e1e22d96..709940f3998e5cb1caa88642fa68fa9a
|
|
|
362
378
|
modifiers: this._lastPointerModifiers
|
|
363
379
|
};
|
|
364
380
|
if (lastOver && !lastOver.isDestroyed) {
|
|
365
|
-
@@ -
|
|
366
|
-
const
|
|
381
|
+
@@ -24531,6 +24637,7 @@ Captured external output:
|
|
382
|
+
const visiblePreviousSplitHeight = pendingSplitFooterTransition?.sourceHeight ?? previousGeometry.effectiveFooterHeight;
|
|
367
383
|
this._terminalWidth = width;
|
|
368
384
|
this._terminalHeight = height;
|
|
369
385
|
+ this.syncPixelMouseMode();
|
|
370
386
|
this.queryPixelResolution();
|
|
371
387
|
this.setCapturedRenderable(undefined);
|
|
372
388
|
this.stdinParser?.resetMouseState();
|
|
373
|
-
@@ -
|
|
374
|
-
|
|
389
|
+
@@ -24848,6 +24955,7 @@ Captured external output:
|
|
390
|
+
this.themeModeState.cancelRefresh();
|
|
375
391
|
this._isRunning = false;
|
|
376
392
|
this.waitingForPixelResolution = false;
|
|
377
393
|
+ this.disablePixelMouseMode();
|
|
378
394
|
this.updateStdinParserProtocolContext({
|
|
379
395
|
privateCapabilityRepliesActive: false,
|
|
380
396
|
pixelResolutionQueryActive: false,
|
|
397
|
+
diff --git a/lib/parse.mouse.d.ts b/lib/parse.mouse.d.ts
|
|
398
|
+
index c29f953fde0b78f09d2ec7a830e5a72452c1fe7e..04613b921bd9b4a9a7a1a4fbd0234d4012df67a1 100644
|
|
399
|
+
--- a/lib/parse.mouse.d.ts
|
|
400
|
+
+++ b/lib/parse.mouse.d.ts
|
|
401
|
+
@@ -8,6 +8,8 @@ export type RawMouseEvent = {
|
|
402
|
+
button: number;
|
|
403
|
+
x: number;
|
|
404
|
+
y: number;
|
|
405
|
+
+ pixelX?: number;
|
|
406
|
+
+ pixelY?: number;
|
|
407
|
+
modifiers: {
|
|
408
|
+
shift: boolean;
|
|
409
|
+
alt: boolean;
|
|
410
|
+
@@ -20,8 +22,23 @@ export declare class MouseParser {
|
|
411
|
+
private static readonly SCROLL_DIRECTIONS;
|
|
412
|
+
reset(): void;
|
|
413
|
+
private decodeInput;
|
|
414
|
+
- parseMouseEvent(data: Buffer | Uint8Array): RawMouseEvent | null;
|
|
415
|
+
- parseAllMouseEvents(data: Buffer | Uint8Array): RawMouseEvent[];
|
|
416
|
+
+ private projectPixelToCell;
|
|
417
|
+
+ parseMouseEvent(data: Buffer | Uint8Array, context?: {
|
|
418
|
+
+ mouseUsesPixels?: boolean;
|
|
419
|
+
+ mousePixelsConfirmed?: boolean;
|
|
420
|
+
+ terminalWidth?: number;
|
|
421
|
+
+ terminalHeight?: number;
|
|
422
|
+
+ pixelWidth?: number;
|
|
423
|
+
+ pixelHeight?: number;
|
|
424
|
+
+ }): RawMouseEvent | null;
|
|
425
|
+
+ parseAllMouseEvents(data: Buffer | Uint8Array, context?: {
|
|
426
|
+
+ mouseUsesPixels?: boolean;
|
|
427
|
+
+ mousePixelsConfirmed?: boolean;
|
|
428
|
+
+ terminalWidth?: number;
|
|
429
|
+
+ terminalHeight?: number;
|
|
430
|
+
+ pixelWidth?: number;
|
|
431
|
+
+ pixelHeight?: number;
|
|
432
|
+
+ }): RawMouseEvent[];
|
|
433
|
+
private parseMouseSequenceAt;
|
|
434
|
+
private parseSgrSequence;
|
|
435
|
+
private parseBasicSequence;
|
|
436
|
+
diff --git a/lib/stdin-parser.d.ts b/lib/stdin-parser.d.ts
|
|
437
|
+
index 6b733d534d8e9b77c5c2773f93c7a22063c18d84..a5c318d591e9f3775e276e555c15052c8dbd20cb 100644
|
|
438
|
+
--- a/lib/stdin-parser.d.ts
|
|
439
|
+
+++ b/lib/stdin-parser.d.ts
|
|
440
|
+
@@ -28,6 +28,12 @@ export interface StdinParserProtocolContext {
|
|
441
|
+
pixelResolutionQueryActive: boolean;
|
|
442
|
+
explicitWidthCprActive: boolean;
|
|
443
|
+
startupCursorCprActive: boolean;
|
|
444
|
+
+ mouseUsesPixels: boolean;
|
|
445
|
+
+ mousePixelsConfirmed: boolean;
|
|
446
|
+
+ terminalWidth: number;
|
|
447
|
+
+ terminalHeight: number;
|
|
448
|
+
+ pixelWidth: number;
|
|
449
|
+
+ pixelHeight: number;
|
|
450
|
+
}
|
|
451
|
+
export interface StdinParserOptions {
|
|
452
|
+
timeoutMs?: number;
|
|
453
|
+
diff --git a/renderer.d.ts b/renderer.d.ts
|
|
454
|
+
index 96189246f423809fc52d2ad182d57ed2e80ac098..7dd0baf1697041cf8ad556b115cd13ad2e18bc65 100644
|
|
455
|
+
--- a/renderer.d.ts
|
|
456
|
+
+++ b/renderer.d.ts
|
|
457
|
+
@@ -143,6 +143,8 @@ export declare class MouseEvent {
|
|
458
|
+
readonly button: number;
|
|
459
|
+
readonly x: number;
|
|
460
|
+
readonly y: number;
|
|
461
|
+
+ readonly pixelX?: number;
|
|
462
|
+
+ readonly pixelY?: number;
|
|
463
|
+
readonly source?: Renderable;
|
|
464
|
+
readonly modifiers: {
|
|
465
|
+
shift: boolean;
|