mirror of
https://github.com/sharkdp/bat.git
synced 2024-12-23 23:08:54 +01:00
Refactor InputDescription API into Input API
This commit is contained in:
parent
11a72ab765
commit
798b742617
@ -257,7 +257,7 @@ impl App {
|
||||
let files: Option<Vec<&OsStr>> = self.matches.values_of_os("FILE").map(|vs| vs.collect());
|
||||
|
||||
if files.is_none() {
|
||||
let input = Input::stdin().with_name(filenames_or_none.next().unwrap_or(None));
|
||||
let input = Input::stdin().as_file(filenames_or_none.next().unwrap_or(None));
|
||||
return Ok(vec![input]);
|
||||
}
|
||||
let files_or_none: Box<dyn Iterator<Item = _>> = match files {
|
||||
@ -269,9 +269,9 @@ impl App {
|
||||
for (filepath, provided_name) in files_or_none.zip(filenames_or_none) {
|
||||
if let Some(filepath) = filepath {
|
||||
if filepath.to_str().unwrap_or_default() == "-" {
|
||||
file_input.push(Input::stdin().with_name(provided_name));
|
||||
file_input.push(Input::stdin().as_file(provided_name));
|
||||
} else {
|
||||
file_input.push(Input::ordinary_file(filepath).with_name(provided_name));
|
||||
file_input.push(Input::ordinary_file(filepath).as_file(provided_name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,6 @@ use assets::{assets_from_cache_or_binary, cache_dir, clear_assets, config_dir};
|
||||
use clap::crate_version;
|
||||
use directories::PROJECT_DIRS;
|
||||
|
||||
use bat::input::InputDescription;
|
||||
use bat::{
|
||||
assets::HighlightingAssets,
|
||||
config::Config,
|
||||
@ -124,7 +123,6 @@ pub fn list_languages(config: &Config) -> Result<()> {
|
||||
fn theme_preview_file<'a>() -> Input<'a> {
|
||||
Input::from_reader(Box::new(BufReader::new(THEME_PREVIEW_DATA)))
|
||||
.with_name(Some("theme.rs".as_ref()))
|
||||
.with_description(Some(InputDescription::new("")))
|
||||
}
|
||||
|
||||
pub fn list_themes(cfg: &Config) -> Result<()> {
|
||||
|
85
src/input.rs
85
src/input.rs
@ -10,39 +10,48 @@ use crate::error::*;
|
||||
/// This tells bat how to refer to the input.
|
||||
#[derive(Clone)]
|
||||
pub struct InputDescription {
|
||||
name: String,
|
||||
pub(crate) name: String,
|
||||
|
||||
/// The input title.
|
||||
/// This replaces the name if provided.
|
||||
title: Option<String>,
|
||||
|
||||
/// The input kind.
|
||||
kind: Option<String>,
|
||||
|
||||
/// A summary description of the input.
|
||||
/// Defaults to "{kind} '{name}'"
|
||||
summary: Option<String>,
|
||||
}
|
||||
|
||||
impl InputDescription {
|
||||
/// Creates a description for an input.
|
||||
///
|
||||
/// The name should describe where the input came from (e.g. "README.md")
|
||||
pub fn new(name: impl Into<String>) -> Self {
|
||||
InputDescription {
|
||||
name: name.into(),
|
||||
title: None,
|
||||
kind: None,
|
||||
summary: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// A description for the type of input (e.g. "File")
|
||||
pub fn with_kind(mut self, kind: Option<impl Into<String>>) -> Self {
|
||||
self.kind = kind.map(|kind| kind.into());
|
||||
self
|
||||
pub fn set_kind(&mut self, kind: Option<String>) -> () {
|
||||
self.kind = kind;
|
||||
}
|
||||
|
||||
/// A summary description of the input.
|
||||
///
|
||||
/// Defaults to "{kind} '{name}'"
|
||||
pub fn with_summary(mut self, summary: Option<impl Into<String>>) -> Self {
|
||||
self.summary = summary.map(|summary| summary.into());
|
||||
self
|
||||
pub fn set_summary(&mut self, summary: Option<String>) -> () {
|
||||
self.summary = summary;
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &String {
|
||||
&self.name
|
||||
pub fn set_title(&mut self, title: Option<String>) -> () {
|
||||
self.title = title;
|
||||
}
|
||||
|
||||
pub fn title(&self) -> &String {
|
||||
match self.title.as_ref() {
|
||||
Some(ref title) => title,
|
||||
None => &self.name,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn kind(&self) -> Option<&String> {
|
||||
@ -66,9 +75,7 @@ pub(crate) enum InputKind<'a> {
|
||||
impl<'a> InputKind<'a> {
|
||||
pub fn description(&self) -> InputDescription {
|
||||
match self {
|
||||
InputKind::OrdinaryFile(ref path) => {
|
||||
InputDescription::new(path.to_string_lossy()).with_kind(Some("File"))
|
||||
}
|
||||
InputKind::OrdinaryFile(ref path) => InputDescription::new(path.to_string_lossy()),
|
||||
InputKind::StdIn => InputDescription::new("STDIN"),
|
||||
InputKind::CustomReader(_) => InputDescription::new("READER"),
|
||||
}
|
||||
@ -83,7 +90,7 @@ pub(crate) struct InputMetadata {
|
||||
pub struct Input<'a> {
|
||||
pub(crate) kind: InputKind<'a>,
|
||||
pub(crate) metadata: InputMetadata,
|
||||
pub(crate) description: Option<InputDescription>,
|
||||
pub(crate) description: InputDescription,
|
||||
}
|
||||
|
||||
pub(crate) enum OpenedInputKind {
|
||||
@ -101,26 +108,29 @@ pub(crate) struct OpenedInput<'a> {
|
||||
|
||||
impl<'a> Input<'a> {
|
||||
pub fn ordinary_file(path: &OsStr) -> Self {
|
||||
let kind = InputKind::OrdinaryFile(path.to_os_string());
|
||||
Input {
|
||||
kind: InputKind::OrdinaryFile(path.to_os_string()),
|
||||
description: kind.description(),
|
||||
metadata: InputMetadata::default(),
|
||||
description: None,
|
||||
kind,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stdin() -> Self {
|
||||
let kind = InputKind::StdIn;
|
||||
Input {
|
||||
kind: InputKind::StdIn,
|
||||
description: kind.description(),
|
||||
metadata: InputMetadata::default(),
|
||||
description: None,
|
||||
kind,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_reader(reader: Box<dyn Read + 'a>) -> Self {
|
||||
let kind = InputKind::CustomReader(reader);
|
||||
Input {
|
||||
kind: InputKind::CustomReader(reader),
|
||||
description: kind.description(),
|
||||
metadata: InputMetadata::default(),
|
||||
description: None,
|
||||
kind,
|
||||
}
|
||||
}
|
||||
|
||||
@ -133,23 +143,26 @@ impl<'a> Input<'a> {
|
||||
}
|
||||
|
||||
pub fn with_name(mut self, provided_name: Option<&OsStr>) -> Self {
|
||||
match provided_name {
|
||||
Some(name) => self.description.name = name.to_string_lossy().to_string(),
|
||||
None => {}
|
||||
}
|
||||
|
||||
self.metadata.user_provided_name = provided_name.map(|n| n.to_owned());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_description(mut self, description: Option<InputDescription>) -> Self {
|
||||
self.description = description;
|
||||
self
|
||||
pub fn as_file(mut self, provided_name: Option<&OsStr>) -> Self {
|
||||
self.description.kind = Some("File".to_owned());
|
||||
self.with_name(provided_name)
|
||||
}
|
||||
|
||||
pub fn description(&self) -> InputDescription {
|
||||
if let Some(ref description) = self.description {
|
||||
description.clone()
|
||||
} else if let Some(ref name) = self.metadata.user_provided_name {
|
||||
InputDescription::new(name.to_string_lossy()).with_kind(Some("File"))
|
||||
} else {
|
||||
self.kind.description()
|
||||
}
|
||||
pub fn description(&self) -> &InputDescription {
|
||||
&self.description
|
||||
}
|
||||
|
||||
pub fn description_mut(&mut self) -> &mut InputDescription {
|
||||
&mut self.description
|
||||
}
|
||||
|
||||
pub(crate) fn open<R: BufRead + 'a>(self, stdin: R) -> Result<OpenedInput<'a>> {
|
||||
|
@ -9,7 +9,7 @@ use crate::{
|
||||
config::{Config, VisibleLines},
|
||||
controller::Controller,
|
||||
error::Result,
|
||||
input::Input,
|
||||
input::Input as BatInput,
|
||||
line_range::{HighlightedLineRanges, LineRange, LineRanges},
|
||||
style::{StyleComponent, StyleComponents},
|
||||
SyntaxMapping, WrappingMode,
|
||||
@ -61,10 +61,17 @@ impl<'a> PrettyPrinter<'a> {
|
||||
self
|
||||
}
|
||||
|
||||
/// Adds multiple inputs which should be pretty-printed
|
||||
pub fn inputs(&mut self, inputs: impl IntoIterator<Item = Input<'a>>) -> &mut Self {
|
||||
for input in inputs {
|
||||
self.inputs.push(input);
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// Add a file which should be pretty-printed
|
||||
pub fn input_file(&mut self, path: impl AsRef<OsStr>) -> &mut Self {
|
||||
self.inputs.push(Input::ordinary_file(path.as_ref()));
|
||||
self
|
||||
self.input(Input::from_file(path).kind("File"))
|
||||
}
|
||||
|
||||
/// Add multiple files which should be pretty-printed
|
||||
@ -73,22 +80,20 @@ impl<'a> PrettyPrinter<'a> {
|
||||
I: IntoIterator<Item = P>,
|
||||
P: AsRef<OsStr>,
|
||||
{
|
||||
for path in paths {
|
||||
self.inputs.push(Input::ordinary_file(path.as_ref()));
|
||||
}
|
||||
self
|
||||
self.inputs(paths.into_iter().map(Input::from_file))
|
||||
}
|
||||
|
||||
/// Add STDIN as an input
|
||||
pub fn input_stdin(&mut self) -> &mut Self {
|
||||
self.inputs.push(Input::stdin());
|
||||
self.inputs.push(Input::from_stdin());
|
||||
self
|
||||
}
|
||||
|
||||
/// Add STDIN as an input (with customized name)
|
||||
#[deprecated]
|
||||
pub fn input_stdin_with_name(&mut self, name: impl AsRef<OsStr>) -> &mut Self {
|
||||
self.inputs
|
||||
.push(Input::stdin().with_name(Some(name.as_ref())));
|
||||
.push(Input::from_stdin().name(name).kind("File"));
|
||||
self
|
||||
}
|
||||
|
||||
@ -98,6 +103,8 @@ impl<'a> PrettyPrinter<'a> {
|
||||
}
|
||||
|
||||
/// Add a byte string as an input (with customized name)
|
||||
#[deprecated]
|
||||
#[allow(deprecated)]
|
||||
pub fn input_from_bytes_with_name(
|
||||
&mut self,
|
||||
content: &'a [u8],
|
||||
@ -108,18 +115,19 @@ impl<'a> PrettyPrinter<'a> {
|
||||
|
||||
/// Add a custom reader as an input
|
||||
pub fn input_from_reader<R: Read + 'a>(&mut self, reader: R) -> &mut Self {
|
||||
self.inputs.push(Input::from_reader(Box::new(reader)));
|
||||
self.inputs.push(Input::from_reader(reader));
|
||||
self
|
||||
}
|
||||
|
||||
/// Add a custom reader as an input (with customized name)
|
||||
#[deprecated]
|
||||
pub fn input_from_reader_with_name<R: Read + 'a>(
|
||||
&mut self,
|
||||
reader: R,
|
||||
name: impl AsRef<OsStr>,
|
||||
) -> &mut Self {
|
||||
self.inputs
|
||||
.push(Input::from_reader(Box::new(reader)).with_name(Some(name.as_ref())));
|
||||
.push(Input::from_reader(reader).name(name).kind("File"));
|
||||
self
|
||||
}
|
||||
|
||||
@ -292,10 +300,74 @@ impl<'a> PrettyPrinter<'a> {
|
||||
}
|
||||
self.config.style_components = StyleComponents::new(&style_components);
|
||||
|
||||
// Collect the inputs to print
|
||||
let mut inputs: Vec<Input> = vec![];
|
||||
std::mem::swap(&mut inputs, &mut self.inputs);
|
||||
|
||||
// Run the controller
|
||||
let controller = Controller::new(&self.config, &self.assets);
|
||||
controller.run(inputs)
|
||||
controller.run(inputs.into_iter().map(|i| i.into()).collect())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Input<'a> {
|
||||
input: BatInput<'a>,
|
||||
}
|
||||
|
||||
impl<'a> Input<'a> {
|
||||
/// A new input from a reader.
|
||||
pub fn from_reader<R: Read + 'a>(reader: R) -> Self {
|
||||
BatInput::from_reader(Box::new(reader)).into()
|
||||
}
|
||||
|
||||
/// A new input from a file.
|
||||
pub fn from_file(path: impl AsRef<OsStr>) -> Self {
|
||||
BatInput::ordinary_file(path.as_ref()).into()
|
||||
}
|
||||
|
||||
/// A new input from bytes.
|
||||
pub fn from_bytes(bytes: &'a [u8]) -> Self {
|
||||
Input::from_reader(bytes).into()
|
||||
}
|
||||
|
||||
/// A new input from STDIN.
|
||||
pub fn from_stdin() -> Self {
|
||||
BatInput::stdin().into()
|
||||
}
|
||||
|
||||
/// The filename of the input.
|
||||
/// This affects syntax detection and changes the default header title.
|
||||
pub fn name(mut self, name: impl AsRef<OsStr>) -> Self {
|
||||
self.input = self.input.with_name(Some(name.as_ref()));
|
||||
self
|
||||
}
|
||||
|
||||
/// The description for the type of input (e.g. "File")
|
||||
/// This defaults to "File" for files, and nothing for other inputs.
|
||||
pub fn kind(mut self, kind: impl Into<String>) -> Self {
|
||||
let kind = kind.into();
|
||||
self.input
|
||||
.description_mut()
|
||||
.set_kind(if kind.is_empty() { None } else { Some(kind) });
|
||||
self
|
||||
}
|
||||
|
||||
/// The title for the input (e.g. "http://example.com/example.txt")
|
||||
/// This defaults to the file name.
|
||||
pub fn title(mut self, title: impl Into<String>) -> Self {
|
||||
self.input.description_mut().set_title(Some(title.into()));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Into<Input<'a>> for BatInput<'a> {
|
||||
fn into(self) -> Input<'a> {
|
||||
Input { input: self }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Into<BatInput<'a>> for Input<'a> {
|
||||
fn into(self) -> BatInput<'a> {
|
||||
self.input
|
||||
}
|
||||
}
|
||||
|
@ -292,7 +292,7 @@ impl<'a> Printer for InteractivePrinter<'a> {
|
||||
.kind()
|
||||
.map(|kind| format!("{}: ", kind))
|
||||
.unwrap_or("".into()),
|
||||
self.colors.filename.paint(description.name()),
|
||||
self.colors.filename.paint(description.title()),
|
||||
mode
|
||||
)?;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user