Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 73 additions & 2 deletions src/diff/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::{
range::{DiffRange, SliceLike},
utils::Classifier,
};
use std::{cmp, ops};
use std::{borrow::Cow, cmp, ops};

mod cleanup;
mod myers;
Expand Down Expand Up @@ -46,6 +46,8 @@ where
pub struct DiffOptions {
compact: bool,
context_len: usize,
original_filename: Option<String>,
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it'd be better or more general to use Option<Cow<'a, str>> here. That'd be a semver-breaking change on DiffOptions so I went with just a String instead.

If you're willing to take a semver break, I'd be happy to add a <'a> to DiffOptions and use Cow<'a, str> here instead. That'd also simplify the changes I made in create_patch.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As a compromise we can use a Cow<'static, str> to avoid adding the lifetime to DiffOptions for now.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, good call. Thanks!

modified_filename: Option<String>,
}

impl DiffOptions {
Expand All @@ -57,6 +59,8 @@ impl DiffOptions {
Self {
compact: true,
context_len: 3,
original_filename: None,
modified_filename: None,
}
}

Expand All @@ -76,6 +80,22 @@ impl DiffOptions {
self
}

/// Set the filename to be used in the patch for the original text
///
/// If not set, the default value is "original".
pub fn set_original_filename(&mut self, filename: impl ToString) -> &mut Self {
self.original_filename = Some(filename.to_string());
self
}

/// Set the filename to be used in the patch for the modified text
///
/// If not set, the default value is "modified".
pub fn set_modified_filename(&mut self, filename: impl ToString) -> &mut Self {
self.modified_filename = Some(filename.to_string());
self
}

// TODO determine if this should be exposed in the public API
#[allow(dead_code)]
fn diff<'a>(&self, original: &'a str, modified: &'a str) -> Vec<Diff<'a, str>> {
Expand All @@ -102,7 +122,19 @@ impl DiffOptions {
let solution = self.diff_slice(&old_ids, &new_ids);

let hunks = to_hunks(&old_lines, &new_lines, &solution, self.context_len);
Patch::new(Some("original"), Some("modified"), hunks)
Patch::new(
self.original_filename
.as_ref()
.map_or(Some(Cow::Borrowed("original")), |s| {
Some(Cow::Owned(s.clone()))
}),
self.modified_filename
.as_ref()
.map_or(Some(Cow::Borrowed("modified")), |s| {
Some(Cow::Owned(s.clone()))
}),
hunks,
)
}

/// Create a patch between two potentially non-utf8 texts
Expand Down Expand Up @@ -358,3 +390,42 @@ fn build_edit_script<T>(solution: &[DiffRange<[T]>]) -> Vec<EditRange> {

edit_script
}

#[cfg(test)]
mod test {
use super::DiffOptions;

#[test]
fn set_original_and_modified_filenames() {
let original = "\
I am afraid, however, that all I have known - that my story - will be forgotten.
I am afraid for the world that is to come.
Afraid that my plans will fail.
Afraid of a doom worse than the Deepness.
";
let modified = "\
I am afraid, however, that all I have known - that my story - will be forgotten.
I am afraid for the world that is to come.
Afraid that Alendi will fail.
Afraid of a doom brought by the Deepness.
";
let expected = "\
--- the old version
+++ the better version
@@ -1,4 +1,4 @@
I am afraid, however, that all I have known - that my story - will be forgotten.
I am afraid for the world that is to come.
-Afraid that my plans will fail.
-Afraid of a doom worse than the Deepness.
+Afraid that Alendi will fail.
+Afraid of a doom brought by the Deepness.
";

let patch = DiffOptions::new()
.set_original_filename("the old version")
.set_modified_filename("the better version")
.create_patch(original, modified);

assert_eq!(patch.to_string(), expected);
}
}