Skip to main content

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}