summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKyle Criddle <criddle.kyle@gmail.com>2020-03-26 16:49:16 -0600
committerDavid Peter <sharkdp@users.noreply.github.com>2020-04-21 08:57:15 +0200
commita3f8140fbe89d4980014e8af4e34469202ce2799 (patch)
treeff18484ab28422ff6f15ee4252494efa72f68639
parent96aedf624031901c34763fa44513628e23ded6ca (diff)
Use --file-name to detect syntax highlighting
Closes #891
-rw-r--r--src/assets.rs68
-rw-r--r--src/controller.rs1
-rw-r--r--src/printer.rs9
3 files changed, 64 insertions, 14 deletions
diff --git a/src/assets.rs b/src/assets.rs
index bc87eb36..73353480 100644
--- a/src/assets.rs
+++ b/src/assets.rs
@@ -176,14 +176,15 @@ impl HighlightingAssets {
pub(crate) fn get_syntax(
&self,
language: Option<&str>,
- filename: InputFile,
+ file: InputFile,
+ file_name: Option<&str>,
reader: &mut InputFileReader,
mapping: &SyntaxMapping,
) -> &SyntaxReference {
- let syntax = match (language, filename) {
- (Some(language), _) => self.syntax_set.find_syntax_by_token(language),
- (None, InputFile::Ordinary(filename)) => {
- let path = Path::new(filename);
+ let syntax = match (language, file, file_name) {
+ (Some(language), _, _) => self.syntax_set.find_syntax_by_token(language),
+ (None, InputFile::Ordinary(file), _) => {
+ let path = Path::new(file);
let file_name = path.file_name().and_then(|n| n.to_str()).unwrap_or("");
let extension = path.extension().and_then(|x| x.to_str()).unwrap_or("");
@@ -207,10 +208,24 @@ impl HighlightingAssets {
None => ext_syntax.or(line_syntax),
}
}
- (None, InputFile::StdIn) => String::from_utf8(reader.first_line.clone())
+ (None, InputFile::StdIn, None) => String::from_utf8(reader.first_line.clone())
.ok()
.and_then(|l| self.syntax_set.find_syntax_by_first_line(&l)),
- (_, InputFile::ThemePreviewFile) => self.syntax_set.find_syntax_by_name("Rust"),
+ (None, InputFile::StdIn, Some(file_name)) => self
+ .syntax_set
+ .find_syntax_by_extension(&file_name)
+ .or_else(|| {
+ self.syntax_set.find_syntax_by_extension(
+ Path::new(file_name)
+ .extension()
+ .and_then(|x| x.to_str())
+ .unwrap_or(""),
+ )
+ })
+ .or(String::from_utf8(reader.first_line.clone())
+ .ok()
+ .and_then(|l| self.syntax_set.find_syntax_by_first_line(&l))),
+ (_, InputFile::ThemePreviewFile, _) => self.syntax_set.find_syntax_by_name("Rust"),
};
syntax.unwrap_or_else(|| self.syntax_set.find_syntax_plain_text())
@@ -246,7 +261,12 @@ mod tests {
}
}
- fn synax_for_file_with_content(&self, file_name: &str, first_line: &str) -> String {
+ fn syntax_for_file_with_content(
+ &self,
+ file_name: &str,
+ first_line: &str,
+ as_stdin: bool,
+ ) -> String {
let file_path = self.temp_dir.path().join(file_name);
{
let mut temp_file = File::create(&file_path).unwrap();
@@ -254,9 +274,15 @@ mod tests {
}
let input_file = InputFile::Ordinary(OsStr::new(&file_path));
+ let (file, file_name) = if as_stdin {
+ (InputFile::StdIn, Some(file_name))
+ } else {
+ (input_file, None)
+ };
let syntax = self.assets.get_syntax(
None,
- input_file,
+ file,
+ file_name,
&mut input_file.get_reader(&io::stdin()).unwrap(),
&self.syntax_mapping,
);
@@ -265,7 +291,7 @@ mod tests {
}
fn syntax_for_file(&self, file_name: &str) -> String {
- self.synax_for_file_with_content(file_name, "")
+ self.syntax_for_file_with_content(file_name, "", false)
}
}
@@ -299,15 +325,15 @@ mod tests {
let test = SyntaxDetectionTest::new();
assert_eq!(
- test.synax_for_file_with_content("my_script", "#!/bin/bash"),
+ test.syntax_for_file_with_content("my_script", "#!/bin/bash", false),
"Bourne Again Shell (bash)"
);
assert_eq!(
- test.synax_for_file_with_content("build", "#!/bin/bash"),
+ test.syntax_for_file_with_content("build", "#!/bin/bash", false),
"Bourne Again Shell (bash)"
);
assert_eq!(
- test.synax_for_file_with_content("my_script", "<?php"),
+ test.syntax_for_file_with_content("my_script", "<?php", false),
"PHP"
);
}
@@ -333,4 +359,20 @@ mod tests {
.ok();
assert_eq!(test.syntax_for_file("README.MD"), "Markdown");
}
+
+ #[test]
+ fn syntax_detection_stdin_filename() {
+ let test = SyntaxDetectionTest::new();
+
+ // from file extension
+ assert_eq!(
+ test.syntax_for_file_with_content("test.cpp", "", true),
+ "C++"
+ );
+ // from first line (fallback)
+ assert_eq!(
+ test.syntax_for_file_with_content("my_script", "#!/bin/bash", true),
+ "Bourne Again Shell (bash)"
+ );
+ }
}
diff --git a/src/controller.rs b/src/controller.rs
index fd874759..120fea5a 100644
--- a/src/controller.rs
+++ b/src/controller.rs
@@ -78,6 +78,7 @@ impl<'b> Controller<'b> {
&self.config,
&self.assets,
*input_file,
+ file_name,
&mut reader,
);
self.print_file(reader, &mut printer, writer, *input_file, file_name)
diff --git a/src/printer.rs b/src/printer.rs
index 3fa20ac7..d0b8fcf0 100644
--- a/src/printer.rs
+++ b/src/printer.rs
@@ -112,6 +112,7 @@ impl<'a> InteractivePrinter<'a> {
config: &'a Config,
assets: &'a HighlightingAssets,
file: InputFile,
+ file_name: Option<&str>,
reader: &mut InputFileReader,
) -> Self {
let theme = assets.get_theme(&config.theme);
@@ -177,7 +178,13 @@ impl<'a> InteractivePrinter<'a> {
}
// Determine the type of syntax for highlighting
- let syntax = assets.get_syntax(config.language, file, reader, &config.syntax_mapping);
+ let syntax = assets.get_syntax(
+ config.language,
+ file,
+ file_name,
+ reader,
+ &config.syntax_mapping,
+ );
Some(HighlightLines::new(syntax, theme))
};