@d3ara1n/pi-command-palette 0.1.0 → 0.1.2

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.
Files changed (2) hide show
  1. package/package.json +2 -1
  2. package/src/index.ts +67 -2
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@d3ara1n/pi-command-palette",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
+ "type": "module",
4
5
  "description": "Global command palette for pi — press Ctrl+Shift+P to search and run commands from anywhere",
5
6
  "main": "src/index.ts",
6
7
  "keywords": [
package/src/index.ts CHANGED
@@ -17,6 +17,9 @@ import { DynamicBorder } from "@earendil-works/pi-coding-agent";
17
17
  import {
18
18
  Container,
19
19
  type SelectItem,
20
+ fuzzyFilter,
21
+ Key,
22
+ matchesKey,
20
23
  SelectList,
21
24
  Text,
22
25
  } from "@earendil-works/pi-tui";
@@ -188,9 +191,25 @@ async function showModelSelector(pi: ExtensionAPI, ctx: ExtensionContext): Promi
188
191
  selectList.onSelect = (item) => done(item.value);
189
192
  selectList.onCancel = () => done(null);
190
193
 
194
+ // Type-to-filter state
195
+ let query = "";
196
+ const queryText = new Text(theme.fg("accent", "> "), 1, 0);
197
+
198
+ function applyQuery() {
199
+ const filtered = query
200
+ ? fuzzyFilter(items, query, (item: SelectItem) => `${item.label} ${item.description ?? ""}`)
201
+ : items;
202
+ (selectList as any).filteredItems = filtered;
203
+ selectList.setSelectedIndex(0);
204
+ queryText.setText(theme.fg("accent", `> ${query}▎`));
205
+ container.invalidate();
206
+ tui.requestRender();
207
+ }
208
+
209
+ container.addChild(queryText);
191
210
  container.addChild(selectList);
192
211
  container.addChild(
193
- new Text(theme.fg("dim", "↑↓ navigate • enter select • esc cancel"), 1, 0),
212
+ new Text(theme.fg("dim", "type to filter • ↑↓ navigate • enter select • esc cancel"), 1, 0),
194
213
  );
195
214
  container.addChild(new DynamicBorder((s: string) => theme.fg("accent", s)));
196
215
 
@@ -202,6 +221,21 @@ async function showModelSelector(pi: ExtensionAPI, ctx: ExtensionContext): Promi
202
221
  container.invalidate();
203
222
  },
204
223
  handleInput(data: string) {
224
+ // Backspace → trim query
225
+ if (matchesKey(data, Key.backspace)) {
226
+ if (query.length > 0) {
227
+ query = query.slice(0, -1);
228
+ applyQuery();
229
+ }
230
+ return;
231
+ }
232
+ // Printable character → append to query
233
+ if (data.length === 1 && data.charCodeAt(0) >= 32) {
234
+ query += data;
235
+ applyQuery();
236
+ return;
237
+ }
238
+ // Navigation / confirm / cancel → pass to SelectList
205
239
  selectList.handleInput(data);
206
240
  tui.requestRender();
207
241
  },
@@ -225,7 +259,7 @@ async function showModelSelector(pi: ExtensionAPI, ctx: ExtensionContext): Promi
225
259
  // ── Command palette overlay ────────────────────────────────────────
226
260
 
227
261
  async function showCommandPalette(pi: ExtensionAPI, ctx: ExtensionContext): Promise<void> {
228
- if (ctx.mode !== "tui") return;
262
+ if (!ctx.hasUI) return;
229
263
 
230
264
  const paletteItems = buildPaletteItems(pi, ctx);
231
265
  const selectItems: SelectItem[] = paletteItems.map((item) => ({
@@ -256,6 +290,22 @@ async function showCommandPalette(pi: ExtensionAPI, ctx: ExtensionContext): Prom
256
290
  };
257
291
  selectList.onCancel = () => done(null);
258
292
 
293
+ // Type-to-filter state
294
+ let query = "";
295
+ const queryText = new Text(theme.fg("accent", "> "), 1, 0);
296
+
297
+ function applyQuery() {
298
+ const filtered = query
299
+ ? fuzzyFilter(selectItems, query, (item: SelectItem) => `${item.label} ${item.description ?? ""}`)
300
+ : selectItems;
301
+ (selectList as any).filteredItems = filtered;
302
+ selectList.setSelectedIndex(0);
303
+ queryText.setText(theme.fg("accent", `> ${query}▎`));
304
+ container.invalidate();
305
+ tui.requestRender();
306
+ }
307
+
308
+ container.addChild(queryText);
259
309
  container.addChild(selectList);
260
310
  container.addChild(
261
311
  new Text(theme.fg("dim", "type to filter • ↑↓ navigate • enter select • esc cancel"), 1, 0),
@@ -270,6 +320,21 @@ async function showCommandPalette(pi: ExtensionAPI, ctx: ExtensionContext): Prom
270
320
  container.invalidate();
271
321
  },
272
322
  handleInput(data: string) {
323
+ // Backspace → trim query
324
+ if (matchesKey(data, Key.backspace)) {
325
+ if (query.length > 0) {
326
+ query = query.slice(0, -1);
327
+ applyQuery();
328
+ }
329
+ return;
330
+ }
331
+ // Printable character → append to query
332
+ if (data.length === 1 && data.charCodeAt(0) >= 32) {
333
+ query += data;
334
+ applyQuery();
335
+ return;
336
+ }
337
+ // Navigation / confirm / cancel → pass to SelectList
273
338
  selectList.handleInput(data);
274
339
  tui.requestRender();
275
340
  },