diff --git a/cli/src/diff_util.rs b/cli/src/diff_util.rs index 414b77020..3ca32d593 100644 --- a/cli/src/diff_util.rs +++ b/cli/src/diff_util.rs @@ -791,10 +791,14 @@ pub fn show_diff_stat( stats.push(stat); } - let display_width = usize::from(ui.term_width().unwrap_or(80)).saturating_sub(4); // padding let number_padding = max_diffs.to_string().len(); - let max_bar_length = - display_width.saturating_sub(max_path_length + " | ".len() + number_padding); + // 4 characters padding for the graph + let available_width = + usize::from(ui.term_width().unwrap_or(80)).saturating_sub(4 + " | ".len() + number_padding); + // Always give at least a tiny bit of room + let available_width = max(available_width, 5); + let max_path_length = max_path_length.clamp(3, (0.7 * available_width as f64) as usize); + let max_bar_length = available_width.saturating_sub(max_path_length); let factor = if max_diffs < max_bar_length { 1.0 } else { @@ -804,11 +808,27 @@ pub fn show_diff_stat( formatter.with_label("diff", |formatter| { let mut total_added = 0; let mut total_removed = 0; - for stat in &stats { + let total_files = stats.len(); + for mut stat in stats { total_added += stat.added; total_removed += stat.removed; let bar_added = (stat.added as f64 * factor).ceil() as usize; let bar_removed = (stat.removed as f64 * factor).ceil() as usize; + // replace start of path with ellipsis if the path is too long + if stat.path.chars().count() > max_path_length { + stat.path = if max_path_length <= 3 { + "...".to_string() + } else { + let start_index = stat + .path + .char_indices() + .rev() + .nth(max_path_length - 4) + .unwrap() + .0; + format!("...{}", &stat.path[start_index..]) + } + } // pad to max_path_length write!( formatter, @@ -823,8 +843,8 @@ pub fn show_diff_stat( writeln!( formatter.labeled("stat-summary"), "{} file{} changed, {} insertion{}(+), {} deletion{}(-)", - stats.len(), - if stats.len() == 1 { "" } else { "s" }, + total_files, + if total_files == 1 { "" } else { "s" }, total_added, if total_added == 1 { "" } else { "s" }, total_removed, diff --git a/cli/tests/test_diff_command.rs b/cli/tests/test_diff_command.rs index 732493f56..0a0f11e73 100644 --- a/cli/tests/test_diff_command.rs +++ b/cli/tests/test_diff_command.rs @@ -805,15 +805,15 @@ fn test_diff_stat_long_name_or_stat() { }; insta::assert_snapshot!(get_stat(&test_env, 1, 1), @r###" - 一 | 1 + + 一 | 1 + 1 file changed, 1 insertion(+), 0 deletions(-) "###); insta::assert_snapshot!(get_stat(&test_env, 1, 10), @r###" - 一 | 10 ++++++++++ + 一 | 10 ++++++++++ 1 file changed, 10 insertions(+), 0 deletions(-) "###); insta::assert_snapshot!(get_stat(&test_env, 1, 100), @r###" - 一 | 100 +++++++++++++++++++ + 一 | 100 +++++++++++++++++ 1 file changed, 100 insertions(+), 0 deletions(-) "###); insta::assert_snapshot!(get_stat(&test_env, 10, 1), @r###" @@ -829,27 +829,49 @@ fn test_diff_stat_long_name_or_stat() { 1 file changed, 100 insertions(+), 0 deletions(-) "###); insta::assert_snapshot!(get_stat(&test_env, 50, 1), @r###" - 一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十 | 1 + ...九十一二三四五六七八九十 | 1 + 1 file changed, 1 insertion(+), 0 deletions(-) "###); insta::assert_snapshot!(get_stat(&test_env, 50, 10), @r###" - 一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十 | 10 + ...十一二三四五六七八九十 | 10 +++++++ 1 file changed, 10 insertions(+), 0 deletions(-) "###); insta::assert_snapshot!(get_stat(&test_env, 50, 100), @r###" - 一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十 | 100 + ...十一二三四五六七八九十 | 100 ++++++ + 1 file changed, 100 insertions(+), 0 deletions(-) + "###); + + // Lengths around where we introduce the ellipsis + insta::assert_snapshot!(get_stat(&test_env, 13, 100), @r###" + 一二三四五六七八九十一二三 | 100 ++++++++ + 1 file changed, 100 insertions(+), 0 deletions(-) + "###); + insta::assert_snapshot!(get_stat(&test_env, 14, 100), @r###" + 一二三四五六七八九十一二三四 | 100 ++++++ + 1 file changed, 100 insertions(+), 0 deletions(-) + "###); + insta::assert_snapshot!(get_stat(&test_env, 15, 100), @r###" + ...五六七八九十一二三四五 | 100 ++++++ + 1 file changed, 100 insertions(+), 0 deletions(-) + "###); + insta::assert_snapshot!(get_stat(&test_env, 16, 100), @r###" + ...六七八九十一二三四五六 | 100 ++++++ 1 file changed, 100 insertions(+), 0 deletions(-) "###); // Very narrow terminal (doesn't have to fit, just don't crash) test_env.add_env_var("COLUMNS", "10"); insta::assert_snapshot!(get_stat(&test_env, 10, 10), @r###" - 一二三四五六七八九十 | 10 + ... | 10 ++ 1 file changed, 10 insertions(+), 0 deletions(-) "###); test_env.add_env_var("COLUMNS", "3"); insta::assert_snapshot!(get_stat(&test_env, 10, 10), @r###" - 一二三四五六七八九十 | 10 + ... | 10 ++ + 1 file changed, 10 insertions(+), 0 deletions(-) + "###); + insta::assert_snapshot!(get_stat(&test_env, 3, 10), @r###" + 一二三 | 10 ++ 1 file changed, 10 insertions(+), 0 deletions(-) "###); }