termcast 1.3.54 → 1.4.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/dist/action-utils.d.ts.map +1 -1
- package/dist/action-utils.js +17 -132
- package/dist/action-utils.js.map +1 -1
- package/dist/apis/cache.d.ts +8 -30
- package/dist/apis/cache.d.ts.map +1 -1
- package/dist/apis/cache.js +9 -271
- package/dist/apis/cache.js.map +1 -1
- package/dist/apis/clipboard.d.ts +4 -2
- package/dist/apis/clipboard.d.ts.map +1 -1
- package/dist/apis/clipboard.js +18 -31
- package/dist/apis/clipboard.js.map +1 -1
- package/dist/apis/environment.d.ts.map +1 -1
- package/dist/apis/environment.js +14 -49
- package/dist/apis/environment.js.map +1 -1
- package/dist/apis/localstorage.d.ts +7 -12
- package/dist/apis/localstorage.d.ts.map +1 -1
- package/dist/apis/localstorage.js +7 -184
- package/dist/apis/localstorage.js.map +1 -1
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +16 -15
- package/dist/app.js.map +1 -1
- package/dist/cli.js +7 -6
- package/dist/cli.js.map +1 -1
- package/dist/components/actions.d.ts.map +1 -1
- package/dist/components/actions.js +13 -2
- package/dist/components/actions.js.map +1 -1
- package/dist/components/extension-preferences.d.ts.map +1 -1
- package/dist/components/extension-preferences.js +7 -8
- package/dist/components/extension-preferences.js.map +1 -1
- package/dist/components/form/file-autocomplete.js +2 -2
- package/dist/components/form/file-autocomplete.js.map +1 -1
- package/dist/components/list.d.ts.map +1 -1
- package/dist/components/list.js +242 -14
- package/dist/components/list.js.map +1 -1
- package/dist/e2e-node.d.ts.map +1 -1
- package/dist/e2e-node.js +5 -4
- package/dist/e2e-node.js.map +1 -1
- package/dist/extensions/dev.d.ts.map +1 -1
- package/dist/extensions/dev.js +5 -2
- package/dist/extensions/dev.js.map +1 -1
- package/dist/globals.d.ts.map +1 -1
- package/dist/globals.js +2 -1
- package/dist/globals.js.map +1 -1
- package/dist/internal/error-handler.d.ts.map +1 -1
- package/dist/internal/error-handler.js +21 -19
- package/dist/internal/error-handler.js.map +1 -1
- package/dist/internal/providers.d.ts.map +1 -1
- package/dist/internal/providers.js +41 -1
- package/dist/internal/providers.js.map +1 -1
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +31 -29
- package/dist/logger.js.map +1 -1
- package/dist/platform/browser/cache.d.ts +41 -0
- package/dist/platform/browser/cache.d.ts.map +1 -0
- package/dist/platform/browser/cache.js +262 -0
- package/dist/platform/browser/cache.js.map +1 -0
- package/dist/platform/browser/localstorage.d.ts +20 -0
- package/dist/platform/browser/localstorage.d.ts.map +1 -0
- package/dist/platform/browser/localstorage.js +102 -0
- package/dist/platform/browser/localstorage.js.map +1 -0
- package/dist/platform/browser/runtime.d.ts +51 -0
- package/dist/platform/browser/runtime.d.ts.map +1 -0
- package/dist/platform/browser/runtime.js +164 -0
- package/dist/platform/browser/runtime.js.map +1 -0
- package/dist/platform/bun/sqlite.d.ts +17 -0
- package/dist/platform/bun/sqlite.d.ts.map +1 -0
- package/dist/platform/bun/sqlite.js +6 -0
- package/dist/platform/bun/sqlite.js.map +1 -0
- package/dist/platform/node/cache.d.ts +35 -0
- package/dist/platform/node/cache.d.ts.map +1 -0
- package/dist/platform/node/cache.js +269 -0
- package/dist/platform/node/cache.js.map +1 -0
- package/dist/platform/node/localstorage.d.ts +17 -0
- package/dist/platform/node/localstorage.d.ts.map +1 -0
- package/dist/platform/node/localstorage.js +186 -0
- package/dist/platform/node/localstorage.js.map +1 -0
- package/dist/platform/node/runtime.d.ts +52 -0
- package/dist/platform/node/runtime.d.ts.map +1 -0
- package/dist/platform/node/runtime.js +230 -0
- package/dist/platform/node/runtime.js.map +1 -0
- package/dist/platform/node/sqlite.d.ts +27 -0
- package/dist/platform/node/sqlite.d.ts.map +1 -0
- package/dist/platform/node/sqlite.js +21 -0
- package/dist/platform/node/sqlite.js.map +1 -0
- package/dist/state.d.ts +5 -0
- package/dist/state.d.ts.map +1 -1
- package/dist/state.js +6 -28
- package/dist/state.js.map +1 -1
- package/dist/utils/file-system.d.ts.map +1 -1
- package/dist/utils/file-system.js +17 -22
- package/dist/utils/file-system.js.map +1 -1
- package/dist/utils.d.ts +1 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +42 -47
- package/dist/utils.js.map +1 -1
- package/dist/vim-mode.d.ts +40 -0
- package/dist/vim-mode.d.ts.map +1 -0
- package/dist/vim-mode.js +135 -0
- package/dist/vim-mode.js.map +1 -0
- package/fonts/Inconsolata.otf +0 -0
- package/fonts/SIL Open Font License.txt +41 -0
- package/package.json +60 -8
- package/src/action-utils.tsx +27 -124
- package/src/apis/cache.test.ts +1 -1
- package/src/apis/cache.tsx +9 -373
- package/src/apis/clipboard.tsx +29 -38
- package/src/apis/environment.tsx +25 -52
- package/src/apis/localstorage.tsx +8 -214
- package/src/app.tsx +16 -15
- package/src/cli.tsx +14 -15
- package/src/compile.vitest.tsx +2 -2
- package/src/components/actions.tsx +19 -1
- package/src/components/extension-preferences.tsx +7 -8
- package/src/components/form/file-autocomplete.tsx +2 -2
- package/src/components/list.tsx +279 -14
- package/src/e2e-node.tsx +7 -7
- package/src/examples/action-shortcut.vitest.tsx +2 -2
- package/src/examples/actions-context.vitest.tsx +1 -1
- package/src/examples/bar-graph-weekly.vitest.tsx +10 -36
- package/src/examples/detail-metadata-showcase.vitest.tsx +36 -36
- package/src/examples/form-basic.vitest.tsx +21 -17
- package/src/examples/github.vitest.tsx +4 -4
- package/src/examples/graph-bar-chart.vitest.tsx +13 -11
- package/src/examples/graph-polymarket.vitest.tsx +2 -2
- package/src/examples/graph-row.vitest.tsx +66 -66
- package/src/examples/graph-styles.vitest.tsx +12 -12
- package/src/examples/internal/simple-scrollbox.vitest.tsx +14 -48
- package/src/examples/list-detail-metadata.vitest.tsx +5 -5
- package/src/examples/list-fetch-data.vitest.tsx +3 -3
- package/src/examples/list-item-accessories.vitest.tsx +2 -2
- package/src/examples/list-loading-empty-view.vitest.tsx +1 -1
- package/src/examples/list-no-actions.vitest.tsx +2 -2
- package/src/examples/list-scrollbox.vitest.tsx +5 -5
- package/src/examples/list-spacing-mode.vitest.tsx +3 -3
- package/src/examples/list-with-detail.vitest.tsx +68 -68
- package/src/examples/list-with-dropdown.vitest.tsx +5 -5
- package/src/examples/list-with-sections.vitest.tsx +27 -27
- package/src/examples/simple-candle-chart.vitest.tsx +7 -7
- package/src/examples/simple-detail-markdown.vitest.tsx +8 -8
- package/src/examples/simple-detail-table.vitest.tsx +8 -8
- package/src/examples/simple-graph.vitest.tsx +3 -3
- package/src/examples/simple-grid.vitest.tsx +14 -14
- package/src/examples/simple-heatmap.vitest.tsx +1 -1
- package/src/examples/simple-navigation.vitest.tsx +17 -17
- package/src/examples/simple-progress-bar.vitest.tsx +1 -1
- package/src/examples/store.vitest.tsx +1 -1
- package/src/examples/swift-extension.vitest.tsx +2 -2
- package/src/examples/table-edge-cases.vitest.tsx +18 -18
- package/src/examples/toast-action.vitest.tsx +2 -2
- package/src/extensions/dev.tsx +5 -2
- package/src/extensions/dev.vitest.tsx +3 -3
- package/src/globals.ts +2 -1
- package/src/internal/error-handler.tsx +19 -21
- package/src/internal/providers.tsx +39 -0
- package/src/logger.tsx +38 -41
- package/src/platform/browser/cache.ts +327 -0
- package/src/platform/browser/localstorage.ts +119 -0
- package/src/platform/browser/runtime.ts +209 -0
- package/src/platform/bun/sqlite.ts +19 -0
- package/src/platform/node/cache.ts +372 -0
- package/src/platform/node/localstorage.ts +214 -0
- package/src/platform/node/runtime.ts +264 -0
- package/src/platform/node/sqlite.ts +43 -0
- package/src/state.tsx +17 -28
- package/src/utils/file-system.ts +17 -22
- package/src/utils.test.tsx +1 -1
- package/src/utils.tsx +56 -47
- package/src/vim-mode.tsx +153 -0
- package/src/apis/sqlite.ts +0 -14
|
@@ -46,7 +46,7 @@ test('navigation between main and detail views', async () => {
|
|
|
46
46
|
|
|
47
47
|
|
|
48
48
|
|
|
49
|
-
↵ open details ↑↓ navigate ^k actions
|
|
49
|
+
↵ open details ↑↓ navigate ^k actions :vim
|
|
50
50
|
|
|
51
51
|
|
|
52
52
|
|
|
@@ -80,7 +80,7 @@ test('navigation between main and detail views', async () => {
|
|
|
80
80
|
|
|
81
81
|
|
|
82
82
|
|
|
83
|
-
↵ open details ↑↓ navigate ^k actions
|
|
83
|
+
↵ open details ↑↓ navigate ^k actions :vim
|
|
84
84
|
|
|
85
85
|
|
|
86
86
|
|
|
@@ -118,7 +118,7 @@ test('navigation between main and detail views', async () => {
|
|
|
118
118
|
|
|
119
119
|
|
|
120
120
|
|
|
121
|
-
↵ go back ↑↓ navigate ^k actions
|
|
121
|
+
↵ go back ↑↓ navigate ^k actions :vim
|
|
122
122
|
|
|
123
123
|
|
|
124
124
|
|
|
@@ -160,7 +160,7 @@ test('navigation between main and detail views', async () => {
|
|
|
160
160
|
|
|
161
161
|
|
|
162
162
|
|
|
163
|
-
↵ open details ↑↓ navigate ^k actions
|
|
163
|
+
↵ open details ↑↓ navigate ^k actions :vim
|
|
164
164
|
|
|
165
165
|
|
|
166
166
|
|
|
@@ -194,7 +194,7 @@ test('navigation between main and detail views', async () => {
|
|
|
194
194
|
|
|
195
195
|
|
|
196
196
|
|
|
197
|
-
↵ open details ↑↓ navigate ^k actions
|
|
197
|
+
↵ open details ↑↓ navigate ^k actions :vim
|
|
198
198
|
|
|
199
199
|
|
|
200
200
|
|
|
@@ -227,7 +227,7 @@ test('navigation between main and detail views', async () => {
|
|
|
227
227
|
|
|
228
228
|
|
|
229
229
|
|
|
230
|
-
↵ go back ↑↓ navigate ^k actions
|
|
230
|
+
↵ go back ↑↓ navigate ^k actions :vim
|
|
231
231
|
|
|
232
232
|
|
|
233
233
|
|
|
@@ -266,7 +266,7 @@ test('navigation between main and detail views', async () => {
|
|
|
266
266
|
|
|
267
267
|
|
|
268
268
|
|
|
269
|
-
↵ open details ↑↓ navigate ^k actions
|
|
269
|
+
↵ open details ↑↓ navigate ^k actions :vim
|
|
270
270
|
|
|
271
271
|
|
|
272
272
|
|
|
@@ -306,12 +306,12 @@ test('navigation with actions panel', async () => {
|
|
|
306
306
|
│ │
|
|
307
307
|
│ Settings │
|
|
308
308
|
│ Change Theme... │
|
|
309
|
+
│ Enable Vim Mode │
|
|
309
310
|
│ Toggle Console Logs │
|
|
310
311
|
│ │
|
|
311
312
|
│ │
|
|
312
313
|
│ │
|
|
313
314
|
│ │
|
|
314
|
-
│ │
|
|
315
315
|
│ ↵ select ↑↓ navigate │
|
|
316
316
|
│ │
|
|
317
317
|
╰────────────────────────────────────────────────────────────────╯
|
|
@@ -339,12 +339,12 @@ test('navigation with actions panel', async () => {
|
|
|
339
339
|
│ │
|
|
340
340
|
│ Settings │
|
|
341
341
|
│ Change Theme... │
|
|
342
|
+
│ Enable Vim Mode │
|
|
342
343
|
│ Toggle Console Logs │
|
|
343
344
|
│ │
|
|
344
345
|
│ │
|
|
345
346
|
│ │
|
|
346
347
|
│ │
|
|
347
|
-
│ │
|
|
348
348
|
│ ↵ select ↑↓ navigate │
|
|
349
349
|
│ │
|
|
350
350
|
╰────────────────────────────────────────────────────────────────╯
|
|
@@ -419,7 +419,7 @@ test('navigation with actions panel', async () => {
|
|
|
419
419
|
|
|
420
420
|
|
|
421
421
|
|
|
422
|
-
↵ go back ↑↓ navigate ^k actions
|
|
422
|
+
↵ go back ↑↓ navigate ^k actions :vim
|
|
423
423
|
|
|
424
424
|
|
|
425
425
|
|
|
@@ -450,12 +450,12 @@ test('navigation with actions panel', async () => {
|
|
|
450
450
|
│ │
|
|
451
451
|
│ Settings │
|
|
452
452
|
│ Change Theme... │
|
|
453
|
+
│ Enable Vim Mode │
|
|
453
454
|
│ Toggle Console Logs │
|
|
454
455
|
│ │
|
|
455
456
|
│ │
|
|
456
457
|
│ │
|
|
457
458
|
│ │
|
|
458
|
-
│ │
|
|
459
459
|
│ ↵ select ↑↓ navigate │
|
|
460
460
|
│ │
|
|
461
461
|
╰────────────────────────────────────────────────────────────────╯
|
|
@@ -489,7 +489,7 @@ test('navigation with actions panel', async () => {
|
|
|
489
489
|
|
|
490
490
|
|
|
491
491
|
|
|
492
|
-
↵ open details ↑↓ navigate ^k actions
|
|
492
|
+
↵ open details ↑↓ navigate ^k actions :vim
|
|
493
493
|
|
|
494
494
|
|
|
495
495
|
|
|
@@ -535,7 +535,7 @@ test('search functionality in main and detail views', async () => {
|
|
|
535
535
|
|
|
536
536
|
|
|
537
537
|
|
|
538
|
-
↵ open details ↑↓ navigate ^k actions
|
|
538
|
+
↵ open details ↑↓ navigate ^k actions :vim
|
|
539
539
|
|
|
540
540
|
|
|
541
541
|
|
|
@@ -573,7 +573,7 @@ test('search functionality in main and detail views', async () => {
|
|
|
573
573
|
|
|
574
574
|
|
|
575
575
|
|
|
576
|
-
↵ open details ↑↓ navigate ^k actions
|
|
576
|
+
↵ open details ↑↓ navigate ^k actions :vim
|
|
577
577
|
|
|
578
578
|
|
|
579
579
|
|
|
@@ -613,7 +613,7 @@ test('search functionality in main and detail views', async () => {
|
|
|
613
613
|
|
|
614
614
|
|
|
615
615
|
|
|
616
|
-
↵ go back ↑↓ navigate ^k actions
|
|
616
|
+
↵ go back ↑↓ navigate ^k actions :vim
|
|
617
617
|
|
|
618
618
|
|
|
619
619
|
|
|
@@ -650,7 +650,7 @@ test('search functionality in main and detail views', async () => {
|
|
|
650
650
|
|
|
651
651
|
|
|
652
652
|
|
|
653
|
-
↵ go back ↑↓ navigate ^k actions
|
|
653
|
+
↵ go back ↑↓ navigate ^k actions :vim
|
|
654
654
|
|
|
655
655
|
|
|
656
656
|
|
|
@@ -687,7 +687,7 @@ test('search functionality in main and detail views', async () => {
|
|
|
687
687
|
|
|
688
688
|
|
|
689
689
|
|
|
690
|
-
↵ open details ↑↓ navigate ^k actions
|
|
690
|
+
↵ open details ↑↓ navigate ^k actions :vim
|
|
691
691
|
|
|
692
692
|
|
|
693
693
|
|
|
@@ -102,7 +102,7 @@ test.skipIf(isLinux)('swift extension dev mode shows command list', async () =>
|
|
|
102
102
|
|
|
103
103
|
|
|
104
104
|
|
|
105
|
-
↵ run command ↑↓ navigate ^k actions
|
|
105
|
+
↵ run command ↑↓ navigate ^k actions :vim
|
|
106
106
|
|
|
107
107
|
|
|
108
108
|
|
|
@@ -153,7 +153,7 @@ test.skipIf(isLinux)('swift extension runs Swift List command and shows items',
|
|
|
153
153
|
|
|
154
154
|
|
|
155
155
|
|
|
156
|
-
↑↓ navigate ^k actions
|
|
156
|
+
↑↓ navigate ^k actions :vim
|
|
157
157
|
|
|
158
158
|
|
|
159
159
|
|
|
@@ -35,8 +35,10 @@ test('inline formatting table renders all rows', async () => {
|
|
|
35
35
|
|
|
36
36
|
Table Edge Cases
|
|
37
37
|
|
|
38
|
+
|
|
38
39
|
Inline Formatting
|
|
39
40
|
|
|
41
|
+
|
|
40
42
|
Feature Syntax Result
|
|
41
43
|
Bold text bold text
|
|
42
44
|
Italic text italic text
|
|
@@ -46,6 +48,7 @@ test('inline formatting table renders all rows', async () => {
|
|
|
46
48
|
|
|
47
49
|
Single Column
|
|
48
50
|
|
|
51
|
+
|
|
49
52
|
Name
|
|
50
53
|
Alice
|
|
51
54
|
Bob
|
|
@@ -53,11 +56,13 @@ test('inline formatting table renders all rows', async () => {
|
|
|
53
56
|
|
|
54
57
|
Single Row
|
|
55
58
|
|
|
59
|
+
|
|
56
60
|
A B C D E
|
|
57
61
|
1 2 3 4 5
|
|
58
62
|
|
|
59
63
|
Empty Cells
|
|
60
64
|
|
|
65
|
+
|
|
61
66
|
Key Value Notes
|
|
62
67
|
host localhost
|
|
63
68
|
8080 default port
|
|
@@ -65,12 +70,14 @@ test('inline formatting table renders all rows', async () => {
|
|
|
65
70
|
|
|
66
71
|
Wide Table
|
|
67
72
|
|
|
73
|
+
|
|
68
74
|
ID Name Email Role Department Location
|
|
69
75
|
1 Alice Johnson alice@example.com Engineer Engineering SF
|
|
70
76
|
2 Bob Smith bob@example.com Designer Design NYC
|
|
71
77
|
|
|
72
78
|
Two Columns
|
|
73
79
|
|
|
80
|
+
|
|
74
81
|
Key Value
|
|
75
82
|
version 2.1.0
|
|
76
83
|
license MIT
|
|
@@ -78,6 +85,7 @@ test('inline formatting table renders all rows', async () => {
|
|
|
78
85
|
|
|
79
86
|
Numeric Data
|
|
80
87
|
|
|
88
|
+
|
|
81
89
|
Metric Q1 Q2 Q3 Q4
|
|
82
90
|
Revenue 100 150 200 250
|
|
83
91
|
Users 1000 1500 2000 3000
|
|
@@ -86,16 +94,8 @@ test('inline formatting table renders all rows', async () => {
|
|
|
86
94
|
Done.
|
|
87
95
|
|
|
88
96
|
|
|
89
|
-
esc go back ^k actions powered by termcast.app
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
97
|
|
|
98
|
+
esc go back ^k actions powered by termcast.app
|
|
99
99
|
|
|
100
100
|
|
|
101
101
|
|
|
@@ -219,8 +219,10 @@ test('all tables render without crash - full page snapshot', async () => {
|
|
|
219
219
|
|
|
220
220
|
Table Edge Cases
|
|
221
221
|
|
|
222
|
+
|
|
222
223
|
Inline Formatting
|
|
223
224
|
|
|
225
|
+
|
|
224
226
|
Feature Syntax Result
|
|
225
227
|
Bold text bold text
|
|
226
228
|
Italic text italic text
|
|
@@ -230,6 +232,7 @@ test('all tables render without crash - full page snapshot', async () => {
|
|
|
230
232
|
|
|
231
233
|
Single Column
|
|
232
234
|
|
|
235
|
+
|
|
233
236
|
Name
|
|
234
237
|
Alice
|
|
235
238
|
Bob
|
|
@@ -237,11 +240,13 @@ test('all tables render without crash - full page snapshot', async () => {
|
|
|
237
240
|
|
|
238
241
|
Single Row
|
|
239
242
|
|
|
243
|
+
|
|
240
244
|
A B C D E
|
|
241
245
|
1 2 3 4 5
|
|
242
246
|
|
|
243
247
|
Empty Cells
|
|
244
248
|
|
|
249
|
+
|
|
245
250
|
Key Value Notes
|
|
246
251
|
host localhost
|
|
247
252
|
8080 default port
|
|
@@ -249,12 +254,14 @@ test('all tables render without crash - full page snapshot', async () => {
|
|
|
249
254
|
|
|
250
255
|
Wide Table
|
|
251
256
|
|
|
257
|
+
|
|
252
258
|
ID Name Email Role Department Location
|
|
253
259
|
1 Alice Johnson alice@example.com Engineer Engineering SF
|
|
254
260
|
2 Bob Smith bob@example.com Designer Design NYC
|
|
255
261
|
|
|
256
262
|
Two Columns
|
|
257
263
|
|
|
264
|
+
|
|
258
265
|
Key Value
|
|
259
266
|
version 2.1.0
|
|
260
267
|
license MIT
|
|
@@ -262,6 +269,7 @@ test('all tables render without crash - full page snapshot', async () => {
|
|
|
262
269
|
|
|
263
270
|
Numeric Data
|
|
264
271
|
|
|
272
|
+
|
|
265
273
|
Metric Q1 Q2 Q3 Q4
|
|
266
274
|
Revenue 100 150 200 250
|
|
267
275
|
Users 1000 1500 2000 3000
|
|
@@ -270,16 +278,8 @@ test('all tables render without crash - full page snapshot', async () => {
|
|
|
270
278
|
Done.
|
|
271
279
|
|
|
272
280
|
|
|
273
|
-
esc go back ^k actions powered by termcast.app
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
281
|
|
|
282
|
+
esc go back ^k actions powered by termcast.app
|
|
283
283
|
|
|
284
284
|
|
|
285
285
|
|
|
@@ -124,7 +124,7 @@ test('pressing escape hides the toast', async () => {
|
|
|
124
124
|
|
|
125
125
|
|
|
126
126
|
|
|
127
|
-
↵ show toast ↑↓ navigate ^k actions
|
|
127
|
+
↵ show toast ↑↓ navigate ^k actions :vim
|
|
128
128
|
|
|
129
129
|
|
|
130
130
|
|
|
@@ -238,7 +238,7 @@ test('form toast: pressing enter triggers primary action (navigation)', async ()
|
|
|
238
238
|
|
|
239
239
|
|
|
240
240
|
|
|
241
|
-
↑↓ navigate ^k actions
|
|
241
|
+
↑↓ navigate ^k actions :vim
|
|
242
242
|
|
|
243
243
|
|
|
244
244
|
|
package/src/extensions/dev.tsx
CHANGED
|
@@ -15,6 +15,7 @@ import { TermcastProvider } from 'termcast/src/internal/providers'
|
|
|
15
15
|
import { showToast, Toast } from 'termcast/src/apis/toast'
|
|
16
16
|
import { Icon } from 'termcast'
|
|
17
17
|
import { useTheme, initializeTheme } from 'termcast/src/theme'
|
|
18
|
+
import { initializeVimMode } from 'termcast/src/vim-mode'
|
|
18
19
|
import { logger } from '../logger'
|
|
19
20
|
import { getCommandsWithFiles, CommandWithFile, RaycastPackageJson } from '../package-json'
|
|
20
21
|
import { buildExtensionCommands } from '../build'
|
|
@@ -226,8 +227,9 @@ export async function startDevMode({
|
|
|
226
227
|
devRebuildCount: 1,
|
|
227
228
|
})
|
|
228
229
|
|
|
229
|
-
// Load theme after state reset — extensionPath is now set so it reads from the correct DB
|
|
230
|
+
// Load theme and vim mode after state reset — extensionPath is now set so it reads from the correct DB
|
|
230
231
|
initializeTheme()
|
|
232
|
+
initializeVimMode()
|
|
231
233
|
|
|
232
234
|
function App(): any {
|
|
233
235
|
const devElement = useStore((state) => state.devElement)
|
|
@@ -299,8 +301,9 @@ export async function startCompiledExtension({
|
|
|
299
301
|
devRebuildCount: 1,
|
|
300
302
|
})
|
|
301
303
|
|
|
302
|
-
// Load theme after state reset — extensionPath is now set so it reads from the correct DB
|
|
304
|
+
// Load theme and vim mode after state reset — extensionPath is now set so it reads from the correct DB
|
|
303
305
|
initializeTheme()
|
|
306
|
+
initializeVimMode()
|
|
304
307
|
|
|
305
308
|
function App(): any {
|
|
306
309
|
const devElement = useStore((state) => state.devElement)
|
|
@@ -65,7 +65,7 @@ test('dev command shows extension commands list', async () => {
|
|
|
65
65
|
Show State Shows the current application state in view
|
|
66
66
|
|
|
67
67
|
|
|
68
|
-
↵ run command ↑↓ navigate ^k actions
|
|
68
|
+
↵ run command ↑↓ navigate ^k actions :vim
|
|
69
69
|
"
|
|
70
70
|
`)
|
|
71
71
|
}, 30000)
|
|
@@ -101,7 +101,7 @@ test('selecting command with arguments shows arguments form', async () => {
|
|
|
101
101
|
|
|
102
102
|
|
|
103
103
|
|
|
104
|
-
↵ run command ↑↓ navigate ^k actions
|
|
104
|
+
↵ run command ↑↓ navigate ^k actions :vim
|
|
105
105
|
"
|
|
106
106
|
`)
|
|
107
107
|
|
|
@@ -217,7 +217,7 @@ test('can fill arguments and run command', async () => {
|
|
|
217
217
|
|
|
218
218
|
|
|
219
219
|
|
|
220
|
-
↵ copy value ↑↓ navigate ^k actions
|
|
220
|
+
↵ copy value ↑↓ navigate ^k actions :vim
|
|
221
221
|
"
|
|
222
222
|
`)
|
|
223
223
|
}, 30000)
|
package/src/globals.ts
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
// Set up global references for external packages
|
|
3
3
|
//
|
|
4
4
|
import { logger } from './logger'
|
|
5
|
+
import { setEnv } from '#platform/runtime'
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
setEnv('TERMCAST', 'true')
|
|
7
8
|
|
|
8
9
|
import * as opentuiCore from '@opentui/core'
|
|
9
10
|
import * as opentuiReact from '@opentui/react'
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { showFailureToast } from 'termcast/src/apis/toast'
|
|
2
2
|
import { logger } from 'termcast/src/logger'
|
|
3
|
+
import { setupErrorHandlers } from '#platform/runtime'
|
|
3
4
|
|
|
4
5
|
let initialized = false
|
|
5
6
|
|
|
@@ -7,26 +8,23 @@ export function initializeErrorHandlers(): void {
|
|
|
7
8
|
if (initialized) return
|
|
8
9
|
initialized = true
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
process.on('uncaughtExceptionMonitor', (err, origin) => {
|
|
30
|
-
logger.error(`Uncaught exception from ${origin}:`, err)
|
|
11
|
+
setupErrorHandlers((err, type) => {
|
|
12
|
+
if (type === 'unhandledRejection') {
|
|
13
|
+
logger.error('Unhandled rejection:', err)
|
|
14
|
+
showFailureToast(err, {
|
|
15
|
+
title: 'Unhandled Promise Rejection',
|
|
16
|
+
}).catch((toastErr) => {
|
|
17
|
+
logger.error('Failed to show toast for unhandled rejection:', toastErr)
|
|
18
|
+
})
|
|
19
|
+
} else if (type === 'uncaughtException') {
|
|
20
|
+
logger.error('Uncaught exception:', err)
|
|
21
|
+
showFailureToast(err, {
|
|
22
|
+
title: 'Uncaught Exception',
|
|
23
|
+
}).catch((toastErr) => {
|
|
24
|
+
logger.error('Failed to show toast for uncaught exception:', toastErr)
|
|
25
|
+
})
|
|
26
|
+
} else {
|
|
27
|
+
logger.error(`Uncaught exception from ${type}:`, err)
|
|
28
|
+
}
|
|
31
29
|
})
|
|
32
30
|
}
|
|
@@ -15,6 +15,7 @@ import { useTheme } from 'termcast/src/theme'
|
|
|
15
15
|
import { useStore } from 'termcast/src/state'
|
|
16
16
|
import { useKeyboard, useRenderer } from '@opentui/react'
|
|
17
17
|
import { initializeErrorHandlers } from 'termcast/src/internal/error-handler'
|
|
18
|
+
import { stdoutWrite } from '#platform/runtime'
|
|
18
19
|
|
|
19
20
|
import { InFocus } from './focus-context'
|
|
20
21
|
import { Clipboard } from '../apis/clipboard'
|
|
@@ -150,6 +151,44 @@ export function TermcastProvider(props: ProvidersProps): any {
|
|
|
150
151
|
const theme = useTheme()
|
|
151
152
|
const renderer = useRenderer()
|
|
152
153
|
|
|
154
|
+
// TODO: Remove this when opentui adds { name: "backspace", super: true, action: "delete-to-line-start" }
|
|
155
|
+
// to defaultTextareaKeybindings in packages/core/src/renderables/Textarea.ts
|
|
156
|
+
// Translate Cmd+Backspace (kitty CSI \x1b[127;9u) to Ctrl+U (\x15) so opentui's
|
|
157
|
+
// textarea keybinding for delete-to-line-start handles it. opentui doesn't have a
|
|
158
|
+
// super+backspace binding, so we remap at the input level before key dispatch.
|
|
159
|
+
React.useLayoutEffect(() => {
|
|
160
|
+
if (!renderer) return
|
|
161
|
+
const handler = (sequence: string) => {
|
|
162
|
+
if (sequence === '\x1b[127;9u') {
|
|
163
|
+
renderer.stdin.emit('data', '\x15')
|
|
164
|
+
return true
|
|
165
|
+
}
|
|
166
|
+
return false
|
|
167
|
+
}
|
|
168
|
+
renderer.prependInputHandler(handler)
|
|
169
|
+
return () => {
|
|
170
|
+
renderer.removeInputHandler(handler)
|
|
171
|
+
}
|
|
172
|
+
}, [renderer])
|
|
173
|
+
|
|
174
|
+
// Sync terminal background with the active termcast theme via OSC 11 (standard escape
|
|
175
|
+
// sequence to set terminal background color). This works on WezTerm, iTerm2, kitty, etc.
|
|
176
|
+
// WezTerm's set_config_overrides for colors has a bug (#5451) where it only hot-reloads
|
|
177
|
+
// non-focused windows, so we use OSC 11 instead which updates immediately.
|
|
178
|
+
// Uses renderer's realStdoutWrite to bypass opentui's stdout interception.
|
|
179
|
+
React.useLayoutEffect(() => {
|
|
180
|
+
if (!renderer) return
|
|
181
|
+
// OSC 11 ; color ST — sets terminal default background color
|
|
182
|
+
const sequence = `\x1b]11;${theme.background}\x07`
|
|
183
|
+
const realWrite = (renderer as any).realStdoutWrite as typeof process.stdout.write | undefined
|
|
184
|
+
if (realWrite) {
|
|
185
|
+
// realStdoutWrite needs process.stdout as `this` context
|
|
186
|
+
realWrite.call(process.stdout, sequence)
|
|
187
|
+
} else {
|
|
188
|
+
stdoutWrite(sequence)
|
|
189
|
+
}
|
|
190
|
+
}, [renderer, theme.background])
|
|
191
|
+
|
|
153
192
|
useKeyboard((key) => {
|
|
154
193
|
if (!renderer) return
|
|
155
194
|
if (key.ctrl && key.name === 'd') {
|
package/src/logger.tsx
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import {
|
|
2
|
+
joinPath,
|
|
3
|
+
cwd,
|
|
4
|
+
unlinkIfExists,
|
|
5
|
+
appendToFile,
|
|
6
|
+
inspectValue,
|
|
7
|
+
getEnv,
|
|
8
|
+
exit,
|
|
9
|
+
setupErrorHandlers,
|
|
10
|
+
} from '#platform/runtime'
|
|
4
11
|
import { useEffect } from 'react'
|
|
5
12
|
|
|
6
|
-
const LOG_FILE =
|
|
13
|
+
const LOG_FILE = joinPath(cwd(), 'app.log')
|
|
7
14
|
|
|
8
15
|
// Delete log file on process start
|
|
9
|
-
|
|
10
|
-
fs.unlinkSync(LOG_FILE)
|
|
11
|
-
}
|
|
16
|
+
unlinkIfExists(LOG_FILE)
|
|
12
17
|
|
|
13
18
|
function serialize(msg: any): string {
|
|
14
19
|
if (msg instanceof Error) {
|
|
@@ -17,7 +22,7 @@ function serialize(msg: any): string {
|
|
|
17
22
|
if (typeof msg === 'string') {
|
|
18
23
|
return msg
|
|
19
24
|
}
|
|
20
|
-
return
|
|
25
|
+
return inspectValue(msg, 3)
|
|
21
26
|
}
|
|
22
27
|
|
|
23
28
|
export const logger = {
|
|
@@ -25,21 +30,21 @@ export const logger = {
|
|
|
25
30
|
const timestamp = new Date().toISOString()
|
|
26
31
|
const formattedMessages = messages.map(serialize).join(' ')
|
|
27
32
|
const logEntry = `[${timestamp}] ${formattedMessages}\n`
|
|
28
|
-
|
|
33
|
+
appendToFile(LOG_FILE, logEntry)
|
|
29
34
|
console.log(...messages)
|
|
30
35
|
},
|
|
31
36
|
error: (...messages: any[]) => {
|
|
32
37
|
const timestamp = new Date().toISOString()
|
|
33
38
|
const formattedMessages = messages.map(serialize).join(' ')
|
|
34
39
|
const logEntry = `[${timestamp}] ERROR: ${formattedMessages}\n`
|
|
35
|
-
|
|
40
|
+
appendToFile(LOG_FILE, logEntry)
|
|
36
41
|
console.error(...messages)
|
|
37
42
|
},
|
|
38
43
|
warn: (...messages: any[]) => {
|
|
39
44
|
const timestamp = new Date().toISOString()
|
|
40
45
|
const formattedMessages = messages.map(serialize).join(' ')
|
|
41
46
|
const logEntry = `[${timestamp}] WARN: ${formattedMessages}\n`
|
|
42
|
-
|
|
47
|
+
appendToFile(LOG_FILE, logEntry)
|
|
43
48
|
console.warn(...messages)
|
|
44
49
|
},
|
|
45
50
|
trace: (...messages: any[]) => {
|
|
@@ -54,41 +59,33 @@ export const logger = {
|
|
|
54
59
|
}
|
|
55
60
|
const formattedMessages = messages.map(serialize).join(' ')
|
|
56
61
|
const logEntry = `[${timestamp}] TRACE: ${formattedMessages}\n${stack}\n`
|
|
57
|
-
|
|
62
|
+
appendToFile(LOG_FILE, logEntry)
|
|
58
63
|
console.trace(...messages)
|
|
59
64
|
},
|
|
60
65
|
}
|
|
61
66
|
|
|
62
67
|
// Catch unhandled errors and exceptions
|
|
63
|
-
|
|
64
|
-
if (
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
'Unhandled Rejection
|
|
81
|
-
|
|
82
|
-
'reason:',
|
|
83
|
-
reason.message,
|
|
84
|
-
reason.stack,
|
|
85
|
-
)
|
|
68
|
+
setupErrorHandlers((error, type) => {
|
|
69
|
+
if (type === 'uncaughtException') {
|
|
70
|
+
if (error instanceof Error) {
|
|
71
|
+
logger.error('Uncaught Exception:', error.message, error.stack)
|
|
72
|
+
} else {
|
|
73
|
+
logger.error('Uncaught Exception:', serialize(error))
|
|
74
|
+
}
|
|
75
|
+
// In app mode, don't exit on uncaught exceptions — the error boundary
|
|
76
|
+
// will catch React errors, and crashing the whole app is worse than
|
|
77
|
+
// a broken screen the user can recover from.
|
|
78
|
+
if (getEnv('TERMCAST_APP_MODE') !== '1') {
|
|
79
|
+
exit(1)
|
|
80
|
+
}
|
|
81
|
+
} else if (type === 'unhandledRejection') {
|
|
82
|
+
if (error instanceof Error) {
|
|
83
|
+
logger.error('Unhandled Rejection:', error.message, error.stack)
|
|
84
|
+
} else {
|
|
85
|
+
logger.error('Unhandled Rejection:', serialize(error))
|
|
86
|
+
}
|
|
86
87
|
} else {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
promise,
|
|
90
|
-
'reason:',
|
|
91
|
-
serialize(reason),
|
|
92
|
-
)
|
|
88
|
+
// uncaughtExceptionMonitor
|
|
89
|
+
logger.error(`Uncaught exception from ${type}:`, error)
|
|
93
90
|
}
|
|
94
91
|
})
|