feat(cli): Use ellipses when truncating progress

Use ellipses when truncating progress instead of three periods. While
this allows an extra two characters to fit on screen, the main
motivation it to reduce the visual quirkiness or the resulting output.

Closes #15330
This commit is contained in:
Hugo Osvaldo Barrera 2025-03-19 18:14:17 +01:00 committed by Ed Page
parent e3f6477f26
commit d9891edffe

View File

@ -75,6 +75,7 @@ struct Format {
max_width: usize,
max_print: usize,
term_integration: TerminalIntegration,
unicode: bool,
}
/// Controls terminal progress integration via OSC sequences.
@ -229,6 +230,7 @@ impl<'gctx> Progress<'gctx> {
// even on narrow (e.g. 80 char) terminals.
max_print: 50,
term_integration: TerminalIntegration::from_config(gctx),
unicode: gctx.shell().err_unicode(),
},
name: name.to_string(),
done: false,
@ -261,8 +263,7 @@ impl<'gctx> Progress<'gctx> {
/// * `cur` should be how far along the progress is.
/// * `max` is the maximum value for the progress bar.
/// * `msg` is a small piece of text to display at the end of the progress
/// bar. It will be truncated with `...` if it does not fit on the
/// terminal.
/// bar. It will be truncated with `…` if it does not fit on the terminal.
///
/// This may not actually update the display if `tick` is being called too
/// quickly.
@ -521,7 +522,10 @@ impl Format {
fn render(&self, string: &mut String, msg: &str) {
let mut avail_msg_len = self.max_width - string.len() - 15;
let mut ellipsis_pos = 0;
if avail_msg_len <= 3 {
let (ellipsis, ellipsis_width) = if self.unicode { ("", 1) } else { ("...", 3) };
if avail_msg_len <= ellipsis_width {
return;
}
for c in msg.chars() {
@ -529,12 +533,12 @@ impl Format {
if avail_msg_len >= display_width {
avail_msg_len -= display_width;
string.push(c);
if avail_msg_len >= 3 {
if avail_msg_len >= ellipsis_width {
ellipsis_pos = string.len();
}
} else {
string.truncate(ellipsis_pos);
string.push_str("...");
string.push_str(ellipsis);
break;
}
}
@ -569,6 +573,7 @@ fn test_progress_status() {
max_print: 40,
max_width: 60,
term_integration: TerminalIntegration::new(false),
unicode: true,
};
assert_eq!(
format.progress_status(0, 4, ""),
@ -610,7 +615,7 @@ fn test_progress_status() {
);
assert_eq!(
format.progress_status(3, 4, ": msg that's just fit"),
Some("[=============> ] 3/4: msg that's just...".to_string())
Some("[=============> ] 3/4: msg that's just f…".to_string())
);
// combining diacritics have width zero and thus can fit max_width.
@ -623,16 +628,16 @@ fn test_progress_status() {
// some non-ASCII ellipsize test
assert_eq!(
format.progress_status(3, 4, "_123456789123456e\u{301}\u{301}8\u{301}90a"),
Some("[=============> ] 3/4_123456789123456e\u{301}\u{301}...".to_string())
Some("[=============> ] 3/4_123456789123456e\u{301}\u{301}8\u{301}9…".to_string())
);
assert_eq!(
format.progress_status(3, 4, ":每個漢字佔據了兩個字元"),
Some("[=============> ] 3/4每個漢字佔據了...".to_string())
Some("[=============> ] 3/4每個漢字佔據了兩…".to_string())
);
assert_eq!(
// handle breaking at middle of character
format.progress_status(3, 4, "-每個漢字佔據了兩個字元"),
Some("[=============> ] 3/4-每個漢字佔據了...".to_string())
Some("[=============> ] 3/4-每個漢字佔據了兩…".to_string())
);
}
@ -643,6 +648,7 @@ fn test_progress_status_percentage() {
max_print: 40,
max_width: 60,
term_integration: TerminalIntegration::new(false),
unicode: true,
};
assert_eq!(
format.progress_status(0, 77, ""),
@ -669,6 +675,7 @@ fn test_progress_status_too_short() {
max_print: 25,
max_width: 25,
term_integration: TerminalIntegration::new(false),
unicode: true,
};
assert_eq!(
format.progress_status(1, 1, ""),
@ -680,6 +687,7 @@ fn test_progress_status_too_short() {
max_print: 24,
max_width: 24,
term_integration: TerminalIntegration::new(false),
unicode: true,
};
assert_eq!(format.progress_status(1, 1, ""), None);
}