diff --git a/README.md b/README.md index 9eb4c095..8826d4e0 100644 --- a/README.md +++ b/README.md @@ -902,7 +902,7 @@ cargo install --path . --locked --force ``` If you want to build an application that uses `bat`'s pretty-printing -features as a library, check out the [the API documentation](https://docs.rs/bat/). +features as a library, check out the [API documentation](https://docs.rs/bat/). Note that you have to use either `regex-onig` or `regex-fancy` as a feature when you depend on `bat` as a library. diff --git a/src/assets.rs b/src/assets.rs index 8407678b..e6adc123 100644 --- a/src/assets.rs +++ b/src/assets.rs @@ -363,11 +363,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 124a9e5b..1263e5a5 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -2559,6 +2559,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";