mirror of
https://github.com/sharkdp/bat.git
synced 2024-11-25 09:13:39 +01:00
Merge pull request #2618 from Piturnah/feat/write-to-buffer
feat: Optionally write to a buffer instead of stdout
This commit is contained in:
commit
b06f13f0c5
17
examples/buffer.rs
Normal file
17
examples/buffer.rs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
use bat::{assets::HighlightingAssets, config::Config, controller::Controller, Input};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut buffer = String::new();
|
||||||
|
let config = Config {
|
||||||
|
colored_output: true,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
let assets = HighlightingAssets::from_binary();
|
||||||
|
let controller = Controller::new(&config, &assets);
|
||||||
|
let input = Input::from_file(file!());
|
||||||
|
controller
|
||||||
|
.run(vec![input.into()], Some(&mut buffer))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
println!("{buffer}");
|
||||||
|
}
|
@ -206,7 +206,7 @@ pub fn list_themes(cfg: &Config, config_dir: &Path, cache_dir: &Path) -> Result<
|
|||||||
)?;
|
)?;
|
||||||
config.theme = theme.to_string();
|
config.theme = theme.to_string();
|
||||||
Controller::new(&config, &assets)
|
Controller::new(&config, &assets)
|
||||||
.run(vec![theme_preview_file()])
|
.run(vec![theme_preview_file()], None)
|
||||||
.ok();
|
.ok();
|
||||||
writeln!(stdout)?;
|
writeln!(stdout)?;
|
||||||
}
|
}
|
||||||
@ -230,7 +230,7 @@ pub fn list_themes(cfg: &Config, config_dir: &Path, cache_dir: &Path) -> Result<
|
|||||||
fn run_controller(inputs: Vec<Input>, config: &Config, cache_dir: &Path) -> Result<bool> {
|
fn run_controller(inputs: Vec<Input>, config: &Config, cache_dir: &Path) -> Result<bool> {
|
||||||
let assets = assets_from_cache_or_binary(config.use_custom_assets, cache_dir)?;
|
let assets = assets_from_cache_or_binary(config.use_custom_assets, cache_dir)?;
|
||||||
let controller = Controller::new(config, &assets);
|
let controller = Controller::new(config, &assets);
|
||||||
controller.run(inputs)
|
controller.run(inputs, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "bugreport")]
|
#[cfg(feature = "bugreport")]
|
||||||
|
@ -12,7 +12,7 @@ use crate::line_range::{LineRanges, RangeCheckResult};
|
|||||||
use crate::output::OutputType;
|
use crate::output::OutputType;
|
||||||
#[cfg(feature = "paging")]
|
#[cfg(feature = "paging")]
|
||||||
use crate::paging::PagingMode;
|
use crate::paging::PagingMode;
|
||||||
use crate::printer::{InteractivePrinter, Printer, SimplePrinter};
|
use crate::printer::{InteractivePrinter, OutputHandle, Printer, SimplePrinter};
|
||||||
|
|
||||||
use clircle::{Clircle, Identifier};
|
use clircle::{Clircle, Identifier};
|
||||||
|
|
||||||
@ -26,13 +26,18 @@ impl<'b> Controller<'b> {
|
|||||||
Controller { config, assets }
|
Controller { config, assets }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(&self, inputs: Vec<Input>) -> Result<bool> {
|
pub fn run(
|
||||||
self.run_with_error_handler(inputs, default_error_handler)
|
&self,
|
||||||
|
inputs: Vec<Input>,
|
||||||
|
output_buffer: Option<&mut dyn std::fmt::Write>,
|
||||||
|
) -> Result<bool> {
|
||||||
|
self.run_with_error_handler(inputs, output_buffer, default_error_handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_with_error_handler(
|
pub fn run_with_error_handler(
|
||||||
&self,
|
&self,
|
||||||
inputs: Vec<Input>,
|
inputs: Vec<Input>,
|
||||||
|
output_buffer: Option<&mut dyn std::fmt::Write>,
|
||||||
handle_error: impl Fn(&Error, &mut dyn Write),
|
handle_error: impl Fn(&Error, &mut dyn Write),
|
||||||
) -> Result<bool> {
|
) -> Result<bool> {
|
||||||
let mut output_type;
|
let mut output_type;
|
||||||
@ -74,7 +79,10 @@ impl<'b> Controller<'b> {
|
|||||||
clircle::Identifier::stdout()
|
clircle::Identifier::stdout()
|
||||||
};
|
};
|
||||||
|
|
||||||
let writer = output_type.handle()?;
|
let mut writer = match output_buffer {
|
||||||
|
Some(buf) => OutputHandle::FmtWrite(buf),
|
||||||
|
None => OutputHandle::IoWrite(output_type.handle()?),
|
||||||
|
};
|
||||||
let mut no_errors: bool = true;
|
let mut no_errors: bool = true;
|
||||||
let stderr = io::stderr();
|
let stderr = io::stderr();
|
||||||
|
|
||||||
@ -82,16 +90,23 @@ impl<'b> Controller<'b> {
|
|||||||
let identifier = stdout_identifier.as_ref();
|
let identifier = stdout_identifier.as_ref();
|
||||||
let is_first = index == 0;
|
let is_first = index == 0;
|
||||||
let result = if input.is_stdin() {
|
let result = if input.is_stdin() {
|
||||||
self.print_input(input, writer, io::stdin().lock(), identifier, is_first)
|
self.print_input(input, &mut writer, io::stdin().lock(), identifier, is_first)
|
||||||
} else {
|
} else {
|
||||||
// Use dummy stdin since stdin is actually not used (#1902)
|
// Use dummy stdin since stdin is actually not used (#1902)
|
||||||
self.print_input(input, writer, io::empty(), identifier, is_first)
|
self.print_input(input, &mut writer, io::empty(), identifier, is_first)
|
||||||
};
|
};
|
||||||
if let Err(error) = result {
|
if let Err(error) = result {
|
||||||
if attached_to_pager {
|
match writer {
|
||||||
handle_error(&error, writer);
|
// It doesn't make much sense to send errors straight to stderr if the user
|
||||||
} else {
|
// provided their own buffer, so we just return it.
|
||||||
handle_error(&error, &mut stderr.lock());
|
OutputHandle::FmtWrite(_) => return Err(error),
|
||||||
|
OutputHandle::IoWrite(ref mut writer) => {
|
||||||
|
if attached_to_pager {
|
||||||
|
handle_error(&error, writer);
|
||||||
|
} else {
|
||||||
|
handle_error(&error, &mut stderr.lock());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
no_errors = false;
|
no_errors = false;
|
||||||
}
|
}
|
||||||
@ -103,7 +118,7 @@ impl<'b> Controller<'b> {
|
|||||||
fn print_input<R: BufRead>(
|
fn print_input<R: BufRead>(
|
||||||
&self,
|
&self,
|
||||||
input: Input,
|
input: Input,
|
||||||
writer: &mut dyn Write,
|
writer: &mut OutputHandle,
|
||||||
stdin: R,
|
stdin: R,
|
||||||
stdout_identifier: Option<&Identifier>,
|
stdout_identifier: Option<&Identifier>,
|
||||||
is_first: bool,
|
is_first: bool,
|
||||||
@ -164,7 +179,7 @@ impl<'b> Controller<'b> {
|
|||||||
fn print_file(
|
fn print_file(
|
||||||
&self,
|
&self,
|
||||||
printer: &mut dyn Printer,
|
printer: &mut dyn Printer,
|
||||||
writer: &mut dyn Write,
|
writer: &mut OutputHandle,
|
||||||
input: &mut OpenedInput,
|
input: &mut OpenedInput,
|
||||||
add_header_padding: bool,
|
add_header_padding: bool,
|
||||||
#[cfg(feature = "git")] line_changes: &Option<LineChanges>,
|
#[cfg(feature = "git")] line_changes: &Option<LineChanges>,
|
||||||
@ -202,7 +217,7 @@ impl<'b> Controller<'b> {
|
|||||||
fn print_file_ranges(
|
fn print_file_ranges(
|
||||||
&self,
|
&self,
|
||||||
printer: &mut dyn Printer,
|
printer: &mut dyn Printer,
|
||||||
writer: &mut dyn Write,
|
writer: &mut OutputHandle,
|
||||||
reader: &mut InputReader,
|
reader: &mut InputReader,
|
||||||
line_ranges: &LineRanges,
|
line_ranges: &LineRanges,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
@ -7,6 +7,8 @@ pub enum Error {
|
|||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Io(#[from] ::std::io::Error),
|
Io(#[from] ::std::io::Error),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
|
Fmt(#[from] ::std::fmt::Error),
|
||||||
|
#[error(transparent)]
|
||||||
SyntectError(#[from] ::syntect::Error),
|
SyntectError(#[from] ::syntect::Error),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
SyntectLoadingError(#[from] ::syntect::LoadingError),
|
SyntectLoadingError(#[from] ::syntect::LoadingError),
|
||||||
|
@ -300,7 +300,7 @@ impl<'a> PrettyPrinter<'a> {
|
|||||||
|
|
||||||
// Run the controller
|
// Run the controller
|
||||||
let controller = Controller::new(&self.config, &self.assets);
|
let controller = Controller::new(&self.config, &self.assets);
|
||||||
controller.run(inputs.into_iter().map(|i| i.into()).collect())
|
controller.run(inputs.into_iter().map(|i| i.into()).collect(), None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
130
src/printer.rs
130
src/printer.rs
@ -1,4 +1,5 @@
|
|||||||
use std::io::Write;
|
use std::fmt;
|
||||||
|
use std::io;
|
||||||
use std::vec::Vec;
|
use std::vec::Vec;
|
||||||
|
|
||||||
use nu_ansi_term::Color::{Fixed, Green, Red, Yellow};
|
use nu_ansi_term::Color::{Fixed, Green, Red, Yellow};
|
||||||
@ -35,21 +36,52 @@ use crate::terminal::{as_terminal_escaped, to_ansi_color};
|
|||||||
use crate::vscreen::AnsiStyle;
|
use crate::vscreen::AnsiStyle;
|
||||||
use crate::wrapping::WrappingMode;
|
use crate::wrapping::WrappingMode;
|
||||||
|
|
||||||
|
pub enum OutputHandle<'a> {
|
||||||
|
IoWrite(&'a mut dyn io::Write),
|
||||||
|
FmtWrite(&'a mut dyn fmt::Write),
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! write_handle {
|
||||||
|
($dst:expr, $($arg:tt)*) => {
|
||||||
|
match $dst {
|
||||||
|
OutputHandle::IoWrite(ref mut handle) => {
|
||||||
|
write!(handle, $($arg)*).map_err(|e| Error::from(e))
|
||||||
|
}
|
||||||
|
OutputHandle::FmtWrite(ref mut handle) => {
|
||||||
|
write!(handle, $($arg)*).map_err(|e| Error::from(e))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! writeln_handle {
|
||||||
|
($dst:expr, $($arg:tt)*) => {
|
||||||
|
match $dst {
|
||||||
|
OutputHandle::IoWrite(ref mut handle) => {
|
||||||
|
writeln!(handle, $($arg)*).map_err(|e| Error::from(e))
|
||||||
|
}
|
||||||
|
OutputHandle::FmtWrite(ref mut handle) => {
|
||||||
|
writeln!(handle, $($arg)*).map_err(|e| Error::from(e))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) trait Printer {
|
pub(crate) trait Printer {
|
||||||
fn print_header(
|
fn print_header(
|
||||||
&mut self,
|
&mut self,
|
||||||
handle: &mut dyn Write,
|
handle: &mut OutputHandle,
|
||||||
input: &OpenedInput,
|
input: &OpenedInput,
|
||||||
add_header_padding: bool,
|
add_header_padding: bool,
|
||||||
) -> Result<()>;
|
) -> Result<()>;
|
||||||
fn print_footer(&mut self, handle: &mut dyn Write, input: &OpenedInput) -> Result<()>;
|
fn print_footer(&mut self, handle: &mut OutputHandle, input: &OpenedInput) -> Result<()>;
|
||||||
|
|
||||||
fn print_snip(&mut self, handle: &mut dyn Write) -> Result<()>;
|
fn print_snip(&mut self, handle: &mut OutputHandle) -> Result<()>;
|
||||||
|
|
||||||
fn print_line(
|
fn print_line(
|
||||||
&mut self,
|
&mut self,
|
||||||
out_of_range: bool,
|
out_of_range: bool,
|
||||||
handle: &mut dyn Write,
|
handle: &mut OutputHandle,
|
||||||
line_number: usize,
|
line_number: usize,
|
||||||
line_buffer: &[u8],
|
line_buffer: &[u8],
|
||||||
) -> Result<()>;
|
) -> Result<()>;
|
||||||
@ -68,25 +100,25 @@ impl<'a> SimplePrinter<'a> {
|
|||||||
impl<'a> Printer for SimplePrinter<'a> {
|
impl<'a> Printer for SimplePrinter<'a> {
|
||||||
fn print_header(
|
fn print_header(
|
||||||
&mut self,
|
&mut self,
|
||||||
_handle: &mut dyn Write,
|
_handle: &mut OutputHandle,
|
||||||
_input: &OpenedInput,
|
_input: &OpenedInput,
|
||||||
_add_header_padding: bool,
|
_add_header_padding: bool,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_footer(&mut self, _handle: &mut dyn Write, _input: &OpenedInput) -> Result<()> {
|
fn print_footer(&mut self, _handle: &mut OutputHandle, _input: &OpenedInput) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_snip(&mut self, _handle: &mut dyn Write) -> Result<()> {
|
fn print_snip(&mut self, _handle: &mut OutputHandle) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_line(
|
fn print_line(
|
||||||
&mut self,
|
&mut self,
|
||||||
out_of_range: bool,
|
out_of_range: bool,
|
||||||
handle: &mut dyn Write,
|
handle: &mut OutputHandle,
|
||||||
_line_number: usize,
|
_line_number: usize,
|
||||||
line_buffer: &[u8],
|
line_buffer: &[u8],
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
@ -97,9 +129,21 @@ impl<'a> Printer for SimplePrinter<'a> {
|
|||||||
self.config.tab_width,
|
self.config.tab_width,
|
||||||
self.config.nonprintable_notation,
|
self.config.nonprintable_notation,
|
||||||
);
|
);
|
||||||
write!(handle, "{}", line)?;
|
write_handle!(handle, "{}", line)?;
|
||||||
} else {
|
} else {
|
||||||
handle.write_all(line_buffer)?
|
match handle {
|
||||||
|
OutputHandle::IoWrite(handle) => handle.write_all(line_buffer)?,
|
||||||
|
OutputHandle::FmtWrite(handle) => {
|
||||||
|
write!(
|
||||||
|
handle,
|
||||||
|
"{}",
|
||||||
|
std::str::from_utf8(line_buffer).map_err(|_| Error::Msg(
|
||||||
|
"encountered invalid utf8 while printing to non-io buffer"
|
||||||
|
.to_string()
|
||||||
|
))?
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -217,8 +261,12 @@ impl<'a> InteractivePrinter<'a> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_horizontal_line_term(&mut self, handle: &mut dyn Write, style: Style) -> Result<()> {
|
fn print_horizontal_line_term(
|
||||||
writeln!(
|
&mut self,
|
||||||
|
handle: &mut OutputHandle,
|
||||||
|
style: Style,
|
||||||
|
) -> Result<()> {
|
||||||
|
writeln_handle!(
|
||||||
handle,
|
handle,
|
||||||
"{}",
|
"{}",
|
||||||
style.paint("─".repeat(self.config.term_width))
|
style.paint("─".repeat(self.config.term_width))
|
||||||
@ -226,13 +274,13 @@ impl<'a> InteractivePrinter<'a> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_horizontal_line(&mut self, handle: &mut dyn Write, grid_char: char) -> Result<()> {
|
fn print_horizontal_line(&mut self, handle: &mut OutputHandle, grid_char: char) -> Result<()> {
|
||||||
if self.panel_width == 0 {
|
if self.panel_width == 0 {
|
||||||
self.print_horizontal_line_term(handle, self.colors.grid)?;
|
self.print_horizontal_line_term(handle, self.colors.grid)?;
|
||||||
} else {
|
} else {
|
||||||
let hline = "─".repeat(self.config.term_width - (self.panel_width + 1));
|
let hline = "─".repeat(self.config.term_width - (self.panel_width + 1));
|
||||||
let hline = format!("{}{}{}", "─".repeat(self.panel_width), grid_char, hline);
|
let hline = format!("{}{}{}", "─".repeat(self.panel_width), grid_char, hline);
|
||||||
writeln!(handle, "{}", self.colors.grid.paint(hline))?;
|
writeln_handle!(handle, "{}", self.colors.grid.paint(hline))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -256,9 +304,9 @@ impl<'a> InteractivePrinter<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_header_component_indent(&mut self, handle: &mut dyn Write) -> std::io::Result<()> {
|
fn print_header_component_indent(&mut self, handle: &mut OutputHandle) -> Result<()> {
|
||||||
if self.config.style_components.grid() {
|
if self.config.style_components.grid() {
|
||||||
write!(
|
write_handle!(
|
||||||
handle,
|
handle,
|
||||||
"{}{}",
|
"{}{}",
|
||||||
" ".repeat(self.panel_width),
|
" ".repeat(self.panel_width),
|
||||||
@ -267,7 +315,7 @@ impl<'a> InteractivePrinter<'a> {
|
|||||||
.paint(if self.panel_width > 0 { "│ " } else { "" }),
|
.paint(if self.panel_width > 0 { "│ " } else { "" }),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
write!(handle, "{}", " ".repeat(self.panel_width))
|
write_handle!(handle, "{}", " ".repeat(self.panel_width))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,7 +332,7 @@ impl<'a> InteractivePrinter<'a> {
|
|||||||
impl<'a> Printer for InteractivePrinter<'a> {
|
impl<'a> Printer for InteractivePrinter<'a> {
|
||||||
fn print_header(
|
fn print_header(
|
||||||
&mut self,
|
&mut self,
|
||||||
handle: &mut dyn Write,
|
handle: &mut OutputHandle,
|
||||||
input: &OpenedInput,
|
input: &OpenedInput,
|
||||||
add_header_padding: bool,
|
add_header_padding: bool,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
@ -294,7 +342,7 @@ impl<'a> Printer for InteractivePrinter<'a> {
|
|||||||
|
|
||||||
if !self.config.style_components.header() {
|
if !self.config.style_components.header() {
|
||||||
if Some(ContentType::BINARY) == self.content_type && !self.config.show_nonprintable {
|
if Some(ContentType::BINARY) == self.content_type && !self.config.show_nonprintable {
|
||||||
writeln!(
|
writeln_handle!(
|
||||||
handle,
|
handle,
|
||||||
"{}: Binary content from {} will not be printed to the terminal \
|
"{}: Binary content from {} will not be printed to the terminal \
|
||||||
(but will be present if the output of 'bat' is piped). You can use 'bat -A' \
|
(but will be present if the output of 'bat' is piped). You can use 'bat -A' \
|
||||||
@ -342,7 +390,7 @@ impl<'a> Printer for InteractivePrinter<'a> {
|
|||||||
} else {
|
} else {
|
||||||
// Only pad space between files, if we haven't already drawn a horizontal rule
|
// Only pad space between files, if we haven't already drawn a horizontal rule
|
||||||
if add_header_padding && !self.config.style_components.rule() {
|
if add_header_padding && !self.config.style_components.rule() {
|
||||||
writeln!(handle)?;
|
writeln_handle!(handle,)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -350,7 +398,7 @@ impl<'a> Printer for InteractivePrinter<'a> {
|
|||||||
self.print_header_component_indent(handle)?;
|
self.print_header_component_indent(handle)?;
|
||||||
|
|
||||||
match component {
|
match component {
|
||||||
StyleComponent::HeaderFilename => writeln!(
|
StyleComponent::HeaderFilename => writeln_handle!(
|
||||||
handle,
|
handle,
|
||||||
"{}{}{}",
|
"{}{}{}",
|
||||||
description
|
description
|
||||||
@ -366,7 +414,7 @@ impl<'a> Printer for InteractivePrinter<'a> {
|
|||||||
.size
|
.size
|
||||||
.map(|s| format!("{}", ByteSize(s)))
|
.map(|s| format!("{}", ByteSize(s)))
|
||||||
.unwrap_or_else(|| "-".into());
|
.unwrap_or_else(|| "-".into());
|
||||||
writeln!(handle, "Size: {}", self.colors.header_value.paint(bsize))
|
writeln_handle!(handle, "Size: {}", self.colors.header_value.paint(bsize))
|
||||||
}
|
}
|
||||||
_ => Ok(()),
|
_ => Ok(()),
|
||||||
}
|
}
|
||||||
@ -383,7 +431,7 @@ impl<'a> Printer for InteractivePrinter<'a> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_footer(&mut self, handle: &mut dyn Write, _input: &OpenedInput) -> Result<()> {
|
fn print_footer(&mut self, handle: &mut OutputHandle, _input: &OpenedInput) -> Result<()> {
|
||||||
if self.config.style_components.grid()
|
if self.config.style_components.grid()
|
||||||
&& (self.content_type.map_or(false, |c| c.is_text()) || self.config.show_nonprintable)
|
&& (self.content_type.map_or(false, |c| c.is_text()) || self.config.show_nonprintable)
|
||||||
{
|
{
|
||||||
@ -393,7 +441,7 @@ impl<'a> Printer for InteractivePrinter<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_snip(&mut self, handle: &mut dyn Write) -> Result<()> {
|
fn print_snip(&mut self, handle: &mut OutputHandle) -> Result<()> {
|
||||||
let panel = self.create_fake_panel(" ...");
|
let panel = self.create_fake_panel(" ...");
|
||||||
let panel_count = panel.chars().count();
|
let panel_count = panel.chars().count();
|
||||||
|
|
||||||
@ -406,7 +454,7 @@ impl<'a> Printer for InteractivePrinter<'a> {
|
|||||||
let snip_right =
|
let snip_right =
|
||||||
" ─".repeat((self.config.term_width - panel_count - snip_left_count - title_count) / 2);
|
" ─".repeat((self.config.term_width - panel_count - snip_left_count - title_count) / 2);
|
||||||
|
|
||||||
writeln!(
|
writeln_handle!(
|
||||||
handle,
|
handle,
|
||||||
"{}",
|
"{}",
|
||||||
self.colors
|
self.colors
|
||||||
@ -420,7 +468,7 @@ impl<'a> Printer for InteractivePrinter<'a> {
|
|||||||
fn print_line(
|
fn print_line(
|
||||||
&mut self,
|
&mut self,
|
||||||
out_of_range: bool,
|
out_of_range: bool,
|
||||||
handle: &mut dyn Write,
|
handle: &mut OutputHandle,
|
||||||
line_number: usize,
|
line_number: usize,
|
||||||
line_buffer: &[u8],
|
line_buffer: &[u8],
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
@ -505,7 +553,7 @@ impl<'a> Printer for InteractivePrinter<'a> {
|
|||||||
.map(|d| d.generate(line_number, false, self));
|
.map(|d| d.generate(line_number, false, self));
|
||||||
|
|
||||||
for deco in decorations {
|
for deco in decorations {
|
||||||
write!(handle, "{} ", deco.text)?;
|
write_handle!(handle, "{} ", deco.text)?;
|
||||||
cursor_max -= deco.width + 1;
|
cursor_max -= deco.width + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -523,7 +571,7 @@ impl<'a> Printer for InteractivePrinter<'a> {
|
|||||||
// ANSI escape passthrough.
|
// ANSI escape passthrough.
|
||||||
(ansi, true) => {
|
(ansi, true) => {
|
||||||
self.ansi_style.update(ansi);
|
self.ansi_style.update(ansi);
|
||||||
write!(handle, "{}", ansi)?;
|
write_handle!(handle, "{}", ansi)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Regular text.
|
// Regular text.
|
||||||
@ -531,7 +579,7 @@ impl<'a> Printer for InteractivePrinter<'a> {
|
|||||||
let text = &*self.preprocess(text, &mut cursor_total);
|
let text = &*self.preprocess(text, &mut cursor_total);
|
||||||
let text_trimmed = text.trim_end_matches(|c| c == '\r' || c == '\n');
|
let text_trimmed = text.trim_end_matches(|c| c == '\r' || c == '\n');
|
||||||
|
|
||||||
write!(
|
write_handle!(
|
||||||
handle,
|
handle,
|
||||||
"{}",
|
"{}",
|
||||||
as_terminal_escaped(
|
as_terminal_escaped(
|
||||||
@ -556,9 +604,13 @@ impl<'a> Printer for InteractivePrinter<'a> {
|
|||||||
} else {
|
} else {
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
write!(handle, "{}", ansi_style.paint(" ".repeat(width)))?;
|
write_handle!(
|
||||||
|
handle,
|
||||||
|
"{}",
|
||||||
|
ansi_style.paint(" ".repeat(width))
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
write!(handle, "{}", &text[text_trimmed.len()..])?;
|
write_handle!(handle, "{}", &text[text_trimmed.len()..])?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -566,7 +618,7 @@ impl<'a> Printer for InteractivePrinter<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !self.config.style_components.plain() && line.bytes().next_back() != Some(b'\n') {
|
if !self.config.style_components.plain() && line.bytes().next_back() != Some(b'\n') {
|
||||||
writeln!(handle)?;
|
writeln_handle!(handle,)?;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for &(style, region) in ®ions {
|
for &(style, region) in ®ions {
|
||||||
@ -576,7 +628,7 @@ impl<'a> Printer for InteractivePrinter<'a> {
|
|||||||
// ANSI escape passthrough.
|
// ANSI escape passthrough.
|
||||||
(ansi, true) => {
|
(ansi, true) => {
|
||||||
self.ansi_style.update(ansi);
|
self.ansi_style.update(ansi);
|
||||||
write!(handle, "{}", ansi)?;
|
write_handle!(handle, "{}", ansi)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Regular text.
|
// Regular text.
|
||||||
@ -621,7 +673,7 @@ impl<'a> Printer for InteractivePrinter<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// It wraps.
|
// It wraps.
|
||||||
write!(
|
write_handle!(
|
||||||
handle,
|
handle,
|
||||||
"{}\n{}",
|
"{}\n{}",
|
||||||
as_terminal_escaped(
|
as_terminal_escaped(
|
||||||
@ -647,7 +699,7 @@ impl<'a> Printer for InteractivePrinter<'a> {
|
|||||||
|
|
||||||
// flush the buffer
|
// flush the buffer
|
||||||
cursor += current_width;
|
cursor += current_width;
|
||||||
write!(
|
write_handle!(
|
||||||
handle,
|
handle,
|
||||||
"{}",
|
"{}",
|
||||||
as_terminal_escaped(
|
as_terminal_escaped(
|
||||||
@ -670,18 +722,18 @@ impl<'a> Printer for InteractivePrinter<'a> {
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
write!(
|
write_handle!(
|
||||||
handle,
|
handle,
|
||||||
"{}",
|
"{}",
|
||||||
ansi_style.paint(" ".repeat(cursor_max - cursor))
|
ansi_style.paint(" ".repeat(cursor_max - cursor))
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
writeln!(handle)?;
|
writeln_handle!(handle,)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if highlight_this_line && self.config.theme == "ansi" {
|
if highlight_this_line && self.config.theme == "ansi" {
|
||||||
self.ansi_style.update("^[24m");
|
self.ansi_style.update("^[24m");
|
||||||
write!(handle, "\x1B[24m")?;
|
write_handle!(handle, "\x1B[24m")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
Loading…
Reference in New Issue
Block a user