ccstatusline 2.0.7 → 2.0.9

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 CHANGED
@@ -42,6 +42,12 @@
42
42
 
43
43
  ## 🆕 Recent Updates
44
44
 
45
+ ### v2.0.8 - Powerline Auto-Alignment
46
+
47
+ ![Powerline Auto-Alignment](https://raw.githubusercontent.com/sirmalloc/ccstatusline/main/screenshots/autoAlign.png)
48
+
49
+ - **🎯 Widget Alignment** - Auto-align widgets across multiple status lines in Powerline mode for a clean, columnar layout (toggle with 'a' in Powerline Setup)
50
+
45
51
  ### v2.0.7 - Current Working Directory & Session Cost
46
52
 
47
53
  ![Current Working Directory and Session Cost](https://raw.githubusercontent.com/sirmalloc/ccstatusline/main/screenshots/cwdAndSessionCost.png)
@@ -88,7 +94,7 @@
88
94
  - **⚡ Powerline Support** - Beautiful Powerline-style rendering with arrow separators, caps, and custom fonts
89
95
  - **📐 Multi-line Support** - Configure up to 3 independent status lines
90
96
  - **🖥️ Interactive TUI** - Built-in configuration interface using React/Ink
91
- - **⚙️ Global Options** - Apply consistent formatting across all items (padding, separators, bold, background)
97
+ - **⚙️ Global Options** - Apply consistent formatting across all widgets (padding, separators, bold, background)
92
98
  - **🚀 Cross-platform** - Works seamlessly with both Bun and Node.js
93
99
  - **📏 Smart Width Detection** - Automatically adapts to terminal width with flex separators
94
100
  - **⚡ Zero Config** - Sensible defaults that work out of the box
@@ -111,10 +117,10 @@ bunx ccstatusline@latest
111
117
 
112
118
  The interactive configuration tool provides a terminal UI where you can:
113
119
  - Configure up to 3 separate status lines
114
- - Add/remove/reorder status line items
115
- - Customize colors for each element
120
+ - Add/remove/reorder status line widgets
121
+ - Customize colors for each widget
116
122
  - Configure flex separator behavior
117
- - Edit custom text items
123
+ - Edit custom text widgets
118
124
  - Install/uninstall to Claude Code settings
119
125
  - Preview your status line in real-time
120
126
 
@@ -126,13 +132,15 @@ The interactive configuration tool provides a terminal UI where you can:
126
132
 
127
133
  Once configured, ccstatusline automatically formats your Claude Code status line. The status line appears at the bottom of your terminal during Claude Code sessions.
128
134
 
129
- ### 📊 Available Status Items
135
+ ### 📊 Available Widgets
130
136
 
131
137
  - **Model Name** - Shows the current Claude model (e.g., "Claude 3.5 Sonnet")
132
138
  - **Git Branch** - Displays current git branch name
133
139
  - **Git Changes** - Shows uncommitted insertions/deletions (e.g., "+42,-10")
134
140
  - **Session Clock** - Shows elapsed time since session start (e.g., "2hr 15m")
141
+ - **Session Cost** - Shows total session cost in USD (e.g., "$1.23")
135
142
  - **Block Timer** - Shows time elapsed in current 5-hour block or progress bar
143
+ - **Current Working Directory** - Shows current working directory with configurable path segments
136
144
  - **Version** - Shows Claude Code version
137
145
  - **Output Style** - Shows the currently set output style in Claude Code
138
146
  - **Tokens Input** - Shows input tokens used
@@ -145,7 +153,7 @@ Once configured, ccstatusline automatically formats your Claude Code status line
145
153
  - **Terminal Width** - Shows detected terminal width (for debugging)
146
154
  - **Custom Text** - Add your own custom text to the status line
147
155
  - **Custom Command** - Execute shell commands and display their output (refreshes whenever the statusline is updated by Claude Code)
148
- - **Separator** - Visual divider between items (customizable: |, -, comma, space)
156
+ - **Separator** - Visual divider between widgets (customizable: |, -, comma, space)
149
157
  - **Flex Separator** - Expands to fill available space
150
158
 
151
159
  ---
@@ -160,13 +168,13 @@ These settings affect where long lines are truncated, and where right-alignment
160
168
 
161
169
  ### ⚙️ Global Options
162
170
 
163
- Configure global formatting preferences that apply to all status items:
171
+ Configure global formatting preferences that apply to all widgets:
164
172
 
165
173
  ![Global Options](https://raw.githubusercontent.com/sirmalloc/ccstatusline/main/screenshots/global.png)
166
174
 
167
175
  #### Default Padding & Separators
168
- - **Default Padding** - Add consistent padding to the left and right of each item
169
- - **Default Separator** - Automatically insert a separator between all items
176
+ - **Default Padding** - Add consistent padding to the left and right of each widget
177
+ - **Default Separator** - Automatically insert a separator between all widgets
170
178
  - Press **(p)** to edit padding
171
179
  - Press **(s)** to edit separator
172
180
 
@@ -175,18 +183,18 @@ Configure global formatting preferences that apply to all status items:
175
183
 
176
184
  - **Inherit Colors** - Default separators inherit foreground and background colors from the preceding widget
177
185
  - Press **(i)** to toggle
178
- - **Global Bold** - Apply bold formatting to all text regardless of individual item settings
186
+ - **Global Bold** - Apply bold formatting to all text regardless of individual widget settings
179
187
  - Press **(o)** to toggle
180
- - **Override Foreground Color** - Force all items to use the same text color
188
+ - **Override Foreground Color** - Force all widgets to use the same text color
181
189
  - Press **(f)** to cycle through colors
182
190
  - Press **(g)** to clear override
183
- - **Override Background Color** - Force all items to use the same background color
191
+ - **Override Background Color** - Force all widgets to use the same background color
184
192
  - Press **(b)** to cycle through colors
185
193
  - Press **(c)** to clear override
186
194
 
187
195
  </details>
188
196
 
189
- > 💡 **Note:** These settings are applied during rendering and don't add items to your widget list. They provide a consistent look across your entire status line without modifying individual item configurations.
197
+ > 💡 **Note:** These settings are applied during rendering and don't add widgets to your widget list. They provide a consistent look across your entire status line without modifying individual widget configurations.
190
198
 
191
199
  > ⚠️ **VSCode Users:** If colors appear incorrect in the VSCode integrated terminal, the "Terminal › Integrated: Minimum Contrast Ratio" (`terminal.integrated.minimumContrastRatio`) setting is forcing a minimum contrast between foreground and background colors. You can adjust this setting to 1 to disable the contrast enforcement, or use a standalone terminal for accurate colors.
192
200
 
@@ -206,11 +214,11 @@ The Block Timer widget helps you track your progress through Claude Code's 5-hou
206
214
  - Floors block start time to the hour for consistent tracking
207
215
  - Shows "Block: 3hr 45m" in normal mode or just "3hr 45m" in raw value mode
208
216
  - Progress bars show completion percentage (e.g., "[████████████████████████░░░░░░░░] 73.9%")
209
- - Toggle between modes with the **(p)** key in the items editor
217
+ - Toggle between modes with the **(p)** key in the widgets editor
210
218
 
211
219
  ### 🔤 Raw Value Mode
212
220
 
213
- Some items support "raw value" mode which displays just the value without a label:
221
+ Some widgets support "raw value" mode which displays just the value without a label:
214
222
  - Normal: `Model: Claude 3.5 Sonnet` → Raw: `Claude 3.5 Sonnet`
215
223
  - Normal: `Session: 2hr 15m` → Raw: `2hr 15m`
216
224
  - Normal: `Block: 3hr 45m` → Raw: `3hr 45m`
@@ -50535,7 +50535,8 @@ var PowerlineConfigSchema = exports_external.object({
50535
50535
  separatorInvertBackground: exports_external.array(exports_external.boolean()).default([false]),
50536
50536
  startCaps: exports_external.array(exports_external.string()).default([]),
50537
50537
  endCaps: exports_external.array(exports_external.string()).default([]),
50538
- theme: exports_external.string().optional()
50538
+ theme: exports_external.string().optional(),
50539
+ autoAlign: exports_external.boolean().default(false)
50539
50540
  });
50540
50541
 
50541
50542
  // src/types/Widget.ts
@@ -50598,7 +50599,8 @@ var SettingsSchema = exports_external.object({
50598
50599
  separatorInvertBackground: [false],
50599
50600
  startCaps: [],
50600
50601
  endCaps: [],
50601
- theme: undefined
50602
+ theme: undefined,
50603
+ autoAlign: false
50602
50604
  }),
50603
50605
  updatemessage: exports_external.object({
50604
50606
  message: exports_external.string().nullable().optional(),
@@ -51035,7 +51037,7 @@ import { execSync as execSync3 } from "child_process";
51035
51037
  import * as fs5 from "fs";
51036
51038
  import * as path4 from "path";
51037
51039
  var __dirname = "/Users/sirmalloc/Projects/Personal/ccstatusline/src/utils";
51038
- var PACKAGE_VERSION = "2.0.7";
51040
+ var PACKAGE_VERSION = "2.0.9";
51039
51041
  function getPackageVersion() {
51040
51042
  if (/^\d+\.\d+\.\d+/.test(PACKAGE_VERSION)) {
51041
51043
  return PACKAGE_VERSION;
@@ -52036,7 +52038,7 @@ function formatTokens(count) {
52036
52038
  return `${(count / 1000).toFixed(1)}k`;
52037
52039
  return count.toString();
52038
52040
  }
52039
- function renderPowerlineStatusLine(widgets, settings, context, lineIndex = 0, globalSeparatorOffset = 0) {
52041
+ function renderPowerlineStatusLine(widgets, settings, context, lineIndex = 0, globalSeparatorOffset = 0, preRenderedWidgets, preCalculatedMaxWidths) {
52040
52042
  const powerlineConfig = settings.powerline;
52041
52043
  const config2 = powerlineConfig ?? {};
52042
52044
  const separators = config2.separators ?? [""];
@@ -52099,12 +52101,13 @@ function renderPowerlineStatusLine(widgets, settings, context, lineIndex = 0, gl
52099
52101
  if (widget.type === "separator" || widget.type === "flex-separator") {
52100
52102
  continue;
52101
52103
  }
52102
- try {
52103
- const widgetImpl = getWidget(widget.type);
52104
- widgetText = widgetImpl.render(widget, context, settings) ?? "";
52105
- defaultColor = widgetImpl.getDefaultColor();
52106
- } catch {
52107
- continue;
52104
+ const preRendered = preRenderedWidgets[i];
52105
+ if (preRendered?.content) {
52106
+ widgetText = preRendered.content;
52107
+ try {
52108
+ const widgetImpl = getWidget(widget.type);
52109
+ defaultColor = widgetImpl.getDefaultColor();
52110
+ } catch {}
52108
52111
  }
52109
52112
  if (widgetText) {
52110
52113
  const padding = settings.defaultPadding ?? "";
@@ -52143,6 +52146,20 @@ function renderPowerlineStatusLine(widgets, settings, context, lineIndex = 0, gl
52143
52146
  }
52144
52147
  if (widgetElements.length === 0)
52145
52148
  return "";
52149
+ const autoAlign = config2.autoAlign;
52150
+ if (autoAlign) {
52151
+ for (let i = 0;i < widgetElements.length; i++) {
52152
+ const element = widgetElements[i];
52153
+ const maxWidth = preCalculatedMaxWidths[i];
52154
+ if (element && maxWidth !== undefined) {
52155
+ const currentLength = element.content.replace(ANSI_REGEX, "").length;
52156
+ const paddingNeeded = maxWidth - currentLength;
52157
+ if (paddingNeeded > 0) {
52158
+ element.content += " ".repeat(paddingNeeded);
52159
+ }
52160
+ }
52161
+ }
52162
+ }
52146
52163
  let result = "";
52147
52164
  if (startCap && widgetElements.length > 0) {
52148
52165
  const firstWidget = widgetElements[0];
@@ -52303,18 +52320,74 @@ function formatSeparator(sep) {
52303
52320
  }
52304
52321
  return sep;
52305
52322
  }
52306
- function renderStatusLineWithInfo(widgets, settings, context) {
52307
- const line = renderStatusLine(widgets, settings, context);
52323
+ function preRenderAllWidgets(allLinesWidgets, settings, context) {
52324
+ const preRenderedLines = [];
52325
+ for (const lineWidgets of allLinesWidgets) {
52326
+ const preRenderedLine = [];
52327
+ for (const widget of lineWidgets) {
52328
+ if (widget.type === "separator" || widget.type === "flex-separator") {
52329
+ preRenderedLine.push({
52330
+ content: "",
52331
+ plainLength: 0,
52332
+ widget
52333
+ });
52334
+ continue;
52335
+ }
52336
+ let widgetText = "";
52337
+ try {
52338
+ const widgetImpl = getWidget(widget.type);
52339
+ widgetText = widgetImpl.render(widget, context, settings) ?? "";
52340
+ } catch {
52341
+ preRenderedLine.push({
52342
+ content: "",
52343
+ plainLength: 0,
52344
+ widget
52345
+ });
52346
+ continue;
52347
+ }
52348
+ const plainLength = widgetText.replace(ANSI_REGEX, "").length;
52349
+ preRenderedLine.push({
52350
+ content: widgetText,
52351
+ plainLength,
52352
+ widget
52353
+ });
52354
+ }
52355
+ preRenderedLines.push(preRenderedLine);
52356
+ }
52357
+ return preRenderedLines;
52358
+ }
52359
+ function calculateMaxWidthsFromPreRendered(preRenderedLines, settings) {
52360
+ const maxWidths = [];
52361
+ const defaultPadding = settings.defaultPadding ?? "";
52362
+ const paddingLength = defaultPadding.length;
52363
+ for (const preRenderedLine of preRenderedLines) {
52364
+ const filteredWidgets = preRenderedLine.filter((w) => w.widget.type !== "separator" && w.widget.type !== "flex-separator" && w.content);
52365
+ for (let pos = 0;pos < filteredWidgets.length; pos++) {
52366
+ const widget = filteredWidgets[pos];
52367
+ if (!widget)
52368
+ continue;
52369
+ const totalWidth = widget.plainLength + paddingLength * 2;
52370
+ const currentMax = maxWidths[pos];
52371
+ if (currentMax === undefined) {
52372
+ maxWidths[pos] = totalWidth;
52373
+ } else {
52374
+ maxWidths[pos] = Math.max(currentMax, totalWidth);
52375
+ }
52376
+ }
52377
+ }
52378
+ return maxWidths;
52379
+ }
52380
+ function renderStatusLineWithInfo(widgets, settings, context, preRenderedWidgets, preCalculatedMaxWidths) {
52381
+ const line = renderStatusLine(widgets, settings, context, preRenderedWidgets, preCalculatedMaxWidths);
52308
52382
  const wasTruncated = line.includes("...");
52309
52383
  return { line, wasTruncated };
52310
52384
  }
52311
- function renderStatusLine(widgets, settings, context) {
52385
+ function renderStatusLine(widgets, settings, context, preRenderedWidgets, preCalculatedMaxWidths) {
52312
52386
  const colorLevel = getColorLevelString(settings.colorLevel);
52313
52387
  const powerlineSettings = settings.powerline;
52314
52388
  const isPowerlineMode = Boolean(powerlineSettings?.enabled);
52315
- if (isPowerlineMode) {
52316
- return renderPowerlineStatusLine(widgets, settings, context, context.lineIndex ?? 0, context.globalSeparatorIndex ?? 0);
52317
- }
52389
+ if (isPowerlineMode)
52390
+ return renderPowerlineStatusLine(widgets, settings, context, context.lineIndex ?? 0, context.globalSeparatorIndex ?? 0, preRenderedWidgets, preCalculatedMaxWidths);
52318
52391
  const applyColorsWithOverride = (text, foregroundColor, backgroundColor, bold) => {
52319
52392
  let fgColor = foregroundColor;
52320
52393
  if (settings.overrideForegroundColor && settings.overrideForegroundColor !== "none") {
@@ -52393,10 +52466,17 @@ function renderStatusLine(widgets, settings, context) {
52393
52466
  continue;
52394
52467
  }
52395
52468
  try {
52396
- const widgetImpl = getWidget(widget.type);
52397
- const widgetText = widgetImpl.render(widget, context, settings);
52469
+ let widgetText;
52470
+ let defaultColor = "white";
52471
+ const preRendered = preRenderedWidgets[i];
52472
+ if (preRendered?.content) {
52473
+ widgetText = preRendered.content;
52474
+ try {
52475
+ const widgetImpl = getWidget(widget.type);
52476
+ defaultColor = widgetImpl.getDefaultColor();
52477
+ } catch {}
52478
+ }
52398
52479
  if (widgetText) {
52399
- const defaultColor = widgetImpl.getDefaultColor();
52400
52480
  if (widget.type === "custom-command" && widget.preserveColors) {
52401
52481
  let finalOutput = widgetText;
52402
52482
  if (widget.maxWidth && widget.maxWidth > 0) {
@@ -53815,12 +53895,12 @@ var ColorMenu = ({ widgets, lineIndex, settings, onUpdate, onBack }) => {
53815
53895
  marginTop: 1,
53816
53896
  children: /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
53817
53897
  dimColor: true,
53818
- children: "No colorable items in the status line."
53898
+ children: "No colorable widgets in the status line."
53819
53899
  }, undefined, false, undefined, this)
53820
53900
  }, undefined, false, undefined, this),
53821
53901
  /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
53822
53902
  dimColor: true,
53823
- children: "Add a Model or Git Branch item first."
53903
+ children: "Add a widget first to continue."
53824
53904
  }, undefined, false, undefined, this),
53825
53905
  /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Box_default, {
53826
53906
  marginTop: 1,
@@ -54244,7 +54324,7 @@ var GlobalOverridesMenu = ({ settings, onUpdate, onBack }) => {
54244
54324
  }, undefined, false, undefined, this),
54245
54325
  /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
54246
54326
  dimColor: true,
54247
- children: "Configure automatic padding and separators between items"
54327
+ children: "Configure automatic padding and separators between widgets"
54248
54328
  }, undefined, false, undefined, this),
54249
54329
  isPowerlineEnabled && /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Box_default, {
54250
54330
  marginTop: 1,
@@ -54262,7 +54342,7 @@ var GlobalOverridesMenu = ({ settings, onUpdate, onBack }) => {
54262
54342
  /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Box_default, {
54263
54343
  children: [
54264
54344
  /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
54265
- children: "Enter default padding (applied to left and right of each item): "
54345
+ children: "Enter default padding (applied to left and right of each widget): "
54266
54346
  }, undefined, false, undefined, this),
54267
54347
  /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
54268
54348
  color: "cyan",
@@ -54281,7 +54361,7 @@ var GlobalOverridesMenu = ({ settings, onUpdate, onBack }) => {
54281
54361
  /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Box_default, {
54282
54362
  children: [
54283
54363
  /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
54284
- children: "Enter default separator (placed between items): "
54364
+ children: "Enter default separator (placed between widgets): "
54285
54365
  }, undefined, false, undefined, this),
54286
54366
  /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
54287
54367
  color: "cyan",
@@ -54492,7 +54572,7 @@ var GlobalOverridesMenu = ({ settings, onUpdate, onBack }) => {
54492
54572
  /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
54493
54573
  dimColor: true,
54494
54574
  wrap: "wrap",
54495
- children: "Note: These settings are applied during rendering and don't add items to your widget list."
54575
+ children: "Note: These settings are applied during rendering and don't add widgets to your widget list."
54496
54576
  }, undefined, false, undefined, this),
54497
54577
  /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
54498
54578
  dimColor: true,
@@ -54507,7 +54587,7 @@ var GlobalOverridesMenu = ({ settings, onUpdate, onBack }) => {
54507
54587
  /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
54508
54588
  dimColor: true,
54509
54589
  wrap: "wrap",
54510
- children: "• Override colors: All items will use these colors instead of their configured colors"
54590
+ children: "• Override colors: All widgets will use these colors instead of their configured colors"
54511
54591
  }, undefined, false, undefined, this)
54512
54592
  ]
54513
54593
  }, undefined, true, undefined, this)
@@ -54934,7 +55014,7 @@ var ItemsEditor = ({ widgets, onUpdate, onBack, lineNumber, settings }) => {
54934
55014
  marginBottom: 1,
54935
55015
  children: /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
54936
55016
  dimColor: true,
54937
- children: "↑↓ to move item, ESC or Enter to exit move mode"
55017
+ children: "↑↓ to move widget, ESC or Enter to exit move mode"
54938
55018
  }, undefined, false, undefined, this)
54939
55019
  }, undefined, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
54940
55020
  flexDirection: "column",
@@ -54967,7 +55047,7 @@ var ItemsEditor = ({ widgets, onUpdate, onBack, lineNumber, settings }) => {
54967
55047
  flexDirection: "column",
54968
55048
  children: widgets.length === 0 ? /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
54969
55049
  dimColor: true,
54970
- children: "No items. Press 'a' to add one."
55050
+ children: "No widgets. Press 'a' to add one."
54971
55051
  }, undefined, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(jsx_dev_runtime8.Fragment, {
54972
55052
  children: [
54973
55053
  widgets.map((widget, index) => {
@@ -55018,7 +55098,7 @@ var ItemsEditor = ({ widgets, onUpdate, onBack, lineNumber, settings }) => {
55018
55098
  dimColor: true,
55019
55099
  children: (() => {
55020
55100
  if (currentWidget.type === "separator") {
55021
- return "A separator character between status line items";
55101
+ return "A separator character between status line widgets";
55022
55102
  } else if (currentWidget.type === "flex-separator") {
55023
55103
  return "Expands to fill available terminal width";
55024
55104
  } else {
@@ -55138,7 +55218,7 @@ var LineSelector = ({ lines, onSelect, onBack, initialSelection = 0, title, bloc
55138
55218
  children: [
55139
55219
  selectedIndex === 0 ? "▶ " : " ",
55140
55220
  "☰ Line 1",
55141
- lines[0] && lines[0].length > 0 ? ` (${lines[0].length} items)` : " (empty)"
55221
+ lines[0] && lines[0].length > 0 ? ` (${lines[0].length} widgets)` : " (empty)"
55142
55222
  ]
55143
55223
  }, undefined, true, undefined, this)
55144
55224
  }, undefined, false, undefined, this),
@@ -55148,7 +55228,7 @@ var LineSelector = ({ lines, onSelect, onBack, initialSelection = 0, title, bloc
55148
55228
  children: [
55149
55229
  selectedIndex === 1 ? "▶ " : " ",
55150
55230
  "☰ Line 2",
55151
- lines[1] && lines[1].length > 0 ? ` (${lines[1].length} items)` : " (empty)"
55231
+ lines[1] && lines[1].length > 0 ? ` (${lines[1].length} widgets)` : " (empty)"
55152
55232
  ]
55153
55233
  }, undefined, true, undefined, this)
55154
55234
  }, undefined, false, undefined, this),
@@ -55158,7 +55238,7 @@ var LineSelector = ({ lines, onSelect, onBack, initialSelection = 0, title, bloc
55158
55238
  children: [
55159
55239
  selectedIndex === 2 ? "▶ " : " ",
55160
55240
  "☰ Line 3",
55161
- lines[2] && lines[2].length > 0 ? ` (${lines[2].length} items)` : " (empty)"
55241
+ lines[2] && lines[2].length > 0 ? ` (${lines[2].length} widgets)` : " (empty)"
55162
55242
  ]
55163
55243
  }, undefined, true, undefined, this)
55164
55244
  }, undefined, false, undefined, this),
@@ -55908,6 +55988,9 @@ var PowerlineSetup = ({
55908
55988
  }
55909
55989
  } else if (input === "i" || input === "I") {
55910
55990
  setConfirmingFontInstall(true);
55991
+ } else if ((input === "a" || input === "A") && powerlineConfig.enabled) {
55992
+ const newConfig = { ...powerlineConfig, autoAlign: !powerlineConfig.autoAlign };
55993
+ onUpdate({ ...settings, powerline: newConfig });
55911
55994
  }
55912
55995
  }
55913
55996
  });
@@ -56175,7 +56258,7 @@ var PowerlineSetup = ({
56175
56258
  flexDirection: "column",
56176
56259
  children: /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
56177
56260
  children: [
56178
- " Font Status: ",
56261
+ " Font Status: ",
56179
56262
  powerlineFontStatus.installed ? /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(jsx_dev_runtime13.Fragment, {
56180
56263
  children: [
56181
56264
  /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
@@ -56205,7 +56288,7 @@ var PowerlineSetup = ({
56205
56288
  /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
56206
56289
  children: [
56207
56290
  /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
56208
- children: "Powerline Mode: "
56291
+ children: " Powerline Mode: "
56209
56292
  }, undefined, false, undefined, this),
56210
56293
  /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
56211
56294
  color: powerlineConfig.enabled ? "green" : "red",
@@ -56217,14 +56300,33 @@ var PowerlineSetup = ({
56217
56300
  }, undefined, false, undefined, this)
56218
56301
  ]
56219
56302
  }, undefined, true, undefined, this),
56220
- powerlineConfig.enabled && /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
56221
- flexDirection: "column",
56222
- marginTop: 1,
56223
- children: /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
56224
- dimColor: true,
56225
- children: "When enabled, global overrides are disabled and powerline separators are used"
56226
- }, undefined, false, undefined, this)
56227
- }, undefined, false, undefined, this),
56303
+ powerlineConfig.enabled && /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(jsx_dev_runtime13.Fragment, {
56304
+ children: [
56305
+ /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
56306
+ children: [
56307
+ /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
56308
+ children: " Align Widgets: "
56309
+ }, undefined, false, undefined, this),
56310
+ /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
56311
+ color: powerlineConfig.autoAlign ? "green" : "red",
56312
+ children: powerlineConfig.autoAlign ? "✓ Enabled " : "✗ Disabled "
56313
+ }, undefined, false, undefined, this),
56314
+ /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
56315
+ dimColor: true,
56316
+ children: " - Press (a) to toggle"
56317
+ }, undefined, false, undefined, this)
56318
+ ]
56319
+ }, undefined, true, undefined, this),
56320
+ /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
56321
+ flexDirection: "column",
56322
+ marginTop: 1,
56323
+ children: /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
56324
+ dimColor: true,
56325
+ children: "When enabled, global overrides are disabled and powerline separators are used"
56326
+ }, undefined, false, undefined, this)
56327
+ }, undefined, false, undefined, this)
56328
+ ]
56329
+ }, undefined, true, undefined, this),
56228
56330
  /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
