@marckrenn/pi-sub-bar 1.0.6 → 1.1.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/CHANGELOG.md +12 -0
- package/README.md +6 -2
- package/index.ts +27 -19
- package/package.json +3 -3
- package/src/settings/menu.ts +8 -0
- package/src/settings/ui.ts +69 -0
- package/src/settings-types.ts +20 -0
- package/src/settings.ts +5 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @marckrenn/pi-sub-bar
|
|
2
2
|
|
|
3
|
+
## 1.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [`e9c1c39`](https://github.com/marckrenn/pi-sub/commit/e9c1c394286b302e018c2c824d16978b2b4d3d44) Thanks [@plesiv](https://github.com/plesiv)! - Make keybindings configurable
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies [[`7ce2a92`](https://github.com/marckrenn/pi-sub/commit/7ce2a92b15e766fd85a4b7eb85d6fc5c5aa32dca)]:
|
|
12
|
+
- @marckrenn/pi-sub-core@1.1.0
|
|
13
|
+
- @marckrenn/pi-sub-shared@1.1.0
|
|
14
|
+
|
|
3
15
|
## 1.0.6
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -94,8 +94,12 @@ The extension loads automatically. Use:
|
|
|
94
94
|
- `sub-bar:settings` - Open display + provider UI settings (includes Provider Shown)
|
|
95
95
|
- `sub-bar:import <share string>` - Preview a shared theme and choose to save/apply
|
|
96
96
|
- `sub-core:settings` - Configure provider enablement/order + usage/status refresh settings
|
|
97
|
-
- `Ctrl+Alt+P` - Cycle through available providers
|
|
98
|
-
- `Ctrl+Alt+R` - Toggle reset timer format (
|
|
97
|
+
- `Ctrl+Alt+P` - Cycle through available providers (configurable)
|
|
98
|
+
- `Ctrl+Alt+R` - Toggle reset timer format (configurable)
|
|
99
|
+
|
|
100
|
+
**Keybindings:**
|
|
101
|
+
|
|
102
|
+
Shortcuts are configurable via `sub-bar:settings` → Keybindings. Enter any valid key combo (e.g. `ctrl+alt+p`, `ctrl+shift+s`) or `none` to disable a shortcut. Keybinding changes take effect after pi restart.
|
|
99
103
|
|
|
100
104
|
**Caching:**
|
|
101
105
|
- Handled by sub-core at `~/.pi/agent/cache/sub-core/cache.json`
|
package/index.ts
CHANGED
|
@@ -10,10 +10,11 @@ import * as fs from "node:fs";
|
|
|
10
10
|
import { homedir, tmpdir } from "node:os";
|
|
11
11
|
import { join } from "node:path";
|
|
12
12
|
import type { ProviderName, ProviderUsageEntry, SubCoreAllState, SubCoreState, UsageSnapshot } from "./src/types.js";
|
|
13
|
-
import {
|
|
13
|
+
import { type Settings, type BaseTextColor } from "./src/settings-types.js";
|
|
14
14
|
import { isBackgroundColor, resolveBaseTextColor, resolveDividerColor } from "./src/settings-types.js";
|
|
15
15
|
import { buildDividerLine } from "./src/dividers.js";
|
|
16
16
|
import type { CoreSettings } from "@marckrenn/pi-sub-shared";
|
|
17
|
+
import type { KeyId } from "@mariozechner/pi-tui";
|
|
17
18
|
import { formatUsageStatus, formatUsageStatusWithWidth } from "./src/formatting.js";
|
|
18
19
|
import { clearSettingsCache, loadSettings, saveSettings, SETTINGS_PATH } from "./src/settings.js";
|
|
19
20
|
import { showSettingsUI } from "./src/settings-ui.js";
|
|
@@ -124,7 +125,7 @@ function loadScopedModelPatterns(cwd: string): string[] {
|
|
|
124
125
|
*/
|
|
125
126
|
export default function createExtension(pi: ExtensionAPI) {
|
|
126
127
|
let lastContext: ExtensionContext | undefined;
|
|
127
|
-
let settings: Settings =
|
|
128
|
+
let settings: Settings = loadSettings();
|
|
128
129
|
let uiEnabled = true;
|
|
129
130
|
let currentUsage: UsageSnapshot | undefined;
|
|
130
131
|
let usageEntries: Partial<Record<ProviderName, UsageSnapshot>> = {};
|
|
@@ -399,6 +400,7 @@ export default function createExtension(pi: ExtensionAPI) {
|
|
|
399
400
|
displayThemes: loaded.displayThemes,
|
|
400
401
|
displayUserTheme: loaded.displayUserTheme,
|
|
401
402
|
pinnedProvider: loaded.pinnedProvider,
|
|
403
|
+
keybindings: loaded.keybindings,
|
|
402
404
|
};
|
|
403
405
|
coreSettings = getFallbackCoreSettings(settings);
|
|
404
406
|
updateFetchFailureTicker();
|
|
@@ -547,7 +549,7 @@ export default function createExtension(pi: ExtensionAPI) {
|
|
|
547
549
|
}),
|
|
548
550
|
{ placement: settings.display.widgetPlacement ?? "belowEditor" },
|
|
549
551
|
);
|
|
550
|
-
|
|
552
|
+
|
|
551
553
|
}
|
|
552
554
|
|
|
553
555
|
function resolveDisplayedUsage(): UsageSnapshot | undefined {
|
|
@@ -905,24 +907,30 @@ export default function createExtension(pi: ExtensionAPI) {
|
|
|
905
907
|
});
|
|
906
908
|
|
|
907
909
|
// Register shortcut to cycle providers
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
910
|
+
const cycleProviderKey = settings.keybindings?.cycleProvider || "ctrl+alt+p";
|
|
911
|
+
if (cycleProviderKey !== "none") {
|
|
912
|
+
pi.registerShortcut(cycleProviderKey as KeyId, {
|
|
913
|
+
description: "Cycle usage provider",
|
|
914
|
+
handler: async () => {
|
|
915
|
+
emitCoreAction({ type: "cycleProvider" });
|
|
916
|
+
},
|
|
917
|
+
});
|
|
918
|
+
}
|
|
914
919
|
|
|
915
920
|
// Register shortcut to toggle reset timer format
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
921
|
+
const toggleResetFormatKey = settings.keybindings?.toggleResetFormat || "ctrl+alt+r";
|
|
922
|
+
if (toggleResetFormatKey !== "none") {
|
|
923
|
+
pi.registerShortcut(toggleResetFormatKey as KeyId, {
|
|
924
|
+
description: "Toggle reset timer format",
|
|
925
|
+
handler: async () => {
|
|
926
|
+
settings.display.resetTimeFormat = settings.display.resetTimeFormat === "datetime" ? "relative" : "datetime";
|
|
927
|
+
saveSettings(settings);
|
|
928
|
+
if (lastContext && currentUsage) {
|
|
929
|
+
renderUsageWidget(lastContext, currentUsage);
|
|
930
|
+
}
|
|
931
|
+
},
|
|
932
|
+
});
|
|
933
|
+
}
|
|
926
934
|
|
|
927
935
|
pi.on("session_start", async (_event, ctx) => {
|
|
928
936
|
lastContext = ctx;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@marckrenn/pi-sub-bar",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Usage widget extension for pi-coding-agent - shows current provider usage above the editor",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package"
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
"typescript": "^5.8.0"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@marckrenn/pi-sub-core": "^1.0
|
|
34
|
-
"@marckrenn/pi-sub-shared": "^1.0
|
|
33
|
+
"@marckrenn/pi-sub-core": "^1.1.0",
|
|
34
|
+
"@marckrenn/pi-sub-shared": "^1.1.0"
|
|
35
35
|
},
|
|
36
36
|
"peerDependencies": {
|
|
37
37
|
"@mariozechner/pi-coding-agent": "*"
|
package/src/settings/menu.ts
CHANGED
|
@@ -12,6 +12,8 @@ export type TooltipSelectItem = SelectItem & { tooltip?: string };
|
|
|
12
12
|
|
|
13
13
|
export function buildMainMenuItems(settings: Settings, pinnedProvider?: ProviderName | null): TooltipSelectItem[] {
|
|
14
14
|
const pinnedLabel = pinnedProvider ? PROVIDER_DISPLAY_NAMES[pinnedProvider] : "auto (current provider)";
|
|
15
|
+
const kb = settings.keybindings;
|
|
16
|
+
const kbDesc = `cycle: ${kb.cycleProvider}, reset: ${kb.toggleResetFormat}`;
|
|
15
17
|
return [
|
|
16
18
|
{
|
|
17
19
|
value: "display-theme",
|
|
@@ -37,6 +39,12 @@ export function buildMainMenuItems(settings: Settings, pinnedProvider?: Provider
|
|
|
37
39
|
description: pinnedLabel,
|
|
38
40
|
tooltip: "Select which provider is shown in the widget.",
|
|
39
41
|
},
|
|
42
|
+
{
|
|
43
|
+
value: "keybindings",
|
|
44
|
+
label: "Keybindings",
|
|
45
|
+
description: kbDesc,
|
|
46
|
+
tooltip: "Configure keyboard shortcuts. Changes take effect after pi restart.",
|
|
47
|
+
},
|
|
40
48
|
{
|
|
41
49
|
value: "open-core-settings",
|
|
42
50
|
label: "Additional settings",
|
package/src/settings/ui.ts
CHANGED
|
@@ -60,6 +60,7 @@ type SettingsCategory =
|
|
|
60
60
|
| "providers"
|
|
61
61
|
| "pin-provider"
|
|
62
62
|
| ProviderCategory
|
|
63
|
+
| "keybindings"
|
|
63
64
|
| "display"
|
|
64
65
|
| "display-theme"
|
|
65
66
|
| "display-theme-save"
|
|
@@ -341,6 +342,7 @@ export async function showSettingsUI(
|
|
|
341
342
|
main: "sub-bar Settings",
|
|
342
343
|
providers: "Provider Settings",
|
|
343
344
|
"pin-provider": "Provider Shown",
|
|
345
|
+
keybindings: "Keybindings",
|
|
344
346
|
display: "Adv. Display Settings",
|
|
345
347
|
"display-theme": "Themes",
|
|
346
348
|
"display-theme-save": "Save Theme",
|
|
@@ -453,6 +455,72 @@ export async function showSettingsUI(
|
|
|
453
455
|
};
|
|
454
456
|
activeList = selectList;
|
|
455
457
|
container.addChild(selectList);
|
|
458
|
+
} else if (currentCategory === "keybindings") {
|
|
459
|
+
const parseKeybinding = (raw: string): string | null => {
|
|
460
|
+
const trimmed = raw.trim().toLowerCase();
|
|
461
|
+
if (!trimmed) {
|
|
462
|
+
ctx.ui.notify("Enter a key combo (e.g. ctrl+alt+p) or 'none' to disable", "warning");
|
|
463
|
+
return null;
|
|
464
|
+
}
|
|
465
|
+
if (trimmed === "none") return "none";
|
|
466
|
+
const parts = trimmed.split("+");
|
|
467
|
+
const modifiers = new Set(["ctrl", "shift", "alt"]);
|
|
468
|
+
const baseKeys = parts.filter((p) => !modifiers.has(p));
|
|
469
|
+
if (baseKeys.length !== 1) {
|
|
470
|
+
ctx.ui.notify("Invalid key combo. Use format like ctrl+alt+p or ctrl+s", "warning");
|
|
471
|
+
return null;
|
|
472
|
+
}
|
|
473
|
+
return trimmed;
|
|
474
|
+
};
|
|
475
|
+
|
|
476
|
+
const kbItems: SettingItem[] = [
|
|
477
|
+
{
|
|
478
|
+
id: "cycleProvider",
|
|
479
|
+
label: "Cycle Provider",
|
|
480
|
+
currentValue: settings.keybindings.cycleProvider,
|
|
481
|
+
description: "Shortcut to cycle through providers. Changes take effect after pi restart.",
|
|
482
|
+
submenu: buildInputSubmenu(
|
|
483
|
+
"Cycle Provider shortcut",
|
|
484
|
+
parseKeybinding,
|
|
485
|
+
undefined,
|
|
486
|
+
"Enter a key combo (e.g. ctrl+alt+p) or 'none' to disable.",
|
|
487
|
+
),
|
|
488
|
+
},
|
|
489
|
+
{
|
|
490
|
+
id: "toggleResetFormat",
|
|
491
|
+
label: "Toggle Reset Format",
|
|
492
|
+
currentValue: settings.keybindings.toggleResetFormat,
|
|
493
|
+
description: "Shortcut to toggle reset timer format. Changes take effect after pi restart.",
|
|
494
|
+
submenu: buildInputSubmenu(
|
|
495
|
+
"Toggle Reset Format shortcut",
|
|
496
|
+
parseKeybinding,
|
|
497
|
+
undefined,
|
|
498
|
+
"Enter a key combo (e.g. ctrl+alt+r) or 'none' to disable.",
|
|
499
|
+
),
|
|
500
|
+
},
|
|
501
|
+
];
|
|
502
|
+
|
|
503
|
+
const handleKbChange = (id: string, value: string) => {
|
|
504
|
+
if (id === "cycleProvider" || id === "toggleResetFormat") {
|
|
505
|
+
settings.keybindings = { ...settings.keybindings, [id]: value };
|
|
506
|
+
saveSettings(settings);
|
|
507
|
+
if (onSettingsChange) void onSettingsChange(settings);
|
|
508
|
+
}
|
|
509
|
+
};
|
|
510
|
+
|
|
511
|
+
const kbList = new SettingsList(
|
|
512
|
+
kbItems,
|
|
513
|
+
Math.min(kbItems.length + 3, 10),
|
|
514
|
+
getSettingsListTheme(),
|
|
515
|
+
handleKbChange,
|
|
516
|
+
() => {
|
|
517
|
+
currentCategory = "main";
|
|
518
|
+
rebuild();
|
|
519
|
+
tui.requestRender();
|
|
520
|
+
},
|
|
521
|
+
);
|
|
522
|
+
activeList = kbList;
|
|
523
|
+
container.addChild(kbList);
|
|
456
524
|
} else if (currentCategory === "providers") {
|
|
457
525
|
const items = buildProviderListItems(settings, coreSettings.providers);
|
|
458
526
|
const selectList = new SelectList(items, Math.min(items.length, 10), {
|
|
@@ -1238,6 +1306,7 @@ export async function showSettingsUI(
|
|
|
1238
1306
|
// Help text
|
|
1239
1307
|
const usesSettingsList =
|
|
1240
1308
|
Boolean(providerCategory) ||
|
|
1309
|
+
currentCategory === "keybindings" ||
|
|
1241
1310
|
currentCategory === "display-layout" ||
|
|
1242
1311
|
currentCategory === "display-bar" ||
|
|
1243
1312
|
currentCategory === "display-provider" ||
|
package/src/settings-types.ts
CHANGED
|
@@ -266,6 +266,19 @@ export interface ProviderSettingsMap {
|
|
|
266
266
|
|
|
267
267
|
export type { BehaviorSettings, CoreSettings } from "@marckrenn/pi-sub-shared";
|
|
268
268
|
|
|
269
|
+
/**
|
|
270
|
+
* Keybinding settings.
|
|
271
|
+
* Values are key-combo strings accepted by pi's registerShortcut (e.g. "ctrl+alt+p").
|
|
272
|
+
* Use "none" to disable a shortcut.
|
|
273
|
+
* Changes take effect after pi restart.
|
|
274
|
+
*/
|
|
275
|
+
export interface KeybindingSettings {
|
|
276
|
+
/** Shortcut to cycle through providers */
|
|
277
|
+
cycleProvider: string;
|
|
278
|
+
/** Shortcut to toggle reset timer format */
|
|
279
|
+
toggleResetFormat: string;
|
|
280
|
+
}
|
|
281
|
+
|
|
269
282
|
/**
|
|
270
283
|
* Display settings
|
|
271
284
|
*/
|
|
@@ -378,6 +391,8 @@ export interface Settings extends Omit<CoreSettings, "providers"> {
|
|
|
378
391
|
displayUserTheme: DisplaySettings | null;
|
|
379
392
|
/** Pinned provider override for display */
|
|
380
393
|
pinnedProvider: ProviderName | null;
|
|
394
|
+
/** Keybinding settings (changes require pi restart) */
|
|
395
|
+
keybindings: KeybindingSettings;
|
|
381
396
|
}
|
|
382
397
|
|
|
383
398
|
/**
|
|
@@ -502,6 +517,11 @@ export function getDefaultSettings(): Settings {
|
|
|
502
517
|
displayUserTheme: null,
|
|
503
518
|
pinnedProvider: null,
|
|
504
519
|
|
|
520
|
+
keybindings: {
|
|
521
|
+
cycleProvider: "ctrl+alt+p",
|
|
522
|
+
toggleResetFormat: "ctrl+alt+r",
|
|
523
|
+
},
|
|
524
|
+
|
|
505
525
|
behavior: {
|
|
506
526
|
refreshInterval: 60,
|
|
507
527
|
minRefreshInterval: 10,
|
package/src/settings.ts
CHANGED
|
@@ -40,6 +40,7 @@ function parseSettings(content: string): Settings {
|
|
|
40
40
|
displayThemes: loaded.displayThemes,
|
|
41
41
|
displayUserTheme: loaded.displayUserTheme,
|
|
42
42
|
pinnedProvider: loaded.pinnedProvider,
|
|
43
|
+
keybindings: loaded.keybindings,
|
|
43
44
|
} as Partial<Settings>);
|
|
44
45
|
}
|
|
45
46
|
|
|
@@ -108,6 +109,7 @@ export function saveSettings(settings: Settings): boolean {
|
|
|
108
109
|
const themesChanged = JSON.stringify(settings.displayThemes) !== JSON.stringify(cachedSettings.displayThemes);
|
|
109
110
|
const userThemeChanged = JSON.stringify(settings.displayUserTheme) !== JSON.stringify(cachedSettings.displayUserTheme);
|
|
110
111
|
const pinnedChanged = settings.pinnedProvider !== cachedSettings.pinnedProvider;
|
|
112
|
+
const keybindingsChanged = JSON.stringify(settings.keybindings) !== JSON.stringify(cachedSettings.keybindings);
|
|
111
113
|
|
|
112
114
|
next = {
|
|
113
115
|
...diskSettings,
|
|
@@ -117,6 +119,7 @@ export function saveSettings(settings: Settings): boolean {
|
|
|
117
119
|
displayThemes: themesChanged ? settings.displayThemes : diskSettings.displayThemes,
|
|
118
120
|
displayUserTheme: userThemeChanged ? settings.displayUserTheme : diskSettings.displayUserTheme,
|
|
119
121
|
pinnedProvider: pinnedChanged ? settings.pinnedProvider : diskSettings.pinnedProvider,
|
|
122
|
+
keybindings: keybindingsChanged ? settings.keybindings : diskSettings.keybindings,
|
|
120
123
|
};
|
|
121
124
|
}
|
|
122
125
|
}
|
|
@@ -127,6 +130,7 @@ export function saveSettings(settings: Settings): boolean {
|
|
|
127
130
|
displayThemes: next.displayThemes,
|
|
128
131
|
displayUserTheme: next.displayUserTheme,
|
|
129
132
|
pinnedProvider: next.pinnedProvider,
|
|
133
|
+
keybindings: next.keybindings,
|
|
130
134
|
}, null, 2);
|
|
131
135
|
storage.writeFile(SETTINGS_PATH, content);
|
|
132
136
|
cachedSettings = next;
|
|
@@ -150,6 +154,7 @@ export function resetSettings(): Settings {
|
|
|
150
154
|
displayThemes: defaults.displayThemes,
|
|
151
155
|
displayUserTheme: defaults.displayUserTheme,
|
|
152
156
|
pinnedProvider: defaults.pinnedProvider,
|
|
157
|
+
keybindings: defaults.keybindings,
|
|
153
158
|
version: defaults.version,
|
|
154
159
|
};
|
|
155
160
|
saveSettings(next);
|