diff --git a/CHANGELOG.md b/CHANGELOG.md index 36b689f218..9265a25ecd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ ## 0.53 (unreleased) +### Command Line Interface + +Added the option `--strip-cr`. This removes all carriage return +characters before diffing, which is helpful when dealing with a mix of +Windows and non-Windows flies. + ## 0.52 (released 8th October 2023) ### Parsing diff --git a/src/main.rs b/src/main.rs index 75a2e74e12..4c395055b8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -335,7 +335,7 @@ fn diff_file( overrides: &[(LanguageOverride, Vec)], ) -> DiffResult { let (lhs_bytes, rhs_bytes) = read_files_or_die(lhs_path, rhs_path, missing_as_empty); - let (lhs_src, rhs_src) = match (guess_content(&lhs_bytes), guess_content(&rhs_bytes)) { + let (mut lhs_src, mut rhs_src) = match (guess_content(&lhs_bytes), guess_content(&rhs_bytes)) { (ProbableFileKind::Binary, _) | (_, ProbableFileKind::Binary) => { return DiffResult { extra_info, @@ -353,6 +353,11 @@ fn diff_file( (ProbableFileKind::Text(lhs_src), ProbableFileKind::Text(rhs_src)) => (lhs_src, rhs_src), }; + if diff_options.strip_cr { + lhs_src.retain(|c| c != '\r'); + rhs_src.retain(|c| c != '\r'); + } + diff_file_content( display_path, extra_info, @@ -374,7 +379,7 @@ fn diff_conflicts_file( overrides: &[(LanguageOverride, Vec)], ) -> DiffResult { let bytes = read_file_or_die(path); - let src = match guess_content(&bytes) { + let mut src = match guess_content(&bytes) { ProbableFileKind::Text(src) => src, ProbableFileKind::Binary => { eprintln!("error: Expected a text file with conflict markers, got a binary file."); @@ -382,6 +387,10 @@ fn diff_conflicts_file( } }; + if diff_options.strip_cr { + src.retain(|c| c != '\r'); + } + let conflict_files = match apply_conflict_markers(&src) { Ok(cf) => cf, Err(msg) => { diff --git a/src/options.rs b/src/options.rs index 593e1a0285..08bff25deb 100644 --- a/src/options.rs +++ b/src/options.rs @@ -68,6 +68,7 @@ pub struct DiffOptions { pub parse_error_limit: usize, pub check_only: bool, pub ignore_comments: bool, + pub strip_cr: bool, } impl Default for DiffOptions { @@ -78,6 +79,7 @@ impl Default for DiffOptions { parse_error_limit: DEFAULT_PARSE_ERROR_LIMIT, check_only: false, ignore_comments: false, + strip_cr: false, } } } @@ -199,6 +201,11 @@ json: Output the results as a machine-readable JSON array with an element per fi .env("DFT_EXIT_CODE") .help("Set the exit code to 1 if there are syntactic changes in any files. For files where there is no detected language (e.g. unsupported language or binary files), sets the exit code if there are any byte changes.") ) + .arg( + Arg::new("strip-cr").long("strip-cr") + .env("DFT_STRIP_CR") + .help("Remove any carriage return characters before diffing. This can be helpful when dealing with files on Windows that contain CRLF, i.e. `\\r\\n`.") + ) .arg( Arg::new("check-only").long("check-only") .env("DFT_CHECK_ONLY") @@ -602,6 +609,8 @@ pub fn parse_args() -> Mode { let set_exit_code = matches.is_present("exit-code"); + let strip_cr = matches.is_present("strip-cr"); + let check_only = matches.is_present("check-only"); let diff_options = DiffOptions { @@ -610,6 +619,7 @@ pub fn parse_args() -> Mode { parse_error_limit, check_only, ignore_comments, + strip_cr, }; let args: Vec<_> = matches.values_of_os("paths").unwrap_or_default().collect();