From 5c5f91d50bbc7acdbc89c7a6b01c9a6b119a5252 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Fri, 22 Sep 2023 08:36:05 +0200 Subject: [PATCH] improve subdired support --- src/uu/ls/src/dired.rs | 34 ++++++++++++---------- src/uu/ls/src/ls.rs | 2 ++ tests/by-util/test_ls.rs | 62 +++++++++++++++++++++++++++++++--------- 3 files changed, 69 insertions(+), 29 deletions(-) diff --git a/src/uu/ls/src/dired.rs b/src/uu/ls/src/dired.rs index 0c627448925..4699d3ddbb5 100644 --- a/src/uu/ls/src/dired.rs +++ b/src/uu/ls/src/dired.rs @@ -32,17 +32,21 @@ impl fmt::Display for BytePosition { // When --dired is used, all lines starts with 2 spaces static DIRED_TRAILING_OFFSET: usize = 2; +fn get_offset_from_previous_line(dired_positions: &[BytePosition]) -> usize { + if let Some(last_position) = dired_positions.last() { + last_position.end + 1 + } else { + 0 + } +} + /// Calculates the byte positions for DIRED pub fn calculate_dired( output_display_len: usize, dfn_len: usize, dired_positions: &[BytePosition], ) -> (usize, usize) { - let offset_from_previous_line = if let Some(last_position) = dired_positions.last() { - last_position.end + 1 - } else { - 0 - }; + let offset_from_previous_line = get_offset_from_previous_line(dired_positions); let start = output_display_len + offset_from_previous_line; let end = start + dfn_len; @@ -55,14 +59,10 @@ pub fn indent(out: &mut BufWriter) -> UResult<()> { } pub fn calculate_subdired(dired: &mut DiredOutput, path_len: usize) { - let offset = if dired.subdired_positions.is_empty() { - DIRED_TRAILING_OFFSET - } else { - dired.subdired_positions[dired.subdired_positions.len() - 1].start + DIRED_TRAILING_OFFSET - }; + let offset_from_previous_line = get_offset_from_previous_line(&dired.dired_positions); dired.subdired_positions.push(BytePosition { - start: offset, - end: path_len + offset, + start: offset_from_previous_line + DIRED_TRAILING_OFFSET, + end: offset_from_previous_line + path_len + DIRED_TRAILING_OFFSET, }); } @@ -73,7 +73,8 @@ pub fn print_dired_output( out: &mut BufWriter, ) -> UResult<()> { out.flush()?; - if !dired.just_printed_total { + // TODO manage when -R and the last doesn't have file + if !dired.just_printed_total && dired.dired_positions.len() >= 1 { print_positions("//DIRED//", &dired.dired_positions); } if config.recursive { @@ -93,11 +94,14 @@ fn print_positions(prefix: &str, positions: &Vec) { } pub fn add_total(total_len: usize, dired: &mut DiredOutput) { + // if we are using ls -R, the position N+1.. need to be with an offset + + let offset_from_previous_line = get_offset_from_previous_line(&dired.dired_positions); dired.just_printed_total = true; dired.dired_positions.push(BytePosition { - start: 0, + start: offset_from_previous_line + 0, // the 1 is from the line ending (\n) - end: total_len + DIRED_TRAILING_OFFSET - 1, + end: offset_from_previous_line + total_len + DIRED_TRAILING_OFFSET - 1, }); } diff --git a/src/uu/ls/src/ls.rs b/src/uu/ls/src/ls.rs index f9e567ea00a..07ba8d58e0e 100644 --- a/src/uu/ls/src/ls.rs +++ b/src/uu/ls/src/ls.rs @@ -2141,7 +2141,9 @@ fn enter_directory( write!(out, "\n")?; if config.dired { dired::indent(out)?; + dired::calculate_subdired(dired, e.display_name.len()); } + show_dir_name(&e.p_buf, out); write!(out, "\n")?; enter_directory(e, rd, config, out, listed_ancestors, dired)?; diff --git a/tests/by-util/test_ls.rs b/tests/by-util/test_ls.rs index 023c6ad3671..05d7a4fe97e 100644 --- a/tests/by-util/test_ls.rs +++ b/tests/by-util/test_ls.rs @@ -3552,27 +3552,61 @@ fn test_ls_dired_recursive() { } #[test] -fn test_ls_dired_recursive_several() { +fn test_ls_dired_recursive_multiple() { let scene = TestScenario::new(util_name!()); let at = &scene.fixtures; at.mkdir("d"); at.mkdir("d/d1"); at.mkdir("d/d2"); + at.touch("d/d2/a"); + at.touch("d/d2/ab"); + at.touch("d/d1/ab"); + let mut cmd = scene.ucmd(); - let result = scene - .ucmd() - .arg("--dired") - .arg("-l") - .arg("-R") - .arg("d") - .succeeds() - .stdout_does_not_contain("//DIRED//") - .stdout_contains(" d/d1:") - .stdout_contains(" d/d2:") - .stdout_contains(" total 0") - .stdout_contains("//SUBDIRED// 2 3") - .stdout_contains("//DIRED-OPTIONS// --quoting-style"); + cmd.arg("--dired").arg("-l").arg("-R").arg("d"); + + let result = cmd.succeeds(); + + let output = result.stdout_str().to_string(); + println!("Output:\n{}", output); + // TODO: Il manque le offset du direname + let dired_line = output + .lines() + .find(|&line| line.starts_with("//DIRED//")) + .unwrap(); + let positions: Vec = dired_line + .split_whitespace() + .skip(1) + .map(|s| s.parse().unwrap()) + .collect(); + println!("{:?}", positions); + println!("Parsed byte positions: {:?}", positions); + assert_eq!(positions.len() % 2, 0); // Ensure there's an even number of positions + + let filenames: Vec = positions + .chunks(2) + .map(|chunk| { + let start_pos = chunk[0]; + let end_pos = chunk[1]; + let filename = String::from_utf8(output.as_bytes()[start_pos..=end_pos].to_vec()) + .unwrap() + .trim() + .to_string(); + println!("Extracted filename: {}", filename); + filename + }) + .collect(); + + println!("Extracted filenames: {:?}", filenames); + assert_eq!(filenames, vec!["a1", "a22", "a333", "a4444", "d"]); + + /* .stdout_contains(" d/d1:") + .stdout_contains(" d/d2:") + .stdout_contains(" total 0") + .stdout_contains("//DIRED//") + .stdout_contains("//SUBDIRED// 2 3") + .stdout_contains("//DIRED-OPTIONS// --quoting-style");*/ } #[test]