Skip to content

fix(terminal): increase minimum width for numeric columns to prevent truncation - #701

Merged
ryoppippi merged 4 commits into
ccusage:mainfrom
tysoncung:fix/table-truncation-700
Nov 8, 2025
Merged

ryoppippi merged 4 commits into
ccusage:mainfrom
tysoncung:fix/table-truncation-700

Conversation

@tysoncung

@tysoncung tysoncung commented Oct 21, 2025 •

Copy link
Copy Markdown
Contributor

Summary

Fixes #700 by increasing the minimum column width for right-aligned numeric columns in responsive table mode.

Problem:
When running ccusage monthly, large token numbers (e.g., 536,073,421) were being truncated with ellipsis (536,073,…) in narrow terminal windows due to insufficient minimum column width in responsive mode.

Solution:
Increased the minimum width for right-aligned numeric columns from 10 to 14 characters in the responsive resizing logic (packages/terminal/src/table.ts line 194). This ensures large comma-formatted numbers display in full without truncation while maintaining table responsiveness.

Changes:

  • Modified packages/terminal/src/table.ts line 194
  • Changed minimum width from Math.max(adjustedWidth, 10) to Math.max(adjustedWidth, 14)
  • Added explanatory comment for future maintainability

Testing:
✅ All format, typecheck, and test checks passed
✅ Tested with wide terminal (120+ columns) - numbers display correctly
✅ Tested with narrow terminal (60-80 columns) - no truncation, responsive mode works
✅ Large numbers (238,430,570+) display in full without ellipsis

Test plan

  • Run pnpm run format in packages/terminal
  • Run pnpm typecheck in packages/terminal
  • Run pnpm run test in packages/terminal (all 32 tests passed)
  • Build and test with pnpm run build
  • Test ccusage monthly with various terminal widths (60, 80, 120 columns)
  • Verify large token numbers display without truncation

Summary by CodeRabbit

  • Bug Fixes
    • Improved table display by increasing minimum spacing for numeric columns, ensuring larger values are rendered with better readability in terminal output.

@coderabbitai

coderabbitai Bot commented Oct 21, 2025 •

Copy link
Copy Markdown

Walkthrough

Increases the minimum width used for right-aligned (numeric) columns in the table renderer from 10 to 14 characters during responsive width adjustment to avoid truncating large numeric values.

Changes

Cohort / File(s) Summary
Numeric column width adjustment
packages/terminal/src/table.ts
Raised the lower bound for right-aligned (numeric) column minimum width from 10 to 14 in the responsive width calculation used by toString so large numbers are not truncated with ellipses.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Caller as Renderer / CLI
  participant Table as Table.toString()
  participant Layout as WidthCalculator

  Note over Caller,Table: Request table rendering
  Caller->>Table: toString()
  Table->>Layout: compute column widths
  Layout-->>Table: widths with minWidth applied
  Note right of Layout: For numeric columns\nminWidth = 14 (was 10)
  Table->>Caller: rendered table string (no truncation for large numbers)
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

Poem

A rabbit nudged the columns wide, 🐇
No more ellipses hide what's right,
Fourteen gaps to hold each tide,
Numbers stretch in clean daylight. ✨

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The pull request title "fix(terminal): increase minimum width for numeric columns to prevent truncation" directly and clearly summarizes the main change in the PR. The title accurately reflects the implementation: the minimum width for right-aligned numeric columns in the table rendering was increased from 10 to 14 characters. The title is concise, specific, and clearly conveys the primary change without unnecessary noise or vague terminology.
Linked Issues Check ✅ Passed The PR meets the core coding objectives from issue #700. The main requirement to prevent truncation of large numeric token values is addressed by increasing the minimum column width from 10 to 14 characters, enabling full display of comma-formatted numbers like 536,073,421. The PR also confirms that responsive table behavior is preserved in narrow terminals. The third objective to optionally provide a --no-truncate flag is marked as optional and was not implemented, which is acceptable given the constraint. The change directly addresses the reported problem without unrelated modifications.
Out of Scope Changes Check ✅ Passed All changes in this PR are directly related to the objective of resolving issue #700. The modification to packages/terminal/src/table.ts involves only a single targeted change: increasing the minimum width threshold for numeric columns from 10 to 14, plus an explanatory comment. There are no extraneous modifications, refactoring, or unrelated code changes. The scope is tightly focused on the specific problem of numeric column truncation.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
packages/terminal/src/table.ts (1)

