-
Notifications
You must be signed in to change notification settings - Fork 405
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support unified diff format #56
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks great! One question: I did this:
$ git show HEAD~1:./src/delta.rs > /tmp/was.rs
$ diff -u /tmp/was.rs src/delta.rs | delta
and see this
I don't think it makes sense to include the "renamed/modified/added" line when processing non-git input, would you agree?
cf raw diff -u
output:
--- /tmp/was.rs 2019-11-19 17:11:36.372066306 -0500
+++ src/delta.rs 2019-11-18 13:23:37.574575743 -0500
@@ -7,6 +7,7 @@
use crate::bat::assets::HighlightingAssets;
Seeing as this is a new feature, it would be fantastic if you could add an "end-to-end" style test with a name like test_unified_diff
in mod tests
in src/delta.rs
, following the same style as those other tests. This would involve adding a new constant with a name like UNIFIED_DIFF_INPUT
and UNIFIED_DIFF_EXPECTED_OUTPUT
containing some example unified diff output and corresponding delta output, and making at least one assertion about the colors applied. Let me know if that makes sense (and whether you have time to do it.)
src/delta.rs
Outdated
state = State::FileMeta; | ||
state = State::GitFileMeta; | ||
painter.set_syntax(parse::get_file_extension_from_diff_line(&line)); | ||
} else if line.starts_with("diff -u ") || line.starts_with("diff -U") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shall we include the trailing space after both?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The -U
parameter takes an argument (the number of context lines)
So something like diff -U3 ...
is a valid command
I avoided a regex matcher because -U
is the only parameter that begins with a capital U, so it seemed unnecessary overhead.
Let me know what you think. I'm happy to either extend the check and look for spaces or digits, or make a regex pattern
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
-U
parameter takes an argument
Oh, I see. Makes sense then, I like your simple and efficient starts_with
implementation.
But, sorry if I'm being stupid, I don't see a string like diff -u
in unified diff output, do you?
$ diff -u <(echo a) <(echo b)
--- /dev/fd/63 2019-11-20 10:08:51.973225512 -0500
+++ /dev/fd/62 2019-11-20 10:08:51.973585959 -0500
@@ -1 +1 @@
-a
+b
$ diff --version
diff (GNU diffutils) 3.6
However, the output pasted by @fdcds in the intro of #53 does show a string like that, so I'm a bit confused. Is there a different version of diff
that outputs such a string? (On a Mac the system diff and the one from the coreutils brew package seem to be the same.) Seems the same on linux:
$ docker run ubuntu bash -c 'diff -u <(echo a) <(echo b); uname -a; diff --version'
--- /dev/fd/63 2019-11-20 15:17:14.345904000 +0000
+++ /dev/fd/62 2019-11-20 15:17:14.345904000 +0000
@@ -1 +1 @@
-a
+b
Linux 7c3c98a876c6 4.9.184-linuxkit #1 SMP Tue Jul 2 22:58:16 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
diff (GNU diffutils) 3.6
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah.. This is what I commented on #53, it wasn't very clear what was happening and I couldn't replicate it. I was very confused at first. But
I did manage to find out what he meant, though. You need to diff -u <directory1> <directory2>
, this will output diff -u ...
before each file, or Only in <directory1>
for files that do not have a name match
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, I see, thanks for explaining.
Hi Dan, thanks for the review. I totally agree that some tests are needed. Just found a couple more new corner cases. I'll go ahead and plop in this different scenarios to be tested As for the "renamed/modified/added", what about something like: |
* Detect the input and passthrough if not a diff * Show better header for diff -u between files
src/delta.rs
Outdated
#[derive(Debug, PartialEq)] | ||
pub enum Source { | ||
GitDiff, // Coming from a `git diff` command | ||
DiffUnified, // Coming from a `git -u` command |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Little typo here: s/git/diff/
if config.opt.commit_style != cli::SectionStyle::Plain { | ||
for raw_line in lines_peekable { | ||
if source == Source::Unknown { | ||
writeln!(painter.writer, "{}", raw_line)?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think a continue
statement here would make the code more readable?
* Fix typo
git diff
virtual pathThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a really nice PR. With the unit tests and careful coding style you've made it very little work for me here! I just have two comments here for you and then I think we'll be ready to merge.
src/delta.rs
Outdated
@@ -252,6 +313,28 @@ fn handle_hunk_line(painter: &mut Painter, line: &str, state: State, config: &Co | |||
} | |||
} | |||
|
|||
fn handle_file_uniqueness( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When I read the code I struggled a bit to understand this function name. The other analogous functions are called handle_commit_meta_header_line
, handle_file_meta_header_line
, handle_hunk_meta_line
, handle_hunk_line
.
WDYT about handle_unified_diff_unique_file_name
? And would you mind adding a brief docstring explaining what it does?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or handle_directory_diff_unique_file_name
?
src/delta.rs
Outdated
// Header | ||
assert_eq!( | ||
lines.nth(1).unwrap(), | ||
"comparing: one.rs\t2019-11-20 ⟶ src/two.rs\t2019-11-18" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm hesitant about including these dates with the file names. What's your thinking on this? I'm kind of thinking that timestamps are orthogonal to the question of how two files differ and we should use
comparing: one.rs ⟶ src/two.rs
.
comparing: bool, | ||
) -> String { | ||
if comparing { | ||
format!("comparing: {} ⟶ {}", minus_file, plus_file) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, I like your style decision here to make this harmonious with the git diff "renamed" output. (I just have that concern above about not including the date timestamps).
Here's an example and a question about the output. This creates two directories that have two comparable files, and also one unique file: mkdir /tmp/z1 /tmp/z2
git show HEAD~10:./src/delta.rs > /tmp/z1/a.rs
git show HEAD:./src/delta.rs > /tmp/z2/a.rs
touch /tmp/z2/b.rs
git show HEAD~10:./src/paint.rs > /tmp/z1/c.rs
git show HEAD:./src/paint.rs > /tmp/z2/c.rs
diff -u /tmp/z1 /tmp/z2 | delta At the end of the diff we get Now, did we expect the |
Thanks for the input, Dan. This is great feedback :) To address some of your points:
|
* Change diff -u function name and add doc * Handle file uniqueness after a hunk change
@@ -90,11 +114,20 @@ where | |||
handle_hunk_meta_line(&mut painter, &line, config)?; | |||
continue; | |||
} | |||
} else if source == Source::DiffUnified && line.starts_with("Only in ") { | |||
state = State::FileMeta; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I want to avoid generating a new state, and since this section should behave like a new file block, I used the same state
Let me know if you'd rather have a new state for it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reusing the same state here makes sense to me.
Thanks very much @m-lima, this is a great contribution. Incidentally, I wonder about the package name |
It was a pleasure picking up an issue with this project and a great first experience contributing to OSS :) |
As discussed on #53, I wasn't able to see the behavior reported. However, there is an assumption that the file name will be prepended by
a/
andb/
as it comes fromgit diff
.I ended up generating a new state to represent that the output is coming from
git diff
, since I didn't want to assume that the user wans't comparing files inside directoriesa
andb
, respectivelySome
cargo fmt
came in as well.. I can undo these, if you wish