From 7f2e61d57961e8fa23a91ec1bd6348cbfc33a2c8 Mon Sep 17 00:00:00 2001 From: Ethan P Date: Fri, 24 May 2019 18:24:13 -0700 Subject: [PATCH] Add new style component to separate multiple '--line-range's --- src/clap_app.rs | 6 +++--- src/controller.rs | 15 ++++++++++++++ src/printer.rs | 50 +++++++++++++++++++++++++++++++++++++++++++++++ src/style.rs | 8 ++++++++ 4 files changed, 76 insertions(+), 3 deletions(-) diff --git a/src/clap_app.rs b/src/clap_app.rs index 88bb0e87..1884dbea 100644 --- a/src/clap_app.rs +++ b/src/clap_app.rs @@ -111,7 +111,7 @@ pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> { .validator(|val| { let mut invalid_vals = val.split(',').filter(|style| { !&[ - "auto", "full", "plain", "changes", "header", "grid", "numbers", + "auto", "full", "plain", "changes", "header", "grid", "numbers", "snip" ] .contains(style) }); @@ -124,7 +124,7 @@ pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> { }) .help( "Comma-separated list of style elements to display \ - (*auto*, full, plain, changes, header, grid, numbers).", + (*auto*, full, plain, changes, header, grid, numbers, snip).", ) .long_help( "Configure which elements (line numbers, file headers, grid \ @@ -134,7 +134,7 @@ pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> { pre-defined style ('full'). To set a default style, add the \ '--style=\"..\"' option to the configuration file or export the \ BAT_STYLE environment variable (e.g.: export BAT_STYLE=\"..\"). \ - Possible values: *auto*, full, plain, changes, header, grid, numbers.", + Possible values: *auto*, full, plain, changes, header, grid, numbers, snip.", ), ) .arg( diff --git a/src/controller.rs b/src/controller.rs index 161a1758..b67d03c5 100644 --- a/src/controller.rs +++ b/src/controller.rs @@ -98,14 +98,29 @@ impl<'b> Controller<'b> { let mut line_buffer = Vec::new(); let mut line_number: usize = 1; + let mut first_range: bool = true; + let mut mid_range: bool = false; + while reader.read_line(&mut line_buffer)? { match line_ranges.check(line_number) { RangeCheckResult::OutsideRange => { // Call the printer in case we need to call the syntax highlighter // for this line. However, set `out_of_range` to `true`. printer.print_line(true, writer, line_number, &line_buffer)?; + mid_range = false; } + RangeCheckResult::InRange => { + if self.config.output_components.snip() { + if first_range { + first_range = false; + mid_range = true; + } else if !mid_range { + mid_range = true; + printer.print_snip(writer)?; + } + } + printer.print_line(false, writer, line_number, &line_buffer)?; } RangeCheckResult::AfterLastRange => { diff --git a/src/printer.rs b/src/printer.rs index e95ebcf0..e2a031a7 100644 --- a/src/printer.rs +++ b/src/printer.rs @@ -32,6 +32,9 @@ use crate::terminal::{as_terminal_escaped, to_ansi_color}; pub trait Printer { fn print_header(&mut self, handle: &mut dyn Write, file: InputFile) -> Result<()>; fn print_footer(&mut self, handle: &mut dyn Write) -> Result<()>; + + fn print_snip(&mut self, handle: &mut dyn Write) -> Result<()>; + fn print_line( &mut self, out_of_range: bool, @@ -58,6 +61,10 @@ impl Printer for SimplePrinter { Ok(()) } + fn print_snip(&mut self, _handle: &mut Write) -> Result<()> { + Ok(()) + } + fn print_line( &mut self, out_of_range: bool, @@ -182,6 +189,24 @@ impl<'a> InteractivePrinter<'a> { Ok(()) } + fn create_fake_panel(&self, text: &str) -> String { + if self.panel_width == 0 { + "".to_string() + } else { + let text_truncated: String = text.chars().take(self.panel_width - 1).collect(); + let text_filled: String = format!( + "{}{}", + text_truncated, + " ".repeat(self.panel_width - 1 - text_truncated.len()) + ); + if self.config.output_components.grid() { + format!("{} │ ", text_filled) + } else { + format!("{}", text_filled) + } + } + } + fn preprocess(&self, text: &str, cursor: &mut usize) -> String { if self.config.tab_width > 0 { expand_tabs(text, self.config.tab_width, cursor) @@ -271,6 +296,31 @@ impl<'a> Printer for InteractivePrinter<'a> { } } + fn print_snip(&mut self, handle: &mut Write) -> Result<()> { + let panel = self.create_fake_panel(" ..."); + let panel_count = panel.chars().count(); + + let title = "8<"; + let title_count = title.chars().count(); + + let snip_left = + "─ ".repeat((self.config.term_width - panel_count - (title_count / 2)) / 4); + let snip_left_count = snip_left.chars().count(); // Can't use .len() with Unicode. + + let snip_right = " ─" + .repeat((self.config.term_width - panel_count - snip_left_count - title_count) / 2); + + write!( + handle, + "{}\n", + self.colors + .grid + .paint(format!("{}{}{}{}", panel, snip_left, title, snip_right)) + )?; + + Ok(()) + } + fn print_line( &mut self, out_of_range: bool, diff --git a/src/style.rs b/src/style.rs index 254604d0..2da84cb5 100644 --- a/src/style.rs +++ b/src/style.rs @@ -10,6 +10,7 @@ pub enum OutputComponent { Grid, Header, Numbers, + Snip, Full, Plain, } @@ -34,11 +35,13 @@ impl OutputComponent { OutputComponent::Grid => &[OutputComponent::Grid], OutputComponent::Header => &[OutputComponent::Header], OutputComponent::Numbers => &[OutputComponent::Numbers], + OutputComponent::Snip => &[OutputComponent::Snip], OutputComponent::Full => &[ OutputComponent::Changes, OutputComponent::Grid, OutputComponent::Header, OutputComponent::Numbers, + OutputComponent::Snip, ], OutputComponent::Plain => &[], } @@ -55,6 +58,7 @@ impl FromStr for OutputComponent { "grid" => Ok(OutputComponent::Grid), "header" => Ok(OutputComponent::Header), "numbers" => Ok(OutputComponent::Numbers), + "snip" => Ok(OutputComponent::Snip), "full" => Ok(OutputComponent::Full), "plain" => Ok(OutputComponent::Plain), _ => Err(format!("Unknown style '{}'", s).into()), @@ -82,6 +86,10 @@ impl OutputComponents { self.0.contains(&OutputComponent::Numbers) } + pub fn snip(&self) -> bool { + self.0.contains(&OutputComponent::Snip) + } + pub fn plain(&self) -> bool { self.0.iter().all(|c| c == &OutputComponent::Plain) }