1extern crate diff;
2
3mod model;
4mod algo;
5
6use diff::Result as DiffDelta;
7use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor};
8use crate::algo::render_diff;
9use crate::model::{DiffU, LineNumber, Range};
10use std::io::Result as IoResult;
11
12pub struct Patchfile<'a> {
14 remote_name: &'a str,
15 local_name: &'a str,
16 remote_time: Option<&'a str>,
17 local_time: Option<&'a str>,
18}
19
20impl<'a> Patchfile<'a> {
21 pub fn new(name: &'a str) -> Self {
23 Patchfile {
24 remote_name: name,
25 local_name: name,
26 remote_time: None,
27 local_time: None,
28 }
29 }
30
31 pub fn with_names(remote_name: &'a str, local_name: &'a str) -> Self {
33 Patchfile {
34 remote_name,
35 local_name,
36 remote_time: None,
37 local_time: None,
38 }
39 }
40
41 pub fn remote_time(&'a mut self, remote_time: &'a str) -> &'a mut Self {
43 self.remote_time = Some(remote_time);
44
45 self
46 }
47
48 pub fn local_time(&'a mut self, local_time: &'a str) -> &'a mut Self {
50 self.local_time = Some(local_time);
51
52 self
53 }
54
55 pub fn print<'b>(&'a self, remote: &'b str, local: &'b str) -> IoResult<()> {
57 self.write_impl(StandardStream::stdout(ColorChoice::Auto), remote, local)
58 }
59
60 pub fn eprint<'b>(&'a self, remote: &'b str, local: &'b str) -> IoResult<()> {
62 self.write_impl(StandardStream::stderr(ColorChoice::Auto), remote, local)
63 }
64
65 fn write_impl<W: WriteColor>(&self, mut w: W, remote: &str, local: &str) -> IoResult<()> {
66 let diff = diff::lines(local, remote);
67
68 w.set_color(ColorSpec::new().set_fg(Some(Color::Red)))?;
69 writeln!(w, "--- {}\t{}", self.local_name, self.local_time.unwrap_or(""))?;
70 w.set_color(ColorSpec::new().set_fg(Some(Color::Green)))?;
71 writeln!(w, "+++ {}\t{}", self.remote_name, self.remote_time.unwrap_or(""))?;
72
73 for d in render_diff(&diff) {
74 let s = d.to_string();
75 match d {
76 DiffU::CaretPos { .. } => {
77 w.set_color(ColorSpec::new().set_fg(Some(Color::Cyan)))
78 }
79 DiffU::Addition(_) => {
80 w.set_color(ColorSpec::new().set_fg(Some(Color::Green)))
81 }
82 DiffU::Deletion(_) => {
83 w.set_color(ColorSpec::new().set_fg(Some(Color::Red)))
84 }
85 DiffU::Display(_) => {
86 w.set_color(ColorSpec::new().set_fg(None))
87 }
88 }?;
89
90 writeln!(w, "{}", s)?;
91 };
92
93 Ok(())
94 }
95}
96
97#[cfg(test)]
98mod tests;