diff --git a/src/controller.rs b/src/controller.rs index ffc5dd5b57..2987966e52 100644 --- a/src/controller.rs +++ b/src/controller.rs @@ -1,4 +1,4 @@ -use std::io::{self, BufRead, Write}; +use std::io::{self, BufRead, BufWriter, Write}; use crate::assets::HighlightingAssets; use crate::config::{Config, VisibleLines}; @@ -88,9 +88,10 @@ impl<'b> Controller<'b> { clircle::Identifier::stdout() }; + const BUF_W_SZ: usize = 1 << 14; let mut writer = match output_buffer { Some(buf) => OutputHandle::FmtWrite(buf), - None => OutputHandle::IoWrite(output_type.handle()?), + None => OutputHandle::IoWrite(BufWriter::with_capacity(BUF_W_SZ, output_type.handle()?)), }; let mut no_errors: bool = true; let stderr = io::stderr(); @@ -124,10 +125,10 @@ impl<'b> Controller<'b> { Ok(no_errors) } - fn print_input( + fn print_input( &self, input: Input, - writer: &mut OutputHandle, + writer: &mut OutputHandle, stdin: R, stdout_identifier: Option<&Identifier>, is_first: bool, @@ -174,7 +175,7 @@ impl<'b> Controller<'b> { None }; - let mut printer: Box = if self.config.loop_through { + let mut printer: Box> = if self.config.loop_through { Box::new(SimplePrinter::new(self.config)) } else { Box::new(InteractivePrinter::new( @@ -196,10 +197,10 @@ impl<'b> Controller<'b> { ) } - fn print_file( + fn print_file( &self, - printer: &mut dyn Printer, - writer: &mut OutputHandle, + printer: &mut dyn Printer, + writer: &mut OutputHandle, input: &mut OpenedInput, add_header_padding: bool, #[cfg(feature = "git")] line_changes: &Option, @@ -234,10 +235,10 @@ impl<'b> Controller<'b> { Ok(()) } - fn print_file_ranges( + fn print_file_ranges( &self, - printer: &mut dyn Printer, - writer: &mut OutputHandle, + printer: &mut dyn Printer, + writer: &mut OutputHandle, reader: &mut InputReader, line_ranges: &LineRanges, ) -> Result<()> { @@ -279,6 +280,7 @@ impl<'b> Controller<'b> { line_number += 1; line_buffer.clear(); } + writer.flush()?; Ok(()) } } diff --git a/src/printer.rs b/src/printer.rs index e9bea3fd8f..5896679f1f 100644 --- a/src/printer.rs +++ b/src/printer.rs @@ -1,5 +1,5 @@ use std::fmt; -use std::io; +use std::io::{self, BufWriter, Write}; use std::vec::Vec; use nu_ansi_term::Color::{Fixed, Green, Red, Yellow}; @@ -67,35 +67,42 @@ const EMPTY_SYNTECT_STYLE: syntect::highlighting::Style = syntect::highlighting: font_style: FontStyle::empty(), }; -pub enum OutputHandle<'a> { - IoWrite(&'a mut dyn io::Write), +pub enum OutputHandle<'a, W: io::Write> { + IoWrite(BufWriter), FmtWrite(&'a mut dyn fmt::Write), } -impl<'a> OutputHandle<'a> { +impl<'a, W: io::Write> OutputHandle<'a, W> { fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> Result<()> { match self { Self::IoWrite(handle) => handle.write_fmt(args).map_err(Into::into), Self::FmtWrite(handle) => handle.write_fmt(args).map_err(Into::into), } } + + pub(crate) fn flush(&mut self) -> Result<()> { + match self { + Self::IoWrite(handle) => handle.flush().map_err(Into::into), + Self::FmtWrite(_handle) => Ok(()), + } + } } -pub(crate) trait Printer { +pub(crate) trait Printer { fn print_header( &mut self, - handle: &mut OutputHandle, + handle: &mut OutputHandle, input: &OpenedInput, add_header_padding: bool, ) -> Result<()>; - fn print_footer(&mut self, handle: &mut OutputHandle, input: &OpenedInput) -> Result<()>; + fn print_footer(&mut self, handle: &mut OutputHandle, input: &OpenedInput) -> Result<()>; - fn print_snip(&mut self, handle: &mut OutputHandle) -> Result<()>; + fn print_snip(&mut self, handle: &mut OutputHandle) -> Result<()>; fn print_line( &mut self, out_of_range: bool, - handle: &mut OutputHandle, + handle: &mut OutputHandle, line_number: usize, line_buffer: &[u8], ) -> Result<()>; @@ -115,28 +122,28 @@ impl<'a> SimplePrinter<'a> { } } -impl<'a> Printer for SimplePrinter<'a> { +impl<'a, W: io::Write> Printer for SimplePrinter<'a> { fn print_header( &mut self, - _handle: &mut OutputHandle, + _handle: &mut OutputHandle, _input: &OpenedInput, _add_header_padding: bool, ) -> Result<()> { Ok(()) } - fn print_footer(&mut self, _handle: &mut OutputHandle, _input: &OpenedInput) -> Result<()> { + fn print_footer(&mut self, _handle: &mut OutputHandle, _input: &OpenedInput) -> Result<()> { Ok(()) } - fn print_snip(&mut self, _handle: &mut OutputHandle) -> Result<()> { + fn print_snip(&mut self, _handle: &mut OutputHandle) -> Result<()> { Ok(()) } fn print_line( &mut self, out_of_range: bool, - handle: &mut OutputHandle, + handle: &mut OutputHandle, _line_number: usize, line_buffer: &[u8], ) -> Result<()> { @@ -321,9 +328,9 @@ impl<'a> InteractivePrinter<'a> { }) } - fn print_horizontal_line_term( + fn print_horizontal_line_term( &mut self, - handle: &mut OutputHandle, + handle: &mut OutputHandle, style: Style, ) -> Result<()> { writeln!( @@ -334,7 +341,7 @@ impl<'a> InteractivePrinter<'a> { Ok(()) } - fn print_horizontal_line(&mut self, handle: &mut OutputHandle, grid_char: char) -> Result<()> { + fn print_horizontal_line(&mut self, handle: &mut OutputHandle, grid_char: char) -> Result<()> { if self.panel_width == 0 { self.print_horizontal_line_term(handle, self.colors.grid)?; } else { @@ -372,7 +379,7 @@ impl<'a> InteractivePrinter<'a> { } } - fn print_header_component_indent(&mut self, handle: &mut OutputHandle) -> Result<()> { + fn print_header_component_indent(&mut self, handle: &mut OutputHandle) -> Result<()> { if self.config.style_components.grid() { write!( handle, @@ -387,18 +394,18 @@ impl<'a> InteractivePrinter<'a> { } } - fn print_header_component_with_indent( + fn print_header_component_with_indent( &mut self, - handle: &mut OutputHandle, + handle: &mut OutputHandle, content: &str, ) -> Result<()> { self.print_header_component_indent(handle)?; writeln!(handle, "{content}") } - fn print_header_multiline_component( + fn print_header_multiline_component( &mut self, - handle: &mut OutputHandle, + handle: &mut OutputHandle, content: &str, ) -> Result<()> { let mut content = content; @@ -446,10 +453,10 @@ impl<'a> InteractivePrinter<'a> { } } -impl<'a> Printer for InteractivePrinter<'a> { +impl<'a, W: io::Write> Printer for InteractivePrinter<'a> { fn print_header( &mut self, - handle: &mut OutputHandle, + handle: &mut OutputHandle, input: &OpenedInput, add_header_padding: bool, ) -> Result<()> { @@ -549,7 +556,7 @@ impl<'a> Printer for InteractivePrinter<'a> { Ok(()) } - fn print_footer(&mut self, handle: &mut OutputHandle, _input: &OpenedInput) -> Result<()> { + fn print_footer(&mut self, handle: &mut OutputHandle, _input: &OpenedInput) -> Result<()> { if self.config.style_components.grid() && (self.content_type.map_or(false, |c| c.is_text()) || self.config.show_nonprintable) { @@ -559,7 +566,7 @@ impl<'a> Printer for InteractivePrinter<'a> { } } - fn print_snip(&mut self, handle: &mut OutputHandle) -> Result<()> { + fn print_snip(&mut self, handle: &mut OutputHandle) -> Result<()> { let panel = self.create_fake_panel(" ..."); let panel_count = panel.chars().count(); @@ -586,7 +593,7 @@ impl<'a> Printer for InteractivePrinter<'a> { fn print_line( &mut self, out_of_range: bool, - handle: &mut OutputHandle, + handle: &mut OutputHandle, line_number: usize, line_buffer: &[u8], ) -> Result<()> {