mirror of
https://github.com/l0ng-ai/tty7.git
synced 2026-09-22 00:02:23 +00:00
fix(cli): exempt the last column from the cell bound
Bounding every cell cost `doctor` the thing it exists to report: the config directory came out with its middle replaced by an ellipsis, and a path a reader cannot copy is not a diagnostic. Caught by running `tty7 doctor` against the isolated daemon right after making the change. Nothing is padded against the last column — `render_row` trims the end of every line — so its width cannot push anything out of line, and cutting it buys nothing. `ws ls` still bounds NAME, which has four columns to its right; `doctor` and the agent listing, whose findings sit last, print whole again.
This commit is contained in:
@@ -129,12 +129,27 @@ pub(crate) fn printable(s: &str) -> std::borrow::Cow<'_, str> {
|
||||
///
|
||||
/// A full classic terminal width, so every realistic name and path still
|
||||
/// prints whole. `--json` is the output for anything that must not be cut.
|
||||
///
|
||||
/// The last column is exempt. Nothing is padded against it — `render_row`
|
||||
/// trims the end of every line — so its width cannot push anything out of
|
||||
/// line, and cutting it is pure loss: `doctor` puts its findings there, and a
|
||||
/// config path with its middle replaced by an ellipsis is the one thing the
|
||||
/// reader of a diagnostic needed whole.
|
||||
const MAX_CELL: usize = 80;
|
||||
|
||||
pub fn table(header: &[&str], rows: &[Vec<String>]) -> String {
|
||||
let last = header.len().saturating_sub(1);
|
||||
let rows: Vec<Vec<String>> = rows
|
||||
.iter()
|
||||
.map(|row| row.iter().map(|c| clamp(&printable(c), MAX_CELL)).collect())
|
||||
.map(|row| {
|
||||
row.iter()
|
||||
.enumerate()
|
||||
.map(|(i, c)| match i == last {
|
||||
true => printable(c).into_owned(),
|
||||
false => clamp(&printable(c), MAX_CELL),
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
.collect();
|
||||
let rows = &rows;
|
||||
let mut widths: Vec<usize> = header.iter().map(|h| width(h)).collect();
|
||||
@@ -497,6 +512,26 @@ mod tests {
|
||||
assert!(widths.iter().all(|w| *w <= widest));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_last_column_is_never_cut() {
|
||||
// `doctor` reports its findings in the last column, and a config path
|
||||
// with an ellipsis through the middle is the one thing the reader of a
|
||||
// diagnostic needed whole. Nothing is padded against the last column,
|
||||
// so its width costs no alignment.
|
||||
let long = format!("/private/var/folders/{}/config", "x".repeat(200));
|
||||
let out = table(
|
||||
&["CHECK", "RESULT"],
|
||||
&[
|
||||
vec!["config".into(), long.clone()],
|
||||
vec!["server".into(), "ok".into()],
|
||||
],
|
||||
);
|
||||
assert!(out.contains(&long), "the last column was cut");
|
||||
// The row that says `ok` is not dragged out to meet it.
|
||||
let ok_row = out.lines().find(|l| l.contains("server")).unwrap();
|
||||
assert!(width(ok_row) < 40, "a short row was padded to the long one");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wide_characters_are_padded_by_display_width_not_byte_length() {
|
||||
// "项目" is 6 bytes but occupies 4 columns. Padding by len() would add
|
||||
|
||||
Reference in New Issue
Block a user