diff options
| author | Sinh Pham <phamansinh@gmail.com> | 2015-09-10 18:27:22 -0400 |
|---|---|---|
| committer | Sinh Pham <phamansinh@gmail.com> | 2015-09-10 18:30:07 -0400 |
| commit | e7a5f9327ea8abbac1e953b31c6e25c1717f6c3d (patch) | |
| tree | 243e065ea8cef70ac2b9db14add993ba2d0e11b0 /src/rustfmt_diff.rs | |
| parent | 6e4ea7842b2e42099953fcba8f7b76c8626bdf4a (diff) | |
Add diff write mode https://github.com/nrc/rustfmt/issues/261
Diffstat (limited to 'src/rustfmt_diff.rs')
| -rw-r--r-- | src/rustfmt_diff.rs | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs new file mode 100644 index 00000000000..375cfd661fa --- /dev/null +++ b/src/rustfmt_diff.rs @@ -0,0 +1,109 @@ +use std::collections::VecDeque; +use diff; +use term; + +pub enum DiffLine { + Context(String), + Expected(String), + Resulting(String), +} + +pub struct Mismatch { + pub line_number: u32, + pub lines: Vec<DiffLine>, +} + +impl Mismatch { + fn new(line_number: u32) -> Mismatch { + Mismatch { line_number: line_number, lines: Vec::new() } + } +} + +// Produces a diff between the expected output and actual output of rustfmt. +pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec<Mismatch> { + let mut line_number = 1; + let mut context_queue: VecDeque<&str> = VecDeque::with_capacity(context_size); + let mut lines_since_mismatch = context_size + 1; + let mut results = Vec::new(); + let mut mismatch = Mismatch::new(0); + + for result in diff::lines(expected, actual) { + match result { + diff::Result::Left(str) => { + if lines_since_mismatch >= context_size { + results.push(mismatch); + mismatch = Mismatch::new(line_number - context_queue.len() as u32); + } + + while let Some(line) = context_queue.pop_front() { + mismatch.lines.push(DiffLine::Context(line.to_owned())); + } + + mismatch.lines.push(DiffLine::Resulting(str.to_owned())); + lines_since_mismatch = 0; + } + diff::Result::Right(str) => { + if lines_since_mismatch >= context_size { + results.push(mismatch); + mismatch = Mismatch::new(line_number - context_queue.len() as u32); + } + + while let Some(line) = context_queue.pop_front() { + mismatch.lines.push(DiffLine::Context(line.to_owned())); + } + + mismatch.lines.push(DiffLine::Expected(str.to_owned())); + line_number += 1; + lines_since_mismatch = 0; + } + diff::Result::Both(str, _) => { + if context_queue.len() >= context_size { + let _ = context_queue.pop_front(); + } + + if lines_since_mismatch < context_size { + mismatch.lines.push(DiffLine::Context(str.to_owned())); + } else { + context_queue.push_back(str); + } + + line_number += 1; + lines_since_mismatch += 1; + } + } + } + + results.push(mismatch); + results.remove(0); + + results +} + +pub fn print_diff<F>(diff: Vec<Mismatch>, get_section_title: F) + where F: Fn(u32) -> String +{ + let mut t = term::stdout().unwrap(); + for mismatch in diff { + t.fg(term::color::BRIGHT_WHITE).unwrap(); + let title = get_section_title(mismatch.line_number); + writeln!(t, "{}", title).unwrap(); + + for line in mismatch.lines { + match line { + DiffLine::Context(ref str) => { + t.fg(term::color::WHITE).unwrap(); + writeln!(t, " {}⏎", str).unwrap(); + } + DiffLine::Expected(ref str) => { + t.fg(term::color::GREEN).unwrap(); + writeln!(t, "+{}⏎", str).unwrap(); + } + DiffLine::Resulting(ref str) => { + t.fg(term::color::RED).unwrap(); + writeln!(t, "-{}⏎", str).unwrap(); + } + } + } + } + t.reset().unwrap(); +} |
