From e7bf88959ab80f618d46bcdee5c8a261675370fe Mon Sep 17 00:00:00 2001 From: Lstarsky0 <59827030+Lstarsky0@users.noreply.github.com> Date: Wed, 21 Oct 2026 21:48:46 +0800 Subject: [PATCH] fix(tui): use the singular for a count of one in the file activity receipt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The work surface's file activity receipt counts with a fixed plural, so a turn that reads one file and runs one search shows "Read 1 files · Searched 1 patterns", and a single edit shows "Wrote 1 files". Count through tool_run's `counted`, which the tool-run summary already uses for "Explored 1 file, 1 search", and update the three tests that pinned the plural. Signed-off-by: Lstarsky0 <59827030+Lstarsky0@users.noreply.github.com> --- crates/tui/src/tui/history.rs | 20 ++++++++++++++++---- crates/tui/src/tui/history/tool_run.rs | 2 +- crates/tui/src/tui/work_surface/mod.rs | 6 +++--- crates/tui/src/tui/work_surface/model.rs | 4 ++-- 4 files changed, 22 insertions(+), 10 deletions(-) diff --git a/crates/tui/src/tui/history.rs b/crates/tui/src/tui/history.rs index b8c3e685f5..9fca30af4d 100644 --- a/crates/tui/src/tui/history.rs +++ b/crates/tui/src/tui/history.rs @@ -3555,16 +3555,28 @@ impl FileActivitySummary { pub fn compact_display(&self) -> Vec { let mut parts = Vec::new(); if self.files_read > 0 { - parts.push(format!("Read {} files", self.files_read)); + parts.push(format!( + "Read {}", + tool_run::counted(self.files_read as usize, "file", "files") + )); } if self.dirs_listed > 0 { - parts.push(format!("Listed {} directories", self.dirs_listed)); + parts.push(format!( + "Listed {}", + tool_run::counted(self.dirs_listed as usize, "directory", "directories") + )); } if self.patterns_searched > 0 { - parts.push(format!("Searched {} patterns", self.patterns_searched)); + parts.push(format!( + "Searched {}", + tool_run::counted(self.patterns_searched as usize, "pattern", "patterns") + )); } if self.files_written > 0 { - parts.push(format!("Wrote {} files", self.files_written)); + parts.push(format!( + "Wrote {}", + tool_run::counted(self.files_written as usize, "file", "files") + )); } parts } diff --git a/crates/tui/src/tui/history/tool_run.rs b/crates/tui/src/tui/history/tool_run.rs index 24c3ccde7c..3bb3638127 100644 --- a/crates/tui/src/tui/history/tool_run.rs +++ b/crates/tui/src/tui/history/tool_run.rs @@ -322,7 +322,7 @@ fn activity_family_summary(run: &ToolRun, activities: &[ToolRunActivity]) -> Opt (!families.is_empty()).then(|| families.join(", ")) } -fn counted(count: usize, singular: &str, plural: &str) -> String { +pub(super) fn counted(count: usize, singular: &str, plural: &str) -> String { let noun = if count == 1 { singular } else { plural }; format!("{count} {noun}") } diff --git a/crates/tui/src/tui/work_surface/mod.rs b/crates/tui/src/tui/work_surface/mod.rs index 0ac7d5a95f..d2aa03d9f5 100644 --- a/crates/tui/src/tui/work_surface/mod.rs +++ b/crates/tui/src/tui/work_surface/mod.rs @@ -985,9 +985,9 @@ mod tests { .find(|row| row.id.0 == "activity:aggregate") .expect("aggregated activity row"); assert!( - activity.label.contains("Read 1 files") - && activity.label.contains("Searched 1 patterns") - && activity.label.contains("Wrote 1 files"), + activity.label.contains("Read 1 file ·") + && activity.label.contains("Searched 1 pattern ·") + && activity.label.ends_with("Wrote 1 file"), "aggregated label: {}", activity.label ); diff --git a/crates/tui/src/tui/work_surface/model.rs b/crates/tui/src/tui/work_surface/model.rs index 39f223fd31..5f80697e4c 100644 --- a/crates/tui/src/tui/work_surface/model.rs +++ b/crates/tui/src/tui/work_surface/model.rs @@ -4059,7 +4059,7 @@ mod tests { #[test] fn work_mutation_rows_keep_labels_privacy_and_all_inline_modes() { let (label, detail, full) = mutation_activity_body(InlineDiffMode::Full); - assert_eq!(label, "Wrote 1 files"); + assert_eq!(label, "Wrote 1 file"); assert_eq!(detail, "Updated · +1 -1"); assert!(full.contains("-old"), "{full}"); assert!(full.contains("+new"), "{full}"); @@ -4260,7 +4260,7 @@ mod tests { .iter() .find(|row| row.id.0 == "activity:aggregate") .expect("aggregate activity"); - assert!(activity_row.label.contains("Read 1 files")); + assert!(activity_row.label.contains("Read 1 file ·")); assert!(activity_row.label.contains("Searched 2 patterns")); assert!(!activity_row.label.contains("super_secret_pattern_xyz")); assert!(!activity_row.detail.contains("super_secret_pattern_xyz"));