termdiff/lib.rs
1//! This library is for helping you create diff for displaying on the terminal
2//!
3//! # Examples
4//!
5//! ```
6//! use termdiff::{diff, ArrowsTheme};
7//! let old = "The quick brown fox and\njumps over the sleepy dog";
8//! let new = "The quick red fox and\njumps over the lazy dog";
9//! let mut buffer: Vec<u8> = Vec::new();
10//! let theme = ArrowsTheme::default();
11//! diff(&mut buffer, old, new, &theme).unwrap();
12//! let actual: String = String::from_utf8(buffer).expect("Not valid UTF-8");
13//!
14//! assert_eq!(
15//! actual,
16//! "< left / > right
17//! <The quick brown fox and
18//! <jumps over the sleepy dog
19//! >The quick red fox and
20//! >jumps over the lazy dog
21//! "
22//! );
23//! ```
24//!
25//! Alternatively if you are dropping this into a `format!` or similar, you
26//! might want to use the displayable instead
27//!
28//! ```
29//! use termdiff::{DrawDiff, SignsTheme};
30//! let old = "The quick brown fox and\njumps over the sleepy dog";
31//! let new = "The quick red fox and\njumps over the lazy dog";
32//! let theme = SignsTheme::default();
33//! let actual = format!("{}", DrawDiff::new(old, new, &theme));
34//!
35//! assert_eq!(
36//! actual,
37//! "--- remove | insert +++
38//! -The quick brown fox and
39//! -jumps over the sleepy dog
40//! +The quick red fox and
41//! +jumps over the lazy dog
42//! "
43//! );
44//! ```
45//!
46//! # Features
47//!
48//! This crate provides several features that can be enabled or disabled in your `Cargo.toml`:
49//!
50//! ## Diff Algorithms
51//!
52//! * `myers` - Provides a Myers diff algorithm variant. This is a from-scratch
53//! implementation of Eugene Myers' O(ND) difference algorithm (1986) that
54//! does not depend on the `similar` crate. It can be used on its own
55//! (without the `similar` feature) and produces output compatible with the
56//! `similar` feature.
57//!
58//! * `similar` - Uses the "similar" crate to compute diffs. This is the primary
59//! algorithm implementation.
60//!
61//! ## Themes
62//!
63//! * `arrows` - A simple, colorless theme that uses arrow symbols (`<` and `>`) to indicate
64//! deleted and inserted lines. The header shows "< left / > right".
65//!
66//! * `arrows_color` - A colored version of the arrows theme. Uses red for deleted content and
67//! green for inserted content. Requires the "crossterm" crate for terminal color support.
68//!
69//! * `signs` - A simple, colorless theme that uses plus and minus signs (`-` and `+`) to indicate
70//! deleted and inserted lines. The header shows "--- remove | insert +++". This style is
71//! similar to traditional diff output.
72//!
73//! * `signs_color` - A colored version of the signs theme. Uses red for deleted content and
74//! green for inserted content. Requires the "crossterm" crate for terminal color support.
75//!
76//! By default, all features are enabled. You can selectively disable features by specifying
77//! `default-features = false` and then listing the features you want to enable.
78//!
79//! You can define your own theme if you like
80//!
81//!
82//! ``` rust
83//! use std::borrow::Cow;
84//!
85//! use crossterm::style::Stylize;
86//! use termdiff::{DrawDiff, Theme};
87//!
88//! #[derive(Debug)]
89//! struct MyTheme {}
90//! impl Theme for MyTheme {
91//! fn highlight_insert<'this>(&self, input: &'this str) -> Cow<'this, str> {
92//! input.into()
93//! }
94//!
95//! fn highlight_delete<'this>(&self, input: &'this str) -> Cow<'this, str> {
96//! input.into()
97//! }
98//!
99//! fn equal_content<'this>(&self, input: &'this str) -> Cow<'this, str> {
100//! input.into()
101//! }
102//!
103//! fn delete_content<'this>(&self, input: &'this str) -> Cow<'this, str> {
104//! input.into()
105//! }
106//!
107//! fn equal_prefix<'this>(&self) -> Cow<'this, str> {
108//! "=".into()
109//! }
110//!
111//! fn delete_prefix<'this>(&self) -> Cow<'this, str> {
112//! "!".into()
113//! }
114//!
115//! fn insert_line<'this>(&self, input: &'this str) -> Cow<'this, str> {
116//! input.into()
117//! }
118//!
119//! fn insert_prefix<'this>(&self) -> Cow<'this, str> {
120//! "|".into()
121//! }
122//!
123//! fn line_end<'this>(&self) -> Cow<'this, str> {
124//! "\n".into()
125//! }
126//!
127//! fn header<'this>(&self) -> Cow<'this, str> {
128//! format!("{}\n", "Header").into()
129//! }
130//! }
131//! let my_theme = MyTheme {};
132//! let old = "The quick brown fox and\njumps over the sleepy dog";
133//! let new = "The quick red fox and\njumps over the lazy dog";
134//! let actual = format!("{}", DrawDiff::new(old, new, &my_theme));
135//!
136//! assert_eq!(
137//! actual,
138//! "Header
139//! !The quick brown fox and
140//! !jumps over the sleepy dog
141//! |The quick red fox and
142//! |jumps over the lazy dog
143//! "
144//! );
145//! ```
146
147#![warn(clippy::nursery)]
148#![deny(
149 unused,
150 nonstandard_style,
151 future_incompatible,
152 missing_copy_implementations,
153 missing_debug_implementations,
154 missing_docs,
155 clippy::pedantic,
156 clippy::cargo,
157 clippy::complexity,
158 clippy::correctness,
159 clippy::perf,
160 clippy::style,
161 clippy::suspicious,
162 non_fmt_panics
163)]
164#![allow(clippy::multiple_crate_versions)]
165
166pub use cmd::{diff, diff_with_algorithm};
167pub use diff_algorithm::Algorithm;
168pub use draw_diff::DrawDiff;
169
170// Re-export the Theme trait and theme implementations
171#[cfg(feature = "arrows_color")]
172pub use themes::ArrowsColorTheme;
173#[cfg(feature = "arrows")]
174pub use themes::ArrowsTheme;
175#[cfg(feature = "signs_color")]
176pub use themes::SignsColorTheme;
177#[cfg(feature = "signs")]
178pub use themes::SignsTheme;
179pub use themes::Theme;
180
181mod cmd;
182mod diff_algorithm;
183mod draw_diff;
184mod themes;
185
186#[cfg(doctest)]
187mod test_readme {
188 macro_rules! external_doc_test {
189 ($x:expr) => {
190 #[doc = $x]
191 extern "C" {}
192 };
193 }
194
195 external_doc_test!(include_str!("../README.md"));
196}