diff --git a/src/assets.rs b/src/assets.rs index 29247bd7..70570d2b 100644 --- a/src/assets.rs +++ b/src/assets.rs @@ -357,11 +357,11 @@ impl HighlightingAssets { reader: &mut InputReader, ) -> Result>> { let syntax_set = self.get_syntax_set()?; - Ok(String::from_utf8(reader.first_line.clone()) + Ok(std::str::from_utf8(&reader.first_line) .ok() .and_then(|l| { // Strip UTF-8 BOM if present - let line = l.strip_prefix('\u{feff}').unwrap_or(&l); + let line = l.strip_prefix('\u{feff}').unwrap_or(l); syntax_set.find_syntax_by_first_line(line) }) .map(|syntax| SyntaxReferenceInSet { syntax, syntax_set })) diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index cfbad253..9c7cc285 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -2470,6 +2470,145 @@ fn no_first_line_fallback_when_mapping_to_invalid_syntax() { .stderr(predicate::str::contains("unknown syntax: 'InvalidSyntax'")); } +#[test] +fn stdin_detects_bash_from_first_line() { + let content = "#!/bin/bash\necho hi\n"; + + let detected_output = bat() + .arg("--color=always") + .arg("--style=plain") + .write_stdin(content) + .assert() + .success() + .get_output() + .stdout + .clone(); + + let explicit_output = bat() + .arg("--color=always") + .arg("--style=plain") + .arg("--language=bash") + .write_stdin(content) + .assert() + .success() + .get_output() + .stdout + .clone(); + + assert_eq!( + from_utf8(&detected_output).expect("output is valid utf-8"), + from_utf8(&explicit_output).expect("output is valid utf-8") + ); +} + +#[test] +fn stdin_detects_diff_from_first_line() { + let content = "diff --git a/x b/y\n--- a/x\n+++ b/y\n@@ -1 +1 @@\n-old\n+new\n"; + + let detected_output = bat() + .arg("--color=always") + .arg("--style=plain") + .write_stdin(content) + .assert() + .success() + .get_output() + .stdout + .clone(); + + let explicit_output = bat() + .arg("--color=always") + .arg("--style=plain") + .arg("--language=diff") + .write_stdin(content) + .assert() + .success() + .get_output() + .stdout + .clone(); + + assert_eq!( + from_utf8(&detected_output).expect("output is valid utf-8"), + from_utf8(&explicit_output).expect("output is valid utf-8") + ); +} + +#[test] +fn empty_stdin_does_not_detect_syntax() { + bat() + .arg("--color=always") + .arg("--style=plain") + .write_stdin("") + .assert() + .success() + .stdout("") + .stderr(""); +} + +#[test] +fn binary_stdin_does_not_detect_syntax_from_invalid_utf8_first_line() { + let content = b"#!/bin/bash\xff\necho hi\n"; + + let detected_output = bat() + .arg("--binary=as-text") + .arg("--color=always") + .arg("--style=plain") + .write_stdin(content.as_slice()) + .assert() + .success() + .get_output() + .stdout + .clone(); + + let plain_text_output = bat() + .arg("--binary=as-text") + .arg("--color=always") + .arg("--style=plain") + .arg("--language=txt") + .write_stdin(content.as_slice()) + .assert() + .success() + .get_output() + .stdout + .clone(); + + assert_eq!( + from_utf8(&detected_output).expect("output is valid utf-8"), + from_utf8(&plain_text_output).expect("output is valid utf-8") + ); +} + +#[test] +fn explicit_language_overrides_stdin_first_line_detection() { + let content = "diff --git a/x b/y\n--- a/x\n+++ b/y\n@@ -1 +1 @@\n-old\n+new\n"; + + let detected_output = bat() + .arg("--color=always") + .arg("--style=plain") + .write_stdin(content) + .assert() + .success() + .get_output() + .stdout + .clone(); + + let explicit_output = bat() + .arg("--color=always") + .arg("--style=plain") + .arg("--language=json") + .arg("-") + .write_stdin(content) + .assert() + .success() + .get_output() + .stdout + .clone(); + + assert_ne!( + from_utf8(&detected_output).expect("output is valid utf-8"), + from_utf8(&explicit_output).expect("output is valid utf-8") + ); +} + #[test] fn fallback_syntax_is_used_when_no_syntax_is_detected() { let content = "# comment\nfoo=bar\n";