@herbertgao/pi-extensions 2026.9.19 → 2026.9.20

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 (186) hide show
  1. package/README.md +1 -8
  2. package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +76 -59
  3. package/node_modules/@herbertgao/pi-cc-extensions/README.md +76 -59
  4. package/node_modules/@herbertgao/pi-cc-extensions/assets/readme/preview.webp +0 -0
  5. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +93 -34
  6. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +346 -117
  7. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/agent-summary/core.ts +6 -36
  8. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/agent-summary/index.ts +2 -2
  9. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/compact-thinking.ts +24 -29
  10. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/context.ts +330 -360
  11. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/reference/index.ts +56 -108
  12. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/reference/session.ts +97 -15
  13. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/reference/subagent.ts +80 -45
  14. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/shell/flush-docked-bash.ts +36 -0
  15. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/shell/footer-layout.ts +229 -0
  16. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/shell/footer.ts +479 -0
  17. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/shell/startup-header.ts +92 -61
  18. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/shell/working-message.ts +58 -38
  19. package/node_modules/@herbertgao/pi-cc-extensions/extensions/index.ts +19 -3
  20. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +1080 -229
  21. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/default-mode.ts +232 -259
  22. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/index.ts +38 -48
  23. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/markdown-enhance.ts +8 -2
  24. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/hover.ts +2 -7
  25. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/interaction.ts +277 -113
  26. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/layout.ts +15 -6
  27. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/packets.ts +18 -72
  28. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/scroll.ts +61 -26
  29. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/ansi-utils.ts +25 -57
  30. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-component.ts +125 -0
  31. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-edit-render.ts +227 -0
  32. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-header.ts +136 -0
  33. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-highlight.ts +115 -0
  34. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-inline.ts +324 -0
  35. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-layout.ts +762 -0
  36. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-limits.ts +152 -0
  37. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-palette.ts +410 -0
  38. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-parse.ts +535 -0
  39. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-presentation.ts +2 -2
  40. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-renderer.ts +21 -3219
  41. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-text.ts +44 -0
  42. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-write-render.ts +568 -0
  43. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/index.ts +19 -18
  44. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/line-width-safety.ts +2 -2
  45. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/write-execution.ts +1 -0
  46. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/grouping.ts +142 -192
  47. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/mcp-title.ts +39 -0
  48. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{message-display.ts → tool/message-display.ts} +24 -90
  49. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/names.ts +426 -0
  50. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/result.ts +90 -132
  51. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{show-more-hint.ts → tool/show-more-hint.ts} +10 -0
  52. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/transcript-refresh.ts +8 -26
  53. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/ansi-color.ts +44 -0
  54. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/ansi-text.ts +76 -0
  55. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/component-tree.ts +34 -0
  56. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/format.ts +28 -0
  57. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/fullscreen-detect.ts +51 -0
  58. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/patch-keys.ts +124 -0
  59. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/sgr-mouse.ts +70 -0
  60. package/node_modules/@herbertgao/pi-cc-extensions/package.json +7 -7
  61. package/package.json +3 -7
  62. package/node_modules/@herbertgao/pi-cc-extensions/assets/readme/hero.en.svg +0 -101
  63. package/node_modules/@herbertgao/pi-cc-extensions/assets/readme/hero.svg +0 -101
  64. package/node_modules/@herbertgao/pi-cc-extensions/assets/readme/welcome.webp +0 -0
  65. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/render-utils.ts +0 -5
  66. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/types.ts +0 -30
  67. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/write-display-utils.ts +0 -12
  68. package/node_modules/pi-footer/CHANGELOG.md +0 -145
  69. package/node_modules/pi-footer/LICENSE +0 -21
  70. package/node_modules/pi-footer/README.md +0 -354
  71. package/node_modules/pi-footer/package.json +0 -68
  72. package/node_modules/pi-footer/src/cache.ts +0 -106
  73. package/node_modules/pi-footer/src/colors.ts +0 -237
  74. package/node_modules/pi-footer/src/config.ts +0 -202
  75. package/node_modules/pi-footer/src/event-widgets.ts +0 -41
  76. package/node_modules/pi-footer/src/extension-statuses.ts +0 -102
  77. package/node_modules/pi-footer/src/git.ts +0 -135
  78. package/node_modules/pi-footer/src/index.ts +0 -268
  79. package/node_modules/pi-footer/src/metrics.ts +0 -141
  80. package/node_modules/pi-footer/src/presets.ts +0 -383
  81. package/node_modules/pi-footer/src/render.ts +0 -114
  82. package/node_modules/pi-footer/src/separators.ts +0 -52
  83. package/node_modules/pi-footer/src/types.ts +0 -122
  84. package/node_modules/pi-footer/src/ui/color-level-confirm.ts +0 -22
  85. package/node_modules/pi-footer/src/ui/color-options.ts +0 -195
  86. package/node_modules/pi-footer/src/ui/config-lifecycle.ts +0 -61
  87. package/node_modules/pi-footer/src/ui/edit-colors.ts +0 -13
  88. package/node_modules/pi-footer/src/ui/events.ts +0 -35
  89. package/node_modules/pi-footer/src/ui/extension-status-picker.ts +0 -60
  90. package/node_modules/pi-footer/src/ui/extension-statuses.ts +0 -73
  91. package/node_modules/pi-footer/src/ui/fields.ts +0 -252
  92. package/node_modules/pi-footer/src/ui/global-menu.ts +0 -126
  93. package/node_modules/pi-footer/src/ui/helpers.ts +0 -44
  94. package/node_modules/pi-footer/src/ui/layout.ts +0 -17
  95. package/node_modules/pi-footer/src/ui/line-list.ts +0 -19
  96. package/node_modules/pi-footer/src/ui/model.ts +0 -64
  97. package/node_modules/pi-footer/src/ui/navigation.ts +0 -29
  98. package/node_modules/pi-footer/src/ui/option-edit.ts +0 -93
  99. package/node_modules/pi-footer/src/ui/overlay-render.ts +0 -103
  100. package/node_modules/pi-footer/src/ui/screen-context.ts +0 -18
  101. package/node_modules/pi-footer/src/ui/screen-controller.ts +0 -27
  102. package/node_modules/pi-footer/src/ui/screen-render.ts +0 -32
  103. package/node_modules/pi-footer/src/ui/screen-state.ts +0 -20
  104. package/node_modules/pi-footer/src/ui/screen.ts +0 -243
  105. package/node_modules/pi-footer/src/ui/screens/add-widget.ts +0 -92
  106. package/node_modules/pi-footer/src/ui/screens/confirm-exit.ts +0 -52
  107. package/node_modules/pi-footer/src/ui/screens/controller.ts +0 -12
  108. package/node_modules/pi-footer/src/ui/screens/edit-colors.ts +0 -68
  109. package/node_modules/pi-footer/src/ui/screens/edit-widget.ts +0 -115
  110. package/node_modules/pi-footer/src/ui/screens/extension-status-row.ts +0 -61
  111. package/node_modules/pi-footer/src/ui/screens/global.ts +0 -75
  112. package/node_modules/pi-footer/src/ui/screens/line-list.ts +0 -108
  113. package/node_modules/pi-footer/src/ui/screens/main.ts +0 -99
  114. package/node_modules/pi-footer/src/ui/screens/terminal.ts +0 -121
  115. package/node_modules/pi-footer/src/ui/screens/widget-list.ts +0 -154
  116. package/node_modules/pi-footer/src/ui/terminal-menu.ts +0 -32
  117. package/node_modules/pi-footer/src/ui/theme.ts +0 -48
  118. package/node_modules/pi-footer/src/ui/title-bar.ts +0 -100
  119. package/node_modules/pi-footer/src/ui/widget-actions.ts +0 -76
  120. package/node_modules/pi-footer/src/ui.ts +0 -66
  121. package/node_modules/pi-footer/src/widgets/context.ts +0 -28
  122. package/node_modules/pi-footer/src/widgets/core/active-tools.ts +0 -17
  123. package/node_modules/pi-footer/src/widgets/core/context-window.ts +0 -24
  124. package/node_modules/pi-footer/src/widgets/core/cwd-basename.ts +0 -19
  125. package/node_modules/pi-footer/src/widgets/core/cwd.ts +0 -108
  126. package/node_modules/pi-footer/src/widgets/core/event.ts +0 -34
  127. package/node_modules/pi-footer/src/widgets/core/external-status.ts +0 -102
  128. package/node_modules/pi-footer/src/widgets/core/model-provider.ts +0 -20
  129. package/node_modules/pi-footer/src/widgets/core/model.ts +0 -35
  130. package/node_modules/pi-footer/src/widgets/core/provider.ts +0 -17
  131. package/node_modules/pi-footer/src/widgets/core/session-name.ts +0 -17
  132. package/node_modules/pi-footer/src/widgets/core/text-verbosity.ts +0 -17
  133. package/node_modules/pi-footer/src/widgets/core/thinking-level.ts +0 -17
  134. package/node_modules/pi-footer/src/widgets/git/ahead-behind.ts +0 -17
  135. package/node_modules/pi-footer/src/widgets/git/branch.ts +0 -81
  136. package/node_modules/pi-footer/src/widgets/git/clean.ts +0 -19
  137. package/node_modules/pi-footer/src/widgets/git/deletions.ts +0 -17
  138. package/node_modules/pi-footer/src/widgets/git/diff.ts +0 -38
  139. package/node_modules/pi-footer/src/widgets/git/insertions.ts +0 -17
  140. package/node_modules/pi-footer/src/widgets/git/remote.ts +0 -17
  141. package/node_modules/pi-footer/src/widgets/git/root.ts +0 -17
  142. package/node_modules/pi-footer/src/widgets/git/sha.ts +0 -17
  143. package/node_modules/pi-footer/src/widgets/git/staged.ts +0 -17
  144. package/node_modules/pi-footer/src/widgets/git/status.ts +0 -19
  145. package/node_modules/pi-footer/src/widgets/git/unstaged.ts +0 -17
  146. package/node_modules/pi-footer/src/widgets/git/untracked.ts +0 -17
  147. package/node_modules/pi-footer/src/widgets/instance.ts +0 -118
  148. package/node_modules/pi-footer/src/widgets/layout/custom-text.ts +0 -18
  149. package/node_modules/pi-footer/src/widgets/layout/flex-separator.ts +0 -32
  150. package/node_modules/pi-footer/src/widgets/layout/separator.ts +0 -57
  151. package/node_modules/pi-footer/src/widgets/layout/spacer.ts +0 -31
  152. package/node_modules/pi-footer/src/widgets/options.ts +0 -122
  153. package/node_modules/pi-footer/src/widgets/project/runtime.ts +0 -361
  154. package/node_modules/pi-footer/src/widgets/registry.ts +0 -223
  155. package/node_modules/pi-footer/src/widgets/session/assistant-messages.ts +0 -17
  156. package/node_modules/pi-footer/src/widgets/session/compactions.ts +0 -17
  157. package/node_modules/pi-footer/src/widgets/session/elapsed.ts +0 -18
  158. package/node_modules/pi-footer/src/widgets/session/last-activity.ts +0 -18
  159. package/node_modules/pi-footer/src/widgets/session/messages.ts +0 -19
  160. package/node_modules/pi-footer/src/widgets/session/session-id.ts +0 -17
  161. package/node_modules/pi-footer/src/widgets/session/session-start.ts +0 -18
  162. package/node_modules/pi-footer/src/widgets/session/tool-results.ts +0 -17
  163. package/node_modules/pi-footer/src/widgets/session/total-messages.ts +0 -19
  164. package/node_modules/pi-footer/src/widgets/session/total-time.ts +0 -18
  165. package/node_modules/pi-footer/src/widgets/session/user-messages.ts +0 -17
  166. package/node_modules/pi-footer/src/widgets/store.ts +0 -26
  167. package/node_modules/pi-footer/src/widgets/tokens/cache-hit-rate.ts +0 -55
  168. package/node_modules/pi-footer/src/widgets/tokens/cache-read.ts +0 -18
  169. package/node_modules/pi-footer/src/widgets/tokens/cache-write.ts +0 -18
  170. package/node_modules/pi-footer/src/widgets/tokens/context-bar.ts +0 -108
  171. package/node_modules/pi-footer/src/widgets/tokens/context-length.ts +0 -26
  172. package/node_modules/pi-footer/src/widgets/tokens/context-remaining.ts +0 -29
  173. package/node_modules/pi-footer/src/widgets/tokens/context.ts +0 -29
  174. package/node_modules/pi-footer/src/widgets/tokens/cost.ts +0 -51
  175. package/node_modules/pi-footer/src/widgets/tokens/input-speed.ts +0 -25
  176. package/node_modules/pi-footer/src/widgets/tokens/input-tokens.ts +0 -18
  177. package/node_modules/pi-footer/src/widgets/tokens/output-speed.ts +0 -25
  178. package/node_modules/pi-footer/src/widgets/tokens/output-tokens.ts +0 -18
  179. package/node_modules/pi-footer/src/widgets/tokens/tokens.ts +0 -20
  180. package/node_modules/pi-footer/src/widgets/tokens/total-speed.ts +0 -25
  181. package/node_modules/pi-footer/src/widgets/tokens/total-tokens.ts +0 -18
  182. package/node_modules/pi-footer/src/widgets/types.ts +0 -181
  183. package/node_modules/pi-footer/src/widgets/utils/colors.ts +0 -11
  184. package/node_modules/pi-footer/src/widgets/utils/context.ts +0 -112
  185. package/node_modules/pi-footer/src/widgets/utils/session.ts +0 -19
  186. package/node_modules/pi-footer/src/widgets/utils/token-format.ts +0 -78
