Skip to content

Commit 5131c5d

Browse files
romamikvrmiguel
andauthored
Better handling of "No newline at end of file" marker (#5)
Fixes #4 Co-authored-by: Vinícius Miguel <36349314+vrmiguel@users.noreply.github.com> Co-authored-by: vrmiguel <lemao.vrm07@hotmail.com>
1 parent ea05b24 commit 5131c5d

6 files changed

Lines changed: 272 additions & 96 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55

66
- `Patch::from_multiple` no longer returns an error on an input that contains no patches, including an empty string. It instead returns an empty vector.
77

8+
### Fixed
9+
- Issue #4: Fixed parsing of “No newline at end of file” markers so they are recognized even when not the final line of a hunk.
10+
811
### Changed
912

1013
## [v0.7]

examples/apply.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,16 @@ fn apply(diff: Patch, old: &str) -> String {
1414
old_line += hunk.old_range.count;
1515
for line in hunk.lines {
1616
match line {
17-
Line::Add(s) | Line::Context(s) => out.push(s),
17+
Line::Add(s) | Line::Context(s) => {
18+
out.push(s);
19+
}
1820
Line::Remove(_) => {}
1921
}
2022
}
2123
}
24+
if !diff.new_missing_newline {
25+
out.push("");
26+
}
2227
out.join("\n")
2328
}
2429

src/ast.rs

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,10 @@ pub struct Patch<'a> {
1414
pub new: File<'a>,
1515
/// hunks of differences; each hunk shows one area where the files differ
1616
pub hunks: Vec<Hunk<'a>>,
17-
/// true if the last line of the file ends in a newline character
18-
///
19-
/// This will only be false if at the end of the patch we encounter the text:
20-
/// `\ No newline at end of file`
21-
pub end_newline: bool,
17+
/// If there was a `No newline at end of file` indicator after the last line of the old version of the file
18+
pub old_missing_newline: bool,
19+
/// If there was a `No newline at end of file` indicator after the last line of the new version of the file
20+
pub new_missing_newline: bool,
2221
}
2322

2423
impl fmt::Display for Patch<'_> {
@@ -28,11 +27,13 @@ impl fmt::Display for Patch<'_> {
2827

2928
write!(f, "--- {}", self.old)?;
3029
write!(f, "\n+++ {}", self.new)?;
31-
for hunk in &self.hunks {
32-
write!(f, "\n{}", hunk)?;
33-
}
34-
if !self.end_newline {
35-
write!(f, "\n\\ No newline at end of file")?;
30+
for (i, hunk) in self.hunks.iter().enumerate() {
31+
writeln!(f)?;
32+
if i == self.hunks.len() - 1 {
33+
hunk.fmt(f, self.old_missing_newline, self.new_missing_newline)?;
34+
} else {
35+
hunk.fmt(f, false, false)?;
36+
}
3637
}
3738
Ok(())
3839
}
@@ -72,7 +73,8 @@ impl<'a> Patch<'a> {
7273
/// let patch = Patch::from_single(sample)?;
7374
/// assert_eq!(&patch.old.path, "lao");
7475
/// assert_eq!(&patch.new.path, "tzu");
75-
/// assert_eq!(patch.end_newline, false);
76+
/// assert_eq!(patch.old_missing_newline, false);
77+
/// assert_eq!(patch.new_missing_newline, true);
7678
/// # Ok(())
7779
/// # }
7880
/// ```
@@ -234,18 +236,41 @@ impl Hunk<'_> {
234236
Some(h)
235237
}
236238
}
237-
}
238239

239-
impl fmt::Display for Hunk<'_> {
240-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
240+
fn fmt(
241+
&self,
242+
f: &mut fmt::Formatter,
243+
old_missing_newline: bool,
244+
new_missing_newline: bool,
245+
) -> fmt::Result {
241246
write!(
242247
f,
243248
"@@ -{} +{} @@{}",
244249
self.old_range, self.new_range, self.range_hint
245250
)?;
246251

247-
for line in &self.lines {
252+
// compute line indices to put "No newline at end of file" indicator after
253+
let last_old_idx = old_missing_newline
254+
.then(|| {
255+
self.lines
256+
.iter()
257+
.rposition(|l| matches!(l, Line::Remove(_) | Line::Context(_)))
258+
})
259+
.flatten();
260+
let last_new_idx = new_missing_newline
261+
.then(|| {
262+
self.lines
263+
.iter()
264+
.rposition(|l| matches!(l, Line::Add(_) | Line::Context(_)))
265+
})
266+
.flatten();
267+
268+
for (i, line) in self.lines.iter().enumerate() {
248269
write!(f, "\n{}", line)?;
270+
if Some(i) == last_old_idx || Some(i) == last_new_idx {
271+
writeln!(f)?;
272+
write!(f, "\\ No newline at end of file")?;
273+
}
249274
}
250275

251276
Ok(())

0 commit comments

Comments
 (0)