mirror of
https://github.com/sharkdp/bat.git
synced 2024-12-23 23:08:54 +01:00
Completely refactor 'input' module
This commit is contained in:
parent
b4d54106fe
commit
590960f7f5
@ -10,7 +10,7 @@ use syntect::parsing::{SyntaxReference, SyntaxSet, SyntaxSetBuilder};
|
||||
|
||||
use crate::assets_metadata::AssetsMetadata;
|
||||
use crate::errors::*;
|
||||
use crate::input::{Input, InputReader};
|
||||
use crate::input::{Input, InputKind, InputReader, OpenedInput, OpenedInputKind};
|
||||
use crate::syntax_mapping::{MappingTarget, SyntaxMapping};
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -188,38 +188,46 @@ impl HighlightingAssets {
|
||||
pub(crate) fn get_syntax(
|
||||
&self,
|
||||
language: Option<&str>,
|
||||
input: &Input,
|
||||
reader: &mut InputReader,
|
||||
input: &mut OpenedInput,
|
||||
mapping: &SyntaxMapping,
|
||||
) -> &SyntaxReference {
|
||||
let syntax = match (language, input) {
|
||||
(Some(language), _) => self.syntax_set.find_syntax_by_token(language),
|
||||
(None, Input::Ordinary(ofile)) => {
|
||||
let path = Path::new(ofile.provided_path());
|
||||
let line_syntax = self.get_first_line_syntax(reader);
|
||||
let syntax = if let Some(language) = language {
|
||||
self.syntax_set.find_syntax_by_token(language)
|
||||
} else {
|
||||
match input.kind {
|
||||
OpenedInputKind::OrdinaryFile(ref actual_path) => {
|
||||
let path_str = input
|
||||
.metadata
|
||||
.user_provided_name
|
||||
.as_ref()
|
||||
.unwrap_or(actual_path);
|
||||
let path = Path::new(path_str);
|
||||
let line_syntax = self.get_first_line_syntax(&mut input.reader);
|
||||
|
||||
let absolute_path = path.canonicalize().ok().unwrap_or(path.to_owned());
|
||||
match mapping.get_syntax_for(absolute_path) {
|
||||
Some(MappingTarget::MapTo(syntax_name)) => {
|
||||
// TODO: we should probably return an error here if this syntax can not be
|
||||
// found. Currently, we just fall back to 'plain'.
|
||||
self.syntax_set.find_syntax_by_name(syntax_name)
|
||||
}
|
||||
Some(MappingTarget::MapToUnknown) => line_syntax,
|
||||
None => {
|
||||
let file_name = path.file_name().unwrap_or_default();
|
||||
self.get_extension_syntax(file_name).or(line_syntax)
|
||||
let absolute_path = path.canonicalize().ok().unwrap_or(path.to_owned());
|
||||
match mapping.get_syntax_for(absolute_path) {
|
||||
Some(MappingTarget::MapTo(syntax_name)) => {
|
||||
// TODO: we should probably return an error here if this syntax can not be
|
||||
// found. Currently, we just fall back to 'plain'.
|
||||
self.syntax_set.find_syntax_by_name(syntax_name)
|
||||
}
|
||||
Some(MappingTarget::MapToUnknown) => line_syntax,
|
||||
None => {
|
||||
let file_name = path.file_name().unwrap_or_default();
|
||||
self.get_extension_syntax(file_name).or(line_syntax)
|
||||
}
|
||||
}
|
||||
}
|
||||
OpenedInputKind::StdIn | OpenedInputKind::CustomReader => {
|
||||
if let Some(ref name) = input.metadata.user_provided_name {
|
||||
self.get_extension_syntax(&name)
|
||||
.or(self.get_first_line_syntax(&mut input.reader))
|
||||
} else {
|
||||
self.get_first_line_syntax(&mut input.reader)
|
||||
}
|
||||
}
|
||||
OpenedInputKind::ThemePreviewFile => self.syntax_set.find_syntax_by_name("Rust"),
|
||||
}
|
||||
(None, Input::StdIn(None)) => String::from_utf8(reader.first_line.clone())
|
||||
.ok()
|
||||
.and_then(|l| self.syntax_set.find_syntax_by_first_line(&l)),
|
||||
(None, Input::StdIn(Some(file_name))) => self
|
||||
.get_extension_syntax(&file_name)
|
||||
.or(self.get_first_line_syntax(reader)),
|
||||
(_, Input::ThemePreviewFile) => self.syntax_set.find_syntax_by_name("Rust"),
|
||||
(None, Input::FromReader(_, _)) => unimplemented!(),
|
||||
};
|
||||
|
||||
syntax.unwrap_or_else(|| self.syntax_set.find_syntax_plain_text())
|
||||
@ -249,8 +257,6 @@ impl HighlightingAssets {
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use crate::input::OrdinaryFile;
|
||||
|
||||
use std::ffi::{OsStr, OsString};
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
@ -281,12 +287,12 @@ mod tests {
|
||||
writeln!(temp_file, "{}", first_line).unwrap();
|
||||
}
|
||||
|
||||
let input = Input::Ordinary(OrdinaryFile::from_path(file_path.as_os_str()));
|
||||
let stdin = io::stdin();
|
||||
let mut reader = input.get_reader(stdin.lock()).unwrap();
|
||||
let input: Input = Input::ordinary_file(file_path.as_os_str());
|
||||
let dummy_stdin: &[u8] = &[];
|
||||
let mut opened_input = input.open(dummy_stdin).unwrap();
|
||||
let syntax = self
|
||||
.assets
|
||||
.get_syntax(None, &input, &mut reader, &self.syntax_mapping);
|
||||
.get_syntax(None, &mut opened_input, &self.syntax_mapping);
|
||||
|
||||
syntax.name.clone()
|
||||
}
|
||||
@ -304,13 +310,13 @@ mod tests {
|
||||
}
|
||||
|
||||
fn syntax_for_stdin_with_content(&self, file_name: &str, content: &[u8]) -> String {
|
||||
let input = Input::StdIn(Some(OsString::from(file_name)));
|
||||
let syntax = self.assets.get_syntax(
|
||||
None,
|
||||
&input,
|
||||
&mut input.get_reader(content).unwrap(),
|
||||
&self.syntax_mapping,
|
||||
);
|
||||
let mut input = Input::stdin();
|
||||
input.set_provided_name(Some(OsStr::new(file_name)));
|
||||
let mut opened_input = input.open(content).unwrap();
|
||||
|
||||
let syntax = self
|
||||
.assets
|
||||
.get_syntax(None, &mut opened_input, &self.syntax_mapping);
|
||||
syntax.name.clone()
|
||||
}
|
||||
}
|
||||
|
@ -15,10 +15,11 @@ use console::Term;
|
||||
|
||||
use bat::{
|
||||
config::{
|
||||
Config, HighlightedLineRanges, Input, LineRange, LineRanges, MappingTarget, OrdinaryFile,
|
||||
PagingMode, StyleComponent, StyleComponents, SyntaxMapping, WrappingMode,
|
||||
Config, HighlightedLineRanges, LineRange, LineRanges, MappingTarget, PagingMode,
|
||||
StyleComponent, StyleComponents, SyntaxMapping, WrappingMode,
|
||||
},
|
||||
errors::*,
|
||||
input::Input,
|
||||
HighlightingAssets,
|
||||
};
|
||||
|
||||
@ -83,13 +84,7 @@ impl App {
|
||||
if self.matches.occurrences_of("plain") > 1 {
|
||||
// If we have -pp as an option when in auto mode, the pager should be disabled.
|
||||
PagingMode::Never
|
||||
} else if inputs.iter().any(|f| {
|
||||
if let Input::StdIn(None) = f {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}) {
|
||||
} else if inputs.iter().any(Input::is_stdin) {
|
||||
// If we are reading from stdin, only enable paging if we write to an
|
||||
// interactive terminal and if we do not *read* from an interactive
|
||||
// terminal.
|
||||
@ -251,9 +246,9 @@ impl App {
|
||||
let files: Option<Vec<&OsStr>> = self.matches.values_of_os("FILE").map(|vs| vs.collect());
|
||||
|
||||
if files.is_none() {
|
||||
return Ok(vec![Input::StdIn(
|
||||
filenames_or_none.nth(0).unwrap().map(|f| f.to_owned()),
|
||||
)]);
|
||||
let mut input = Input::stdin();
|
||||
input.set_provided_name(filenames_or_none.nth(0).unwrap_or(None));
|
||||
return Ok(vec![input]);
|
||||
}
|
||||
let files_or_none: Box<dyn Iterator<Item = _>> = match files {
|
||||
Some(ref files) => Box::new(files.into_iter().map(|name| Some(*name))),
|
||||
@ -261,16 +256,16 @@ impl App {
|
||||
};
|
||||
|
||||
let mut file_input = Vec::new();
|
||||
for (input, name) in files_or_none.zip(filenames_or_none) {
|
||||
if let Some(input) = input {
|
||||
if input.to_str().unwrap_or_default() == "-" {
|
||||
file_input.push(Input::StdIn(name.map(|n| n.to_owned())));
|
||||
for (filepath, provided_name) in files_or_none.zip(filenames_or_none) {
|
||||
if let Some(filepath) = filepath {
|
||||
if filepath.to_str().unwrap_or_default() == "-" {
|
||||
let mut input = Input::stdin();
|
||||
input.set_provided_name(provided_name);
|
||||
file_input.push(input);
|
||||
} else {
|
||||
let mut ofile = OrdinaryFile::from_path(input);
|
||||
if let Some(path) = name {
|
||||
ofile.set_provided_path(path);
|
||||
}
|
||||
file_input.push(Input::Ordinary(ofile))
|
||||
let mut input = Input::ordinary_file(filepath);
|
||||
input.set_provided_name(provided_name);
|
||||
file_input.push(input);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,8 +26,9 @@ use clap::crate_version;
|
||||
use directories::PROJECT_DIRS;
|
||||
|
||||
use bat::{
|
||||
config::{Config, Input, OrdinaryFile, StyleComponent, StyleComponents},
|
||||
config::{Config, StyleComponent, StyleComponents},
|
||||
errors::*,
|
||||
input::Input,
|
||||
Controller, HighlightingAssets,
|
||||
};
|
||||
|
||||
@ -134,7 +135,7 @@ pub fn list_themes(cfg: &Config) -> Result<()> {
|
||||
)?;
|
||||
config.theme = theme.to_string();
|
||||
Controller::new(&config, &assets)
|
||||
.run(vec![Input::ThemePreviewFile])
|
||||
.run(vec![Input::theme_preview_file()])
|
||||
.ok();
|
||||
writeln!(stdout)?;
|
||||
}
|
||||
@ -167,9 +168,7 @@ fn run() -> Result<bool> {
|
||||
run_cache_subcommand(cache_matches)?;
|
||||
Ok(true)
|
||||
} else {
|
||||
let inputs = vec![Input::Ordinary(OrdinaryFile::from_path(OsStr::new(
|
||||
"cache",
|
||||
)))];
|
||||
let inputs = vec![Input::ordinary_file(OsStr::new("cache"))];
|
||||
let config = app.config(&inputs)?;
|
||||
|
||||
run_controller(inputs, &config)
|
||||
|
@ -1,5 +1,3 @@
|
||||
pub use crate::input::Input;
|
||||
pub use crate::input::OrdinaryFile;
|
||||
pub use crate::line_range::{HighlightedLineRanges, LineRange, LineRanges};
|
||||
pub use crate::style::{StyleComponent, StyleComponents};
|
||||
pub use crate::syntax_mapping::{MappingTarget, SyntaxMapping};
|
||||
|
@ -5,7 +5,7 @@ use crate::config::Config;
|
||||
#[cfg(feature = "paging")]
|
||||
use crate::config::PagingMode;
|
||||
use crate::errors::*;
|
||||
use crate::input::{Input, InputDescription, InputReader};
|
||||
use crate::input::{Input, InputDescription, InputKind, InputReader, OpenedInput};
|
||||
use crate::line_range::{LineRanges, RangeCheckResult};
|
||||
use crate::output::OutputType;
|
||||
use crate::printer::{InteractivePrinter, Printer, SimplePrinter};
|
||||
@ -38,9 +38,9 @@ impl<'b> Controller<'b> {
|
||||
// Do not launch the pager if NONE of the input files exist
|
||||
let mut paging_mode = self.config.paging_mode;
|
||||
if self.config.paging_mode != PagingMode::Never {
|
||||
let call_pager = inputs.iter().any(|file| {
|
||||
if let Input::Ordinary(ofile) = file {
|
||||
return Path::new(ofile.provided_path()).exists();
|
||||
let call_pager = inputs.iter().any(|ref input| {
|
||||
if let InputKind::OrdinaryFile(ref path) = input.kind {
|
||||
return Path::new(path).exists();
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
@ -61,27 +61,24 @@ impl<'b> Controller<'b> {
|
||||
let mut no_errors: bool = true;
|
||||
|
||||
for input in inputs.into_iter() {
|
||||
let description = input.description();
|
||||
|
||||
match input.get_reader(io::stdin().lock()) {
|
||||
match input.open(io::stdin().lock()) {
|
||||
Err(error) => {
|
||||
handle_error(&error);
|
||||
no_errors = false;
|
||||
}
|
||||
Ok(mut reader) => {
|
||||
let result = if self.config.loop_through {
|
||||
let mut printer = SimplePrinter::new();
|
||||
self.print_file(reader, &mut printer, writer, &description)
|
||||
Ok(mut opened_input) => {
|
||||
let mut printer: Box<dyn Printer> = if self.config.loop_through {
|
||||
Box::new(SimplePrinter::new())
|
||||
} else {
|
||||
let mut printer = InteractivePrinter::new(
|
||||
Box::new(InteractivePrinter::new(
|
||||
&self.config,
|
||||
&self.assets,
|
||||
&input,
|
||||
&mut reader,
|
||||
);
|
||||
self.print_file(reader, &mut printer, writer, &description)
|
||||
&mut opened_input,
|
||||
))
|
||||
};
|
||||
|
||||
let result = self.print_file(&mut *printer, writer, &mut opened_input);
|
||||
|
||||
if let Err(error) = result {
|
||||
handle_error(&error);
|
||||
no_errors = false;
|
||||
@ -93,30 +90,29 @@ impl<'b> Controller<'b> {
|
||||
Ok(no_errors)
|
||||
}
|
||||
|
||||
fn print_file<'a, P: Printer>(
|
||||
fn print_file<'a>(
|
||||
&self,
|
||||
reader: InputReader,
|
||||
printer: &mut P,
|
||||
printer: &mut dyn Printer,
|
||||
writer: &mut dyn Write,
|
||||
input_description: &InputDescription,
|
||||
input: &mut OpenedInput,
|
||||
) -> Result<()> {
|
||||
if !reader.first_line.is_empty() || self.config.style_components.header() {
|
||||
printer.print_header(writer, input_description)?;
|
||||
if !input.reader.first_line.is_empty() || self.config.style_components.header() {
|
||||
printer.print_header(writer, input)?;
|
||||
}
|
||||
|
||||
if !reader.first_line.is_empty() {
|
||||
self.print_file_ranges(printer, writer, reader, &self.config.line_ranges)?;
|
||||
if !input.reader.first_line.is_empty() {
|
||||
self.print_file_ranges(printer, writer, &mut input.reader, &self.config.line_ranges)?;
|
||||
}
|
||||
printer.print_footer(writer)?;
|
||||
printer.print_footer(writer, input)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn print_file_ranges<P: Printer>(
|
||||
fn print_file_ranges(
|
||||
&self,
|
||||
printer: &mut P,
|
||||
printer: &mut dyn Printer,
|
||||
writer: &mut dyn Write,
|
||||
mut reader: InputReader,
|
||||
reader: &mut InputReader,
|
||||
line_ranges: &LineRanges,
|
||||
) -> Result<()> {
|
||||
let mut line_buffer = Vec::new();
|
||||
|
195
src/input.rs
195
src/input.rs
@ -7,30 +7,6 @@ use content_inspector::{self, ContentType};
|
||||
use crate::errors::*;
|
||||
|
||||
const THEME_PREVIEW_FILE: &[u8] = include_bytes!("../assets/theme_preview.rs");
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct OrdinaryFile {
|
||||
path: OsString,
|
||||
user_provided_path: Option<OsString>,
|
||||
}
|
||||
|
||||
impl OrdinaryFile {
|
||||
pub fn from_path(path: &OsStr) -> OrdinaryFile {
|
||||
OrdinaryFile {
|
||||
path: path.to_os_string(),
|
||||
user_provided_path: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_provided_path(&mut self, user_provided_path: &OsStr) {
|
||||
self.user_provided_path = Some(user_provided_path.to_os_string());
|
||||
}
|
||||
|
||||
pub(crate) fn provided_path<'a>(&'a self) -> &'a OsStr {
|
||||
self.user_provided_path
|
||||
.as_ref()
|
||||
.unwrap_or_else(|| &self.path)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct InputDescription {
|
||||
@ -39,69 +15,134 @@ pub struct InputDescription {
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
pub enum Input {
|
||||
StdIn(Option<OsString>),
|
||||
Ordinary(OrdinaryFile),
|
||||
FromReader(Box<dyn Read>, Option<OsString>),
|
||||
pub enum InputKind {
|
||||
OrdinaryFile(OsString),
|
||||
StdIn,
|
||||
ThemePreviewFile,
|
||||
CustomReader(Box<dyn BufRead>),
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct InputMetadata {
|
||||
pub user_provided_name: Option<OsString>,
|
||||
}
|
||||
|
||||
pub struct Input {
|
||||
pub kind: InputKind,
|
||||
pub metadata: InputMetadata,
|
||||
}
|
||||
|
||||
pub enum OpenedInputKind {
|
||||
OrdinaryFile(OsString),
|
||||
StdIn,
|
||||
ThemePreviewFile,
|
||||
CustomReader,
|
||||
}
|
||||
|
||||
pub struct OpenedInput<'a> {
|
||||
pub kind: OpenedInputKind,
|
||||
pub metadata: InputMetadata,
|
||||
pub reader: InputReader<'a>,
|
||||
}
|
||||
|
||||
impl Input {
|
||||
pub(crate) fn get_reader<'a, R: BufRead + 'a>(&self, stdin: R) -> Result<InputReader<'a>> {
|
||||
match self {
|
||||
Input::StdIn(_) => Ok(InputReader::new(stdin)),
|
||||
Input::Ordinary(ofile) => {
|
||||
let file = File::open(&ofile.path)
|
||||
.map_err(|e| format!("'{}': {}", ofile.path.to_string_lossy(), e))?;
|
||||
|
||||
if file.metadata()?.is_dir() {
|
||||
return Err(
|
||||
format!("'{}' is a directory.", ofile.path.to_string_lossy()).into(),
|
||||
);
|
||||
}
|
||||
|
||||
Ok(InputReader::new(BufReader::new(file)))
|
||||
}
|
||||
Input::ThemePreviewFile => Ok(InputReader::new(THEME_PREVIEW_FILE)),
|
||||
Input::FromReader(_, _) => unimplemented!(), //Ok(InputReader::new(BufReader::new(reader))),
|
||||
pub fn ordinary_file(path: &OsStr) -> Self {
|
||||
Input {
|
||||
kind: InputKind::OrdinaryFile(path.to_os_string()),
|
||||
metadata: InputMetadata::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn description(&self) -> InputDescription {
|
||||
match self {
|
||||
Input::Ordinary(ofile) => InputDescription {
|
||||
full: format!("file '{}'", &ofile.provided_path().to_string_lossy()),
|
||||
prefix: "File: ".to_owned(),
|
||||
name: ofile.provided_path().to_string_lossy().into_owned(),
|
||||
},
|
||||
Input::StdIn(Some(name)) => InputDescription {
|
||||
full: format!(
|
||||
"STDIN (with name '{}')",
|
||||
name.to_string_lossy().into_owned()
|
||||
),
|
||||
prefix: "File: ".to_owned(),
|
||||
name: name.to_string_lossy().into_owned(),
|
||||
},
|
||||
Input::StdIn(None) => InputDescription {
|
||||
full: "STDIN".to_owned(),
|
||||
prefix: "".to_owned(),
|
||||
name: "STDIN".to_owned(),
|
||||
},
|
||||
Input::ThemePreviewFile => InputDescription {
|
||||
full: "".to_owned(),
|
||||
prefix: "".to_owned(),
|
||||
name: "".to_owned(),
|
||||
},
|
||||
Input::FromReader(_, Some(name)) => InputDescription {
|
||||
pub fn stdin() -> Self {
|
||||
Input {
|
||||
kind: InputKind::StdIn,
|
||||
metadata: InputMetadata::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn theme_preview_file() -> Self {
|
||||
Input {
|
||||
kind: InputKind::ThemePreviewFile,
|
||||
metadata: InputMetadata::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_stdin(&self) -> bool {
|
||||
if let InputKind::StdIn = self.kind {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_provided_name(&mut self, provided_name: Option<&OsStr>) {
|
||||
self.metadata.user_provided_name = provided_name.map(|n| n.to_owned());
|
||||
}
|
||||
|
||||
pub fn open<'a, R: BufRead + 'a>(self, stdin: R) -> Result<OpenedInput<'a>> {
|
||||
match self.kind {
|
||||
InputKind::StdIn => Ok(OpenedInput {
|
||||
kind: OpenedInputKind::StdIn,
|
||||
metadata: self.metadata,
|
||||
reader: InputReader::new(stdin),
|
||||
}),
|
||||
InputKind::OrdinaryFile(path) => Ok(OpenedInput {
|
||||
kind: OpenedInputKind::OrdinaryFile(path.clone()),
|
||||
metadata: self.metadata,
|
||||
reader: {
|
||||
let file = File::open(&path)
|
||||
.map_err(|e| format!("'{}': {}", path.to_string_lossy(), e))?;
|
||||
if file.metadata()?.is_dir() {
|
||||
return Err(format!("'{}' is a directory.", path.to_string_lossy()).into());
|
||||
}
|
||||
InputReader::new(BufReader::new(file))
|
||||
},
|
||||
}),
|
||||
InputKind::ThemePreviewFile => Ok(OpenedInput {
|
||||
kind: OpenedInputKind::ThemePreviewFile,
|
||||
metadata: self.metadata,
|
||||
reader: InputReader::new(THEME_PREVIEW_FILE),
|
||||
}),
|
||||
InputKind::CustomReader(reader) => Ok(OpenedInput {
|
||||
kind: OpenedInputKind::CustomReader,
|
||||
metadata: self.metadata,
|
||||
reader: InputReader::new(BufReader::new(reader)),
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> OpenedInput<'a> {
|
||||
pub fn description(&self) -> InputDescription {
|
||||
if let Some(ref name) = self.metadata.user_provided_name {
|
||||
InputDescription {
|
||||
full: format!("file '{}'", name.to_string_lossy()),
|
||||
prefix: "File: ".to_owned(),
|
||||
name: name.to_string_lossy().into_owned(),
|
||||
},
|
||||
Input::FromReader(_, None) => InputDescription {
|
||||
full: "reader".to_owned(),
|
||||
prefix: "".to_owned(),
|
||||
name: "READER".into(),
|
||||
},
|
||||
}
|
||||
} else {
|
||||
match self.kind {
|
||||
OpenedInputKind::OrdinaryFile(ref path) => InputDescription {
|
||||
full: format!("file '{}'", path.to_string_lossy()),
|
||||
prefix: "File: ".to_owned(),
|
||||
name: path.to_string_lossy().into_owned(),
|
||||
},
|
||||
OpenedInputKind::StdIn => InputDescription {
|
||||
full: "STDIN".to_owned(),
|
||||
prefix: "".to_owned(),
|
||||
name: "STDIN".to_owned(),
|
||||
},
|
||||
OpenedInputKind::ThemePreviewFile => InputDescription {
|
||||
full: "".to_owned(),
|
||||
prefix: "".to_owned(),
|
||||
name: "".to_owned(),
|
||||
},
|
||||
OpenedInputKind::CustomReader => InputDescription {
|
||||
full: "reader".to_owned(),
|
||||
prefix: "".to_owned(),
|
||||
name: "READER".into(),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ pub(crate) mod controller;
|
||||
mod decorations;
|
||||
mod diff;
|
||||
pub mod errors;
|
||||
pub(crate) mod input;
|
||||
pub mod input;
|
||||
mod less;
|
||||
pub(crate) mod line_range;
|
||||
mod output;
|
||||
|
@ -3,10 +3,10 @@ use std::io::Read;
|
||||
|
||||
use crate::{
|
||||
config::{
|
||||
Config, HighlightedLineRanges, Input, LineRanges, OrdinaryFile, StyleComponents,
|
||||
SyntaxMapping, WrappingMode,
|
||||
Config, HighlightedLineRanges, LineRanges, StyleComponents, SyntaxMapping, WrappingMode,
|
||||
},
|
||||
errors::Result,
|
||||
input::{Input, InputKind, OpenedInput},
|
||||
Controller, HighlightingAssets,
|
||||
};
|
||||
|
||||
@ -35,8 +35,8 @@ impl<'a> PrettyPrinter<'a> {
|
||||
|
||||
/// Add a file which should be pretty-printed
|
||||
pub fn input_file(&mut self, path: &OsStr) -> &mut Self {
|
||||
self.inputs
|
||||
.push(Input::Ordinary(OrdinaryFile::from_path(path)));
|
||||
// self.inputs
|
||||
// .push(Input::Ordinary(OrdinaryFile::from_path(path)));
|
||||
self
|
||||
}
|
||||
|
||||
@ -47,15 +47,15 @@ impl<'a> PrettyPrinter<'a> {
|
||||
P: AsRef<OsStr>,
|
||||
{
|
||||
for path in paths {
|
||||
self.inputs
|
||||
.push(Input::Ordinary(OrdinaryFile::from_path(path.as_ref())));
|
||||
// self.inputs
|
||||
// .push(Input::Ordinary(OrdinaryFile::from_path(path.as_ref())));
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// Add STDIN as an input
|
||||
pub fn input_stdin(&mut self) -> &mut Self {
|
||||
self.inputs.push(Input::StdIn(None));
|
||||
// self.inputs.push(Input::StdIn(None));
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -27,15 +27,15 @@ use crate::decorations::{Decoration, GridBorderDecoration, LineNumberDecoration}
|
||||
#[cfg(feature = "git")]
|
||||
use crate::diff::{get_git_diff, LineChanges};
|
||||
use crate::errors::*;
|
||||
use crate::input::{Input, InputDescription, InputReader};
|
||||
use crate::input::{Input, InputDescription, InputKind, InputReader, OpenedInput, OpenedInputKind};
|
||||
use crate::line_range::RangeCheckResult;
|
||||
use crate::preprocessor::{expand_tabs, replace_nonprintable};
|
||||
use crate::terminal::{as_terminal_escaped, to_ansi_color};
|
||||
use crate::wrap::WrappingMode;
|
||||
|
||||
pub trait Printer {
|
||||
fn print_header(&mut self, handle: &mut dyn Write, input: &InputDescription) -> Result<()>;
|
||||
fn print_footer(&mut self, handle: &mut dyn Write) -> Result<()>;
|
||||
fn print_header(&mut self, handle: &mut dyn Write, input: &OpenedInput) -> Result<()>;
|
||||
fn print_footer(&mut self, handle: &mut dyn Write, input: &OpenedInput) -> Result<()>;
|
||||
|
||||
fn print_snip(&mut self, handle: &mut dyn Write) -> Result<()>;
|
||||
|
||||
@ -57,11 +57,11 @@ impl SimplePrinter {
|
||||
}
|
||||
|
||||
impl Printer for SimplePrinter {
|
||||
fn print_header(&mut self, _handle: &mut dyn Write, input: &InputDescription) -> Result<()> {
|
||||
fn print_header(&mut self, _handle: &mut dyn Write, _input: &OpenedInput) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn print_footer(&mut self, _handle: &mut dyn Write) -> Result<()> {
|
||||
fn print_footer(&mut self, _handle: &mut dyn Write, _input: &OpenedInput) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -101,8 +101,7 @@ impl<'a> InteractivePrinter<'a> {
|
||||
pub fn new(
|
||||
config: &'a Config,
|
||||
assets: &'a HighlightingAssets,
|
||||
input: &Input,
|
||||
reader: &mut InputReader,
|
||||
input: &mut OpenedInput,
|
||||
) -> Self {
|
||||
let theme = assets.get_theme(&config.theme);
|
||||
|
||||
@ -150,7 +149,8 @@ impl<'a> InteractivePrinter<'a> {
|
||||
#[cfg(feature = "git")]
|
||||
let mut line_changes = None;
|
||||
|
||||
let highlighter = if reader
|
||||
let highlighter = if input
|
||||
.reader
|
||||
.content_type
|
||||
.map_or(false, |c| c.is_binary() && !config.show_nonprintable)
|
||||
{
|
||||
@ -160,14 +160,14 @@ impl<'a> InteractivePrinter<'a> {
|
||||
#[cfg(feature = "git")]
|
||||
{
|
||||
if config.style_components.changes() {
|
||||
if let Input::Ordinary(ofile) = input {
|
||||
line_changes = get_git_diff(ofile.provided_path());
|
||||
if let OpenedInputKind::OrdinaryFile(ref path) = input.kind {
|
||||
line_changes = get_git_diff(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Determine the type of syntax for highlighting
|
||||
let syntax = assets.get_syntax(config.language, input, reader, &config.syntax_mapping);
|
||||
let syntax = assets.get_syntax(config.language, input, &config.syntax_mapping);
|
||||
Some(HighlightLines::new(syntax, theme))
|
||||
};
|
||||
|
||||
@ -176,7 +176,7 @@ impl<'a> InteractivePrinter<'a> {
|
||||
colors,
|
||||
config,
|
||||
decorations,
|
||||
content_type: reader.content_type,
|
||||
content_type: input.reader.content_type,
|
||||
ansi_prefix_sgr: String::new(),
|
||||
#[cfg(feature = "git")]
|
||||
line_changes,
|
||||
@ -230,11 +230,7 @@ impl<'a> InteractivePrinter<'a> {
|
||||
}
|
||||
|
||||
impl<'a> Printer for InteractivePrinter<'a> {
|
||||
fn print_header(
|
||||
&mut self,
|
||||
handle: &mut dyn Write,
|
||||
description: &InputDescription,
|
||||
) -> Result<()> {
|
||||
fn print_header(&mut self, handle: &mut dyn Write, input: &OpenedInput) -> Result<()> {
|
||||
if !self.config.style_components.header() {
|
||||
if Some(ContentType::BINARY) == self.content_type && !self.config.show_nonprintable {
|
||||
writeln!(
|
||||
@ -243,7 +239,7 @@ impl<'a> Printer for InteractivePrinter<'a> {
|
||||
(but will be present if the output of 'bat' is piped). You can use 'bat -A' \
|
||||
to show the binary file contents.",
|
||||
Yellow.paint("[bat warning]"),
|
||||
description.full,
|
||||
input.description().full,
|
||||
)?;
|
||||
} else {
|
||||
if self.config.style_components.grid() {
|
||||
@ -276,6 +272,8 @@ impl<'a> Printer for InteractivePrinter<'a> {
|
||||
_ => "",
|
||||
};
|
||||
|
||||
let description = input.description();
|
||||
|
||||
writeln!(
|
||||
handle,
|
||||
"{}{}{}",
|
||||
@ -295,7 +293,7 @@ impl<'a> Printer for InteractivePrinter<'a> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn print_footer(&mut self, handle: &mut dyn Write) -> Result<()> {
|
||||
fn print_footer(&mut self, handle: &mut dyn Write, _input: &OpenedInput) -> Result<()> {
|
||||
if self.config.style_components.grid()
|
||||
&& (self.content_type.map_or(false, |c| c.is_text()) || self.config.show_nonprintable)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user