mirror of
https://github.com/uutils/diffutils.git
synced 2026-06-10 15:48:59 -07:00
Implement --tabsize option
This commit is contained in:
Generated
+1
@@ -81,6 +81,7 @@ dependencies = [
|
||||
"diff",
|
||||
"predicates",
|
||||
"pretty_assertions",
|
||||
"regex",
|
||||
"same-file",
|
||||
"tempfile",
|
||||
"unicode-width",
|
||||
|
||||
@@ -16,6 +16,7 @@ path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
diff = "0.1.10"
|
||||
regex = "1.10.3"
|
||||
same-file = "1.0.6"
|
||||
unicode-width = "0.1.11"
|
||||
|
||||
|
||||
+15
-6
@@ -273,6 +273,7 @@ pub fn diff(
|
||||
context_size: usize,
|
||||
stop_early: bool,
|
||||
expand_tabs: bool,
|
||||
tabsize: usize,
|
||||
) -> Vec<u8> {
|
||||
let mut output = format!("*** {expected_filename}\t\n--- {actual_filename}\t\n").into_bytes();
|
||||
let diff_results = make_diff(expected, actual, context_size, stop_early);
|
||||
@@ -317,19 +318,19 @@ pub fn diff(
|
||||
match line {
|
||||
DiffLine::Context(e) => {
|
||||
write!(output, " ").expect("write to Vec is infallible");
|
||||
do_write_line(&mut output, &e, expand_tabs)
|
||||
do_write_line(&mut output, &e, expand_tabs, tabsize)
|
||||
.expect("write to Vec is infallible");
|
||||
writeln!(output).unwrap();
|
||||
}
|
||||
DiffLine::Change(e) => {
|
||||
write!(output, "! ").expect("write to Vec is infallible");
|
||||
do_write_line(&mut output, &e, expand_tabs)
|
||||
do_write_line(&mut output, &e, expand_tabs, tabsize)
|
||||
.expect("write to Vec is infallible");
|
||||
writeln!(output).unwrap();
|
||||
}
|
||||
DiffLine::Add(e) => {
|
||||
write!(output, "- ").expect("write to Vec is infallible");
|
||||
do_write_line(&mut output, &e, expand_tabs)
|
||||
do_write_line(&mut output, &e, expand_tabs, tabsize)
|
||||
.expect("write to Vec is infallible");
|
||||
writeln!(output).unwrap();
|
||||
}
|
||||
@@ -347,19 +348,19 @@ pub fn diff(
|
||||
match line {
|
||||
DiffLine::Context(e) => {
|
||||
write!(output, " ").expect("write to Vec is infallible");
|
||||
do_write_line(&mut output, &e, expand_tabs)
|
||||
do_write_line(&mut output, &e, expand_tabs, tabsize)
|
||||
.expect("write to Vec is infallible");
|
||||
writeln!(output).unwrap();
|
||||
}
|
||||
DiffLine::Change(e) => {
|
||||
write!(output, "! ").expect("write to Vec is infallible");
|
||||
do_write_line(&mut output, &e, expand_tabs)
|
||||
do_write_line(&mut output, &e, expand_tabs, tabsize)
|
||||
.expect("write to Vec is infallible");
|
||||
writeln!(output).unwrap();
|
||||
}
|
||||
DiffLine::Add(e) => {
|
||||
write!(output, "+ ").expect("write to Vec is infallible");
|
||||
do_write_line(&mut output, &e, expand_tabs)
|
||||
do_write_line(&mut output, &e, expand_tabs, tabsize)
|
||||
.expect("write to Vec is infallible");
|
||||
writeln!(output).unwrap();
|
||||
}
|
||||
@@ -434,6 +435,7 @@ mod tests {
|
||||
2,
|
||||
false,
|
||||
false,
|
||||
8,
|
||||
);
|
||||
File::create(&format!("{target}/ab.diff"))
|
||||
.unwrap()
|
||||
@@ -514,6 +516,7 @@ mod tests {
|
||||
2,
|
||||
false,
|
||||
false,
|
||||
8,
|
||||
);
|
||||
File::create(&format!("{target}/ab_.diff"))
|
||||
.unwrap()
|
||||
@@ -597,6 +600,7 @@ mod tests {
|
||||
2,
|
||||
false,
|
||||
false,
|
||||
8,
|
||||
);
|
||||
File::create(&format!("{target}/abx.diff"))
|
||||
.unwrap()
|
||||
@@ -683,6 +687,7 @@ mod tests {
|
||||
2,
|
||||
false,
|
||||
false,
|
||||
8,
|
||||
);
|
||||
File::create(&format!("{target}/abr.diff"))
|
||||
.unwrap()
|
||||
@@ -729,6 +734,7 @@ mod tests {
|
||||
context_size,
|
||||
false,
|
||||
false,
|
||||
8,
|
||||
);
|
||||
let expected_full = [
|
||||
"*** foo\t",
|
||||
@@ -755,6 +761,7 @@ mod tests {
|
||||
context_size,
|
||||
true,
|
||||
false,
|
||||
8,
|
||||
);
|
||||
let expected_brief = ["*** foo\t", "--- bar\t", ""].join("\n");
|
||||
assert_eq!(diff_brief, expected_brief.as_bytes());
|
||||
@@ -767,6 +774,7 @@ mod tests {
|
||||
context_size,
|
||||
false,
|
||||
false,
|
||||
8,
|
||||
);
|
||||
assert!(nodiff_full.is_empty());
|
||||
|
||||
@@ -778,6 +786,7 @@ mod tests {
|
||||
context_size,
|
||||
true,
|
||||
false,
|
||||
8,
|
||||
);
|
||||
assert!(nodiff_brief.is_empty());
|
||||
}
|
||||
|
||||
+8
-7
@@ -114,6 +114,7 @@ pub fn diff(
|
||||
actual: &[u8],
|
||||
stop_early: bool,
|
||||
expand_tabs: bool,
|
||||
tabsize: usize,
|
||||
) -> Result<Vec<u8>, DiffError> {
|
||||
let mut output = Vec::new();
|
||||
let diff_results = make_diff(expected, actual, stop_early)?;
|
||||
@@ -152,7 +153,7 @@ pub fn diff(
|
||||
if actual == b"." {
|
||||
writeln!(&mut output, "..\n.\ns/.//\na").unwrap();
|
||||
} else {
|
||||
do_write_line(&mut output, actual, expand_tabs).unwrap();
|
||||
do_write_line(&mut output, actual, expand_tabs, tabsize).unwrap();
|
||||
writeln!(&mut output).unwrap();
|
||||
}
|
||||
}
|
||||
@@ -167,7 +168,7 @@ mod tests {
|
||||
use super::*;
|
||||
use pretty_assertions::assert_eq;
|
||||
pub fn diff_w(expected: &[u8], actual: &[u8], filename: &str) -> Result<Vec<u8>, DiffError> {
|
||||
let mut output = diff(expected, actual, false, false)?;
|
||||
let mut output = diff(expected, actual, false, false, 8)?;
|
||||
writeln!(&mut output, "w {filename}").unwrap();
|
||||
Ok(output)
|
||||
}
|
||||
@@ -176,7 +177,7 @@ mod tests {
|
||||
fn test_basic() {
|
||||
let from = b"a\n";
|
||||
let to = b"b\n";
|
||||
let diff = diff(from, to, false, false).unwrap();
|
||||
let diff = diff(from, to, false, false, 8).unwrap();
|
||||
let expected = ["1c", "b", ".", ""].join("\n");
|
||||
assert_eq!(diff, expected.as_bytes());
|
||||
}
|
||||
@@ -411,18 +412,18 @@ mod tests {
|
||||
let from = ["a", "b", "c", ""].join("\n");
|
||||
let to = ["a", "d", "c", ""].join("\n");
|
||||
|
||||
let diff_full = diff(from.as_bytes(), to.as_bytes(), false, false).unwrap();
|
||||
let diff_full = diff(from.as_bytes(), to.as_bytes(), false, false, 8).unwrap();
|
||||
let expected_full = ["2c", "d", ".", ""].join("\n");
|
||||
assert_eq!(diff_full, expected_full.as_bytes());
|
||||
|
||||
let diff_brief = diff(from.as_bytes(), to.as_bytes(), true, false).unwrap();
|
||||
let diff_brief = diff(from.as_bytes(), to.as_bytes(), true, false, 8).unwrap();
|
||||
let expected_brief = "\0".as_bytes();
|
||||
assert_eq!(diff_brief, expected_brief);
|
||||
|
||||
let nodiff_full = diff(from.as_bytes(), from.as_bytes(), false, false).unwrap();
|
||||
let nodiff_full = diff(from.as_bytes(), from.as_bytes(), false, false, 8).unwrap();
|
||||
assert!(nodiff_full.is_empty());
|
||||
|
||||
let nodiff_brief = diff(from.as_bytes(), from.as_bytes(), true, false).unwrap();
|
||||
let nodiff_brief = diff(from.as_bytes(), from.as_bytes(), true, false, 8).unwrap();
|
||||
assert!(nodiff_brief.is_empty());
|
||||
}
|
||||
}
|
||||
|
||||
+9
-5
@@ -32,6 +32,7 @@ fn main() -> ExitCode {
|
||||
report_identical_files,
|
||||
brief,
|
||||
expand_tabs,
|
||||
tabsize,
|
||||
} = parse_params(opts).unwrap_or_else(|error| {
|
||||
eprintln!("{error}");
|
||||
exit(2);
|
||||
@@ -67,7 +68,9 @@ fn main() -> ExitCode {
|
||||
};
|
||||
// run diff
|
||||
let result: Vec<u8> = match format {
|
||||
Format::Normal => normal_diff::diff(&from_content, &to_content, brief, expand_tabs),
|
||||
Format::Normal => {
|
||||
normal_diff::diff(&from_content, &to_content, brief, expand_tabs, tabsize)
|
||||
}
|
||||
Format::Unified => unified_diff::diff(
|
||||
&from_content,
|
||||
&from.to_string_lossy(),
|
||||
@@ -76,6 +79,7 @@ fn main() -> ExitCode {
|
||||
context_count,
|
||||
brief,
|
||||
expand_tabs,
|
||||
tabsize,
|
||||
),
|
||||
Format::Context => context_diff::diff(
|
||||
&from_content,
|
||||
@@ -85,13 +89,13 @@ fn main() -> ExitCode {
|
||||
context_count,
|
||||
brief,
|
||||
expand_tabs,
|
||||
tabsize,
|
||||
),
|
||||
Format::Ed => {
|
||||
ed_diff::diff(&from_content, &to_content, brief, expand_tabs).unwrap_or_else(|error| {
|
||||
Format::Ed => ed_diff::diff(&from_content, &to_content, brief, expand_tabs, tabsize)
|
||||
.unwrap_or_else(|error| {
|
||||
eprintln!("{error}");
|
||||
exit(2);
|
||||
})
|
||||
}
|
||||
}),
|
||||
};
|
||||
if brief && !result.is_empty() {
|
||||
println!(
|
||||
|
||||
+18
-12
@@ -116,7 +116,13 @@ fn make_diff(expected: &[u8], actual: &[u8], stop_early: bool) -> Vec<Mismatch>
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn diff(expected: &[u8], actual: &[u8], stop_early: bool, expand_tabs: bool) -> Vec<u8> {
|
||||
pub fn diff(
|
||||
expected: &[u8],
|
||||
actual: &[u8],
|
||||
stop_early: bool,
|
||||
expand_tabs: bool,
|
||||
tabsize: usize,
|
||||
) -> Vec<u8> {
|
||||
// See https://www.gnu.org/software/diffutils/manual/html_node/Detailed-Normal.html
|
||||
// for details on the syntax of the normal format.
|
||||
let mut output = Vec::new();
|
||||
@@ -190,7 +196,7 @@ pub fn diff(expected: &[u8], actual: &[u8], stop_early: bool, expand_tabs: bool)
|
||||
}
|
||||
for expected in &result.expected {
|
||||
write!(&mut output, "< ").unwrap();
|
||||
do_write_line(&mut output, expected, expand_tabs).unwrap();
|
||||
do_write_line(&mut output, expected, expand_tabs, tabsize).unwrap();
|
||||
writeln!(&mut output).unwrap();
|
||||
}
|
||||
if result.expected_missing_nl {
|
||||
@@ -201,7 +207,7 @@ pub fn diff(expected: &[u8], actual: &[u8], stop_early: bool, expand_tabs: bool)
|
||||
}
|
||||
for actual in &result.actual {
|
||||
write!(&mut output, "> ").unwrap();
|
||||
do_write_line(&mut output, actual, expand_tabs).unwrap();
|
||||
do_write_line(&mut output, actual, expand_tabs, tabsize).unwrap();
|
||||
writeln!(&mut output).unwrap();
|
||||
}
|
||||
if result.actual_missing_nl {
|
||||
@@ -222,7 +228,7 @@ mod tests {
|
||||
a.write_all(b"a\n").unwrap();
|
||||
let mut b = Vec::new();
|
||||
b.write_all(b"b\n").unwrap();
|
||||
let diff = diff(&a, &b, false, false);
|
||||
let diff = diff(&a, &b, false, false, 8);
|
||||
let expected = b"1c1\n< a\n---\n> b\n".to_vec();
|
||||
assert_eq!(diff, expected);
|
||||
}
|
||||
@@ -275,7 +281,7 @@ mod tests {
|
||||
}
|
||||
// This test diff is intentionally reversed.
|
||||
// We want it to turn the alef into bet.
|
||||
let diff = diff(&alef, &bet, false, false);
|
||||
let diff = diff(&alef, &bet, false, false, 8);
|
||||
File::create(&format!("{target}/ab.diff"))
|
||||
.unwrap()
|
||||
.write_all(&diff)
|
||||
@@ -367,7 +373,7 @@ mod tests {
|
||||
}
|
||||
// This test diff is intentionally reversed.
|
||||
// We want it to turn the alef into bet.
|
||||
let diff = diff(&alef, &bet, false, false);
|
||||
let diff = diff(&alef, &bet, false, false, 8);
|
||||
File::create(&format!("{target}/abn.diff"))
|
||||
.unwrap()
|
||||
.write_all(&diff)
|
||||
@@ -441,7 +447,7 @@ mod tests {
|
||||
}
|
||||
// This test diff is intentionally reversed.
|
||||
// We want it to turn the alef into bet.
|
||||
let diff = diff(&alef, &bet, false, false);
|
||||
let diff = diff(&alef, &bet, false, false, 8);
|
||||
File::create(&format!("{target}/ab_.diff"))
|
||||
.unwrap()
|
||||
.write_all(&diff)
|
||||
@@ -519,7 +525,7 @@ mod tests {
|
||||
}
|
||||
// This test diff is intentionally reversed.
|
||||
// We want it to turn the alef into bet.
|
||||
let diff = diff(&alef, &bet, false, false);
|
||||
let diff = diff(&alef, &bet, false, false, 8);
|
||||
File::create(&format!("{target}/abr.diff"))
|
||||
.unwrap()
|
||||
.write_all(&diff)
|
||||
@@ -554,18 +560,18 @@ mod tests {
|
||||
let from = ["a", "b", "c"].join("\n");
|
||||
let to = ["a", "d", "c"].join("\n");
|
||||
|
||||
let diff_full = diff(from.as_bytes(), to.as_bytes(), false, false);
|
||||
let diff_full = diff(from.as_bytes(), to.as_bytes(), false, false, 8);
|
||||
let expected_full = ["2c2", "< b", "---", "> d", ""].join("\n");
|
||||
assert_eq!(diff_full, expected_full.as_bytes());
|
||||
|
||||
let diff_brief = diff(from.as_bytes(), to.as_bytes(), true, false);
|
||||
let diff_brief = diff(from.as_bytes(), to.as_bytes(), true, false, 8);
|
||||
let expected_brief = "\0".as_bytes();
|
||||
assert_eq!(diff_brief, expected_brief);
|
||||
|
||||
let nodiff_full = diff(from.as_bytes(), from.as_bytes(), false, false);
|
||||
let nodiff_full = diff(from.as_bytes(), from.as_bytes(), false, false, 8);
|
||||
assert!(nodiff_full.is_empty());
|
||||
|
||||
let nodiff_brief = diff(from.as_bytes(), from.as_bytes(), true, false);
|
||||
let nodiff_brief = diff(from.as_bytes(), from.as_bytes(), true, false, 8);
|
||||
assert!(nodiff_brief.is_empty());
|
||||
}
|
||||
}
|
||||
|
||||
+130
@@ -1,5 +1,7 @@
|
||||
use std::ffi::{OsStr, OsString};
|
||||
|
||||
use regex::Regex;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub enum Format {
|
||||
Normal,
|
||||
@@ -8,6 +10,8 @@ pub enum Format {
|
||||
Ed,
|
||||
}
|
||||
|
||||
const DEFAULT_TABSIZE: usize = 8;
|
||||
|
||||
#[cfg(unix)]
|
||||
fn osstr_bytes(osstr: &OsStr) -> &[u8] {
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
@@ -28,6 +32,7 @@ pub struct Params {
|
||||
pub report_identical_files: bool,
|
||||
pub brief: bool,
|
||||
pub expand_tabs: bool,
|
||||
pub tabsize: usize,
|
||||
}
|
||||
|
||||
pub fn parse_params<I: IntoIterator<Item = OsString>>(opts: I) -> Result<Params, String> {
|
||||
@@ -44,6 +49,8 @@ pub fn parse_params<I: IntoIterator<Item = OsString>>(opts: I) -> Result<Params,
|
||||
let mut report_identical_files = false;
|
||||
let mut brief = false;
|
||||
let mut expand_tabs = false;
|
||||
let tabsize_re = Regex::new(r"^--tabsize=(?<num>\d+)$").unwrap();
|
||||
let mut tabsize = DEFAULT_TABSIZE;
|
||||
while let Some(param) = opts.next() {
|
||||
if param == "--" {
|
||||
break;
|
||||
@@ -70,6 +77,22 @@ pub fn parse_params<I: IntoIterator<Item = OsString>>(opts: I) -> Result<Params,
|
||||
expand_tabs = true;
|
||||
continue;
|
||||
}
|
||||
if tabsize_re.is_match(param.to_string_lossy().as_ref()) {
|
||||
// Because param matches the regular expression,
|
||||
// it is safe to assume it is valid UTF-8.
|
||||
let param = param.into_string().unwrap();
|
||||
let tabsize_str = tabsize_re
|
||||
.captures(param.as_str())
|
||||
.unwrap()
|
||||
.name("num")
|
||||
.unwrap()
|
||||
.as_str();
|
||||
tabsize = match tabsize_str.parse::<usize>() {
|
||||
Ok(num) => num,
|
||||
Err(_) => return Err(format!("invalid tabsize «{}»", tabsize_str)),
|
||||
};
|
||||
continue;
|
||||
}
|
||||
let p = osstr_bytes(¶m);
|
||||
if p.first() == Some(&b'-') && p.get(1) != Some(&b'-') {
|
||||
let mut bit = p[1..].iter().copied().peekable();
|
||||
@@ -154,6 +177,7 @@ pub fn parse_params<I: IntoIterator<Item = OsString>>(opts: I) -> Result<Params,
|
||||
report_identical_files,
|
||||
brief,
|
||||
expand_tabs,
|
||||
tabsize,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -174,6 +198,7 @@ mod tests {
|
||||
report_identical_files: false,
|
||||
brief: false,
|
||||
expand_tabs: false,
|
||||
tabsize: DEFAULT_TABSIZE,
|
||||
}),
|
||||
parse_params([os("diff"), os("foo"), os("bar")].iter().cloned())
|
||||
);
|
||||
@@ -189,6 +214,7 @@ mod tests {
|
||||
report_identical_files: false,
|
||||
brief: false,
|
||||
expand_tabs: false,
|
||||
tabsize: DEFAULT_TABSIZE,
|
||||
}),
|
||||
parse_params([os("diff"), os("-e"), os("foo"), os("bar")].iter().cloned())
|
||||
);
|
||||
@@ -204,6 +230,7 @@ mod tests {
|
||||
report_identical_files: false,
|
||||
brief: false,
|
||||
expand_tabs: false,
|
||||
tabsize: DEFAULT_TABSIZE,
|
||||
}),
|
||||
parse_params(
|
||||
[os("diff"), os("-u54"), os("foo"), os("bar")]
|
||||
@@ -220,6 +247,7 @@ mod tests {
|
||||
report_identical_files: false,
|
||||
brief: false,
|
||||
expand_tabs: false,
|
||||
tabsize: DEFAULT_TABSIZE,
|
||||
}),
|
||||
parse_params(
|
||||
[os("diff"), os("-U54"), os("foo"), os("bar")]
|
||||
@@ -236,6 +264,7 @@ mod tests {
|
||||
report_identical_files: false,
|
||||
brief: false,
|
||||
expand_tabs: false,
|
||||
tabsize: DEFAULT_TABSIZE,
|
||||
}),
|
||||
parse_params(
|
||||
[os("diff"), os("-U"), os("54"), os("foo"), os("bar")]
|
||||
@@ -252,6 +281,7 @@ mod tests {
|
||||
report_identical_files: false,
|
||||
brief: false,
|
||||
expand_tabs: false,
|
||||
tabsize: DEFAULT_TABSIZE,
|
||||
}),
|
||||
parse_params(
|
||||
[os("diff"), os("-c54"), os("foo"), os("bar")]
|
||||
@@ -271,6 +301,7 @@ mod tests {
|
||||
report_identical_files: false,
|
||||
brief: false,
|
||||
expand_tabs: false,
|
||||
tabsize: DEFAULT_TABSIZE,
|
||||
}),
|
||||
parse_params([os("diff"), os("foo"), os("bar")].iter().cloned())
|
||||
);
|
||||
@@ -283,6 +314,7 @@ mod tests {
|
||||
report_identical_files: true,
|
||||
brief: false,
|
||||
expand_tabs: false,
|
||||
tabsize: DEFAULT_TABSIZE,
|
||||
}),
|
||||
parse_params([os("diff"), os("-s"), os("foo"), os("bar")].iter().cloned())
|
||||
);
|
||||
@@ -295,6 +327,7 @@ mod tests {
|
||||
report_identical_files: true,
|
||||
brief: false,
|
||||
expand_tabs: false,
|
||||
tabsize: DEFAULT_TABSIZE,
|
||||
}),
|
||||
parse_params(
|
||||
[
|
||||
@@ -319,6 +352,7 @@ mod tests {
|
||||
report_identical_files: false,
|
||||
brief: false,
|
||||
expand_tabs: false,
|
||||
tabsize: 8,
|
||||
}),
|
||||
parse_params([os("diff"), os("foo"), os("bar")].iter().cloned())
|
||||
);
|
||||
@@ -331,6 +365,7 @@ mod tests {
|
||||
report_identical_files: false,
|
||||
brief: true,
|
||||
expand_tabs: false,
|
||||
tabsize: 8,
|
||||
}),
|
||||
parse_params([os("diff"), os("-q"), os("foo"), os("bar")].iter().cloned())
|
||||
);
|
||||
@@ -343,6 +378,7 @@ mod tests {
|
||||
report_identical_files: false,
|
||||
brief: true,
|
||||
expand_tabs: false,
|
||||
tabsize: 8,
|
||||
}),
|
||||
parse_params(
|
||||
[os("diff"), os("--brief"), os("foo"), os("bar"),]
|
||||
@@ -362,6 +398,7 @@ mod tests {
|
||||
report_identical_files: false,
|
||||
brief: false,
|
||||
expand_tabs: false,
|
||||
tabsize: DEFAULT_TABSIZE,
|
||||
}),
|
||||
parse_params([os("diff"), os("foo"), os("bar")].iter().cloned())
|
||||
);
|
||||
@@ -375,6 +412,7 @@ mod tests {
|
||||
report_identical_files: false,
|
||||
brief: false,
|
||||
expand_tabs: true,
|
||||
tabsize: DEFAULT_TABSIZE,
|
||||
}),
|
||||
parse_params(
|
||||
[os("diff"), os(option), os("foo"), os("bar")]
|
||||
@@ -385,6 +423,97 @@ mod tests {
|
||||
}
|
||||
}
|
||||
#[test]
|
||||
fn tabsize() {
|
||||
assert_eq!(
|
||||
Ok(Params {
|
||||
from: os("foo"),
|
||||
to: os("bar"),
|
||||
format: Format::Normal,
|
||||
context_count: 3,
|
||||
report_identical_files: false,
|
||||
brief: false,
|
||||
expand_tabs: false,
|
||||
tabsize: DEFAULT_TABSIZE,
|
||||
}),
|
||||
parse_params([os("diff"), os("foo"), os("bar")].iter().cloned())
|
||||
);
|
||||
assert_eq!(
|
||||
Ok(Params {
|
||||
from: os("foo"),
|
||||
to: os("bar"),
|
||||
format: Format::Normal,
|
||||
context_count: 3,
|
||||
report_identical_files: false,
|
||||
brief: false,
|
||||
expand_tabs: false,
|
||||
tabsize: 0,
|
||||
}),
|
||||
parse_params(
|
||||
[os("diff"), os("--tabsize=0"), os("foo"), os("bar")]
|
||||
.iter()
|
||||
.cloned()
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
Ok(Params {
|
||||
from: os("foo"),
|
||||
to: os("bar"),
|
||||
format: Format::Normal,
|
||||
context_count: 3,
|
||||
report_identical_files: false,
|
||||
brief: false,
|
||||
expand_tabs: false,
|
||||
tabsize: 42,
|
||||
}),
|
||||
parse_params(
|
||||
[os("diff"), os("--tabsize=42"), os("foo"), os("bar")]
|
||||
.iter()
|
||||
.cloned()
|
||||
)
|
||||
);
|
||||
assert!(parse_params(
|
||||
[os("diff"), os("--tabsize"), os("foo"), os("bar")]
|
||||
.iter()
|
||||
.cloned()
|
||||
)
|
||||
.is_err());
|
||||
assert!(parse_params(
|
||||
[os("diff"), os("--tabsize="), os("foo"), os("bar")]
|
||||
.iter()
|
||||
.cloned()
|
||||
)
|
||||
.is_err());
|
||||
assert!(parse_params(
|
||||
[os("diff"), os("--tabsize=r2"), os("foo"), os("bar")]
|
||||
.iter()
|
||||
.cloned()
|
||||
)
|
||||
.is_err());
|
||||
assert!(parse_params(
|
||||
[os("diff"), os("--tabsize=-1"), os("foo"), os("bar")]
|
||||
.iter()
|
||||
.cloned()
|
||||
)
|
||||
.is_err());
|
||||
assert!(parse_params(
|
||||
[os("diff"), os("--tabsize=r2"), os("foo"), os("bar")]
|
||||
.iter()
|
||||
.cloned()
|
||||
)
|
||||
.is_err());
|
||||
assert!(parse_params(
|
||||
[
|
||||
os("diff"),
|
||||
os("--tabsize=92233720368547758088"),
|
||||
os("foo"),
|
||||
os("bar")
|
||||
]
|
||||
.iter()
|
||||
.cloned()
|
||||
)
|
||||
.is_err());
|
||||
}
|
||||
#[test]
|
||||
fn double_dash() {
|
||||
assert_eq!(
|
||||
Ok(Params {
|
||||
@@ -395,6 +524,7 @@ mod tests {
|
||||
report_identical_files: false,
|
||||
brief: false,
|
||||
expand_tabs: false,
|
||||
tabsize: DEFAULT_TABSIZE,
|
||||
}),
|
||||
parse_params([os("diff"), os("--"), os("-g"), os("-h")].iter().cloned())
|
||||
);
|
||||
|
||||
+13
-3
@@ -244,6 +244,7 @@ pub fn diff(
|
||||
context_size: usize,
|
||||
stop_early: bool,
|
||||
expand_tabs: bool,
|
||||
tabsize: usize,
|
||||
) -> Vec<u8> {
|
||||
let mut output = format!("--- {expected_filename}\t\n+++ {actual_filename}\t\n").into_bytes();
|
||||
let diff_results = make_diff(expected, actual, context_size, stop_early);
|
||||
@@ -374,19 +375,19 @@ pub fn diff(
|
||||
match line {
|
||||
DiffLine::Expected(e) => {
|
||||
write!(output, "-").expect("write to Vec is infallible");
|
||||
do_write_line(&mut output, &e, expand_tabs)
|
||||
do_write_line(&mut output, &e, expand_tabs, tabsize)
|
||||
.expect("write to Vec is infallible");
|
||||
writeln!(output).unwrap();
|
||||
}
|
||||
DiffLine::Context(c) => {
|
||||
write!(output, " ").expect("write to Vec is infallible");
|
||||
do_write_line(&mut output, &c, expand_tabs)
|
||||
do_write_line(&mut output, &c, expand_tabs, tabsize)
|
||||
.expect("write to Vec is infallible");
|
||||
writeln!(output).unwrap();
|
||||
}
|
||||
DiffLine::Actual(r) => {
|
||||
write!(output, "+",).expect("write to Vec is infallible");
|
||||
do_write_line(&mut output, &r, expand_tabs)
|
||||
do_write_line(&mut output, &r, expand_tabs, tabsize)
|
||||
.expect("write to Vec is infallible");
|
||||
writeln!(output).unwrap();
|
||||
}
|
||||
@@ -461,6 +462,7 @@ mod tests {
|
||||
2,
|
||||
false,
|
||||
false,
|
||||
8,
|
||||
);
|
||||
File::create(&format!("{target}/ab.diff"))
|
||||
.unwrap()
|
||||
@@ -576,6 +578,7 @@ mod tests {
|
||||
2,
|
||||
false,
|
||||
false,
|
||||
8,
|
||||
);
|
||||
File::create(&format!("{target}/abn.diff"))
|
||||
.unwrap()
|
||||
@@ -671,6 +674,7 @@ mod tests {
|
||||
2,
|
||||
false,
|
||||
false,
|
||||
8,
|
||||
);
|
||||
File::create(&format!("{target}/ab_.diff"))
|
||||
.unwrap()
|
||||
@@ -751,6 +755,7 @@ mod tests {
|
||||
2,
|
||||
false,
|
||||
false,
|
||||
8,
|
||||
);
|
||||
File::create(&format!("{target}/abx.diff"))
|
||||
.unwrap()
|
||||
@@ -836,6 +841,7 @@ mod tests {
|
||||
2,
|
||||
false,
|
||||
false,
|
||||
8,
|
||||
);
|
||||
File::create(&format!("{target}/abr.diff"))
|
||||
.unwrap()
|
||||
@@ -881,6 +887,7 @@ mod tests {
|
||||
context_size,
|
||||
false,
|
||||
false,
|
||||
8,
|
||||
);
|
||||
let expected_full = [
|
||||
"--- foo\t",
|
||||
@@ -903,6 +910,7 @@ mod tests {
|
||||
context_size,
|
||||
true,
|
||||
false,
|
||||
8,
|
||||
);
|
||||
let expected_brief = ["--- foo\t", "+++ bar\t", ""].join("\n");
|
||||
assert_eq!(diff_brief, expected_brief.as_bytes());
|
||||
@@ -915,6 +923,7 @@ mod tests {
|
||||
context_size,
|
||||
false,
|
||||
false,
|
||||
8,
|
||||
);
|
||||
assert!(nodiff_full.is_empty());
|
||||
|
||||
@@ -926,6 +935,7 @@ mod tests {
|
||||
context_size,
|
||||
true,
|
||||
false,
|
||||
8,
|
||||
);
|
||||
assert!(nodiff_brief.is_empty());
|
||||
}
|
||||
|
||||
+12
-7
@@ -38,9 +38,14 @@ pub fn do_expand_tabs(line: &[u8], tabsize: usize) -> Vec<u8> {
|
||||
/// Write a single line to an output stream, expanding tabs to space if necessary.
|
||||
/// This assumes that line does not contain any line breaks
|
||||
/// (if it does and tabs are to be expanded to spaces, the result is undefined).
|
||||
pub fn do_write_line(output: &mut Vec<u8>, line: &[u8], expand_tabs: bool) -> std::io::Result<()> {
|
||||
pub fn do_write_line(
|
||||
output: &mut Vec<u8>,
|
||||
line: &[u8],
|
||||
expand_tabs: bool,
|
||||
tabsize: usize,
|
||||
) -> std::io::Result<()> {
|
||||
if expand_tabs {
|
||||
output.write_all(do_expand_tabs(line, 8).as_slice())
|
||||
output.write_all(do_expand_tabs(line, tabsize).as_slice())
|
||||
} else {
|
||||
output.write_all(line)
|
||||
}
|
||||
@@ -96,17 +101,17 @@ mod tests {
|
||||
use super::*;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
fn assert_line_written(line: &str, expand_tabs: bool, expected: &str) {
|
||||
fn assert_line_written(line: &str, expand_tabs: bool, tabsize: usize, expected: &str) {
|
||||
let mut output: Vec<u8> = Vec::new();
|
||||
assert!(do_write_line(&mut output, line.as_bytes(), expand_tabs).is_ok());
|
||||
assert!(do_write_line(&mut output, line.as_bytes(), expand_tabs, tabsize).is_ok());
|
||||
assert_eq!(output, expected.as_bytes());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn basics() {
|
||||
assert_line_written("foo bar baz", false, "foo bar baz");
|
||||
assert_line_written("foo bar\tbaz", false, "foo bar\tbaz");
|
||||
assert_line_written("foo bar\tbaz", true, "foo bar baz");
|
||||
assert_line_written("foo bar baz", false, 8, "foo bar baz");
|
||||
assert_line_written("foo bar\tbaz", false, 8, "foo bar\tbaz");
|
||||
assert_line_written("foo bar\tbaz", true, 8, "foo bar baz");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user