From e7a5f9327ea8abbac1e953b31c6e25c1717f6c3d Mon Sep 17 00:00:00 2001 From: Sinh Pham Date: Thu, 10 Sep 2015 18:27:22 -0400 Subject: Add diff write mode https://github.com/nrc/rustfmt/issues/261 --- src/rustfmt_diff.rs | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 src/rustfmt_diff.rs (limited to 'src/rustfmt_diff.rs') 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, +} + +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 { + 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(diff: Vec, 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(); +} -- cgit 1.4.1-3-g733a5