diff --git a/src/cmd/diff.rs b/src/cmd/diff.rs index 1f36470d2..2233a9f34 100644 --- a/src/cmd/diff.rs +++ b/src/cmd/diff.rs @@ -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 @@ -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.: @@ -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 The field delimiter for reading CSV data on the left. Must be a single character. (default: ,) --delimiter-right The field delimiter for reading CSV data on the right. Must be a single character. (default: ,) + --delimiter-output The field delimiter for writing the CSV diff result. + Must be a single character. (default: ,) -k, --key The column indices that uniquely identify a record as a comma separated list of indices, e.g. 0,1,2. (default: 0) @@ -94,9 +102,10 @@ struct Args { flag_jobs: Option, flag_no_headers_left: bool, flag_no_headers_right: bool, + flag_no_headers_output: bool, flag_delimiter_left: Option, flag_delimiter_right: Option, - flag_no_headers_result: bool, + flag_delimiter_output: Option, flag_key: Option, flag_sort_columns: Option, } @@ -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()?; @@ -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)?) } diff --git a/tests/test_diff.rs b/tests/test_diff.rs index d45c782ae..a6c3dd1ba 100644 --- a/tests/test_diff.rs +++ b/tests/test_diff.rs @@ -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> = wrk.read_stdout(&mut cmd); let expected = vec![ @@ -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> = wrk.read_stdout(&mut cmd); let expected: Vec> = vec![]; @@ -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> = wrk.read_stdout(&mut cmd); @@ -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]);