diff --git a/src/assets.rs b/src/assets.rs index 1ad1f876..36436f29 100644 --- a/src/assets.rs +++ b/src/assets.rs @@ -8,10 +8,7 @@ use syntect::dumps::{dump_to_file, from_binary, from_reader}; use syntect::highlighting::{Theme, ThemeSet}; use syntect::parsing::{SyntaxDefinition, SyntaxSet}; -#[cfg(unix)] -use std::os::unix::fs::FileTypeExt; - -use inputfile::InputFile; +use inputfile::{InputFile, InputFileReader}; lazy_static! { static ref PROJECT_DIRS: ProjectDirs = @@ -166,27 +163,33 @@ impl HighlightingAssets { } } - pub fn get_syntax(&self, language: Option<&str>, filename: InputFile) -> &SyntaxDefinition { + pub fn get_syntax( + &self, + language: Option<&str>, + filename: InputFile, + reader: &mut InputFileReader, + ) -> &SyntaxDefinition { let syntax = match (language, filename) { (Some(language), _) => self.syntax_set.find_syntax_by_token(language), (None, InputFile::Ordinary(filename)) => { - #[cfg(not(unix))] - let may_read_from_file = true; - - // Do not peek at the file (to determine the syntax) if it is a FIFO because they can - // only be read once. - #[cfg(unix)] - let may_read_from_file = !fs::metadata(filename) - .map(|m| m.file_type().is_fifo()) - .unwrap_or(false); - - if may_read_from_file { - self.syntax_set - .find_syntax_for_file(filename) - .unwrap_or(None) + let path = Path::new(filename); + 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(""); + let ext_syntax = self + .syntax_set + .find_syntax_by_extension(file_name) + .or_else(|| self.syntax_set.find_syntax_by_extension(extension)); + let line_syntax = if ext_syntax.is_none() { + reader + .get_first_line() + .ok() + .and_then(|v| String::from_utf8(v).ok()) + .and_then(|l| self.syntax_set.find_syntax_by_first_line(&l)) } else { None - } + }; + let syntax = ext_syntax.or(line_syntax); + syntax } (None, InputFile::StdIn) => None, (_, InputFile::ThemePreviewFile) => self.syntax_set.find_syntax_by_name("Rust"), diff --git a/src/controller.rs b/src/controller.rs index da9b710e..ccbb6c31 100644 --- a/src/controller.rs +++ b/src/controller.rs @@ -23,13 +23,18 @@ impl<'b> Controller<'b> { let writer = output_type.handle()?; let mut no_errors: bool = true; + let stdin = io::stdin(); + for input_file in &self.config.files { + let mut reader = input_file.get_reader(&stdin)?; + let result = if self.config.loop_through { let mut printer = SimplePrinter::new(); - self.print_file(&mut printer, writer, *input_file) + self.print_file(reader, &mut printer, writer, *input_file) } else { - let mut printer = InteractivePrinter::new(&self.config, &self.assets, *input_file); - self.print_file(&mut printer, writer, *input_file) + let mut printer = + InteractivePrinter::new(&self.config, &self.assets, *input_file, &mut reader); + self.print_file(reader, &mut printer, writer, *input_file) }; if let Err(error) = result { @@ -43,13 +48,11 @@ impl<'b> Controller<'b> { fn print_file<'a, P: Printer>( &self, + reader: InputFileReader, printer: &mut P, writer: &mut Write, input_file: InputFile<'a>, ) -> Result<()> { - let stdin = io::stdin(); - let reader = input_file.get_reader(&stdin)?; - printer.print_header(writer, input_file)?; self.print_file_ranges(printer, writer, reader, &self.config.line_range)?; printer.print_footer(writer)?; diff --git a/src/printer.rs b/src/printer.rs index 527aff0b..98011fc3 100644 --- a/src/printer.rs +++ b/src/printer.rs @@ -15,7 +15,7 @@ use decorations::{Decoration, GridBorderDecoration, LineChangesDecoration, LineN use diff::get_git_diff; use diff::LineChanges; use errors::*; -use inputfile::InputFile; +use inputfile::{InputFile, InputFileReader}; use preprocessor::expand; use style::OutputWrap; use terminal::{as_terminal_escaped, to_ansi_color}; @@ -74,7 +74,12 @@ pub struct InteractivePrinter<'a> { } impl<'a> InteractivePrinter<'a> { - pub fn new(config: &'a Config, assets: &'a HighlightingAssets, file: InputFile) -> Self { + pub fn new( + config: &'a Config, + assets: &'a HighlightingAssets, + file: InputFile, + reader: &mut InputFileReader, + ) -> Self { let theme = assets.get_theme(&config.theme); let colors = if config.colored_output { @@ -124,7 +129,7 @@ impl<'a> InteractivePrinter<'a> { }; // Determine the type of syntax for highlighting - let syntax = assets.get_syntax(config.language, file); + let syntax = assets.get_syntax(config.language, file, reader); let highlighter = HighlightLines::new(syntax, theme); InteractivePrinter {