56229
56331
  marginTop: 1,
56230
56332
  flexDirection: "column",
@@ -56291,27 +56393,30 @@ var PowerlineSetup = ({
56291
56393
  // src/tui/components/StatusLinePreview.tsx
56292
56394
  var import_react42 = __toESM(require_react(), 1);
56293
56395
  var jsx_dev_runtime14 = __toESM(require_jsx_dev_runtime(), 1);
56294
- var renderSingleLine = (widgets, terminalWidth, widthDetectionAvailable, settings, lineIndex, globalSeparatorIndex) => {
56396
+ var renderSingleLine = (widgets, terminalWidth, widthDetectionAvailable, settings, lineIndex, globalSeparatorIndex, preRenderedWidgets, preCalculatedMaxWidths) => {
56295
56397
  const context = {
56296
56398
  terminalWidth,
56297
56399
  isPreview: true,
56298
56400
  lineIndex,
56299
56401
  globalSeparatorIndex
56300
56402
  };
56301
- return renderStatusLineWithInfo(widgets, settings, context);
56403
+ return renderStatusLineWithInfo(widgets, settings, context, preRenderedWidgets, preCalculatedMaxWidths);
56302
56404
  };
56303
56405
  var StatusLinePreview = ({ lines, terminalWidth, settings, onTruncationChange }) => {
56304
56406
  const widthDetectionAvailable = import_react42.default.useMemo(() => canDetectTerminalWidth(), []);
56305
56407
  const { renderedLines, anyTruncated } = import_react42.default.useMemo(() => {
56306
56408
  if (!settings)
56307
56409
  return { renderedLines: [], anyTruncated: false };
56410
+ const preRenderedLines = preRenderAllWidgets(lines, settings, { terminalWidth, isPreview: true });
56411
+ const preCalculatedMaxWidths = calculateMaxWidthsFromPreRendered(preRenderedLines, settings);
56308
56412
  let globalSeparatorIndex = 0;
56309
56413
  const result = [];
56310
56414
  let truncated = false;
56311
56415
  for (let i = 0;i < lines.length; i++) {
56312
56416
  const lineItems = lines[i];
56313
56417
  if (lineItems && lineItems.length > 0) {
56314
- const renderResult = renderSingleLine(lineItems, terminalWidth, widthDetectionAvailable, settings, i, globalSeparatorIndex);
56418
+ const preRenderedWidgets = preRenderedLines[i] ?? [];
56419
+ const renderResult = renderSingleLine(lineItems, terminalWidth, widthDetectionAvailable, settings, i, globalSeparatorIndex, preRenderedWidgets, preCalculatedMaxWidths);
56315
56420
  result.push(renderResult.line);
56316
56421
  if (renderResult.wasTruncated) {
56317
56422
  truncated = true;
@@ -58253,12 +58358,15 @@ async function renderMultipleLines(data) {
58253
58358
  blockMetrics,
58254
58359
  isPreview: false
58255
58360
  };
58361
+ const preRenderedLines = preRenderAllWidgets(lines, settings, context);
58362
+ const preCalculatedMaxWidths = calculateMaxWidthsFromPreRendered(preRenderedLines, settings);
58256
58363
  let globalSeparatorIndex = 0;
58257
58364
  for (let i = 0;i < lines.length; i++) {
58258
58365
  const lineItems = lines[i];
58259
58366
  if (lineItems && lineItems.length > 0) {
58260
58367
  const lineContext = { ...context, lineIndex: i, globalSeparatorIndex };
58261
- const line = renderStatusLine(lineItems, settings, lineContext);
58368
+ const preRenderedWidgets = preRenderedLines[i] ?? [];
58369
+ const line = renderStatusLine(lineItems, settings, lineContext, preRenderedWidgets, preCalculatedMaxWidths);
58262
58370
  const strippedLine = line.replace(/\x1b\[[0-9;]*m/g, "").trim();
58263
58371
  if (strippedLine.length > 0) {
58264
58372
  const nonMergedWidgets = lineItems.filter((_, idx) => idx === lineItems.length - 1 || !lineItems[idx]?.merge);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccstatusline",
3
- "version": "2.0.7",
3
+ "version": "2.0.9",
4
4
  "description": "A customizable status line formatter for Claude Code CLI",
5
5
  "module": "src/ccstatusline.ts",
6
6
  "type": "module",