diff --git a/Cargo.lock b/Cargo.lock index 321f41d89..e35bcc68c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2058,6 +2058,7 @@ dependencies = [ "term_grid", "termsize", "time", + "unicode-width", "uucore", "uucore_procs", ] diff --git a/src/uu/ls/Cargo.toml b/src/uu/ls/Cargo.toml index 3787d3562..d479a57f4 100644 --- a/src/uu/ls/Cargo.toml +++ b/src/uu/ls/Cargo.toml @@ -16,6 +16,7 @@ path = "src/ls.rs" [dependencies] clap = "2.33" +unicode-width = "0.1.8" number_prefix = "0.4" term_grid = "0.1.5" termsize = "0.1.6" diff --git a/src/uu/ls/src/ls.rs b/src/uu/ls/src/ls.rs index 1cebeb38a..3245e2a56 100644 --- a/src/uu/ls/src/ls.rs +++ b/src/uu/ls/src/ls.rs @@ -40,6 +40,7 @@ use std::{ }; use term_grid::{Cell, Direction, Filling, Grid, GridOptions}; use time::{strftime, Timespec}; +use unicode_width::UnicodeWidthStr; #[cfg(unix)] use uucore::libc::{S_IXGRP, S_IXOTH, S_IXUSR}; @@ -1597,6 +1598,10 @@ fn display_file_name(path: &PathData, config: &Config) -> Option { } } + // We need to keep track of the width ourselves instead of letting term_grid + // infer it because the color codes mess up term_grid's width calculation. + let mut width = name.width(); + if let Some(ls_colors) = &config.color { name = color_name(&ls_colors, &path.p_buf, name, path.md()?); } @@ -1625,6 +1630,7 @@ fn display_file_name(path: &PathData, config: &Config) -> Option { if let Some(c) = char_opt { name.push(c); + width += 1; } } @@ -1635,7 +1641,10 @@ fn display_file_name(path: &PathData, config: &Config) -> Option { } } - Some(name.into()) + Some(Cell { + contents: name, + width, + }) } fn color_name(ls_colors: &LsColors, path: &Path, name: String, md: &Metadata) -> String { diff --git a/tests/by-util/test_ls.rs b/tests/by-util/test_ls.rs index 6a1c7764b..1a3bdf78a 100644 --- a/tests/by-util/test_ls.rs +++ b/tests/by-util/test_ls.rs @@ -775,6 +775,18 @@ fn test_ls_color() { .arg("z") .succeeds() .stdout_only(""); + + // The colors must not mess up the grid layout + at.touch("b"); + scene + .ucmd() + .arg("--color") + .arg("-w=15") + .succeeds() + .stdout_only(format!( + "{} test-color\nb {}\n", + a_with_colors, z_with_colors + )); } #[cfg(unix)] @@ -1723,7 +1735,7 @@ fn test_ls_sort_extension() { let expected = vec![ ".", "..", - ".hidden", + ".hidden", "anotherFile", "file1", "file2", @@ -1741,8 +1753,14 @@ fn test_ls_sort_extension() { ]; let result = scene.ucmd().arg("-1aX").run(); - assert_eq!(result.stdout_str().split('\n').collect::>(), expected,); + assert_eq!( + result.stdout_str().split('\n').collect::>(), + expected, + ); let result = scene.ucmd().arg("-1a").arg("--sort=extension").run(); - assert_eq!(result.stdout_str().split('\n').collect::>(), expected,); + assert_eq!( + result.stdout_str().split('\n').collect::>(), + expected, + ); }