64-64: Consider using logger from logger.ts instead of console.warn.

The coding guidelines specify using logger.ts instead of console methods for logging. While console.warn is used here as a default fallback, consider importing and using the proper logger from logger.ts as the default value.

As per coding guidelines.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5b279f3 and 85cd0da.

📒 Files selected for processing (1)
  • packages/terminal/src/table.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.ts: Use tab indentation and double quotes (ESLint formatting)
Do not use console.log; only allow where explicitly disabled via eslint-disable
Always use Node.js path utilities for file paths for cross-platform compatibility
Use .ts extensions for local file imports (e.g., import { foo } from './utils.ts')
Prefer @praha/byethrow Result type over traditional try-catch for functional error handling
Use Result.try() to wrap operations that may throw (e.g., JSON parsing)
Use Result.isFailure() for checking errors instead of negating isSuccess()
Use early return on failures (e.g., if (Result.isFailure(r)) continue) instead of ternary patterns
For async operations, create a wrapper using Result.try() and call it
Keep traditional try-catch only for complex file I/O or legacy code that’s hard to refactor
Always use Result.isFailure() and Result.isSuccess() type guards for clarity
Variables use camelCase naming
Types use PascalCase naming
Constants can use UPPER_SNAKE_CASE
Only export constants, functions, and types that are actually used by other modules
Do not export internal/private constants that are only used within the same file
Before exporting a constant, verify it is referenced by other modules
Use Vitest globals (describe, it, expect) without imports in test blocks
Never use await import() dynamic imports anywhere in the codebase
Never use dynamic imports inside Vitest test blocks
Use fs-fixture createFixture() for mock Claude data directories in tests
All tests must use current Claude 4 models (not Claude 3)
Test coverage should include both Sonnet and Opus models
Model names in tests must exactly match LiteLLM pricing database entries
Use logger.ts instead of console.log for logging

Files:

  • packages/terminal/src/table.ts
🔇 Additional comments (2)
packages/terminal/src/table.ts (2)

193-194: Fix is correct; test coverage for numeric truncation in narrow terminals would improve robustness.

The minimum width increase from 10 to 14 at line 194 correctly aligns with the non-responsive path's calculation at line 173 (Math.max(width + 3, 11), which yields 14 for 11-character numbers). This prevents truncation of comma-formatted token numbers like "536,073,421" (11 characters) when the table scales down in narrow terminals.

While unit tests for formatNumber exist (lines 886-914), there's no integration test coverage for verifying numeric values don't truncate when rendering tables in narrow terminal widths. Consider adding a test case that calls renderStatistics or similar with a mocked terminal width to validate this scenario and prevent regression.


185-207: No changes needed—compact mode already mitigates the concern about minimum width constraints in narrow terminals.

The code correctly handles the interaction between the increased minimum width (14) for numeric columns and compact mode. Compact mode is activated at line 135 when terminal width drops below the compactThreshold (default 100), which triggers before the width calculation logic. At line 137, the active configuration switches to compactHead with fewer columns, and rows are filtered accordingly at lines 145-146. This means the minimum width constraints at lines 194-206 are applied to an already-reduced column set, preventing overflow in narrow terminals. For example, in typical configurations, compact mode reduces from 5 columns to 3, eliminating extra numeric columns before the 14-character minimum is enforced.

…truncation

Fixes ccusage#700 by increasing the minimum column width for right-aligned numeric
columns from 10 to 14 characters in responsive mode. This ensures large
token numbers (e.g., 536,073,421) are displayed in full without ellipsis
truncation when the table is resized to fit narrow terminals.

