1
0
mirror of https://github.com/sharkdp/bat.git synced 2025-01-31 18:21:04 +00:00

Add first-line detection for all input types

closes #205
This commit is contained in:
sharkdp 2018-10-07 13:26:50 +02:00 committed by David Peter
parent 869cf6368c
commit 0502a3bd4a
3 changed files with 40 additions and 29 deletions

View File

@ -8,10 +8,7 @@ use syntect::dumps::{dump_to_file, from_binary, from_reader};
use syntect::highlighting::{Theme, ThemeSet}; use syntect::highlighting::{Theme, ThemeSet};
use syntect::parsing::{SyntaxDefinition, SyntaxSet}; use syntect::parsing::{SyntaxDefinition, SyntaxSet};
#[cfg(unix)] use inputfile::{InputFile, InputFileReader};
use std::os::unix::fs::FileTypeExt;
use inputfile::InputFile;
lazy_static! { lazy_static! {
static ref PROJECT_DIRS: ProjectDirs = 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) { let syntax = match (language, filename) {
(Some(language), _) => self.syntax_set.find_syntax_by_token(language), (Some(language), _) => self.syntax_set.find_syntax_by_token(language),
(None, InputFile::Ordinary(filename)) => { (None, InputFile::Ordinary(filename)) => {
#[cfg(not(unix))] let path = Path::new(filename);
let may_read_from_file = true; 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("");
// Do not peek at the file (to determine the syntax) if it is a FIFO because they can let ext_syntax = self
// only be read once. .syntax_set
#[cfg(unix)] .find_syntax_by_extension(file_name)
let may_read_from_file = !fs::metadata(filename) .or_else(|| self.syntax_set.find_syntax_by_extension(extension));
.map(|m| m.file_type().is_fifo()) let line_syntax = if ext_syntax.is_none() {
.unwrap_or(false); reader
.get_first_line()
if may_read_from_file { .ok()
self.syntax_set .and_then(|v| String::from_utf8(v).ok())
.find_syntax_for_file(filename) .and_then(|l| self.syntax_set.find_syntax_by_first_line(&l))
.unwrap_or(None)
} else { } else {
None None
} };
let syntax = ext_syntax.or(line_syntax);
syntax
} }
(None, InputFile::StdIn) => None, (None, InputFile::StdIn) => None,
(_, InputFile::ThemePreviewFile) => self.syntax_set.find_syntax_by_name("Rust"), (_, InputFile::ThemePreviewFile) => self.syntax_set.find_syntax_by_name("Rust"),

View File

@ -23,13 +23,18 @@ impl<'b> Controller<'b> {
let writer = output_type.handle()?; let writer = output_type.handle()?;
let mut no_errors: bool = true; let mut no_errors: bool = true;
let stdin = io::stdin();
for input_file in &self.config.files { for input_file in &self.config.files {
let mut reader = input_file.get_reader(&stdin)?;
let result = if self.config.loop_through { let result = if self.config.loop_through {
let mut printer = SimplePrinter::new(); let mut printer = SimplePrinter::new();
self.print_file(&mut printer, writer, *input_file) self.print_file(reader, &mut printer, writer, *input_file)
} else { } else {
let mut printer = InteractivePrinter::new(&self.config, &self.assets, *input_file); let mut printer =
self.print_file(&mut printer, writer, *input_file) InteractivePrinter::new(&self.config, &self.assets, *input_file, &mut reader);
self.print_file(reader, &mut printer, writer, *input_file)
}; };
if let Err(error) = result { if let Err(error) = result {
@ -43,13 +48,11 @@ impl<'b> Controller<'b> {
fn print_file<'a, P: Printer>( fn print_file<'a, P: Printer>(
&self, &self,
reader: InputFileReader,
printer: &mut P, printer: &mut P,
writer: &mut Write, writer: &mut Write,
input_file: InputFile<'a>, input_file: InputFile<'a>,
) -> Result<()> { ) -> Result<()> {
let stdin = io::stdin();
let reader = input_file.get_reader(&stdin)?;
printer.print_header(writer, input_file)?; printer.print_header(writer, input_file)?;
self.print_file_ranges(printer, writer, reader, &self.config.line_range)?; self.print_file_ranges(printer, writer, reader, &self.config.line_range)?;
printer.print_footer(writer)?; printer.print_footer(writer)?;

View File

@ -15,7 +15,7 @@ use decorations::{Decoration, GridBorderDecoration, LineChangesDecoration, LineN
use diff::get_git_diff; use diff::get_git_diff;
use diff::LineChanges; use diff::LineChanges;
use errors::*; use errors::*;
use inputfile::InputFile; use inputfile::{InputFile, InputFileReader};
use preprocessor::expand; use preprocessor::expand;
use style::OutputWrap; use style::OutputWrap;
use terminal::{as_terminal_escaped, to_ansi_color}; use terminal::{as_terminal_escaped, to_ansi_color};
@ -74,7 +74,12 @@ pub struct InteractivePrinter<'a> {
} }
impl<'a> 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 theme = assets.get_theme(&config.theme);
let colors = if config.colored_output { let colors = if config.colored_output {
@ -124,7 +129,7 @@ impl<'a> InteractivePrinter<'a> {
}; };
// Determine the type of syntax for highlighting // 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); let highlighter = HighlightLines::new(syntax, theme);
InteractivePrinter { InteractivePrinter {