cc-usage-bar 0.4.0 → 0.4.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/AGENTS.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # AGENTS.md — cc-usage-bar 全功能说明
2
2
 
3
- > 这份文件是面向 AI 助手(Claude Code、Cursor、Codex 等)的安装/配置说明。如果用户对你说「装 cc-usage-bar」「帮我配 statusline 用量条」「装下 cc-usage-bar 帮我配好」之类的话,请按本文档完成全部步骤。**默认无需向用户追加确认**,除以下情况:用户的现有 `statusLine.command` 看上去包含定制脚本而你不确定如何保留时;或者用户没登录过 Claude Code(凭证查不到)。
3
+ > 这份文件是面向 AI 助手(Claude Code、Cursor、Codex 等)的安装/配置说明。如果用户对你说「装 cc-usage-bar」「帮我配 statusline 用量条」「装下 cc-usage-bar 帮我配好」之类的话,请按本文档完成全部步骤。**默认无需向用户追加确认**;只有用户没登录过 Claude Code(凭证查不到)时才停下来让用户先登录。
4
4
 
5
5
  ## 1. 这个包是什么
6
6
 
@@ -18,6 +18,8 @@
18
18
 
19
19
  > **用户只描述偏好,你把 `statusLine.command` 配成 `cc-usage-bar-wrap`,并保留用户原有前缀。**
20
20
 
21
+ 如果已有 `statusLine.command`、`statusline-command.sh`、自定义 shell 脚本、git/path/model 展示等前缀内容,**一律视为要保留的前缀**:按 3.4 抽出它,并用 `cc-usage-bar-wrap --prefix=...` 串起来。不要询问是否覆盖、追加或暂不修改;追加保留是本项目默认行为。
22
+
21
23
  ## 3. 安装流程(必走)
22
24
 
23
25
  按顺序执行,每一步执行前简要告知用户:
@@ -39,7 +41,7 @@ which cc-usage-bar-wrap && which cc-usage-fetch
39
41
  where.exe cc-usage-bar-wrap
40
42
  ```
41
43
 
42
- 要求:`cc-usage-bar` ≥ **0.4.0**(自适应换行 + 周限额上色 + countdown 预设 + 颜色 ramp 自定义)。已装旧版的话用 `npm i -g cc-usage-bar@latest` 升级。
44
+ 要求:`cc-usage-bar` ≥ **0.4.1**(自适应换行 + 周限额上色 + countdown 预设 + 颜色 ramp 自定义 + tint reverse 样式)。已装旧版的话用 `npm i -g cc-usage-bar@latest` 升级。
43
45
 
44
46
  ### 3.3 读取现有 statusLine.command
45
47
 
@@ -172,6 +174,9 @@ CC_USAGE_COLORS_BALANCE='0:cyan,60:yellow,90:red'
172
174
  # 单色渐变(tint)—— 完成部分上色,剩余部分变暗
173
175
  --bar-spec='{"mode":"tint","text":"████████","emptyStyle":"dim"}'
174
176
 
177
+ # 反色填充(reverse)—— 完成部分用反色底块增强对比
178
+ --bar-spec='{"mode":"tint","text":"Ciallo~(∠・ω< )⌒★","style":"reverse"}'
179
+
175
180
  # 动画帧(frames)—— 按百分比从帧序列里挑一帧
176
181
  --bar-spec='{"mode":"frames","frames":["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"]}'
177
182
  ```
package/README.md CHANGED
@@ -117,6 +117,12 @@ cc-usage-bar install --format=bar-time \
117
117
  {"mode":"tint","text":"Ciallo~(∠・ω< )⌒★"}
118
118
  ```
119
119
 
120
+ For stronger contrast, add `style:"reverse"` so the completed prefix is rendered as a reversed-color block:
121
+
122
+ ```json
123
+ {"mode":"tint","text":"Ciallo~(∠・ω< )⌒★","style":"reverse"}
124
+ ```
125
+
120
126
  `cells` replaces the default block characters:
121
127
 
122
128
  ```json
package/README.zh-CN.md CHANGED
@@ -122,6 +122,12 @@ cc-usage-bar install --format=bar-time \
122
122
  {"mode":"tint","text":"Ciallo~(∠・ω< )⌒★"}
123
123
  ```
124
124
 
125
+ 如果想让完成部分更像“填充底块”,可以加 `style:"reverse"`,完成部分会用反色块增强对比:
126
+
127
+ ```json
128
+ {"mode":"tint","text":"Ciallo~(∠・ω< )⌒★","style":"reverse"}
129
+ ```
130
+
125
131
  #### cells:替换默认块字符
126
132
 
127
133
  ```json
@@ -23,6 +23,7 @@ exports.FORMAT_PRESETS = [
23
23
  'bar-countdown',
24
24
  ];
25
25
  const ANSI_RESET = '\x1b[0m';
