//! This module provides unified diff functionality. //! //! It is available for as long as the `text` feature is enabled which //! is enabled by default: //! //! ```rust //! use similar::TextDiff; //! # let old_text = ""; //! # let new_text = ""; //! let text_diff = TextDiff::from_lines(old_text, new_text); //! print!("{}", text_diff //! .unified_diff() //! .context_radius(10) //! .header("old_file", "new_file")); //! ``` //! //! # Unicode vs Bytes //! //! The [`UnifiedDiff`] type supports both unicode and byte diffs for all //! types compatible with [`DiffableStr`]. You can pick between the two //! versions by using the [`Display`](std::fmt::Display) implementation or //! [`UnifiedDiff`] or [`UnifiedDiff::to_writer`]. //! //! The former uses [`DiffableStr::to_string_lossy`], the latter uses //! [`DiffableStr::as_bytes`] for each line. #[cfg(feature = "text")] use std::{fmt, io};
impl fmt::Display for UnifiedDiffHunkRange { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { letmut beginning = self.start() + 1; let len = self.end().saturating_sub(self.start()); if len == 1 {
write!(f, "{}", beginning)
} else { if len == 0 { // empty ranges begin at line just before the range
beginning -= 1;
}
write!(f, "{},{}", beginning, len)
}
}
}
impl UnifiedHunkHeader { /// Creates a hunk header from a (non empty) slice of diff ops. pubfn new(ops: &[DiffOp]) -> UnifiedHunkHeader { let first = ops[0]; let last = ops[ops.len() - 1]; let old_start = first.old_range().start; let new_start = first.new_range().start; let old_end = last.old_range().end; let new_end = last.new_range().end;
UnifiedHunkHeader {
old_range: UnifiedDiffHunkRange(old_start, old_end),
new_range: UnifiedDiffHunkRange(new_start, new_end),
}
}
}
/// Unified diff formatter. /// /// ```rust /// use similar::TextDiff; /// # let old_text = ""; /// # let new_text = ""; /// let text_diff = TextDiff::from_lines(old_text, new_text); /// print!("{}", text_diff /// .unified_diff() /// .context_radius(10) /// .header("old_file", "new_file")); /// ``` /// /// ## Unicode vs Bytes /// /// The [`UnifiedDiff`] type supports both unicode and byte diffs for all /// types compatible with [`DiffableStr`]. You can pick between the two /// versions by using [`UnifiedDiff.to_string`] or [`UnifiedDiff.to_writer`]. /// The former uses [`DiffableStr::to_string_lossy`], the latter uses /// [`DiffableStr::as_bytes`] for each line. pubstruct UnifiedDiff<'diff, 'old, 'new, 'bufs, T: DiffableStr + ?Sized> {
diff: &'diff TextDiff<'old, 'new, 'bufs, T>,
context_radius: usize,
missing_newline_hint: bool,
header: Option<(String, String)>,
}
/// Changes the context radius. /// /// The context radius is the number of lines between changes that should /// be emitted. This defaults to `3`. pubfn context_radius(&mutself, n: usize) -> &mutSelf { self.context_radius = n; self
}
/// Sets a header to the diff. /// /// `a` and `b` are the file names that are added to the top of the unified /// file format. The names are accepted verbatim which lets you encode /// a timestamp into it when separated by a tab (`\t`). For more information, /// see [the unified diff format specification](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/diff.html#tag_20_34_10_07). pubfn header(&mutself, a: &str, b: &str) -> &>mutSelf { self.header = Some((a.to_string(), b.to_string())); self
}
/// Controls the missing newline hint. /// /// By default a special `\ No newline at end of file` marker is added to /// the output when a file is not terminated with a final newline. This can /// be disabled with this flag. pubfn missing_newline_hint(&mutself, yes: bool) -> &mutSelf { self.missing_newline_hint = yes; self
}
/// Iterates over all hunks as configured. pubfn iter_hunks(&self) -> impl Iterator<Item = UnifiedDiffHunk<'diff, 'old, 'new, 'bufs, T>> { let diff = self.diff; let missing_newline_hint = self.missing_newline_hint; self.diff
.grouped_ops(self.context_radius)
.into_iter()
.filter(|ops| !ops.is_empty())
.map(move |ops| UnifiedDiffHunk::new(ops, diff, missing_newline_hint))
}
/// Write the unified diff as bytes to the output stream. pubfn to_writer<W: io::Write>(&self, mut w: W) -> Result<(), io::Error> where 'diff: 'old + 'new + 'bufs,
{ letmut header = self.header.as_ref(); for hunk inself.iter_hunks() { iflet Some((old_file, new_file)) = header.take() {
writeln!(w, "--- {}", old_file)?;
writeln!(w, "+++ {}", new_file)?;
}
write!(w, "{}", hunk)?;
}
Ok(())
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.