1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
use anyhow::{Context, Result};
use colored::Colorize;
use std::fs;
use std::path::Path;
pub fn write_generated<F>(
absolute_path: &Path,
new_source: &str,
postprocess: Option<F>,
) -> Result<()>
where
F: FnOnce() -> Result<()>,
{
println!(
"{} {}",
"[WRITING FILE]".yellow(),
absolute_path.display().to_string().cyan(),
);
let parent_dir = absolute_path
.parent()
.with_context(|| format!("Can't get parent of `{}`", &absolute_path.display()))?;
if !parent_dir.exists() {
println!(
"{}",
format!("[CREATE_DIRECTORY] {}", parent_dir.display()).yellow()
);
fs::create_dir_all(parent_dir)
.with_context(|| format!("Failed to create parent dir `{}`", parent_dir.display()))?;
}
let mut old_source = None;
if absolute_path.exists() {
println!(
"{}",
format!("[FILE ALREADY EXISTS] {}", absolute_path.display()).yellow()
);
old_source = Some(fs::read_to_string(absolute_path)?);
}
fs::write(absolute_path, new_source)?;
println!(
"{} {}",
"[WRITTEN]".yellow(),
absolute_path.display().to_string().cyan()
);
if let Some(postprocess) = postprocess {
postprocess().context("Failed on postprocess step")?;
}
let postprocessed_new_source = fs::read_to_string(absolute_path)?;
if let Some(old_source) = old_source {
if let Some(diff) = colored_diff(&old_source, &postprocessed_new_source) {
println!("{}", "[DIFF BETWEEN OLD AND NEW SOURCE BELOW]".yellow());
println!("{}", "-------------------------------------------".dimmed());
println!("{}", diff);
println!("{}", "-------------------------------------------".dimmed());
} else {
println!("<NO VISUAL DIFFERENCE>");
}
}
Ok(())
}
pub fn colored_diff(left: &str, right: &str) -> Option<String> {
use diff::{lines, Result};
let mut result = String::new();
if left == right {
return None;
}
let lines = lines(left, right);
result.push('\n');
for line in lines {
match line {
Result::Left(l) => {
result.push_str(&format!("{} {}\n", "-".red(), &l.red()));
}
Result::Right(r) => {
result.push_str(&format!("{} {}\n", "+".green(), &r.green()));
}
Result::Both(l, _r) => {
result.push_str(&format!(" {}\n", &l.dimmed()));
}
}
}
Some(result)
}