1use std::fmt::Write;
2
3use crate::diff::RowKind;
4use crate::moves::detect;
5use crate::project::LayerMode;
6use crate::review::{Detection, DiffModes, FileReview, Layers, Summary};
7
8pub fn plain(files: &[FileReview], layers: Layers) -> String {
11 let mut out = String::new();
12 let listed: Vec<&FileReview> = files
13 .iter()
14 .filter(|file| file.is_visible(layers.tests))
15 .collect();
16 let moves = detect(&listed, layers.into());
17 for (file_index, file) in listed.iter().enumerate() {
18 let view = file.view(layers);
19 let _ = writeln!(out, "{} [{}]", file_title(file), file.tag());
20 if file.detection == Detection::Binary {
21 let _ = writeln!(out, " (binary file not shown)");
22 } else if view.hunks.is_empty() {
23 let _ = writeln!(out, " ({})", empty_message(file, layers.into()));
24 }
25 for (hunk_index, hunk) in view.hunks.iter().enumerate() {
26 let _ = writeln!(out, "{}", hunk.header());
27 for (row_index, row) in hunk.rows.iter().enumerate() {
28 if let Some(moved) = moves.get(&(file_index, hunk_index, row_index))
29 && moved.starts_block
30 {
31 let _ = writeln!(out, "{}", moved.describe(&file.path));
32 }
33 let sign = match row.kind {
34 RowKind::Context => ' ',
35 RowKind::Removed => '-',
36 RowKind::Added => '+',
37 };
38 let _ = writeln!(out, "{sign}{}", row.text);
39 }
40 }
41 let _ = writeln!(out);
42 }
43 let _ = writeln!(out, "{}", Summary::new(files, layers).status_line(layers));
44 out
45}
46
47pub fn file_title(file: &FileReview) -> String {
48 match &file.old_path {
49 Some(old) => format!("{} {old} → {}", file.status.letter(), file.path),
50 None => format!("{} {}", file.status.letter(), file.path),
51 }
52}
53
54pub fn empty_message(file: &FileReview, modes: DiffModes) -> String {
56 let hidden = file.view(modes).hidden_hunks;
57 let adjective = modes.adjective();
58 match modes.outcome().0 {
59 _ if file.total_hunks() == 0 => "no textual changes".to_string(),
60 LayerMode::Hidden => format!(
61 "{adjective}-only changes: {hidden} hunk{} hidden",
62 if hidden == 1 { "" } else { "s" }
63 ),
64 LayerMode::Only => format!("no {adjective} changes"),
65 LayerMode::Shown => "no changes".to_string(),
66 }
67}