Moved code around for unified diff handling

This commit is contained in:
Armin Ronacher 2021-01-30 22:42:01 +01:00
parent 503d912262
commit 861c53889d
10 changed files with 49 additions and 50 deletions

View file

@ -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. * Add `DiffOp::apply_to_hook` to apply a captured op to a diff hook.
* Added virtual newline handling to `iter_changes`. * 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 ## 0.4.0

View file

@ -18,7 +18,6 @@
//! trait bounds necessary, as well as a generic interface. //! trait bounds necessary, as well as a generic interface.
//! * [`text`]: This extends the general diffing functionality to text (and more //! * [`text`]: This extends the general diffing functionality to text (and more
//! specifically line) based diff operations. //! specifically line) based diff operations.
//! * [`udiff`]: Unified diff functionality.
//! //!
//! ## Features //! ## Features
//! //!
@ -33,4 +32,3 @@
//! If the crate is used without default features it's removed. //! If the crate is used without default features it's removed.
pub mod algorithms; pub mod algorithms;
pub mod text; pub mod text;
pub mod udiff;

View file

@ -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

View file

@ -55,8 +55,10 @@ use std::borrow::Cow;
use std::cmp::Reverse; use std::cmp::Reverse;
use std::collections::{BinaryHeap, HashMap}; 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::algorithms::{capture_diff_slices, group_diff_ops, Algorithm, DiffOp, DiffTag};
use crate::udiff::UnifiedDiff;
/// A builder type config for more complex uses of [`TextDiff`]. /// A builder type config for more complex uses of [`TextDiff`].
#[derive(Clone, Debug)] #[derive(Clone, Debug)]

View file

@ -1,5 +1,5 @@
--- ---
source: src/text.rs source: src/text/mod.rs
expression: "&diff.ops()" expression: "&diff.ops()"
--- ---
[ [

View file

@ -1,5 +1,5 @@
--- ---
source: src/text.rs source: src/text/mod.rs
expression: diff.ops() expression: diff.ops()
--- ---
[ [

View file

@ -1,5 +1,5 @@
--- ---
source: src/text.rs source: src/text/mod.rs
expression: "&changes" expression: "&changes"
--- ---
[ [

View file

@ -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

View file

@ -1,5 +1,5 @@
--- ---
source: src/text.rs source: src/text/mod.rs
expression: "&changes" expression: "&changes"
--- ---
[ [

View file

@ -13,7 +13,6 @@
//! .context_radius(10) //! .context_radius(10)
//! .header("old_file", "new_file")); //! .header("old_file", "new_file"));
//! ``` //! ```
#![cfg(feature = "text")]
use std::fmt; use std::fmt;
use std::ops::Range; use std::ops::Range;
@ -21,13 +20,12 @@ use std::ops::Range;
use crate::algorithms::{Algorithm, DiffOp}; use crate::algorithms::{Algorithm, DiffOp};
use crate::text::{Change, ChangeTag, TextDiff}; use crate::text::{Change, ChangeTag, TextDiff};
/// Represents a range of a unified diff hunk.
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
struct HunkRange(usize, usize); struct UnifiedDiffHunkRange(usize, usize);
impl HunkRange { impl UnifiedDiffHunkRange {
fn new(range: Range<usize>) -> HunkRange { fn new(range: Range<usize>) -> UnifiedDiffHunkRange {
HunkRange(range.start, range.end) UnifiedDiffHunkRange(range.start, range.end)
} }
fn start(&self) -> usize { 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 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut beginning = self.start(); let mut beginning = self.start();
let len = self.end() - 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. /// Unified diff hunk header formatter.
pub struct HunkHeader { pub struct UnifiedHunkHeader {
old_range: HunkRange, old_range: UnifiedDiffHunkRange,
new_range: HunkRange, new_range: UnifiedDiffHunkRange,
} }
impl HunkHeader { impl UnifiedHunkHeader {
/// Creates a hunk header from a (non empty) slice of diff ops. /// Creates a hunk header from a (non empty) slice of diff ops.
pub fn new(ops: &[DiffOp]) -> HunkHeader { pub fn new(ops: &[DiffOp]) -> UnifiedHunkHeader {
HunkHeader { UnifiedHunkHeader {
old_range: HunkRange::new(ops[0].old_range()), old_range: UnifiedDiffHunkRange::new(ops[0].old_range()),
new_range: HunkRange::new(ops[ops.len() - 1].new_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 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "@@ -{} +{} @@", &self.old_range, &self.new_range) write!(f, "@@ -{} +{} @@", &self.old_range, &self.new_range)
} }
} }
/// A unified diff formatter. /// Unified diff formatter.
/// ///
/// The `Display` implementation renders a unified diff. /// The `Display` implementation renders a unified diff.
pub struct UnifiedDiff<'diff, 'old, 'new, 'bufs> { 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. /// Iterates over all hunks as configured.
pub fn iter_hunks(&self) -> impl Iterator<Item = Hunk<'diff, 'old, 'new, 'bufs>> { pub fn iter_hunks(&self) -> impl Iterator<Item = UnifiedDiffHunk<'diff, 'old, 'new, 'bufs>> {
let diff = self.diff; let diff = self.diff;
self.diff self.diff
.grouped_ops(self.context_radius) .grouped_ops(self.context_radius)
.into_iter() .into_iter()
.filter(|ops| !ops.is_empty()) .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 { 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 /// The `Display` this renders out a single unified diff's hunk.
/// hunk. pub struct UnifiedDiffHunk<'diff, 'old, 'new, 'bufs> {
pub struct Hunk<'diff, 'old, 'new, 'bufs> {
diff: &'diff TextDiff<'old, 'new, 'bufs>, diff: &'diff TextDiff<'old, 'new, 'bufs>,
ops: Vec<DiffOp>, ops: Vec<DiffOp>,
} }
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. /// Creates a new hunk for some operations.
pub fn new( pub fn new(
ops: Vec<DiffOp>, ops: Vec<DiffOp>,
diff: &'diff TextDiff<'old, 'new, 'bufs>, diff: &'diff TextDiff<'old, 'new, 'bufs>,
) -> Hunk<'diff, 'old, 'new, 'bufs> { ) -> UnifiedDiffHunk<'diff, 'old, 'new, 'bufs> {
Hunk { diff, ops } UnifiedDiffHunk { diff, ops }
} }
/// Returns the header for the hunk. /// Returns the header for the hunk.
pub fn header(&self) -> HunkHeader { pub fn header(&self) -> UnifiedHunkHeader {
HunkHeader::new(&self.ops) UnifiedHunkHeader::new(&self.ops)
} }
/// Returns all operations in the hunk. /// 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. /// Iterates over all changes in a hunk.
pub fn iter_changes(&self) -> impl Iterator<Item = Change<'_>> { pub fn iter_changes(&self) -> impl Iterator<Item = Change<'_>> + '_ {
// unclear why this needs Box::new here. It seems to infer some really // unclear why this needs Box::new here. It seems to infer some really
// odd lifetimes I can't figure out how to work with. // odd lifetimes I can't figure out how to work with.
(Box::new( (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 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let nl = if self.diff.newline_terminated() { let nl = if self.diff.newline_terminated() {
"" ""