The fix maintains consistency with the normal mode's generous padding while
providing enough space for comma-formatted large numbers.
@tysoncung
tysoncung force-pushed the fix/table-truncation-700 branch from 85cd0da to a70e497 Compare October 21, 2025 11:48

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
packages/terminal/src/table.ts (1)

783-832: Consider adding a test case for large numeric values in narrow terminals.

While the existing tests cover responsive behavior well, consider adding a test that specifically verifies large token numbers (e.g., 536,073,421 or larger) are not truncated when the terminal width is narrow. This would prevent regression of the fix and document the expected behavior.

Example test structure:

it('should not truncate large numeric values in narrow terminals', () => {
	const table = new ResponsiveTable({
		head: ['Date', 'Tokens', 'Cost'],
		colAligns: ['left', 'right', 'right'],
	});

	const originalColumns = process.env.COLUMNS;
	process.env.COLUMNS = '60'; // Very narrow terminal

	table.push(['2024-01-01', '536,073,421', '$1.50']);
	const output = table.toString();

	// Verify the large number is not truncated with ellipsis
	expect(output).toContain('536,073,421');
	expect(output).not.toContain('…');

	process.env.COLUMNS = originalColumns;
});
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 85cd0da and a70e497.

📒 Files selected for processing (1)
  • packages/terminal/src/table.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.ts: Use tab indentation and double quotes (ESLint formatting)
Do not use console.log; only allow where explicitly disabled via eslint-disable
Always use Node.js path utilities for file paths for cross-platform compatibility
Use .ts extensions for local file imports (e.g., import { foo } from './utils.ts')
Prefer @praha/byethrow Result type over traditional try-catch for functional error handling
Use Result.try() to wrap operations that may throw (e.g., JSON parsing)
Use Result.isFailure() for checking errors instead of negating isSuccess()
Use early return on failures (e.g., if (Result.isFailure(r)) continue) instead of ternary patterns
For async operations, create a wrapper using Result.try() and call it
Keep traditional try-catch only for complex file I/O or legacy code that’s hard to refactor
Always use Result.isFailure() and Result.isSuccess() type guards for clarity
Variables use camelCase naming
Types use PascalCase naming
Constants can use UPPER_SNAKE_CASE
Only export constants, functions, and types that are actually used by other modules
Do not export internal/private constants that are only used within the same file
Before exporting a constant, verify it is referenced by other modules
Use Vitest globals (describe, it, expect) without imports in test blocks
Never use await import() dynamic imports anywhere in the codebase
Never use dynamic imports inside Vitest test blocks
Use fs-fixture createFixture() for mock Claude data directories in tests
All tests must use current Claude 4 models (not Claude 3)
Test coverage should include both Sonnet and Opus models
Model names in tests must exactly match LiteLLM pricing database entries
Use logger.ts instead of console.log for logging

Files:

  • packages/terminal/src/table.ts
🔇 Additional comments (1)
packages/terminal/src/table.ts (1)

193-195: LGTM! Appropriate fix for numeric truncation.

The increase from 10 to 14 characters directly addresses the truncation issue for large token numbers. The comment clearly explains the rationale, and the minimum of 14 accommodates numbers like 536,073,421 (11 characters) with adequate padding. The responsive path having a higher minimum (14) than the non-responsive path (11 at line 173) makes sense since scaled-down columns need extra cushion to prevent truncation.

@ryoppippi ryoppippi left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@pkg-pr-new

pkg-pr-new Bot commented Nov 8, 2025 •

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/ryoppippi/ccusage@701
npm i https://pkg.pr.new/ryoppippi/ccusage/@ccusage/codex@701
npm i https://pkg.pr.new/ryoppippi/ccusage/@ccusage/mcp@701

commit: 03f015d

@ryoppippi
ryoppippi merged commit 2235f2a into ccusage:main Nov 8, 2025
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ccusage monthly output truncates token numbers with ellipsis

2 participants