on master help sign in
Add first-line detection for all input types

closes #205

commit0502a3bd4a3b70958e920e1a49511e2968c00a2c authorsharkdp <davidpeter@web.de> dateSun 7 Oct 2018, 13:26 (8 years ago) parent869cf63
3 files changed+40−29
src/assets.rs+23−20 src/controller.rs+9−6 src/printer.rs+8−3
src/assets.rs+23−20
@@ -8,10 +8,7 @@ use syntect::dumps::{dump_to_file, from_binary, from_reader};
88use syntect::highlighting::{Theme, ThemeSet};
99use syntect::parsing::{SyntaxDefinition, SyntaxSet};
1010
11−#[cfg(unix)]
12−use std::os::unix::fs::FileTypeExt;
13−
14−use inputfile::InputFile;
11+use inputfile::{InputFile, InputFileReader};
1512
1613lazy_static! {
1714 static ref PROJECT_DIRS: ProjectDirs =
@@ -166,27 +163,33 @@ impl HighlightingAssets {
166163 }
167164 }
168165
169− pub fn get_syntax(&self, language: Option<&str>, filename: InputFile) -> &SyntaxDefinition {
166+ pub fn get_syntax(
167+ &self,
168+ language: Option<&str>,
169+ filename: InputFile,
170+ reader: &mut InputFileReader,
171+ ) -> &SyntaxDefinition {
170172 let syntax = match (language, filename) {
171173 (Some(language), _) => self.syntax_set.find_syntax_by_token(language),
172174 (None, InputFile::Ordinary(filename)) => {
173− #[cfg(not(unix))]
174− let may_read_from_file = true;
175−
176− // Do not peek at the file (to determine the syntax) if it is a FIFO because they can
177− // only be read once.
178− #[cfg(unix)]
179− let may_read_from_file = !fs::metadata(filename)
180− .map(|m| m.file_type().is_fifo())
181− .unwrap_or(false);
182−
183− if may_read_from_file {
184− self.syntax_set
185− .find_syntax_for_file(filename)
186− .unwrap_or(None)
175+ let path = Path::new(filename);
176+ let file_name = path.file_name().and_then(|n| n.to_str()).unwrap_or("");
177+ let extension = path.extension().and_then(|x| x.to_str()).unwrap_or("");
178+ let ext_syntax = self
179+ .syntax_set
180+ .find_syntax_by_extension(file_name)
181+ .or_else(|| self.syntax_set.find_syntax_by_extension(extension));
182+ let line_syntax = if ext_syntax.is_none() {
183+ reader
184+ .get_first_line()
185+ .ok()
186+ .and_then(|v| String::from_utf8(v).ok())
187+ .and_then(|l| self.syntax_set.find_syntax_by_first_line(&l))
187188 } else {
188189 None
189− }
190+ };
191+ let syntax = ext_syntax.or(line_syntax);
192+ syntax
190193 }
191194 (None, InputFile::StdIn) => None,
192195 (_, InputFile::ThemePreviewFile) => self.syntax_set.find_syntax_by_name("Rust"),
src/controller.rs+9−6
@@ -23,13 +23,18 @@ impl<'b> Controller<'b> {
2323 let writer = output_type.handle()?;
2424 let mut no_errors: bool = true;
2525
26+ let stdin = io::stdin();
27+
2628 for input_file in &self.config.files {
29+ let mut reader = input_file.get_reader(&stdin)?;
30+
2731 let result = if self.config.loop_through {
2832 let mut printer = SimplePrinter::new();
29− self.print_file(&mut printer, writer, *input_file)
33+ self.print_file(reader, &mut printer, writer, *input_file)
3034 } else {
31− let mut printer = InteractivePrinter::new(&self.config, &self.assets, *input_file);
32− self.print_file(&mut printer, writer, *input_file)
35+ let mut printer =
36+ InteractivePrinter::new(&self.config, &self.assets, *input_file, &mut reader);
37+ self.print_file(reader, &mut printer, writer, *input_file)
3338 };
3439
3540 if let Err(error) = result {
@@ -43,13 +48,11 @@ impl<'b> Controller<'b> {
4348
4449 fn print_file<'a, P: Printer>(
4550 &self,
51+ reader: InputFileReader,
4652 printer: &mut P,
4753 writer: &mut Write,
4854 input_file: InputFile<'a>,
4955 ) -> Result<()> {
50− let stdin = io::stdin();
51− let reader = input_file.get_reader(&stdin)?;
52−
5356 printer.print_header(writer, input_file)?;
5457 self.print_file_ranges(printer, writer, reader, &self.config.line_range)?;
5558 printer.print_footer(writer)?;
src/printer.rs+8−3
@@ -15,7 +15,7 @@ use decorations::{Decoration, GridBorderDecoration, LineChangesDecoration, LineN
1515use diff::get_git_diff;
1616use diff::LineChanges;
1717use errors::*;
18−use inputfile::InputFile;
18+use inputfile::{InputFile, InputFileReader};
1919use preprocessor::expand;
2020use style::OutputWrap;
2121use terminal::{as_terminal_escaped, to_ansi_color};
@@ -74,7 +74,12 @@ pub struct InteractivePrinter<'a> {
7474}
7575
7676impl<'a> InteractivePrinter<'a> {
77− pub fn new(config: &'a Config, assets: &'a HighlightingAssets, file: InputFile) -> Self {
77+ pub fn new(
78+ config: &'a Config,
79+ assets: &'a HighlightingAssets,
80+ file: InputFile,
81+ reader: &mut InputFileReader,
82+ ) -> Self {
7883 let theme = assets.get_theme(&config.theme);
7984
8085 let colors = if config.colored_output {
@@ -124,7 +129,7 @@ impl<'a> InteractivePrinter<'a> {
124129 };
125130
126131 // Determine the type of syntax for highlighting
127− let syntax = assets.get_syntax(config.language, file);
132+ let syntax = assets.get_syntax(config.language, file, reader);
128133 let highlighter = HighlightLines::new(syntax, theme);
129134
130135 InteractivePrinter {