diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ef5ff0..2a11f5d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,8 @@ All notable changes to similar are documented here. * Add `DiffOp::apply_to_hook` to apply a captured op to a diff hook. * Added virtual newline handling to `iter_changes`. -* Moved unified diff support into separate module `udiff`. +* Made unified diff support more flexible through the introduction of + the `UnifiedDiff` type. ## 0.4.0 diff --git a/src/lib.rs b/src/lib.rs index 9669d69..1c33e6c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,7 +18,6 @@ //! trait bounds necessary, as well as a generic interface. //! * [`text`]: This extends the general diffing functionality to text (and more //! specifically line) based diff operations. -//! * [`udiff`]: Unified diff functionality. //! //! ## Features //! @@ -33,4 +32,3 @@ //! If the crate is used without default features it's removed. pub mod algorithms; pub mod text; -pub mod udiff; diff --git a/src/snapshots/similar__text__unified_diff.snap b/src/snapshots/similar__text__unified_diff.snap deleted file mode 100644 index 70f8474..0000000 --- a/src/snapshots/similar__text__unified_diff.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/text.rs -expression: "&diff.unified_diff(3, Some((\"old\", \"new\")))" ---- ---- old -+++ new -@@ -0 +2 @@ - Hello World --some stuff here -+some amazing stuff here - some more stuff here diff --git a/src/text.rs b/src/text/mod.rs similarity index 99% rename from src/text.rs rename to src/text/mod.rs index 94e8772..c300c55 100644 --- a/src/text.rs +++ b/src/text/mod.rs @@ -55,8 +55,10 @@ use std::borrow::Cow; use std::cmp::Reverse; use std::collections::{BinaryHeap, HashMap}; +mod udiff; +pub use self::udiff::*; + use crate::algorithms::{capture_diff_slices, group_diff_ops, Algorithm, DiffOp, DiffTag}; -use crate::udiff::UnifiedDiff; /// A builder type config for more complex uses of [`TextDiff`]. #[derive(Clone, Debug)] diff --git a/src/snapshots/similar__text__captured_ops.snap b/src/text/snapshots/similar__text__captured_ops.snap similarity index 92% rename from src/snapshots/similar__text__captured_ops.snap rename to src/text/snapshots/similar__text__captured_ops.snap index cf74a13..cce4066 100644 --- a/src/snapshots/similar__text__captured_ops.snap +++ b/src/text/snapshots/similar__text__captured_ops.snap @@ -1,5 +1,5 @@ --- -source: src/text.rs +source: src/text/mod.rs expression: "&diff.ops()" --- [ diff --git a/src/snapshots/similar__text__char_diff.snap b/src/text/snapshots/similar__text__char_diff.snap similarity index 96% rename from src/snapshots/similar__text__char_diff.snap rename to src/text/snapshots/similar__text__char_diff.snap index 82217b6..b32f29a 100644 --- a/src/snapshots/similar__text__char_diff.snap +++ b/src/text/snapshots/similar__text__char_diff.snap @@ -1,5 +1,5 @@ --- -source: src/text.rs +source: src/text/mod.rs expression: diff.ops() --- [ diff --git a/src/snapshots/similar__text__line_ops.snap b/src/text/snapshots/similar__text__line_ops.snap similarity index 96% rename from src/snapshots/similar__text__line_ops.snap rename to src/text/snapshots/similar__text__line_ops.snap index 2fc6396..f187259 100644 --- a/src/snapshots/similar__text__line_ops.snap +++ b/src/text/snapshots/similar__text__line_ops.snap @@ -1,5 +1,5 @@ --- -source: src/text.rs +source: src/text/mod.rs expression: "&changes" --- [ diff --git a/src/text/snapshots/similar__text__unified_diff.snap b/src/text/snapshots/similar__text__unified_diff.snap new file mode 100644 index 0000000..aa8deb2 --- /dev/null +++ b/src/text/snapshots/similar__text__unified_diff.snap @@ -0,0 +1,12 @@ +--- +source: src/text/mod.rs +expression: "&diff.unified_diff().context_radius(3).header(\"old\", \"new\").to_string()" +--- +--- old ++++ new +@@ -0 +2 @@ + Hello World +-some stuff here ++some amazing stuff here + some more stuff here + diff --git a/src/snapshots/similar__text__virtual_newlines.snap b/src/text/snapshots/similar__text__virtual_newlines.snap similarity index 96% rename from src/snapshots/similar__text__virtual_newlines.snap rename to src/text/snapshots/similar__text__virtual_newlines.snap index 59f6e60..609ff4e 100644 --- a/src/snapshots/similar__text__virtual_newlines.snap +++ b/src/text/snapshots/similar__text__virtual_newlines.snap @@ -1,5 +1,5 @@ --- -source: src/text.rs +source: src/text/mod.rs expression: "&changes" --- [ diff --git a/src/udiff.rs b/src/text/udiff.rs similarity index 78% rename from src/udiff.rs rename to src/text/udiff.rs index 0a08c01..845997f 100644 --- a/src/udiff.rs +++ b/src/text/udiff.rs @@ -13,7 +13,6 @@ //! .context_radius(10) //! .header("old_file", "new_file")); //! ``` -#![cfg(feature = "text")] use std::fmt; use std::ops::Range; @@ -21,13 +20,12 @@ use std::ops::Range; use crate::algorithms::{Algorithm, DiffOp}; use crate::text::{Change, ChangeTag, TextDiff}; -/// Represents a range of a unified diff hunk. #[derive(Copy, Clone, Debug)] -struct HunkRange(usize, usize); +struct UnifiedDiffHunkRange(usize, usize); -impl HunkRange { - fn new(range: Range) -> HunkRange { - HunkRange(range.start, range.end) +impl UnifiedDiffHunkRange { + fn new(range: Range) -> UnifiedDiffHunkRange { + UnifiedDiffHunkRange(range.start, range.end) } fn start(&self) -> usize { @@ -39,7 +37,7 @@ impl HunkRange { } } -impl fmt::Display for HunkRange { +impl fmt::Display for UnifiedDiffHunkRange { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut beginning = self.start(); let len = self.end() - self.start(); @@ -55,29 +53,29 @@ impl fmt::Display for HunkRange { } } -/// Formats a unified diff hunk header for a group of diff operations. -pub struct HunkHeader { - old_range: HunkRange, - new_range: HunkRange, +/// Unified diff hunk header formatter. +pub struct UnifiedHunkHeader { + old_range: UnifiedDiffHunkRange, + new_range: UnifiedDiffHunkRange, } -impl HunkHeader { +impl UnifiedHunkHeader { /// Creates a hunk header from a (non empty) slice of diff ops. - pub fn new(ops: &[DiffOp]) -> HunkHeader { - HunkHeader { - old_range: HunkRange::new(ops[0].old_range()), - new_range: HunkRange::new(ops[ops.len() - 1].new_range()), + pub fn new(ops: &[DiffOp]) -> UnifiedHunkHeader { + UnifiedHunkHeader { + old_range: UnifiedDiffHunkRange::new(ops[0].old_range()), + new_range: UnifiedDiffHunkRange::new(ops[ops.len() - 1].new_range()), } } } -impl fmt::Display for HunkHeader { +impl fmt::Display for UnifiedHunkHeader { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "@@ -{} +{} @@", &self.old_range, &self.new_range) } } -/// A unified diff formatter. +/// Unified diff formatter. /// /// The `Display` implementation renders a unified diff. pub struct UnifiedDiff<'diff, 'old, 'new, 'bufs> { @@ -109,13 +107,13 @@ impl<'diff, 'old, 'new, 'bufs> UnifiedDiff<'diff, 'old, 'new, 'bufs> { } /// Iterates over all hunks as configured. - pub fn iter_hunks(&self) -> impl Iterator> { + pub fn iter_hunks(&self) -> impl Iterator> { let diff = self.diff; self.diff .grouped_ops(self.context_radius) .into_iter() .filter(|ops| !ops.is_empty()) - .map(move |ops| Hunk::new(ops, diff)) + .map(move |ops| UnifiedDiffHunk::new(ops, diff)) } fn header_opt(&mut self, header: Option<(&str, &str)>) -> &mut Self { @@ -126,27 +124,26 @@ impl<'diff, 'old, 'new, 'bufs> UnifiedDiff<'diff, 'old, 'new, 'bufs> { } } -/// Represents a single hunk in a unified diff. +/// Unified diff hunk formatter. /// -/// When formatted with `Display` this renders out a single unified diff's -/// hunk. -pub struct Hunk<'diff, 'old, 'new, 'bufs> { +/// The `Display` this renders out a single unified diff's hunk. +pub struct UnifiedDiffHunk<'diff, 'old, 'new, 'bufs> { diff: &'diff TextDiff<'old, 'new, 'bufs>, ops: Vec, } -impl<'diff, 'old, 'new, 'bufs> Hunk<'diff, 'old, 'new, 'bufs> { +impl<'diff, 'old, 'new, 'bufs> UnifiedDiffHunk<'diff, 'old, 'new, 'bufs> { /// Creates a new hunk for some operations. pub fn new( ops: Vec, diff: &'diff TextDiff<'old, 'new, 'bufs>, - ) -> Hunk<'diff, 'old, 'new, 'bufs> { - Hunk { diff, ops } + ) -> UnifiedDiffHunk<'diff, 'old, 'new, 'bufs> { + UnifiedDiffHunk { diff, ops } } /// Returns the header for the hunk. - pub fn header(&self) -> HunkHeader { - HunkHeader::new(&self.ops) + pub fn header(&self) -> UnifiedHunkHeader { + UnifiedHunkHeader::new(&self.ops) } /// Returns all operations in the hunk. @@ -155,7 +152,7 @@ impl<'diff, 'old, 'new, 'bufs> Hunk<'diff, 'old, 'new, 'bufs> { } /// Iterates over all changes in a hunk. - pub fn iter_changes(&self) -> impl Iterator> { + pub fn iter_changes(&self) -> impl Iterator> + '_ { // unclear why this needs Box::new here. It seems to infer some really // odd lifetimes I can't figure out how to work with. (Box::new( @@ -166,7 +163,7 @@ impl<'diff, 'old, 'new, 'bufs> Hunk<'diff, 'old, 'new, 'bufs> { } } -impl<'diff, 'old, 'new, 'bufs> fmt::Display for Hunk<'diff, 'old, 'new, 'bufs> { +impl<'diff, 'old, 'new, 'bufs> fmt::Display for UnifiedDiffHunk<'diff, 'old, 'new, 'bufs> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let nl = if self.diff.newline_terminated() { ""