pi-powerline 0.1.0 → 0.2.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 +19 -190
- package/breadcrumb.ts +2 -2
- package/editor.ts +24 -6
- package/footer.ts +7 -4
- package/header.ts +7 -4
- package/index.ts +25 -3
- package/package.json +2 -2
- package/settings.ts +12 -0
- package/widget.ts +11 -9
package/README.md
CHANGED
|
@@ -1,58 +1,19 @@
|
|
|
1
1
|
# pi-powerline
|
|
2
2
|
|
|
3
|
-
Powerline-style UI extensions for [pi](https://github.com/badlogic/pi-mono)
|
|
3
|
+
Powerline-style UI extensions for [pi](https://github.com/badlogic/pi-mono): custom editor, breadcrumb, footer, and header.
|
|
4
4
|
|
|
5
|
-

|
|
6
6
|
|
|
7
|
-
##
|
|
8
|
-
|
|
9
|
-
**Custom editor** — Always-on bordered input area with a `❯` prompt prefix. Switches to bash-mode coloring when the prompt starts with `!`. Breadcrumb info (model → directory) can be embedded in the top border.
|
|
10
|
-
|
|
11
|
-
**Breadcrumb widget** — Displays current model → working directory above the editor, shown only when breadcrumb mode is `top`.
|
|
12
|
-
|
|
13
|
-
**Custom footer** — A compact status bar showing token usage (`↑input ↓output` + cache read/write), context usage % with auto-compact indicator, session cost, thinking level, git branch, and extension statuses. Updates in real-time during streaming.
|
|
14
|
-
|
|
15
|
-
**Custom header** — A gradient-colored PI logo rendered with ANSI 256-color codes, replacing the built-in header.
|
|
16
|
-
|
|
17
|
-
> Highly inspired by [nicobailon/pi-powerline-footer](https://github.com/nicobailon/pi-powerline-footer).
|
|
18
|
-
|
|
19
|
-
## Installation
|
|
20
|
-
|
|
21
|
-
### Local development
|
|
22
|
-
|
|
23
|
-
Clone the repository and use pi's `--extension` flag:
|
|
24
|
-
|
|
25
|
-
```bash
|
|
26
|
-
git clone <repo-url> pi-powerline
|
|
27
|
-
cd pi-powerline
|
|
28
|
-
pi -e ./index.ts
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
Or add it to your project's `.pi/settings.json`:
|
|
32
|
-
|
|
33
|
-
```json
|
|
34
|
-
{
|
|
35
|
-
"extensions": ["./index.ts"]
|
|
36
|
-
}
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
### From npm (after publishing)
|
|
7
|
+
## Install
|
|
40
8
|
|
|
41
9
|
```bash
|
|
42
10
|
pi install npm:pi-powerline
|
|
43
11
|
```
|
|
44
12
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
## Usage
|
|
48
|
-
|
|
49
|
-
All extensions activate automatically on session start. Each can be configured via the `/powerline` command.
|
|
50
|
-
|
|
51
|
-
### Settings
|
|
52
|
-
|
|
53
|
-
Configure in `.pi/settings.json`:
|
|
13
|
+
## Settings
|
|
54
14
|
|
|
55
15
|
```json
|
|
16
|
+
// .pi/settings.json
|
|
56
17
|
{
|
|
57
18
|
"breadcrumb": "inner",
|
|
58
19
|
"footer": true,
|
|
@@ -60,154 +21,22 @@ Configure in `.pi/settings.json`:
|
|
|
60
21
|
}
|
|
61
22
|
```
|
|
62
23
|
|
|
63
|
-
| Setting |
|
|
64
|
-
|
|
65
|
-
| `
|
|
66
|
-
| `
|
|
67
|
-
| `
|
|
68
|
-
|
|
69
|
-
**Breadcrumb modes:**
|
|
70
|
-
|
|
71
|
-
- `hide` — No breadcrumb display
|
|
72
|
-
- `top` — Breadcrumb as a widget above the editor
|
|
73
|
-
- `inner` — Breadcrumb embedded in the editor's top border
|
|
74
|
-
|
|
75
|
-
### Commands
|
|
76
|
-
|
|
77
|
-
| Command | Description |
|
|
78
|
-
|---------|-------------|
|
|
79
|
-
| `/powerline` | Show current powerline settings |
|
|
80
|
-
| `/powerline breadcrumb:hide` | Disable breadcrumb |
|
|
81
|
-
| `/powerline breadcrumb:top` | Breadcrumb as top widget |
|
|
82
|
-
| `/powerline breadcrumb:inner` | Breadcrumb in editor border |
|
|
83
|
-
| `/powerline footer:on` | Enable custom footer |
|
|
84
|
-
| `/powerline footer:off` | Disable custom footer |
|
|
85
|
-
| `/powerline header:on` | Enable custom header |
|
|
86
|
-
| `/powerline header:off` | Disable custom header |
|
|
87
|
-
|
|
88
|
-
### Nerd Fonts
|
|
89
|
-
|
|
90
|
-
The breadcrumb and footer use Nerd Font icons when a compatible terminal is detected (iTerm, WezTerm, Kitty, Ghostty, Alacritty). Set `POWERLINE_NERD_FONTS=1` or `POWERLINE_NERD_FONTS=0` to explicitly enable/disable.
|
|
91
|
-
|
|
92
|
-
## Development
|
|
93
|
-
|
|
94
|
-
### Project structure
|
|
95
|
-
|
|
96
|
-
```
|
|
97
|
-
.
|
|
98
|
-
├── index.ts # Single entry point (default export)
|
|
99
|
-
├── editor.ts # Custom editor with prompt prefix
|
|
100
|
-
├── breadcrumb.ts # Shared breadcrumb data & rendering helpers
|
|
101
|
-
├── widget.ts # Top widget (shown when breadcrumb=top)
|
|
102
|
-
├── footer.ts # Custom footer (token stats, git, thinking level)
|
|
103
|
-
├── header.ts # Gradient-logo header
|
|
104
|
-
├── settings.ts # Shared .pi/settings.json read/write helpers
|
|
105
|
-
├── tests/
|
|
106
|
-
│ ├── editor.test.ts
|
|
107
|
-
│ ├── footer.test.ts
|
|
108
|
-
│ ├── header.test.ts
|
|
109
|
-
│ └── widget.test.ts
|
|
110
|
-
├── .pi/
|
|
111
|
-
│ ├── settings.json
|
|
112
|
-
│ ├── APPEND_SYSTEM.md
|
|
113
|
-
│ └── extensions/
|
|
114
|
-
│ └── auto-format.ts # Auto prettier on edit/write
|
|
115
|
-
├── .husky/
|
|
116
|
-
│ └── pre-commit # prettier check + bun test
|
|
117
|
-
├── .editorconfig
|
|
118
|
-
├── .prettierrc
|
|
119
|
-
├── .prettierignore
|
|
120
|
-
├── package.json
|
|
121
|
-
└── tsconfig.json # gitignored
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
### Architecture
|
|
125
|
-
|
|
126
|
-
`index.ts` is the single entry point registered in `package.json` → `"pi": { "extensions": ["./index.ts"] }`. It registers four extensions:
|
|
127
|
-
|
|
128
|
-
```ts
|
|
129
|
-
import type { ExtensionAPI } from '@mariozechner/pi-coding-agent';
|
|
130
|
-
import { registerEditor } from './editor.ts';
|
|
131
|
-
import { registerFooter } from './footer.ts';
|
|
132
|
-
import { registerHeader } from './header.ts';
|
|
133
|
-
import { registerWidget } from './widget.ts';
|
|
134
|
-
|
|
135
|
-
export default function (pi: ExtensionAPI) {
|
|
136
|
-
registerEditor(pi);
|
|
137
|
-
registerFooter(pi);
|
|
138
|
-
registerHeader(pi);
|
|
139
|
-
registerWidget(pi);
|
|
140
|
-
}
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
Settings are managed via `settings.ts` — a shared module that reads/writes `.pi/settings.json`. When `/powerline` changes a setting, it emits a `powerline_settings_changed` event that all modules listen to for live reconfiguration.
|
|
144
|
-
|
|
145
|
-
### Code quality
|
|
146
|
-
|
|
147
|
-
- **Formatting**: `.pi/extensions/auto-format.ts` runs prettier automatically after edit/write tools touch `.ts` files. Prettier config: single quotes, semicolons, trailing commas, 2-space indent, 100 char width.
|
|
148
|
-
- **Pre-commit**: `.husky/pre-commit` runs `prettier --check` + `bun test` before every commit.
|
|
149
|
-
- Use `bun run format` to format all files, `bun run format:check` to verify.
|
|
150
|
-
|
|
151
|
-
### Editor setup
|
|
152
|
-
|
|
153
|
-
Neovim's tsserver can't resolve `@mariozechner/pi-*` imports because those packages are bundled inside pi, not in `node_modules`. Create a `tsconfig.json` with path mappings pointing to the global pi installation:
|
|
154
|
-
|
|
155
|
-
```bash
|
|
156
|
-
# Find the pi install path
|
|
157
|
-
ls -d $(dirname $(which pi))/../lib/node_modules/@mariozechner/pi-coding-agent
|
|
158
|
-
```
|
|
24
|
+
| Setting | Values | Default |
|
|
25
|
+
|---------|--------|---------|
|
|
26
|
+
| `powerline` | `true` / `false` | `true` |
|
|
27
|
+
| `breadcrumb` | `"hide"` / `"top"` / `"inner"` | `"inner"` |
|
|
28
|
+
| `footer` | `true` / `false` | `true` |
|
|
29
|
+
| `header` | `true` / `false` | `true` |
|
|
159
30
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
```json
|
|
163
|
-
{
|
|
164
|
-
"compilerOptions": {
|
|
165
|
-
"target": "ESNext",
|
|
166
|
-
"module": "ESNext",
|
|
167
|
-
"moduleResolution": "bundler",
|
|
168
|
-
"strict": true,
|
|
169
|
-
"noEmit": true,
|
|
170
|
-
"allowImportingTsExtensions": true,
|
|
171
|
-
"baseUrl": ".",
|
|
172
|
-
"paths": {
|
|
173
|
-
"@mariozechner/pi-coding-agent": [
|
|
174
|
-
"/path/to/.nvm/versions/node/vXX/lib/node_modules/@mariozechner/pi-coding-agent/dist"
|
|
175
|
-
],
|
|
176
|
-
"@mariozechner/pi-ai": [
|
|
177
|
-
"/path/to/.nvm/.../pi-coding-agent/node_modules/@mariozechner/pi-ai/dist"
|
|
178
|
-
],
|
|
179
|
-
"@mariozechner/pi-tui": [
|
|
180
|
-
"/path/to/.nvm/.../pi-coding-agent/node_modules/@mariozechner/pi-tui/dist"
|
|
181
|
-
]
|
|
182
|
-
}
|
|
183
|
-
},
|
|
184
|
-
"include": ["*.ts", "tests/**/*.ts"]
|
|
185
|
-
}
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
`tsconfig.json` is gitignored — each developer creates their own.
|
|
189
|
-
|
|
190
|
-
### Running tests
|
|
191
|
-
|
|
192
|
-
```bash
|
|
193
|
-
bun test
|
|
194
|
-
# or via npm:
|
|
195
|
-
npm run test:bun
|
|
196
|
-
```
|
|
197
|
-
|
|
198
|
-
Tests use bun's built-in test runner (compatible with `node:test`). Run `npm run test` for the Node.js variant.
|
|
199
|
-
|
|
200
|
-
### Testing a single extension
|
|
201
|
-
|
|
202
|
-
```bash
|
|
203
|
-
pi -e ./index.ts
|
|
204
|
-
```
|
|
31
|
+
## Commands
|
|
205
32
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
33
|
+
| Command | Effect |
|
|
34
|
+
|---------|--------|
|
|
35
|
+
| `/powerline` | Toggle all extensions on/off |
|
|
36
|
+
| `/powerline info` | Show current settings |
|
|
37
|
+
| `/powerline breadcrumb:top\|inner\|hide` | Set breadcrumb mode |
|
|
38
|
+
| `/powerline footer:on\|off` | Toggle footer |
|
|
39
|
+
| `/powerline header:on\|off` | Toggle header |
|
|
211
40
|
|
|
212
41
|
## License
|
|
213
42
|
|
package/breadcrumb.ts
CHANGED
|
@@ -22,8 +22,8 @@ export function hasNerdFonts(): boolean {
|
|
|
22
22
|
const NERD = hasNerdFonts();
|
|
23
23
|
|
|
24
24
|
export const ICON_MODEL = NERD ? '\uF4BC' : '';
|
|
25
|
-
export const ICON_FOLDER = NERD ? '\uF115' : '
|
|
26
|
-
export const SEP = NERD ? '\
|
|
25
|
+
export const ICON_FOLDER = NERD ? '\uF115' : '';
|
|
26
|
+
export const SEP = NERD ? '\uf054' : '/';
|
|
27
27
|
|
|
28
28
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
29
29
|
// helpers
|
package/editor.ts
CHANGED
|
@@ -147,8 +147,10 @@ export function updateTheme(theme: Theme): void {
|
|
|
147
147
|
currentTheme = theme;
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
-
/** Register the custom editor extension.
|
|
150
|
+
/** Register the custom editor extension. Controlled by powerline master switch + breadcrumb mode. */
|
|
151
151
|
export function registerEditor(pi: ExtensionAPI) {
|
|
152
|
+
let editorEnabled = false;
|
|
153
|
+
|
|
152
154
|
function createEditorFactory() {
|
|
153
155
|
return (tui: any, theme: EditorTheme, keybindings: any) => {
|
|
154
156
|
liveEditorTui = tui;
|
|
@@ -157,15 +159,24 @@ export function registerEditor(pi: ExtensionAPI) {
|
|
|
157
159
|
}
|
|
158
160
|
|
|
159
161
|
function enable(ctx: ExtensionContext) {
|
|
162
|
+
editorEnabled = true;
|
|
160
163
|
liveCtx = ctx;
|
|
161
164
|
currentTheme = ctx.ui.theme;
|
|
162
165
|
breadcrumbMode = readPowerlineSettings(ctx.cwd).breadcrumb;
|
|
163
166
|
ctx.ui.setEditorComponent(createEditorFactory());
|
|
164
167
|
}
|
|
165
168
|
|
|
166
|
-
|
|
169
|
+
function disable(ctx: ExtensionContext) {
|
|
170
|
+
editorEnabled = false;
|
|
171
|
+
liveEditorTui = null;
|
|
172
|
+
ctx.ui.setEditorComponent(undefined);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// enable on session start if powerline master switch is on
|
|
167
176
|
pi.on('session_start', (_event, ctx) => {
|
|
168
|
-
|
|
177
|
+
if (readPowerlineSettings(ctx.cwd).powerline) {
|
|
178
|
+
enable(ctx);
|
|
179
|
+
}
|
|
169
180
|
});
|
|
170
181
|
|
|
171
182
|
// keep widget info in sync when model/cwd changes
|
|
@@ -175,11 +186,18 @@ export function registerEditor(pi: ExtensionAPI) {
|
|
|
175
186
|
liveEditorTui?.requestRender();
|
|
176
187
|
});
|
|
177
188
|
|
|
178
|
-
// re-
|
|
189
|
+
// re-evaluate on /powerline command (settings changed)
|
|
179
190
|
pi.events.on('powerline_settings_changed', (ctx) => {
|
|
180
191
|
const c = ctx as ExtensionContext;
|
|
181
|
-
|
|
192
|
+
const s = readPowerlineSettings(c.cwd);
|
|
193
|
+
breadcrumbMode = s.breadcrumb;
|
|
182
194
|
liveCtx = c;
|
|
183
|
-
|
|
195
|
+
if (s.powerline && !editorEnabled) {
|
|
196
|
+
enable(c);
|
|
197
|
+
} else if (!s.powerline && editorEnabled) {
|
|
198
|
+
disable(c);
|
|
199
|
+
} else if (editorEnabled) {
|
|
200
|
+
liveEditorTui?.requestRender();
|
|
201
|
+
}
|
|
184
202
|
});
|
|
185
203
|
}
|
package/footer.ts
CHANGED
|
@@ -338,10 +338,11 @@ export function registerFooter(pi: ExtensionAPI) {
|
|
|
338
338
|
ctx.ui.setFooter(undefined);
|
|
339
339
|
}
|
|
340
340
|
|
|
341
|
-
// enable on session start if footer setting
|
|
341
|
+
// enable on session start if powerline master switch + footer setting are both on
|
|
342
342
|
pi.on('session_start', (_event, ctx) => {
|
|
343
343
|
autoCompactEnabled = readAutoCompactEnabled(ctx.cwd);
|
|
344
|
-
|
|
344
|
+
const s = readPowerlineSettings(ctx.cwd);
|
|
345
|
+
if (s.powerline && s.footer) {
|
|
345
346
|
enable(ctx);
|
|
346
347
|
}
|
|
347
348
|
});
|
|
@@ -355,7 +356,8 @@ export function registerFooter(pi: ExtensionAPI) {
|
|
|
355
356
|
|
|
356
357
|
// model switch may affect reasoning support / provider count
|
|
357
358
|
pi.on('model_select', (_event, ctx) => {
|
|
358
|
-
const
|
|
359
|
+
const s = readPowerlineSettings(ctx.cwd);
|
|
360
|
+
const show = s.powerline && s.footer;
|
|
359
361
|
if (show && !enabled) {
|
|
360
362
|
enable(ctx);
|
|
361
363
|
} else if (!show && enabled) {
|
|
@@ -369,7 +371,8 @@ export function registerFooter(pi: ExtensionAPI) {
|
|
|
369
371
|
// re-evaluate on /powerline command (settings changed)
|
|
370
372
|
pi.events.on('powerline_settings_changed', (ctx) => {
|
|
371
373
|
const c = ctx as ExtensionContext;
|
|
372
|
-
const
|
|
374
|
+
const s = readPowerlineSettings(c.cwd);
|
|
375
|
+
const show = s.powerline && s.footer;
|
|
373
376
|
if (show && !enabled) {
|
|
374
377
|
enable(c);
|
|
375
378
|
} else if (!show && enabled) {
|
package/header.ts
CHANGED
|
@@ -77,17 +77,19 @@ export function registerHeader(pi: ExtensionAPI) {
|
|
|
77
77
|
ctx.ui.setHeader(undefined);
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
// auto-enable on session start if header setting
|
|
80
|
+
// auto-enable on session start if powerline master switch + header setting are both on
|
|
81
81
|
pi.on('session_start', (_event, ctx) => {
|
|
82
82
|
if (!ctx.hasUI) return;
|
|
83
|
-
|
|
83
|
+
const s = readPowerlineSettings(ctx.cwd);
|
|
84
|
+
if (s.powerline && s.header) {
|
|
84
85
|
enable(ctx);
|
|
85
86
|
}
|
|
86
87
|
});
|
|
87
88
|
|
|
88
89
|
// re-evaluate on model switch
|
|
89
90
|
pi.on('model_select', (_event, ctx) => {
|
|
90
|
-
const
|
|
91
|
+
const s = readPowerlineSettings(ctx.cwd);
|
|
92
|
+
const show = s.powerline && s.header;
|
|
91
93
|
if (show && !headerEnabled) {
|
|
92
94
|
enable(ctx);
|
|
93
95
|
} else if (!show && headerEnabled) {
|
|
@@ -98,7 +100,8 @@ export function registerHeader(pi: ExtensionAPI) {
|
|
|
98
100
|
// re-evaluate on /powerline command (settings changed)
|
|
99
101
|
pi.events.on('powerline_settings_changed', (ctx) => {
|
|
100
102
|
const c = ctx as ExtensionContext;
|
|
101
|
-
const
|
|
103
|
+
const s = readPowerlineSettings(c.cwd);
|
|
104
|
+
const show = s.powerline && s.header;
|
|
102
105
|
if (show && !headerEnabled) {
|
|
103
106
|
enable(c);
|
|
104
107
|
} else if (!show && headerEnabled) {
|
package/index.ts
CHANGED
|
@@ -8,6 +8,12 @@ import { readPowerlineSettings, writePowerlineSetting } from './settings.ts';
|
|
|
8
8
|
|
|
9
9
|
export default function (pi: ExtensionAPI) {
|
|
10
10
|
// flags
|
|
11
|
+
pi.registerFlag('powerline', {
|
|
12
|
+
description: 'Enable pi-powerline extensions',
|
|
13
|
+
type: 'boolean',
|
|
14
|
+
default: true,
|
|
15
|
+
});
|
|
16
|
+
|
|
11
17
|
pi.registerFlag('breadcrumb', {
|
|
12
18
|
description: 'Breadcrumb display mode: hide, top, inner',
|
|
13
19
|
type: 'string',
|
|
@@ -37,6 +43,11 @@ export default function (pi: ExtensionAPI) {
|
|
|
37
43
|
description: 'Configure powerline: breadcrumb, footer, header',
|
|
38
44
|
getArgumentCompletions: (prefix: string): AutocompleteItem[] | null => {
|
|
39
45
|
const items: AutocompleteItem[] = [
|
|
46
|
+
{
|
|
47
|
+
value: 'info',
|
|
48
|
+
label: 'info',
|
|
49
|
+
description: 'Show current powerline settings',
|
|
50
|
+
},
|
|
40
51
|
{
|
|
41
52
|
value: 'breadcrumb:hide',
|
|
42
53
|
label: 'breadcrumb:hide',
|
|
@@ -79,10 +90,21 @@ export default function (pi: ExtensionAPI) {
|
|
|
79
90
|
handler: async (args, ctx) => {
|
|
80
91
|
const arg = args?.trim().toLowerCase();
|
|
81
92
|
|
|
82
|
-
// no args:
|
|
93
|
+
// no args: toggle master switch
|
|
83
94
|
if (!arg) {
|
|
84
|
-
const {
|
|
95
|
+
const { powerline } = readPowerlineSettings(ctx.cwd);
|
|
96
|
+
const next = !powerline;
|
|
97
|
+
writePowerlineSetting(ctx.cwd, 'powerline', next);
|
|
98
|
+
pi.events.emit('powerline_settings_changed', ctx);
|
|
99
|
+
ctx.ui.notify(`powerline → ${next ? 'on' : 'off'}`, 'info');
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// show status
|
|
104
|
+
if (arg === 'info') {
|
|
105
|
+
const { powerline, breadcrumb, footer, header } = readPowerlineSettings(ctx.cwd);
|
|
85
106
|
const lines = [
|
|
107
|
+
`powerline: ${powerline ? 'on' : 'off'}`,
|
|
86
108
|
`breadcrumb: ${breadcrumb}`,
|
|
87
109
|
`footer: ${footer ? 'on' : 'off'}`,
|
|
88
110
|
`header: ${header ? 'on' : 'off'}`,
|
|
@@ -95,7 +117,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
95
117
|
const colonIdx = arg.indexOf(':');
|
|
96
118
|
if (colonIdx === -1) {
|
|
97
119
|
ctx.ui.notify(
|
|
98
|
-
'Usage: /powerline <breadcrumb:hide|top|inner|footer:on|off|header:on|off>',
|
|
120
|
+
'Usage: /powerline <info|breadcrumb:hide|top|inner|footer:on|off|header:on|off>',
|
|
99
121
|
'warning',
|
|
100
122
|
);
|
|
101
123
|
return;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-powerline",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Powerline-style UI extensions for pi coding agent (custom editor, breadcrumb, footer, header)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"extensions": [
|
|
33
33
|
"./index.ts"
|
|
34
34
|
],
|
|
35
|
-
"image": "
|
|
35
|
+
"image": "./assets/pi-powerline.png"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
38
|
"@mariozechner/pi-coding-agent": "*",
|
package/settings.ts
CHANGED
|
@@ -5,12 +5,14 @@ import { join } from 'node:path';
|
|
|
5
5
|
export type BreadcrumbMode = 'hide' | 'top' | 'inner';
|
|
6
6
|
|
|
7
7
|
export interface PowerlineSettings {
|
|
8
|
+
powerline: boolean;
|
|
8
9
|
breadcrumb: BreadcrumbMode;
|
|
9
10
|
footer: boolean;
|
|
10
11
|
header: boolean;
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
const DEFAULTS: PowerlineSettings = {
|
|
15
|
+
powerline: true,
|
|
14
16
|
breadcrumb: 'inner',
|
|
15
17
|
footer: true,
|
|
16
18
|
header: true,
|
|
@@ -36,6 +38,7 @@ function writeSettings(cwd: string, settings: Record<string, unknown>): void {
|
|
|
36
38
|
export function readPowerlineSettings(cwd: string): PowerlineSettings {
|
|
37
39
|
const s = readSettings(cwd);
|
|
38
40
|
return {
|
|
41
|
+
powerline: typeof s.powerline === 'boolean' ? s.powerline : DEFAULTS.powerline,
|
|
39
42
|
breadcrumb: (['hide', 'top', 'inner'].includes(s.breadcrumb as string)
|
|
40
43
|
? s.breadcrumb
|
|
41
44
|
: DEFAULTS.breadcrumb) as BreadcrumbMode,
|
|
@@ -54,3 +57,12 @@ export function writePowerlineSetting(
|
|
|
54
57
|
s[key] = value;
|
|
55
58
|
writeSettings(cwd, s);
|
|
56
59
|
}
|
|
60
|
+
|
|
61
|
+
/** Write multiple powerline settings at once, preserving other keys. */
|
|
62
|
+
export function writePowerlineSettings(cwd: string, patch: Partial<PowerlineSettings>): void {
|
|
63
|
+
const s = readSettings(cwd);
|
|
64
|
+
for (const [k, v] of Object.entries(patch)) {
|
|
65
|
+
s[k] = v;
|
|
66
|
+
}
|
|
67
|
+
writeSettings(cwd, s);
|
|
68
|
+
}
|
package/widget.ts
CHANGED
|
@@ -64,21 +64,22 @@ export function registerWidget(pi: ExtensionAPI) {
|
|
|
64
64
|
ctx.ui.setWidget('powerline-status', undefined);
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
// enable only when breadcrumb mode is "top"
|
|
67
|
+
// enable only when powerline master switch is on and breadcrumb mode is "top"
|
|
68
68
|
pi.on('session_start', (_event, ctx) => {
|
|
69
69
|
if (!ctx.hasUI) return;
|
|
70
|
-
const
|
|
71
|
-
if (breadcrumb === 'top') {
|
|
70
|
+
const s = readPowerlineSettings(ctx.cwd);
|
|
71
|
+
if (s.powerline && s.breadcrumb === 'top') {
|
|
72
72
|
enable(ctx);
|
|
73
73
|
}
|
|
74
74
|
});
|
|
75
75
|
|
|
76
76
|
// re-evaluate on model switch (breadcrumb setting may have changed)
|
|
77
77
|
pi.on('model_select', (_event, ctx) => {
|
|
78
|
-
const
|
|
79
|
-
|
|
78
|
+
const s = readPowerlineSettings(ctx.cwd);
|
|
79
|
+
const show = s.powerline && s.breadcrumb === 'top';
|
|
80
|
+
if (show && !widgetEnabled) {
|
|
80
81
|
enable(ctx);
|
|
81
|
-
} else if (
|
|
82
|
+
} else if (!show && widgetEnabled) {
|
|
82
83
|
disable(ctx);
|
|
83
84
|
} else if (widgetEnabled) {
|
|
84
85
|
liveCtx = ctx;
|
|
@@ -89,10 +90,11 @@ export function registerWidget(pi: ExtensionAPI) {
|
|
|
89
90
|
// re-evaluate on /powerline command (settings changed)
|
|
90
91
|
pi.events.on('powerline_settings_changed', (ctx) => {
|
|
91
92
|
const c = ctx as ExtensionContext;
|
|
92
|
-
const
|
|
93
|
-
|
|
93
|
+
const s = readPowerlineSettings(c.cwd);
|
|
94
|
+
const show = s.powerline && s.breadcrumb === 'top';
|
|
95
|
+
if (show && !widgetEnabled) {
|
|
94
96
|
enable(c);
|
|
95
|
-
} else if (
|
|
97
|
+
} else if (!show && widgetEnabled) {
|
|
96
98
|
disable(c);
|
|
97
99
|
}
|
|
98
100
|
});
|