diff --git a/Cargo.lock b/Cargo.lock index 8611596c2..f2b06b3cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1458,9 +1458,9 @@ dependencies = [ [[package]] name = "term_grid" -version = "0.1.7" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "230d3e804faaed5a39b08319efb797783df2fd9671b39b7596490cb486d702cf" +checksum = "a7c9eb7705cb3f0fd71d3955b23db6d372142ac139e8c473952c93bf3c3dc4b7" dependencies = [ "unicode-width 0.1.13", ] diff --git a/Cargo.toml b/Cargo.toml index 3c1af8968..cfca8197e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,11 +28,10 @@ libc = "0.2.*" human-sort = "0.2.2" # should stick to 0.1, the 0.2 needs some adaptation # check https://github.com/lsd-rs/lsd/issues/1014 -term_grid = "0.1" +term_grid = "0.2.0" terminal_size = "0.4.*" thiserror = "2.0" sys-locale = "0.3" -#once_cell = "1.17.1" once_cell = "1.21" chrono = { version = "0.4", features = ["unstable-locales"] } chrono-humanize = "0.2" diff --git a/src/display.rs b/src/display.rs index 842ffb248..51bfde833 100644 --- a/src/display.rs +++ b/src/display.rs @@ -6,7 +6,7 @@ use crate::icon::Icons; use crate::meta::name::DisplayOption; use crate::meta::{FileType, Meta, OwnerCache}; use std::collections::HashMap; -use term_grid::{Cell, Direction, Filling, Grid, GridOptions}; +use term_grid::{Alignment, Cell, Direction, Filling, Grid, GridOptions}; use terminal_size::terminal_size; use unicode_width::UnicodeWidthStr; @@ -137,6 +137,7 @@ fn inner_display_grid( cells.push(Cell { width: get_visible_width(&block, flags.hyperlink == HyperlinkOption::Always), contents: block, + alignment: Alignment::Left, }); } } @@ -224,6 +225,8 @@ fn add_header(flags: &Flags, cells: &[Cell], grid: &mut Grid) { grid.add(Cell { width: widths[idx], contents: underlined_header, + // term_grid 0.2 only has Left/Right; centering is done above + alignment: Alignment::Left, }); } } @@ -269,6 +272,7 @@ fn inner_display_tree( cells.push(Cell { width: get_visible_width(&block, flags.hyperlink == HyperlinkOption::Always), contents: block, + alignment: Alignment::Left, }); } @@ -987,4 +991,89 @@ mod tests { drop(file); drop(link); } + + /// Test for issue #1014: Grid layout should work correctly with colors + /// When files can fit on multiple columns, they should not be displayed vertically. + /// The fix is to use get_visible_width() for the Cell width field, which strips + /// ANSI escape codes from the width calculation. + #[test] + fn test_grid_layout_with_colors_issue_1014() { + // Force color output to ensure ANSI codes are present + crossterm::style::force_color_output(true); + + let argv = ["lsd"]; // Default grid layout + let cli = Cli::try_parse_from(argv).unwrap(); + let flags = Flags::configure_from(&cli, &Config::with_none()).unwrap(); + + // Create directory with multiple short-named files + let dir = assert_fs::TempDir::new().unwrap(); + for i in 1..=10 { + dir.child(format!("f{}.txt", i)).touch().unwrap(); + } + + let metas = Meta::from_path(Path::new(dir.path()), false, PermissionFlag::Rwx) + .unwrap() + .recurse_into(1, &flags, None) + .unwrap() + .0 + .unwrap(); + + // Use colors to ensure ANSI codes are in the output + let colors = Colors::new(color::ThemeOption::NoLscolors); + let icons = Icons::new(true, IconOption::Never, FlagTheme::Fancy, " ".to_string()); + let git_theme = GitTheme::new(); + + // Build cells the same way inner_display_grid does + let padding_rules = get_padding_rules(&metas, &flags); + let mut test_cells = Vec::new(); + let owner_cache = OwnerCache::default(); + + for meta in &metas { + let blocks = get_output( + meta, + &owner_cache, + &colors, + &icons, + &git_theme, + &flags, + &DisplayOption::FileName, + &padding_rules, + (0, ""), + ); + for block in blocks { + test_cells.push(Cell { + width: get_visible_width(&block, false), + contents: block, + alignment: Alignment::Left, + }); + } + } + + // Create grid with these cells + let mut grid = Grid::new(GridOptions { + filling: Filling::Spaces(2), + direction: Direction::TopToBottom, + }); + for cell in &test_cells { + grid.add(cell.clone()); + } + + // With 200 columns and ~7 char filenames, fit_into_width should succeed + let result = grid.fit_into_width(200); + assert!( + result.is_some(), + "fit_into_width returned None - grid layout failed with ANSI colors" + ); + + // Verify multiple files fit per line + let output = result.unwrap().to_string(); + let newline_count = output.matches('\n').count(); + assert!( + newline_count < 10, + "Grid layout broken: {} newlines for 10 files (should fit multiple per line)", + newline_count + ); + + dir.close().unwrap(); + } }