diff options
author | Kyle Criddle <criddle.kyle@gmail.com> | 2020-03-26 16:49:16 -0600 |
---|---|---|
committer | David Peter <sharkdp@users.noreply.github.com> | 2020-04-21 08:57:15 +0200 |
commit | a3f8140fbe89d4980014e8af4e34469202ce2799 (patch) | |
tree | ff18484ab28422ff6f15ee4252494efa72f68639 | |
parent | 96aedf624031901c34763fa44513628e23ded6ca (diff) |
Use --file-name to detect syntax highlighting
Closes #891
-rw-r--r-- | src/assets.rs | 68 | ||||
-rw-r--r-- | src/controller.rs | 1 | ||||
-rw-r--r-- | src/printer.rs | 9 |
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)) }; |