Skip to content

Commit 49c44f3

Browse files
authored
Merge 654df00 into 7d8d39b
2 parents 7d8d39b + 654df00 commit 49c44f3

2 files changed

Lines changed: 90 additions & 3 deletions

File tree

src/app/sub.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,12 @@ where
200200

201201
let coloring: Option<Coloring> = color.map(|ls_colors| {
202202
let mut map = HashMap::new();
203-
build_coloring_map(&data_tree, &mut Vec::new(), &mut map);
203+
// In the multi-arg case the root is the virtual "(total)" node, which does not
204+
// correspond to a real filesystem path. Pass `fs_path_skip = 1` so that
205+
// `file_color` receives the actual relative path (e.g. "dir-a/file.txt") rather
206+
// than the fake one ("(total)/dir-a/file.txt").
207+
let fs_path_skip = usize::from(!only_one_arg);
208+
build_coloring_map(&data_tree, &mut Vec::new(), fs_path_skip, &mut map);
204209
Coloring::new(ls_colors, map)
205210
});
206211

@@ -288,18 +293,25 @@ where
288293
/// Leaf nodes (files or childless directories after pruning) are added to the map.
289294
/// Nodes with children are skipped because the [`Visualizer`] uses the children count to
290295
/// determine their color at render time.
296+
///
297+
/// `fs_path_skip` controls how many leading components of `path_stack` to skip when building
298+
/// the filesystem path passed to [`file_color`]. This is set to `1` in the multi-argument case
299+
/// so that the virtual `(total)` root component is excluded from the path used for filesystem
300+
/// queries, while still being included in the map key (which must match what
301+
/// [`maybe_colored_slice`](crate::visualizer::coloring::maybe_colored_slice) constructs).
291302
fn build_coloring_map<'a>(
292303
node: &'a DataTree<OsStringDisplay, impl size::Size>,
293304
path_stack: &mut Vec<&'a OsStr>,
305+
fs_path_skip: usize,
294306
map: &mut HashMap<Vec<&'a OsStr>, Color>,
295307
) {
296308
path_stack.push(node.name().as_os_str());
297309
if node.children().is_empty() {
298-
let color = file_color(&path_stack.iter().collect::<PathBuf>());
310+
let color = file_color(&path_stack[fs_path_skip..].iter().collect::<PathBuf>());
299311
map.insert(path_stack.clone(), color);
300312
} else {
301313
for child in node.children() {
302-
build_coloring_map(child, path_stack, map);
314+
build_coloring_map(child, path_stack, fs_path_skip, map);
303315
}
304316
}
305317
path_stack.pop();

tests/usual_cli.rs

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -880,6 +880,81 @@ fn color_always() {
880880
assert_eq!(actual, expected);
881881
}
882882

883+
#[cfg(unix)]
884+
#[test]
885+
fn color_always_multiple_args() {
886+
let workspace = SampleWorkspace::simple_tree_with_diverse_kinds();
887+
888+
let actual = Command::new(PDU)
889+
.with_current_dir(&workspace)
890+
.with_arg("--color=always")
891+
.with_arg("--quantity=apparent-size")
892+
.with_arg("--total-width=100")
893+
.with_arg("--min-ratio=0")
894+
.with_arg("dir-a")
895+
.with_arg("link-dir")
896+
.with_env("LS_COLORS", LS_COLORS)
897+
.pipe(stdio)
898+
.output()
899+
.expect("spawn command with --color=always and multiple args")
900+
.pipe(stdout_text);
901+
eprintln!("ACTUAL:\n{actual}\n");
902+
903+
let data_tree = ["dir-a", "link-dir"]
904+
.iter()
905+
.map(|name| {
906+
let builder = FsTreeBuilder {
907+
root: workspace.to_path_buf().join(name),
908+
size_getter: GetApparentSize,
909+
hardlinks_recorder: &HardlinkIgnorant,
910+
reporter: &ErrorOnlyReporter::new(ErrorReport::SILENT),
911+
max_depth: 10,
912+
};
913+
let mut data_tree: DataTree<OsStringDisplay, _> = builder.into();
914+
*data_tree.name_mut() = OsStringDisplay::os_string_from(name);
915+
data_tree
916+
})
917+
.pipe(|children| {
918+
DataTree::dir(
919+
OsStringDisplay::os_string_from("(total)"),
920+
0u64.into(),
921+
children.collect(),
922+
)
923+
})
924+
.into_par_sorted(|left, right| left.size().cmp(&right.size()).reverse());
925+
926+
let ls_colors = LsColors::from_str(LS_COLORS);
927+
let leaf_colors = [
928+
("(total)/dir-a/file-a1.txt", Color::Normal),
929+
("(total)/dir-a/file-a2.txt", Color::Normal),
930+
("(total)/dir-a/subdir-a/file-a3.txt", Color::Normal),
931+
("(total)/link-dir", Color::Symlink),
932+
];
933+
let leaf_colors = HashMap::from(leaf_colors.map(|(path, color)| {
934+
(
935+
path.split('/')
936+
.map(AsRef::<OsStr>::as_ref)
937+
.collect::<Vec<_>>(),
938+
color,
939+
)
940+
}));
941+
let coloring = Coloring::new(ls_colors, leaf_colors);
942+
943+
let visualizer = Visualizer::<OsStringDisplay, _> {
944+
data_tree: &data_tree,
945+
bytes_format: BytesFormat::MetricUnits,
946+
direction: Direction::BottomUp,
947+
bar_alignment: BarAlignment::Left,
948+
column_width_distribution: ColumnWidthDistribution::total(100),
949+
coloring: Some(&coloring),
950+
};
951+
let expected = format!("{visualizer}");
952+
let expected = expected.trim_end();
953+
eprintln!("EXPECTED:\n{expected}\n");
954+
955+
assert_eq!(actual, expected);
956+
}
957+
883958
#[test]
884959
fn colorful_equals_colorless() {
885960
let workspace = SampleWorkspace::default();

0 commit comments

Comments
 (0)