mirror of
https://github.com/sharkdp/bat.git
synced 2025-03-13 22:28:26 +00:00
Merge branch 'master' into split-modules
This commit is contained in:
commit
eaa257f0ad
105
src/main.rs
105
src/main.rs
@ -22,10 +22,12 @@ mod diff;
|
||||
mod printer;
|
||||
mod terminal;
|
||||
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::env;
|
||||
use std::fs::{self, File};
|
||||
use std::io::{self, BufRead, BufReader, Write};
|
||||
use std::process::{self, Child, Command, Stdio};
|
||||
use std::str::FromStr;
|
||||
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::fs::FileTypeExt;
|
||||
@ -46,22 +48,92 @@ use printer::Printer;
|
||||
mod errors {
|
||||
error_chain! {
|
||||
foreign_links {
|
||||
Clap(::clap::Error);
|
||||
Io(::std::io::Error);
|
||||
}
|
||||
|
||||
errors {
|
||||
NoCorrectStylesSpecified {
|
||||
description("no correct styles specified")
|
||||
}
|
||||
|
||||
UnknownStyleName(name: String) {
|
||||
description("unknown style name")
|
||||
display("unknown style name: '{}'", name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
use errors::*;
|
||||
|
||||
pub enum OptionsStyle {
|
||||
Plain,
|
||||
LineNumbers,
|
||||
#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)]
|
||||
pub enum OutputComponent {
|
||||
Changes,
|
||||
Grid,
|
||||
Header,
|
||||
Numbers,
|
||||
Full,
|
||||
Plain,
|
||||
}
|
||||
|
||||
impl OutputComponent {
|
||||
fn components(&self) -> &'static [OutputComponent] {
|
||||
match *self {
|
||||
OutputComponent::Changes => &[OutputComponent::Changes],
|
||||
OutputComponent::Grid => &[OutputComponent::Grid],
|
||||
OutputComponent::Header => &[OutputComponent::Header],
|
||||
OutputComponent::Numbers => &[OutputComponent::Numbers],
|
||||
OutputComponent::Full => &[
|
||||
OutputComponent::Changes,
|
||||
OutputComponent::Grid,
|
||||
OutputComponent::Header,
|
||||
OutputComponent::Numbers,
|
||||
],
|
||||
OutputComponent::Plain => &[],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for OutputComponent {
|
||||
type Err = Error;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self> {
|
||||
match s {
|
||||
"changes" => Ok(OutputComponent::Changes),
|
||||
"grid" => Ok(OutputComponent::Grid),
|
||||
"header" => Ok(OutputComponent::Header),
|
||||
"numbers" => Ok(OutputComponent::Numbers),
|
||||
"full" => Ok(OutputComponent::Full),
|
||||
"plain" => Ok(OutputComponent::Plain),
|
||||
_ => Err(ErrorKind::UnknownStyleName(s.to_owned()).into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct OutputComponents(HashSet<OutputComponent>);
|
||||
|
||||
impl OutputComponents {
|
||||
fn changes(&self) -> bool {
|
||||
self.0.contains(&OutputComponent::Changes)
|
||||
}
|
||||
|
||||
fn grid(&self) -> bool {
|
||||
self.0.contains(&OutputComponent::Grid)
|
||||
}
|
||||
|
||||
fn header(&self) -> bool {
|
||||
self.0.contains(&OutputComponent::Header)
|
||||
}
|
||||
|
||||
fn numbers(&self) -> bool {
|
||||
self.0.contains(&OutputComponent::Numbers)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Options<'a> {
|
||||
pub true_color: bool,
|
||||
pub style: OptionsStyle,
|
||||
pub output_components: OutputComponents,
|
||||
pub language: Option<&'a str>,
|
||||
pub colored_output: bool,
|
||||
pub paging: bool,
|
||||
@ -256,8 +328,10 @@ fn run() -> Result<()> {
|
||||
.arg(
|
||||
Arg::with_name("style")
|
||||
.long("style")
|
||||
.possible_values(&["auto", "plain", "line-numbers", "full"])
|
||||
.default_value("auto")
|
||||
.use_delimiter(true)
|
||||
.takes_value(true)
|
||||
.possible_values(&["full", "plain", "changes", "header", "grid", "numbers"])
|
||||
.default_value("full")
|
||||
.help("Additional info to display along with content"),
|
||||
)
|
||||
.arg(
|
||||
@ -345,18 +419,17 @@ fn run() -> Result<()> {
|
||||
})
|
||||
.unwrap_or_else(|| vec![None]); // read from stdin (None) if no args are given
|
||||
|
||||
let output_components = values_t!(app_matches.values_of("style"), OutputComponent)?
|
||||
.into_iter()
|
||||
.map(|style| style.components())
|
||||
.fold(HashSet::new(), |mut acc, components| {
|
||||
acc.extend(components.iter().cloned());
|
||||
acc
|
||||
});
|
||||
|
||||
let options = Options {
|
||||
true_color: is_truecolor_terminal(),
|
||||
style: match app_matches.value_of("style") {
|
||||
Some("plain") => OptionsStyle::Plain,
|
||||
Some("line-numbers") => OptionsStyle::LineNumbers,
|
||||
Some("full") => OptionsStyle::Full,
|
||||
Some("auto") | _ => if interactive_terminal {
|
||||
OptionsStyle::Full
|
||||
} else {
|
||||
OptionsStyle::Plain
|
||||
},
|
||||
},
|
||||
output_components: OutputComponents(output_components),
|
||||
language: app_matches.value_of("language"),
|
||||
colored_output: match app_matches.value_of("color") {
|
||||
Some("always") => true,
|
||||
|
101
src/printer.rs
101
src/printer.rs
@ -4,7 +4,7 @@ use errors::*;
|
||||
use std::io::Write;
|
||||
use syntect::highlighting;
|
||||
use terminal::as_terminal_escaped;
|
||||
use {Colors, Options, OptionsStyle};
|
||||
use {Colors, Options};
|
||||
|
||||
const PANEL_WIDTH: usize = 7;
|
||||
|
||||
@ -32,19 +32,20 @@ impl<'a> Printer<'a> {
|
||||
}
|
||||
|
||||
pub fn print_header(&mut self, filename: Option<&str>) -> Result<()> {
|
||||
match self.options.style {
|
||||
OptionsStyle::Full => {}
|
||||
_ => return Ok(()),
|
||||
if !self.options.output_components.header() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
self.print_horizontal_line('┬')?;
|
||||
if self.options.output_components.grid() {
|
||||
self.print_horizontal_line('┬')?;
|
||||
|
||||
write!(
|
||||
self.handle,
|
||||
"{}{} ",
|
||||
" ".repeat(PANEL_WIDTH),
|
||||
self.colors.grid.paint("│"),
|
||||
)?;
|
||||
write!(
|
||||
self.handle,
|
||||
"{}{} ",
|
||||
" ".repeat(PANEL_WIDTH),
|
||||
self.colors.grid.paint("│"),
|
||||
)?;
|
||||
}
|
||||
|
||||
writeln!(
|
||||
self.handle,
|
||||
@ -53,11 +54,15 @@ impl<'a> Printer<'a> {
|
||||
self.colors.filename.paint(filename.unwrap_or("STDIN"))
|
||||
)?;
|
||||
|
||||
self.print_horizontal_line('┼')
|
||||
if self.options.output_components.grid() {
|
||||
self.print_horizontal_line('┼')?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn print_footer(&mut self) -> Result<()> {
|
||||
if let OptionsStyle::Full = self.options.style {
|
||||
if self.options.output_components.grid() {
|
||||
self.print_horizontal_line('┴')
|
||||
} else {
|
||||
Ok(())
|
||||
@ -80,12 +85,17 @@ impl<'a> Printer<'a> {
|
||||
)),
|
||||
];
|
||||
|
||||
let grid_requested = self.options.output_components.grid();
|
||||
write!(
|
||||
self.handle,
|
||||
"{}",
|
||||
decorations
|
||||
.into_iter()
|
||||
.filter_map(|dec| dec)
|
||||
.filter_map(|dec| if grid_requested {
|
||||
Some(dec.unwrap_or(" ".to_owned()))
|
||||
} else {
|
||||
dec
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join(" ")
|
||||
)?;
|
||||
@ -94,45 +104,48 @@ impl<'a> Printer<'a> {
|
||||
}
|
||||
|
||||
fn print_line_number(&self, line_number: usize) -> Option<String> {
|
||||
if let OptionsStyle::Plain = self.options.style {
|
||||
return None;
|
||||
if self.options.output_components.numbers() {
|
||||
Some(
|
||||
self.colors
|
||||
.line_number
|
||||
.paint(format!("{:4}", line_number))
|
||||
.to_string(),
|
||||
)
|
||||
} else if self.options.output_components.grid() {
|
||||
Some(" ".to_owned())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
||||
Some(
|
||||
self.colors
|
||||
.line_number
|
||||
.paint(format!("{:4}", line_number))
|
||||
.to_string(),
|
||||
)
|
||||
}
|
||||
|
||||
fn print_git_marker(&self, line_number: usize) -> Option<String> {
|
||||
match self.options.style {
|
||||
OptionsStyle::Full => {}
|
||||
_ => return None,
|
||||
}
|
||||
|
||||
let marker = if let Some(ref changes) = self.line_changes {
|
||||
match changes.get(&(line_number as u32)) {
|
||||
Some(&LineChange::Added) => self.colors.git_added.paint("+"),
|
||||
Some(&LineChange::RemovedAbove) => self.colors.git_removed.paint("‾"),
|
||||
Some(&LineChange::RemovedBelow) => self.colors.git_removed.paint("_"),
|
||||
Some(&LineChange::Modified) => self.colors.git_modified.paint("~"),
|
||||
_ => Style::default().paint(" "),
|
||||
}
|
||||
if self.options.output_components.changes() {
|
||||
Some(
|
||||
if let Some(ref changes) = self.line_changes {
|
||||
match changes.get(&(line_number as u32)) {
|
||||
Some(&LineChange::Added) => self.colors.git_added.paint("+"),
|
||||
Some(&LineChange::RemovedAbove) => self.colors.git_removed.paint("‾"),
|
||||
Some(&LineChange::RemovedBelow) => self.colors.git_removed.paint("_"),
|
||||
Some(&LineChange::Modified) => self.colors.git_modified.paint("~"),
|
||||
_ => Style::default().paint(" "),
|
||||
}
|
||||
} else {
|
||||
Style::default().paint(" ")
|
||||
}.to_string(),
|
||||
)
|
||||
} else if self.options.output_components.grid() {
|
||||
Some(" ".to_owned())
|
||||
} else {
|
||||
Style::default().paint(" ")
|
||||
};
|
||||
|
||||
Some(marker.to_string())
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn print_line_border(&self) -> Option<String> {
|
||||
if let OptionsStyle::Plain = self.options.style {
|
||||
return None;
|
||||
if self.options.output_components.grid() {
|
||||
Some(self.colors.grid.paint("│").to_string())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
||||
Some(self.colors.grid.paint("│").to_string())
|
||||
}
|
||||
|
||||
fn print_horizontal_line(&mut self, grid_char: char) -> Result<()> {
|
||||
|
Loading…
x
Reference in New Issue
Block a user