Skip to content

Commit

Permalink
Merge pull request #1402 from janriemer/diff-flag-delimiter-output
Browse files Browse the repository at this point in the history
`diff`: add option/flag `--delimiter-output`
Thanks @janriemer!
  • Loading branch information
jqnatividad authored Nov 6, 2023
2 parents c358360 + f934fb1 commit 7be69db
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 8 deletions.
21 changes: 16 additions & 5 deletions src/cmd/diff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ Find the difference between two CSVs. The left CSV uses a tab as the delimiter:
# or ';' as the delimiter
qsv diff --delimiter-left ';' left.csv right-semicolon.csv
Find the difference between two CSVs. The output CSV uses a tab as the delimiter
and is written to a file:
qsv diff -o diff-tab.tsv --delimiter-output '\t' left.csv right.csv
# or ';' as the delimiter
qsv diff -o diff-semicolon.csv --delimiter-output ';' left.csv right.csv
Find the difference between two CSVs, but only for the first two columns:
qsv diff --key 0,1 left.csv right.csv
Expand All @@ -24,7 +30,7 @@ sort the result by the first and second column:
qsv diff -k 0,1 --sort-columns 0,1 left.csv right.csv
Find the difference between two CSVs, but do not output headers in the result:
qsv diff --no-headers-result left.csv right.csv
qsv diff --no-headers-output left.csv right.csv
Find the difference between two CSVs. Both CSVs have no headers, but the result should have
headers, so generic headers will be used in the form of: _col_1, _col_2, etc.:
Expand All @@ -45,13 +51,15 @@ diff options:
the right CSV to diff. (When not set, the
first row is the header row and will be skipped during
the diff. It will always appear in the output.)
--no-headers-result When set, the diff result won't have a header row in
--no-headers-output When set, the diff result won't have a header row in
it's output. If not set and both CSVs have no headers,
headers in the result will be: _col_1,_col_2, etc.
--delimiter-left <arg> The field delimiter for reading CSV data on the left.
Must be a single character. (default: ,)
--delimiter-right <arg> The field delimiter for reading CSV data on the right.
Must be a single character. (default: ,)
--delimiter-output <arg> The field delimiter for writing the CSV diff result.
Must be a single character. (default: ,)
-k, --key <arg...> The column indices that uniquely identify a record
as a comma separated list of indices, e.g. 0,1,2.
(default: 0)
Expand Down Expand Up @@ -94,9 +102,10 @@ struct Args {
flag_jobs: Option<usize>,
flag_no_headers_left: bool,
flag_no_headers_right: bool,
flag_no_headers_output: bool,
flag_delimiter_left: Option<Delimiter>,
flag_delimiter_right: Option<Delimiter>,
flag_no_headers_result: bool,
flag_delimiter_output: Option<Delimiter>,
flag_key: Option<String>,
flag_sort_columns: Option<String>,
}
Expand Down Expand Up @@ -137,7 +146,9 @@ pub fn run(argv: &[&str]) -> CliResult<()> {
})
.transpose()?;

let wtr = Config::new(&args.flag_output).writer()?;
let wtr = Config::new(&args.flag_output)
.delimiter(args.flag_delimiter_output)
.writer()?;
let csv_rdr_left = rconfig_left.reader()?;
let csv_rdr_right = rconfig_right.reader()?;

Expand Down Expand Up @@ -166,7 +177,7 @@ pub fn run(argv: &[&str]) -> CliResult<()> {
},
}

let mut csv_diff_writer = CsvDiffWriter::new(wtr, args.flag_no_headers_result);
let mut csv_diff_writer = CsvDiffWriter::new(wtr, args.flag_no_headers_output);
Ok(csv_diff_writer.write_diff_byte_records(diff_byte_records)?)
}

Expand Down
48 changes: 45 additions & 3 deletions tests/test_diff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ fn diff_with_no_headers_in_result() {
wrk.create("right.csv", right);

let mut cmd = wrk.command("diff");
cmd.args(["left.csv", "right.csv", "--no-headers-result"]);
cmd.args(["left.csv", "right.csv", "--no-headers-output"]);

let got: Vec<Vec<String>> = wrk.read_stdout(&mut cmd);
let expected = vec![
Expand All @@ -249,7 +249,7 @@ fn diff_no_diff_with_no_headers_in_result() {
wrk.create("right.csv", right);

let mut cmd = wrk.command("diff");
cmd.args(["left.csv", "right.csv", "--no-headers-result"]);
cmd.args(["left.csv", "right.csv", "--no-headers-output"]);

let got: Vec<Vec<String>> = wrk.read_stdout(&mut cmd);
let expected: Vec<Vec<String>> = vec![];
Expand Down Expand Up @@ -347,7 +347,7 @@ fn diff_with_no_left_no_right_and_no_headers_in_result() {
"right.csv",
"--no-headers-left",
"--no-headers-right",
"--no-headers-result",
"--no-headers-output",
]);

let got: Vec<Vec<String>> = wrk.read_stdout(&mut cmd);
Expand Down Expand Up @@ -425,6 +425,48 @@ fn diff_left_has_one_column_right_has_none_headers_in_result() {
assert_eq!(got, expected);
}

#[test]
fn diff_with_default_delimiter_in_result() {
let wrk = Workdir::new("diff_with_default_delimiter_in_result");

let left = vec![svec!["h1", "h2", "h3"], svec!["1", "foo", "bar"]];
wrk.create("left.csv", left);

let right = vec![svec!["h1", "h2", "h3"], svec!["1", "foo_changed", "bar"]];
wrk.create("right.csv", right);

let mut cmd = wrk.command("diff");
cmd.args(["left.csv", "right.csv"]);

let got: String = wrk.stdout(&mut cmd);
let expected = "\
diffresult,h1,h2,h3
-,1,foo,bar
+,1,foo_changed,bar";
assert_eq!(got.as_str(), expected);
}

#[test]
fn diff_with_different_delimiter_in_result() {
let wrk = Workdir::new("diff_with_different_delimiter_in_result");

let left = vec![svec!["h1", "h2", "h3"], svec!["1", "foo", "bar"]];
wrk.create("left.csv", left);

let right = vec![svec!["h1", "h2", "h3"], svec!["1", "foo_changed", "bar"]];
wrk.create("right.csv", right);

let mut cmd = wrk.command("diff");
cmd.args(["left.csv", "right.csv", "--delimiter-output", ";"]);

let got: String = wrk.stdout(&mut cmd);
let expected = "\
diffresult;h1;h2;h3
-;1;foo;bar
+;1;foo_changed;bar";
assert_eq!(got.as_str(), expected);
}

fn create_file_with_delim(wrk: &Workdir, file_path_new: &str, file_path: &str, delimiter: u8) {
let mut select_cmd = wrk.command("select");
select_cmd.args(["1-", file_path]);
Expand Down

0 comments on commit 7be69db

Please sign in to comment.