@@ -1,17 +0,0 @@
1
- import { defineWidget } from "../types.js";
2
-
3
- export const TextVerbosityWidget = defineWidget({
4
- type: "text-verbosity",
5
- label: "Text Verbosity",
6
- category: "Core",
7
- description: "Text verbosity for models/providers that support it",
8
- dependencies: ["textVerbosity"],
9
- baseOptions: ["raw", "hideWhenEmpty", "icon", "text"],
10
- baseOptionDefaults: { text: "" },
11
- properties: [],
12
- icons: { emoji: "📝", nerd: "󰉿", text: "verbosity" },
13
- defaultStyle: { fg: "cyan", bg: "default", bold: false },
14
- render({ ctx, renderWidget }) {
15
- return renderWidget(ctx.textVerbosity);
16
- },
17
- });
@@ -1,17 +0,0 @@
1
- import { defineWidget } from "../types.js";
2
-
3
- export const ThinkingLevelWidget = defineWidget({
4
- type: "thinking-level",
5
- label: "Thinking Level",
6
- category: "Core",
7
- description: "Pi reasoning/thinking level for reasoning-capable models",
8
- dependencies: ["thinkingLevel"],
9
- baseOptions: ["raw", "hideWhenEmpty", "icon", "text"],
10
- baseOptionDefaults: { text: "" },
11
- properties: [],
12
- icons: { emoji: "🧠", nerd: "󰈈", text: "thinking" },
13
- defaultStyle: { fg: "magenta", bg: "default", bold: false },
14
- render({ ctx, renderWidget }) {
15
- return renderWidget(ctx.thinkingLevel);
16
- },
17
- });
@@ -1,17 +0,0 @@
1
- import { defineWidget } from "../types.js";
2
-
3
- export const GitAheadBehindWidget = defineWidget({
4
- type: "git-ahead-behind",
5
- label: "Git Ahead/Behind",
6
- category: "Git",
7
- description: "Ahead/behind upstream counts",
8
- dependencies: ["git"],
9
- baseOptions: ["raw", "hideWhenEmpty", "icon", "text"],
10
- baseOptionDefaults: { text: "" },
11
- properties: [],
12
- icons: { emoji: "↕️", nerd: "󰦻", text: "upstream" },
13
- defaultStyle: { fg: "cyan", bg: "default", bold: false },
14
- render({ ctx, renderWidget }) {
15
- return renderWidget(ctx.git.isRepo ? `↑${ctx.git.ahead} ↓${ctx.git.behind}` : "");
16
- },
17
- });
@@ -1,81 +0,0 @@
1
- import { defineWidget } from "../types.js";
2
-
3
- const GIT_BRANCH_DISPLAY_STYLES = {
4
- default: {
5
- label: "Default",
6
- list: "default",
7
- },
8
- "round-brackets": {
9
- label: "Round brackets",
10
- list: "brackets",
11
- },
12
- custom: {
13
- label: "Custom surround text",
14
- list: "custom",
15
- },
16
- } as const;
17
-
18
- type GitBranchDisplayStyle = keyof typeof GIT_BRANCH_DISPLAY_STYLES;
19
-
20
- const GIT_BRANCH_DISPLAY_STYLE_VALUES = Object.keys(
21
- GIT_BRANCH_DISPLAY_STYLES,
22
- ) as GitBranchDisplayStyle[];
23
-
24
- export const GitBranchWidget = defineWidget({
25
- type: "git-branch",
26
- label: "Git Branch",
27
- category: "Git",
28
- description: "Current Git branch",
29
- dependencies: ["git"],
30
- baseOptions: ["raw", "hideWhenEmpty", "icon", "text"],
31
- baseOptionDefaults: { text: "" },
32
- properties: [
33
- {
34
- id: "gitBranchDisplayStyle",
35
- label: "Display style",
36
- kind: "choice",
37
- description: "Branch name display style",
38
- default: "default",
39
- options: {
40
- choices: GIT_BRANCH_DISPLAY_STYLE_VALUES.map((style) => ({
41
- id: style,
42
- label: GIT_BRANCH_DISPLAY_STYLES[style].label,
43
- list: GIT_BRANCH_DISPLAY_STYLES[style].list,
44
- })),
45
- showInWidgets: true,
46
- showInColors: false,
47
- listProperty: "display",
48
- },
49
- },
50
- {
51
- id: "surroundLeft",
52
- label: "Surround left",
53
- kind: "text",
54
- description: "Text before the branch name when custom display is enabled",
55
- default: "",
56
- showWhen: { property: "gitBranchDisplayStyle", equals: "custom" },
57
- options: { showInWidgets: false, showInColors: false },
58
- },
59
- {
60
- id: "surroundRight",
61
- label: "Surround right",
62
- kind: "text",
63
- description: "Text after the branch name when custom display is enabled",
64
- default: "",
65
- showWhen: { property: "gitBranchDisplayStyle", equals: "custom" },
66
- options: { showInWidgets: false, showInColors: false },
67
- },
68
- ],
69
- icons: { emoji: "🌿", nerd: "", text: "git" },
70
- defaultStyle: { fg: "magenta", bg: "default", bold: false },
71
- render({ ctx, options, renderWidget }) {
72
- const branch = ctx.git.branch;
73
- if (!branch) return renderWidget("");
74
-
75
- if (options.gitBranchDisplayStyle === "round-brackets") return renderWidget(`(${branch})`);
76
- if (options.gitBranchDisplayStyle === "custom") {
77
- return renderWidget(`${options.surroundLeft}${branch}${options.surroundRight}`);
78
- }
79
- return renderWidget(branch);
80
- },
81
- });
@@ -1,19 +0,0 @@
1
- import { defineWidget } from "../types.js";
2
-
3
- export const GitCleanStatusWidget = defineWidget({
4
- type: "git-clean",
5
- label: "Git Clean Status",
6
- category: "Git",
7
- description: "Clean/dirty state",
8
- dependencies: ["git"],
9
- baseOptions: ["raw", "hideWhenEmpty", "icon", "text"],
10
- baseOptionDefaults: { text: "" },
11
- properties: [],
12
- icons: { emoji: "✅", nerd: "󰄬", text: "git" },
13
- defaultStyle: { fg: "green", bg: "default", bold: false },
14
- render({ ctx, renderWidget }) {
15
- if (!ctx.git.isRepo) return renderWidget("");
16
- const changes = ctx.git.staged + ctx.git.unstaged + ctx.git.untracked;
17
- return renderWidget(changes === 0 ? "clean" : "dirty");
18
- },
19
- });
@@ -1,17 +0,0 @@
1
- import { defineWidget } from "../types.js";
2
-
3
- export const GitDeletionsWidget = defineWidget({
4
- type: "git-deletions",
5
- label: "Git Deletions",
6
- category: "Git",
7
- description: "Uncommitted deletion count",
8
- dependencies: ["git"],
9
- baseOptions: ["raw", "hideWhenZero", "icon", "text"],
10
- baseOptionDefaults: { text: "" },
11
- properties: [],
12
- icons: { emoji: "➖", nerd: "-", text: "del" },
13
- defaultStyle: { fg: "red", bg: "default", bold: false },
14
- render({ ctx, renderWidget }) {
15
- return renderWidget(`${ctx.git.deletions}`);
16
- },
17
- });
@@ -1,38 +0,0 @@
1
- import { defineWidget } from "../types.js";
2
-
3
- export const GitDiffWidget = defineWidget({
4
- type: "git-diff",
5
- label: "Git Diff",
6
- category: "Git",
7
- description: "Insertion/deletion diff summary",
8
- dependencies: ["git"],
9
- baseOptions: ["raw", "hideWhenEmpty", "icon", "text"],
10
- baseOptionDefaults: { text: "" },
11
- properties: [
12
- {
13
- id: "gitDiffMode",
14
- label: "Display",
15
- kind: "choice",
16
- description: "Git diff display mode",
17
- default: "plain",
18
- options: {
19
- choices: [
20
- { id: "plain", label: "Plain (+/-)", list: "Plain (+/-)" },
21
- { id: "compact", label: "Compact (+n,-n)", list: "Compact (+n,-n)" },
22
- ],
23
- showInWidgets: true,
24
- showInColors: false,
25
- listProperty: "display",
26
- },
27
- },
28
- ],
29
- icons: { emoji: "📈", nerd: "", text: "diff" },
30
- defaultStyle: { fg: "yellow", bg: "default", bold: false },
31
- render({ ctx, options, renderWidget }) {
32
- return renderWidget(
33
- options.gitDiffMode === "compact"
34
- ? `(+${ctx.git.insertions},-${ctx.git.deletions})`
35
- : `+${ctx.git.insertions}/-${ctx.git.deletions}`,
36
- );
37
- },
38
- });
@@ -1,17 +0,0 @@
1
- import { defineWidget } from "../types.js";
2
-
3
- export const GitInsertionsWidget = defineWidget({
4
- type: "git-insertions",
5
- label: "Git Insertions",
6
- category: "Git",
7
- description: "Uncommitted insertion count",
8
- dependencies: ["git"],
9
- baseOptions: ["raw", "hideWhenZero", "icon", "text"],
10
- baseOptionDefaults: { text: "" },
11
- properties: [],
12
- icons: { emoji: "➕", nerd: "+", text: "ins" },
13
- defaultStyle: { fg: "green", bg: "default", bold: false },
14
- render({ ctx, renderWidget }) {
15
- return renderWidget(`${ctx.git.insertions}`);
16
- },
17
- });
@@ -1,17 +0,0 @@
1
- import { defineWidget } from "../types.js";
2
-
3
- export const GitRemoteWidget = defineWidget({
4
- type: "git-remote",
5
- label: "Git Remote",
6
- category: "Git",
7
- description: "Origin remote",
8
- dependencies: ["git"],
9
- baseOptions: ["raw", "hideWhenEmpty", "icon", "text"],
10
- baseOptionDefaults: { text: "" },
11
- properties: [],
12
- icons: { emoji: "🌐", nerd: "󰊢", text: "remote" },
13
- defaultStyle: { fg: "cyan", bg: "default", bold: false },
14
- render({ ctx, renderWidget }) {
15
- return renderWidget(ctx.git.remote ?? "");
16
- },
17
- });
@@ -1,17 +0,0 @@
1
- import { defineWidget } from "../types.js";
2
-
3
- export const GitRootDirWidget = defineWidget({
4
- type: "git-root",
5
- label: "Git Root Dir",
6
- category: "Git",
7
- description: "Repository root directory name",
8
- dependencies: ["git"],
9
- baseOptions: ["raw", "hideWhenEmpty", "icon", "text"],
10
- baseOptionDefaults: { text: "" },
11
- properties: [],
12
- icons: { emoji: "📦", nerd: "", text: "repo" },
13
- defaultStyle: { fg: "cyan", bg: "default", bold: false },
14
- render({ ctx, renderWidget }) {
15
- return renderWidget(ctx.git.root ?? "");
16
- },
17
- });
@@ -1,17 +0,0 @@
1
- import { defineWidget } from "../types.js";
2
-
3
- export const GitShaWidget = defineWidget({
4
- type: "git-sha",
5
- label: "Git SHA",
6
- category: "Git",
7
- description: "Short HEAD commit SHA",
8
- dependencies: ["git"],
9
- baseOptions: ["raw", "hideWhenEmpty", "icon", "text"],
10
- baseOptionDefaults: { text: "" },
11
- properties: [],
12
- icons: { emoji: "🔖", nerd: "", text: "sha" },
13
- defaultStyle: { fg: "brightBlack", bg: "default", bold: false },
14
- render({ ctx, renderWidget }) {
15
- return renderWidget(ctx.git.sha ?? "");
16
- },
17
- });
@@ -1,17 +0,0 @@
1
- import { defineWidget } from "../types.js";
2
-
3
- export const GitStagedWidget = defineWidget({
4
- type: "git-staged",
5
- label: "Git Staged Files",
6
- category: "Git",
7
- description: "Staged file count",
8
- dependencies: ["git"],
9
- baseOptions: ["raw", "hideWhenZero", "icon", "text"],
10
- baseOptionDefaults: { text: "" },
11
- properties: [],
12
- icons: { emoji: "➕", nerd: "+", text: "staged" },
13
- defaultStyle: { fg: "green", bg: "default", bold: false },
14
- render({ ctx, renderWidget }) {
15
- return renderWidget(`${ctx.git.staged}`);
16
- },
17
- });
@@ -1,19 +0,0 @@
1
- import { defineWidget } from "../types.js";
2
-
3
- export const GitStatusWidget = defineWidget({
4
- type: "git-status",
5
- label: "Git Status",
6
- category: "Git",
7
- description: "Staged/unstaged/untracked counts",
8
- dependencies: ["git"],
9
- baseOptions: ["raw", "hideWhenEmpty", "icon", "text"],
10
- baseOptionDefaults: { text: "" },
11
- properties: [],
12
- icons: { emoji: "🔀", nerd: "", text: "git" },
13
- defaultStyle: { fg: "yellow", bg: "default", bold: false },
14
- render({ ctx, renderWidget }) {
15
- return renderWidget(
16
- ctx.git.isRepo ? `+${ctx.git.staged} ±${ctx.git.unstaged} ?${ctx.git.untracked}` : "",
17
- );
18
- },
19
- });
@@ -1,17 +0,0 @@
1
- import { defineWidget } from "../types.js";
2
-
3
- export const GitUnstagedWidget = defineWidget({
4
- type: "git-unstaged",
5
- label: "Git Unstaged Files",
6
- category: "Git",
7
- description: "Unstaged file count",
8
- dependencies: ["git"],
9
- baseOptions: ["raw", "hideWhenZero", "icon", "text"],
10
- baseOptionDefaults: { text: "" },
11
- properties: [],
12
- icons: { emoji: "📝", nerd: "±", text: "unstaged" },
13
- defaultStyle: { fg: "yellow", bg: "default", bold: false },
14
- render({ ctx, renderWidget }) {
15
- return renderWidget(`${ctx.git.unstaged}`);
16
- },
17
- });
@@ -1,17 +0,0 @@
1
- import { defineWidget } from "../types.js";
2
-
3
- export const GitUntrackedWidget = defineWidget({
4
- type: "git-untracked",
5
- label: "Git Untracked Files",
6
- category: "Git",
7
- description: "Untracked file count",
8
- dependencies: ["git"],
9
- baseOptions: ["raw", "hideWhenZero", "icon", "text"],
10
- baseOptionDefaults: { text: "" },
11
- properties: [],
12
- icons: { emoji: "❓", nerd: "?", text: "untracked" },
13
- defaultStyle: { fg: "red", bg: "default", bold: false },
14
- render({ ctx, renderWidget }) {
15
- return renderWidget(`${ctx.git.untracked}`);
16
- },
17
- });
@@ -1,118 +0,0 @@
1
- import { applyColors, stripAnsi } from "../colors.js";
2
- import type { WidgetEntry, WidgetOptions } from "../types.js";
3
- import type { WidgetSpecUnion } from "./registry.js";
4
- import type {
5
- BaseWidgetContext,
6
- ContextFor,
7
- OptionsFor,
8
- TypedWidgetRenderArgs,
9
- Widget,
10
- WidgetContext,
11
- WidgetRenderOptions,
12
- } from "./types.js";
13
-
14
- export class WidgetInstance<TSpec extends WidgetSpecUnion = WidgetSpecUnion> implements Widget {
15
- constructor(
16
- readonly spec: TSpec,
17
- readonly entry: WidgetEntry,
18
- ) {}
19
-
20
- get id(): string {
21
- return this.entry.id;
22
- }
23
-
24
- get type(): WidgetEntry["type"] {
25
- return this.entry.type;
26
- }
27
-
28
- get enabled(): boolean {
29
- return this.entry.enabled;
30
- }
31
-
32
- set enabled(value: boolean) {
33
- this.entry.enabled = value;
34
- }
35
-
36
- get options(): WidgetOptions {
37
- return this.entry.options;
38
- }
39
-
40
- set options(value: WidgetOptions) {
41
- this.entry.options = value;
42
- }
43
-
44
- // TODO(widget-spec): remove casts once render context and hydrated entries preserve concrete spec types.
45
- render(ctx: WidgetContext): string | undefined {
46
- const spec = this.spec as unknown as TSpec & {
47
- render(args: TypedWidgetRenderArgs<TSpec>): string | undefined;
48
- };
49
- return spec.render({
50
- ctx: ctx as ContextFor<TSpec>,
51
- options: this.options as OptionsFor<TSpec>,
52
- renderWidget: (value, renderOptions) => {
53
- return renderWidgetValue(this.entry, value, ctx, {
54
- ...renderOptions,
55
- icons: renderOptions?.icons ?? this.spec.icons,
56
- });
57
- },
58
- });
59
- }
60
-
61
- toggle(enabled = !this.enabled): void {
62
- this.enabled = enabled;
63
- }
64
-
65
- update(options: Partial<WidgetOptions>): void {
66
- this.options = { ...this.options, ...options };
67
- }
68
-
69
- toEntry(): WidgetEntry {
70
- return {
71
- id: this.id,
72
- type: this.type,
73
- enabled: this.enabled,
74
- options: { ...this.options },
75
- };
76
- }
77
- }
78
-
79
- function renderWidgetValue(
80
- entry: WidgetEntry,
81
- value: string | undefined,
82
- ctx: BaseWidgetContext,
83
- renderOptions: WidgetRenderOptions = {},
84
- ): string | undefined {
85
- // The persisted option fields the renderer reads (style + base options) — entry.options is
86
- // already WidgetOptions, which is a superset, so no narrowing is needed.
87
- const options = entry.options;
88
- if (!entry.enabled) return undefined;
89
-
90
- const rawValue = value ?? "";
91
- if (rawValue.length === 0 && options.hideWhenEmpty) return undefined;
92
- if (rawValue === "0" && options.hideWhenZero) return undefined;
93
-
94
- const fallbackValue = rawValue.length === 0 ? (options.text ?? "-") : rawValue;
95
- const displayValue = renderOptions.stripIncomingStyles ? stripAnsi(fallbackValue) : fallbackValue;
96
- const label = renderOptions.icons?.[ctx.iconMode];
97
- const unstyled =
98
- options.raw === true || ctx.minimalist
99
- ? displayValue
100
- : options.icon
101
- ? `${options.icon}${displayValue}`
102
- : label
103
- ? `${label} ${displayValue}`
104
- : displayValue;
105
- const styled =
106
- renderOptions.preservedTrimStyles && !renderOptions.stripIncomingStyles
107
- ? `${renderOptions.preservedTrimStyles}${unstyled}`
108
- : unstyled;
109
-
110
- return applyColors(
111
- styled,
112
- renderOptions.fg ?? options.fg,
113
- renderOptions.bg ?? options.bg,
114
- renderOptions.bold ?? options.bold,
115
- ctx.colorLevel,
116
- ctx.theme,
117
- );
118
- }
@@ -1,18 +0,0 @@
1
- import { defineWidget } from "../types.js";
2
-
3
- export const CustomTextWidget = defineWidget({
4
- type: "custom-text",
5
- label: "Custom Text",
6
- category: "Custom/Layout",
7
- description: "User-defined text segment",
8
- dependencies: [],
9
- baseOptions: ["text"],
10
- // Custom text only exposes the shared `text` field, with a widget-specific default.
11
- baseOptionDefaults: { text: "custom" },
12
- properties: [],
13
- icons: { emoji: "", nerd: "", text: "" },
14
- defaultStyle: { fg: "default", bg: "default", bold: false },
15
- render({ options, renderWidget }) {
16
- return renderWidget(options.text);
17
- },
18
- });
@@ -1,32 +0,0 @@
1
- import { defineWidget } from "../types.js";
2
-
3
- export const FlexSeparatorWidget = defineWidget({
4
- type: "flex-separator",
5
- label: "Flex Separator",
6
- category: "Custom/Layout",
7
- description: "Push following widgets to the right",
8
- dependencies: [],
9
- baseOptions: [],
10
- baseOptionDefaults: {},
11
- properties: [
12
- {
13
- id: "hideWhenEmpty",
14
- label: "Hide when empty",
15
- kind: "boolean",
16
- description: "Hide empty flex separator output",
17
- default: true,
18
- options: {
19
- // Hidden implementation detail: flex separators are structural and should not render text,
20
- // while the visible UI remains only Enabled as it was before migration.
21
- showInFields: false,
22
- showInWidgets: false,
23
- showInColors: false,
24
- },
25
- },
26
- ],
27
- icons: { emoji: "", nerd: "", text: "" },
28
- defaultStyle: { fg: "default", bg: "default", bold: false },
29
- render({ renderWidget }) {
30
- return renderWidget("");
31
- },
32
- });
@@ -1,57 +0,0 @@
1
- import { WIDGET_SEPARATOR_VALUES, widgetSeparatorText } from "../../separators.js";
2
- import { defineWidget } from "../types.js";
3
-
4
- export const SeparatorWidget = defineWidget({
5
- type: "separator",
6
- label: "Separator",
7
- category: "Custom/Layout",
8
- description: "Predefined or custom separator segment",
9
- dependencies: [],
10
- baseOptions: [],
11
- baseOptionDefaults: {},
12
- properties: [
13
- {
14
- id: "hideWhenEmpty",
15
- label: "Hide when empty",
16
- kind: "boolean",
17
- description: "Hide empty separator output",
18
- default: true,
19
- options: {
20
- // Hidden implementation detail: `separator=none` and empty custom text must render no segment,
21
- // while the visible UI remains only Enabled/Separator/Text as it was before migration.
22
- showInFields: false,
23
- showInWidgets: false,
24
- showInColors: false,
25
- },
26
- },
27
- {
28
- id: "separator",
29
- label: "Separator",
30
- kind: "choice",
31
- description: "Separator style",
32
- default: "pipe",
33
- options: {
34
- choices: WIDGET_SEPARATOR_VALUES.map((id) => ({ id, label: id, list: id })),
35
- listProperty: "separator",
36
- showInColors: true,
37
- },
38
- },
39
- {
40
- id: "text",
41
- label: "Text",
42
- kind: "text",
43
- description: "Custom separator text",
44
- default: "|",
45
- showWhen: { property: "separator", equals: "custom" },
46
- options: {
47
- quoteValue: true,
48
- showInColors: true,
49
- },
50
- },
51
- ],
52
- icons: { emoji: "", nerd: "", text: "" },
53
- defaultStyle: { fg: "default", bg: "default", bold: false },
54
- render({ options, renderWidget }) {
55
- return renderWidget(widgetSeparatorText(options.separator, options.text));
56
- },
57
- });
@@ -1,31 +0,0 @@
1
- import { defineWidget } from "../types.js";
2
-
3
- export const SpacerWidget = defineWidget({
4
- type: "spacer",
5
- label: "Spacer",
6
- category: "Custom/Layout",
7
- description: "Fixed-width blank spacer",
8
- dependencies: [],
9
- baseOptions: [],
10
- baseOptionDefaults: {},
11
- properties: [
12
- {
13
- id: "width",
14
- label: "Width",
15
- kind: "number",
16
- description: "Spacer width",
17
- default: 2,
18
- options: {
19
- min: 1,
20
- max: 40,
21
- listProperty: "width",
22
- showInColors: true,
23
- },
24
- },
25
- ],
26
- icons: { emoji: "", nerd: "", text: "" },
27
- defaultStyle: { fg: "default", bg: "default", bold: false },
28
- render({ options, renderWidget }) {
29
- return renderWidget(" ".repeat(options.width));
30
- },
31
- });