@runminton/pi-tidy-tools 0.2.0 → 0.2.1
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 -2
- package/README.zh-CN.md +9 -2
- package/package.json +1 -1
- package/tidy-tools.ts +65 -25
package/README.md
CHANGED
|
@@ -18,6 +18,8 @@ All three tools start **Collapsed**:
|
|
|
18
18
|
|
|
19
19
|
Collapsed summaries are single-line per slot: one command line plus one output line (the count suffix is inline at the end of the output line).
|
|
20
20
|
|
|
21
|
+
In Pi's fullscreen mode, left-click any tool block to toggle that row between its compact summary and full rendering. Click it again to collapse it. Each tool has only these two states; `bash` and `write` skip Pi's intermediate previews.
|
|
22
|
+
|
|
21
23
|
## Modes
|
|
22
24
|
|
|
23
25
|
| Mode | Behavior |
|
|
@@ -25,7 +27,7 @@ Collapsed summaries are single-line per slot: one command line plus one output l
|
|
|
25
27
|
| compact (default) | all three tools collapsed |
|
|
26
28
|
| markdown (`/tidy-markdown` toggles) | `edit`/`write` on Markdown files (`.md`, `.mdx`, `.markdown`) expand to full content; everything else stays collapsed |
|
|
27
29
|
|
|
28
|
-
Switching modes clears
|
|
30
|
+
Switching modes clears shortcut state and row-local click state, then re-renders existing rows. The mode is not persisted across restarts.
|
|
29
31
|
|
|
30
32
|
## Shortcuts
|
|
31
33
|
|
|
@@ -37,7 +39,7 @@ On Mac press `Command+Option+letter` (verified; maps to the registered `Ctrl+Alt
|
|
|
37
39
|
| `Command+Option+E` | `edit` | official rendering ↔ collapsed summary |
|
|
38
40
|
| `Command+Option+W` | `write` | official rendering ↔ collapsed summary |
|
|
39
41
|
|
|
40
|
-
A notification shows the
|
|
42
|
+
A shortcut toggles all existing rows of that tool type and clears their prior row-local click state. A notification shows the new state; press again to switch back.
|
|
41
43
|
|
|
42
44
|
`bash` and `write` expand to the **complete output** in one keypress — they skip Pi's built-in previews (bash's 5-line tail preview, write's 10-line preview). `edit` expands to Pi's **official rendering** (it has no preview state). The global `Ctrl+O` tool expansion does not affect these three tools.
|
|
43
45
|
|
|
@@ -89,6 +91,11 @@ If a shortcut still does nothing on your machine, check:
|
|
|
89
91
|
|
|
90
92
|
## Changelog
|
|
91
93
|
|
|
94
|
+
### 0.2.1
|
|
95
|
+
|
|
96
|
+
- Added per-block fullscreen clicking for bash/edit/write, toggling between compact and full rendering
|
|
97
|
+
- Kept tool-wide shortcuts; a shortcut applies one state to all rows of that tool type
|
|
98
|
+
|
|
92
99
|
### 0.2.0
|
|
93
100
|
|
|
94
101
|
- All three tools collapsed by default (edit/write used to expand)
|
package/README.zh-CN.md
CHANGED
|
@@ -18,6 +18,8 @@
|
|
|
18
18
|
|
|
19
19
|
折叠摘要每槽单行:命令 1 行加输出 1 行(计数后缀内联在输出行尾)。
|
|
20
20
|
|
|
21
|
+
在 Pi 的 fullscreen 模式下,左键点击任意一个工具块,可单独在紧凑摘要和完整渲染之间切换。再次点击即收起。三个工具都只有这两种状态;`bash` 和 `write` 不经过官方中间预览。
|
|
22
|
+
|
|
21
23
|
## 模式
|
|
22
24
|
|
|
23
25
|
| 模式 | 行为 |
|
|
@@ -25,7 +27,7 @@
|
|
|
25
27
|
| compact(默认) | 三工具全折叠 |
|
|
26
28
|
| markdown(`/tidy-markdown` 切换) | Markdown 文件(`.md`、`.mdx`、`.markdown`)的 `edit`/`write` 展开全文,其余照样折叠 |
|
|
27
29
|
|
|
28
|
-
|
|
30
|
+
切换模式会清空快捷键状态和各工具块的点击状态,并重渲染已有行。模式不持久化,重启后回到 compact。
|
|
29
31
|
|
|
30
32
|
## 快捷键
|
|
31
33
|
|
|
@@ -37,7 +39,7 @@ Mac 上按 `Command+Option+字母`(实测有效,对应插件注册的 `Ctrl+
|
|
|
37
39
|
| `Command+Option+E` | `edit` | 官方渲染 ↔ 折叠摘要 |
|
|
38
40
|
| `Command+Option+W` | `write` | 官方渲染 ↔ 折叠摘要 |
|
|
39
41
|
|
|
40
|
-
|
|
42
|
+
快捷键按工具类型切换所有已有工具块,并清除该工具之前的逐块点击状态。每次切换会弹出通知;再按一次切回。
|
|
41
43
|
|
|
42
44
|
`bash` 和 `write` 展开时**一次按键直接显示完整输出**——跳过 Pi 内置预览(bash 的 5 行尾部预览、write 的 10 行预览)。`edit` 展开时使用 Pi **官方渲染**(它没有预览态)。全局 `Ctrl+O` 对这三个工具均无效。
|
|
43
45
|
|
|
@@ -89,6 +91,11 @@ Pi 会在终端支持时协商 [Kitty 键盘协议](https://sw.kovidgoyal.net/ki
|
|
|
89
91
|
|
|
90
92
|
## 更新日志
|
|
91
93
|
|
|
94
|
+
### 0.2.1
|
|
95
|
+
|
|
96
|
+
- 支持在 Pi fullscreen 模式下点击单个 bash/edit/write 工具块,在紧凑摘要和完整渲染之间切换
|
|
97
|
+
- 保留工具级快捷键;快捷键会统一设置同类工具块
|
|
98
|
+
|
|
92
99
|
### 0.2.0 - 2026-09-05
|
|
93
100
|
|
|
94
101
|
- 默认三工具全折叠(edit/write 原默认展开)
|
package/package.json
CHANGED
package/tidy-tools.ts
CHANGED
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
* Overrides the TUI rendering of bash, edit and write while delegating
|
|
5
5
|
* execution to the official implementations:
|
|
6
6
|
* - Collapsed: show a small summary with an ellipsis for long content.
|
|
7
|
-
* - Expanded:
|
|
8
|
-
*
|
|
7
|
+
* - Expanded: click an individual tool block in fullscreen mode, or use
|
|
8
|
+
* Ctrl+Alt+E (edit), Ctrl+Alt+W (write), Ctrl+Alt+B (bash) for all rows
|
|
9
|
+
* of that tool, to toggle collapsed and fully expanded rendering.
|
|
9
10
|
* - The global Ctrl+O tool expansion does not affect these three tools.
|
|
10
11
|
* - Modes: compact (default, all three collapsed) and markdown
|
|
11
12
|
* (`/tidy-markdown` toggles; edit/write on Markdown files expand,
|
|
@@ -26,6 +27,7 @@ import type { EditToolDetails } from "@earendil-works/pi-coding-agent";
|
|
|
26
27
|
import {
|
|
27
28
|
Box,
|
|
28
29
|
Container,
|
|
30
|
+
MouseRegion,
|
|
29
31
|
Text,
|
|
30
32
|
type Component,
|
|
31
33
|
sliceByColumn,
|
|
@@ -216,6 +218,9 @@ function getCollapsedBackground(isPartial: boolean, isError: boolean): string {
|
|
|
216
218
|
let markdownMode = false;
|
|
217
219
|
// 手动钉选:Ctrl+Alt+? 或 /tidy-<tool> 设置,优先于模式默认;切换模式时清空。
|
|
218
220
|
const manualExpanded = new Map<string, boolean>();
|
|
221
|
+
// Per-tool revisions let a mode or tool-wide toggle replace row-local clicks
|
|
222
|
+
// without disturbing clicked rows belonging to the other tools.
|
|
223
|
+
const expansionRevisions = new Map<string, number>();
|
|
219
224
|
|
|
220
225
|
function isMarkdownPath(value: unknown): boolean {
|
|
221
226
|
if (typeof value !== "string") return false;
|
|
@@ -239,8 +244,34 @@ function modeDefaultExpanded(name: string, args: any): boolean {
|
|
|
239
244
|
return false;
|
|
240
245
|
}
|
|
241
246
|
|
|
242
|
-
|
|
243
|
-
|
|
247
|
+
interface RowExpansionState {
|
|
248
|
+
revision: number;
|
|
249
|
+
override?: boolean;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function getRowExpansionState(name: string, context: any): RowExpansionState {
|
|
253
|
+
const revision = expansionRevisions.get(name) ?? 0;
|
|
254
|
+
let state = context.state.tidyExpansion as RowExpansionState | undefined;
|
|
255
|
+
if (!state || state.revision !== revision) {
|
|
256
|
+
state = { revision };
|
|
257
|
+
context.state.tidyExpansion = state;
|
|
258
|
+
}
|
|
259
|
+
return state;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
function isToolExpanded(name: string, args: any, context: any): boolean {
|
|
263
|
+
const rowState = getRowExpansionState(name, context);
|
|
264
|
+
return rowState.override ?? manualExpanded.get(name) ?? modeDefaultExpanded(name, args);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
function makeToolClickable(component: Component, name: string, args: any, context: any): Component {
|
|
268
|
+
return new MouseRegion(component, (event) => {
|
|
269
|
+
if (event.type !== "click" || event.button !== "left") return undefined;
|
|
270
|
+
const rowState = getRowExpansionState(name, context);
|
|
271
|
+
rowState.override = !isToolExpanded(name, args, context);
|
|
272
|
+
context.invalidate();
|
|
273
|
+
return { handled: true };
|
|
274
|
+
});
|
|
244
275
|
}
|
|
245
276
|
|
|
246
277
|
// Some terminals (Kitty keyboard protocol flag-1 mode) encode Ctrl+letter as
|
|
@@ -286,6 +317,7 @@ function refreshToolRows(ctx: ExtensionContext): void {
|
|
|
286
317
|
|
|
287
318
|
function toggleToolExpanded(ctx: ExtensionContext, name: string): void {
|
|
288
319
|
manualExpanded.set(name, !(manualExpanded.get(name) ?? modeBaseExpanded(name)));
|
|
320
|
+
expansionRevisions.set(name, (expansionRevisions.get(name) ?? 0) + 1);
|
|
289
321
|
refreshToolRows(ctx);
|
|
290
322
|
ctx.ui.notify(`${name}: ${manualExpanded.get(name) ? "expanded" : "collapsed"}`, "info");
|
|
291
323
|
}
|
|
@@ -350,8 +382,8 @@ function registerCollapsibleTool(
|
|
|
350
382
|
|
|
351
383
|
renderCall(args, theme, context) {
|
|
352
384
|
const def = getDef(context.cwd);
|
|
353
|
-
if (isToolExpanded(def.name, args) && def.renderCall) {
|
|
354
|
-
|
|
385
|
+
if (isToolExpanded(def.name, args, context) && def.renderCall) {
|
|
386
|
+
const component = def.renderCall(
|
|
355
387
|
args as never,
|
|
356
388
|
theme as never,
|
|
357
389
|
// One-key full expansion: skip the official preview so
|
|
@@ -362,9 +394,10 @@ function registerCollapsibleTool(
|
|
|
362
394
|
lastComponent: undefined,
|
|
363
395
|
} as never,
|
|
364
396
|
);
|
|
397
|
+
return makeToolClickable(component, def.name, args, context);
|
|
365
398
|
}
|
|
366
399
|
const component = collapsedCall(args, theme);
|
|
367
|
-
if (!usesSelfShell) return component;
|
|
400
|
+
if (!usesSelfShell) return makeToolClickable(component, def.name, args, context);
|
|
368
401
|
|
|
369
402
|
const shell = getCollapsedToolShell(
|
|
370
403
|
context.state,
|
|
@@ -372,21 +405,22 @@ function registerCollapsibleTool(
|
|
|
372
405
|
getCollapsedBackground(context.isPartial, context.isError),
|
|
373
406
|
);
|
|
374
407
|
shell.setCall(component);
|
|
375
|
-
return shell;
|
|
408
|
+
return makeToolClickable(shell, def.name, args, context);
|
|
376
409
|
},
|
|
377
410
|
|
|
378
411
|
renderResult(result, options, theme, context) {
|
|
379
412
|
const def = getDef(context.cwd);
|
|
380
|
-
if (isToolExpanded(def.name, context.args) && def.renderResult) {
|
|
381
|
-
|
|
413
|
+
if (isToolExpanded(def.name, context.args, context) && def.renderResult) {
|
|
414
|
+
const component = def.renderResult(
|
|
382
415
|
result as never,
|
|
383
416
|
{ ...options, ...(forceFullExpansion ? { expanded: true } : {}) } as never,
|
|
384
417
|
theme as never,
|
|
385
418
|
{ ...context, lastComponent: undefined } as never,
|
|
386
419
|
);
|
|
420
|
+
return makeToolClickable(component, def.name, context.args, context);
|
|
387
421
|
}
|
|
388
422
|
const component = collapsedResult(result, options, theme, context);
|
|
389
|
-
if (!usesSelfShell) return component;
|
|
423
|
+
if (!usesSelfShell) return makeToolClickable(component, def.name, context.args, context);
|
|
390
424
|
|
|
391
425
|
const shell = getCollapsedToolShell(
|
|
392
426
|
context.state,
|
|
@@ -436,16 +470,17 @@ export default function (pi: ExtensionAPI) {
|
|
|
436
470
|
},
|
|
437
471
|
|
|
438
472
|
renderCall(args, theme, context) {
|
|
439
|
-
if (isToolExpanded("bash", args)) {
|
|
473
|
+
if (isToolExpanded("bash", args, context)) {
|
|
440
474
|
const def = getBashDef(context.cwd);
|
|
441
475
|
if (def.renderCall) {
|
|
442
|
-
|
|
476
|
+
const component = def.renderCall(
|
|
443
477
|
args as never,
|
|
444
478
|
theme as never,
|
|
445
479
|
// One-key full expansion for bash: skip the official
|
|
446
480
|
// preview so Ctrl+Alt+B shows the complete output.
|
|
447
481
|
{ ...context, expanded: true, lastComponent: undefined } as never,
|
|
448
482
|
);
|
|
483
|
+
return makeToolClickable(component, "bash", args, context);
|
|
449
484
|
}
|
|
450
485
|
}
|
|
451
486
|
|
|
@@ -455,18 +490,18 @@ export default function (pi: ExtensionAPI) {
|
|
|
455
490
|
const timeoutSuffix = timeout ? theme.fg("muted", ` (timeout ${timeout}s)`) : "";
|
|
456
491
|
const renderedCommand = theme.fg("toolTitle", theme.bold(`$ ${command}`)) + timeoutSuffix;
|
|
457
492
|
|
|
458
|
-
return new LimitedLinesText(
|
|
493
|
+
return makeToolClickable(new LimitedLinesText(
|
|
459
494
|
renderedCommand,
|
|
460
495
|
MAX_COLLAPSED_COMMAND_LINES,
|
|
461
496
|
theme.fg("muted", "..."),
|
|
462
|
-
);
|
|
497
|
+
), "bash", args, context);
|
|
463
498
|
},
|
|
464
499
|
|
|
465
500
|
renderResult(result, options, theme, context) {
|
|
466
|
-
if (isToolExpanded("bash", context.args)) {
|
|
501
|
+
if (isToolExpanded("bash", context.args, context)) {
|
|
467
502
|
const def = getBashDef(context.cwd);
|
|
468
503
|
if (def.renderResult) {
|
|
469
|
-
|
|
504
|
+
const component = def.renderResult(
|
|
470
505
|
result as never,
|
|
471
506
|
// One-key full expansion for bash: skip the official
|
|
472
507
|
// preview so Ctrl+Alt+B shows the complete output.
|
|
@@ -474,9 +509,11 @@ export default function (pi: ExtensionAPI) {
|
|
|
474
509
|
theme as never,
|
|
475
510
|
{ ...context, lastComponent: undefined } as never,
|
|
476
511
|
);
|
|
512
|
+
return makeToolClickable(component, "bash", context.args, context);
|
|
477
513
|
}
|
|
478
514
|
}
|
|
479
515
|
|
|
516
|
+
const clickable = (component: Component) => makeToolClickable(component, "bash", context.args, context);
|
|
480
517
|
const output = expandTabs(errorText(result).trim().replace(/\r/g, ""));
|
|
481
518
|
const allLines = output.split("\n");
|
|
482
519
|
const first = allLines[0] ?? "";
|
|
@@ -487,32 +524,32 @@ export default function (pi: ExtensionAPI) {
|
|
|
487
524
|
// 失败输出同样压成 1 行:红色首行 + 内联计数,与成功态同形。
|
|
488
525
|
if (context.isError) {
|
|
489
526
|
if (!first) {
|
|
490
|
-
return new CollapsedBashOutput(
|
|
527
|
+
return clickable(new CollapsedBashOutput(
|
|
491
528
|
theme.fg("error", "failed"),
|
|
492
529
|
"",
|
|
493
530
|
theme.fg("muted", "..."),
|
|
494
|
-
);
|
|
531
|
+
));
|
|
495
532
|
}
|
|
496
|
-
return new CollapsedBashOutput(
|
|
533
|
+
return clickable(new CollapsedBashOutput(
|
|
497
534
|
theme.fg("error", first),
|
|
498
535
|
moreSuffix,
|
|
499
536
|
theme.fg("muted", "..."),
|
|
500
|
-
);
|
|
537
|
+
));
|
|
501
538
|
}
|
|
502
539
|
// Preview only the first line. Wrapping the full output on every
|
|
503
540
|
// frame is what made the TUI lag with large outputs.
|
|
504
541
|
if (!first) {
|
|
505
|
-
return new CollapsedBashOutput(
|
|
542
|
+
return clickable(new CollapsedBashOutput(
|
|
506
543
|
theme.fg("muted", "(no output)"),
|
|
507
544
|
"",
|
|
508
545
|
theme.fg("muted", "..."),
|
|
509
|
-
);
|
|
546
|
+
));
|
|
510
547
|
}
|
|
511
|
-
return new CollapsedBashOutput(
|
|
548
|
+
return clickable(new CollapsedBashOutput(
|
|
512
549
|
theme.fg("toolOutput", first),
|
|
513
550
|
moreSuffix,
|
|
514
551
|
theme.fg("muted", "..."),
|
|
515
|
-
);
|
|
552
|
+
));
|
|
516
553
|
},
|
|
517
554
|
});
|
|
518
555
|
|
|
@@ -589,6 +626,9 @@ export default function (pi: ExtensionAPI) {
|
|
|
589
626
|
handler: async (_args, ctx) => {
|
|
590
627
|
markdownMode = !markdownMode;
|
|
591
628
|
manualExpanded.clear();
|
|
629
|
+
for (const name of ["bash", "edit", "write"]) {
|
|
630
|
+
expansionRevisions.set(name, (expansionRevisions.get(name) ?? 0) + 1);
|
|
631
|
+
}
|
|
592
632
|
refreshToolRows(ctx);
|
|
593
633
|
ctx.ui.notify(`markdown mode: ${markdownMode ? "on" : "off"}`, "info");
|
|
594
634
|
},
|