Skip to content

Commit 588ee58

Browse files
committed
fix(terminal): correct compact and unicode widths
Fix the terminal table width logic called out during review in a follow-up commit stacked on the terminal split. The compact date mode now lowers the first-column minimum only when the table is actually too wide, which lets date compaction render in narrow layouts. Width calculation now uses unicode-width so combining marks and CJK glyphs do not distort table and title layout. This is separate from the mechanical module split so the first PR can stay behavior-preserving.
1 parent d8c775e commit 588ee58

5 files changed

Lines changed: 40 additions & 24 deletions

File tree

‎rust/Cargo.lock‎

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎rust/crates/ccusage-terminal/Cargo.toml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ version = "20.0.4"
44
edition = "2021"
55

66
[dependencies]
7+
unicode-width = "0.2.2"
78

89
[dev-dependencies]
910
insta = "1.47.2"
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
---
22
source: crates/ccusage-terminal/src/table.rs
3-
assertion_line: 494
3+
assertion_line: 495
44
expression: "table.render_lines().join(\"\\n\")"
55
---
6-
┌────────────┬────────────┬──────────┬──────────┬──────────┐
7-
│ Date │ Models │ Input │ Output │ Cost │
8-
│ │ │ │ │ (USD) │
9-
├────────────┼────────────┼──────────┼──────────┼──────────┤
10-
│ 2026-05-18 │ - │ 123,456… │ 9,876,5… │ $12345.… │
11-
│ │ claude-so… │ │ │ │
12-
│ │ - │ │ │ │
13-
│ │ unusually… │ │ │ │
14-
└────────────┴────────────┴──────────┴──────────┴──────────┘
6+
┌──────────┬────────────┬──────────┬──────────┬──────────┐
7+
│ Date │ Models │ Input │ Output │ Cost │
8+
│ │ │ │ │ (USD) │
9+
├──────────┼────────────┼──────────┼──────────┼──────────┤
10+
│ 2026 │ - │ 123,456… │ 9,876,5… │ $12345.… │
11+
│ 05-18 │ claude-so… │ │ │ │
12+
│ │ - │ │ │ │
13+
│ │ unusually… │ │ │ │
14+
└──────────┴────────────┴──────────┴──────────┴──────────┘

‎rust/crates/ccusage-terminal/src/table.rs‎

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -139,15 +139,14 @@ impl SimpleTable {
139139
})
140140
.collect::<Vec<_>>();
141141
let total_required = cli_table_required_width(&widths);
142-
let first_column_min = if self.compact_dates { 12 } else { 10 };
143-
let mut widths =
144-
fit_widths_to_terminal(widths, &self.aligns, self.terminal_width, first_column_min);
145-
if self.compact_dates && total_required > self.terminal_width {
146-
if let Some(width) = widths.first_mut() {
147-
*width = (*width).max(10);
148-
}
149-
}
150-
widths
142+
let first_column_min = if self.compact_dates && total_required > self.terminal_width {
143+
10
144+
} else if self.compact_dates {
145+
12
146+
} else {
147+
10
148+
};
149+
fit_widths_to_terminal(widths, &self.aligns, self.terminal_width, first_column_min)
151150
}
152151

153152
fn compact_date_row(&self, row: &[String], widths: &[usize]) -> Vec<String> {

‎rust/crates/ccusage-terminal/src/width.rs‎

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use unicode_width::UnicodeWidthChar;
2+
13
pub(crate) fn visible_width(value: &str) -> usize {
24
let bytes = value.as_bytes();
35
let mut width = 0;
@@ -28,11 +30,7 @@ pub(crate) fn contains_ansi(value: &str) -> bool {
2830
}
2931

3032
pub(crate) fn char_display_width(ch: char) -> usize {
31-
if ch.is_ascii() {
32-
1
33-
} else {
34-
2
35-
}
33+
UnicodeWidthChar::width_cjk(ch).unwrap_or(0)
3634
}
3735

3836
pub(crate) fn visible_width_max_line(value: &str) -> usize {
@@ -42,3 +40,14 @@ pub(crate) fn visible_width_max_line(value: &str) -> usize {
4240
pub(crate) fn visible_width_sum(value: &str) -> usize {
4341
value.lines().map(visible_width).sum()
4442
}
43+
44+
#[cfg(test)]
45+
mod tests {
46+
use super::*;
47+
48+
#[test]
49+
fn visible_width_handles_combining_marks_and_cjk() {
50+
assert_eq!(visible_width("e\u{0301}"), 1);
51+
assert_eq!(visible_width("表"), 2);
52+
}
53+
}

0 commit comments

Comments
 (0)