26
+ const ANSI_REVERSE = '\x1b[7m';
26
27
  exports.COLOR_MAP = {
27
28
  none: '',
28
29
  dim: '\x1b[2m',
@@ -146,6 +147,8 @@ function parseBarSpec(raw) {
146
147
  const out = { mode: 'tint', text: obj.text };
147
148
  if (obj.emptyStyle === 'plain' || obj.emptyStyle === 'dim')
148
149
  out.emptyStyle = obj.emptyStyle;
150
+ if (obj.style === 'fg' || obj.style === 'reverse')
151
+ out.style = obj.style;
149
152
  return out;
150
153
  }
151
154
  if (obj.mode === 'frames') {
@@ -240,7 +243,8 @@ function formatBar(pct, width = 10, spec, activeColor = null, useColor = false)
240
243
  const inactive = chars.slice(filled).join('');
241
244
  if (!useColor)
242
245
  return active + inactive;
243
- const activePart = activeColor && active ? paint(active, activeColor, true) : active;
246
+ const activeStyle = activeColor && spec.style === 'reverse' ? `${activeColor}${ANSI_REVERSE}` : activeColor;
247
+ const activePart = activeStyle && active ? paint(active, activeStyle, true) : active;
244
248
  const inactivePart = inactive && spec.emptyStyle !== 'plain' ? paint(inactive, exports.COLOR_MAP.dim, true) : inactive;
245
249
  return activePart + inactivePart;
246
250
  }
@@ -257,10 +261,22 @@ function paint(text, color, useColor) {
257
261
  return `${color}${text}${ANSI_RESET}`;
258
262
  }
259
263
  function applyTierPaint(text, color, opts, tpl) {
260
- if (opts.barSpec?.mode === 'tint' && opts.color && tpl.includes('{bar}'))
261
- return text;
262
264
  return paint(text, color, opts.color);
263
265
  }
266
+ function applyTintTemplate(tpl, vars, color, opts) {
267
+ if (!opts.color || !color)
268
+ return applyTemplate(tpl, vars);
269
+ return tpl
270
+ .split(/(\{bar\})/g)
271
+ .map((part) => (part === '{bar}' ? vars.bar ?? '{bar}' : paint(applyTemplate(part, vars), color, true)))
272
+ .join('');
273
+ }
274
+ function renderTemplate(tpl, vars, color, opts) {
275
+ if (opts.barSpec?.mode === 'tint' && tpl.includes('{bar}')) {
276
+ return applyTintTemplate(tpl, vars, color, opts);
277
+ }
278
+ return applyTierPaint(applyTemplate(tpl, vars), color, opts, tpl);
279
+ }
264
280
  function prependProvider(text, planName, opts) {
265
281
  return opts.showProviderName && planName ? `${planName} ${text}` : text;
266
282
  }
@@ -272,15 +288,15 @@ function renderTier(ctx, opts) {
272
288
  const tpl = opts.template ?? SUB_PRESET_TPL[opts.format];
273
289
  const ramp = ctx.label === '5h' ? opts.colorRamp5h ?? exports.DEFAULT_RAMP : opts.colorRampWk ?? exports.DEFAULT_RAMP;
274
290
  const color = colorFromRamp(pct, ramp);
275
- const text = applyTemplate(tpl, {
291
+ const vars = {
276
292
  label: ctx.label,
277
293
  percent: String(pct),
278
294
  bar: formatBar(pct, opts.barWidth, opts.barSpec, color, opts.color),
279
295
  expiry: formatExpiry(ctx.tier.resets_at, opts.now),
280
296
  countdown: formatCountdown(ctx.tier.resets_at, opts.now),
281
297
  provider: ctx.provider,
282
- });
283
- return applyTierPaint(text, color, opts, tpl);
298
+ };
299
+ return renderTemplate(tpl, vars, color, opts);
284
300
  }
285
301
  function currencySymbol(unit) {
286
302
  switch (unit.toUpperCase()) {
@@ -315,18 +331,18 @@ function renderBalance(d, opts) {
315
331
  }
316
332
  if (typeof d.total !== 'number') {
317
333
  const tpl = opts.template ?? BAL_PRESET_TPL.compact;
318
- const text = applyTemplate(tpl, {
334
+ const vars = {
319
335
  label: '', percent: '0', bar: '', expiry: '', countdown: '',
320
336
  provider: d.planName ?? '',
321
337
  amount: fmtMoney(d.remaining, d.unit),
322
- });
323
- return prependProvider(applyTierPaint(text, null, opts, tpl), d.planName, opts);
338
+ };
339
+ return prependProvider(renderTemplate(tpl, vars, null, opts), d.planName, opts);
324
340
  }
325
341
  const total = d.total;
326
342
  const usedPct = total > 0 ? ((total - d.remaining) / total) * 100 : 0;
327
343
  const tpl = opts.template ?? BAL_PRESET_TPL[opts.format];
328
344
  const color = colorFromRamp(usedPct, opts.colorRampBalance ?? exports.DEFAULT_RAMP);
329
- const text = applyTemplate(tpl, {
345
+ const vars = {
330
346
  label: '',
331
347
  percent: String(Math.round(usedPct)),
332
348
  bar: formatBar(usedPct, opts.barWidth, opts.barSpec, color, opts.color),
@@ -334,8 +350,8 @@ function renderBalance(d, opts) {
334
350
  countdown: '',
335
351
  provider: d.planName ?? '',
336
352
  amount: `${fmtMoney(d.remaining, d.unit)}/${fmtMoney(total, d.unit)}`,
337
- });
338
- return prependProvider(applyTierPaint(text, color, opts, tpl), d.planName, opts);
353
+ };
354
+ return prependProvider(renderTemplate(tpl, vars, color, opts), d.planName, opts);
339
355
  }
340
356
  function renderUsage(data, opts) {
341
357
  if (!data)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cc-usage-bar",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "Show your Claude Code subscription usage (5h / 7d, or balance) in the statusline. Supports Anthropic, Kimi, GLM, MiniMax, DeepSeek, StepFun, SiliconFlow, OpenRouter, Novita.",
5
5
  "keywords": [
6
6
  "claude",