use std::fmt;
use std::io;
use std::vec::Vec;
use nu_ansi_term::Color::{Fixed, Green, Red, Yellow};
use nu_ansi_term::Style;
use bytesize::ByteSize;
use syntect::easy::HighlightLines;
use syntect::highlighting::Color;
use syntect::highlighting::FontStyle;
use syntect::highlighting::Theme;
use syntect::parsing::SyntaxSet;
use content_inspector::ContentType;
use encoding_rs::{UTF_16BE, UTF_16LE};
use unicode_width::UnicodeWidthChar;
use crate::assets::{HighlightingAssets, SyntaxReferenceInSet};
use crate::config::Config;
#[cfg(feature = "git")]
use crate::decorations::LineChangesDecoration;
use crate::decorations::{Decoration, GridBorderDecoration, LineNumberDecoration};
#[cfg(feature = "git")]
use crate::diff::LineChanges;
use crate::error::*;
use crate::input::OpenedInput;
use crate::line_range::RangeCheckResult;
use crate::preprocessor::{expand_tabs, replace_nonprintable};
use crate::style::StyleComponent;
use crate::terminal::{as_terminal_escaped, to_ansi_color};
use crate::vscreen::{AnsiStyle, EscapeSequence, EscapeSequenceIterator};
use crate::wrapping::WrappingMode;
const ANSI_UNDERLINE_ENABLE: EscapeSequence = EscapeSequence::CSI {
raw_sequence: "\x1B[4m",
parameters: "4",
intermediates: "",
final_byte: "m",
};
const ANSI_UNDERLINE_DISABLE: EscapeSequence = EscapeSequence::CSI {
raw_sequence: "\x1B[24m",
parameters: "24",
intermediates: "",
final_byte: "m",
};
const EMPTY_SYNTECT_STYLE: syntect::highlighting::Style = syntect::highlighting::Style {
foreground: Color {
r: 127,
g: 127,
b: 127,
a: 255,
},
background: Color {
r: 127,
g: 127,
b: 127,
a: 255,
},
font_style: FontStyle::empty(),
};
pub enum OutputHandle<'a> {
IoWrite(&'a mut dyn io::Write),
FmtWrite(&'a mut dyn fmt::Write),
}
impl<'a> OutputHandle<'a> {
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) trait Printer {
fn print_header(
&mut self,
handle: &mut OutputHandle,
input: &OpenedInput,
add_header_padding: bool,
) -> Result<()>;
fn print_footer(&mut self, handle: &mut OutputHandle, input: &OpenedInput) -> Result<()>;
fn print_snip(&mut self, handle: &mut OutputHandle) -> Result<()>;
fn print_line(
&mut self,
out_of_range: bool,
handle: &mut OutputHandle,
line_number: usize,
line_buffer: &[u8],
) -> Result<()>;
}
pub struct SimplePrinter<'a> {
config: &'a Config<'a>,
}
impl<'a> SimplePrinter<'a> {
pub fn new(config: &'a Config) -> Self {
SimplePrinter { config }
}
}
impl<'a> Printer for SimplePrinter<'a> {
fn print_header(
&mut self,
_handle: &mut OutputHandle,
_input: &OpenedInput,
_add_header_padding: bool,
) -> Result<()> {
Ok(())
}
fn print_footer(&mut self, _handle: &mut OutputHandle, _input: &OpenedInput) -> Result<()> {
Ok(())
}
fn print_snip(&mut self, _handle: &mut OutputHandle) -> Result<()> {
Ok(())
}
fn print_line(
&mut self,
out_of_range: bool,
handle: &mut OutputHandle,
_line_number: usize,
line_buffer: &[u8],
) -> Result<()> {
if !out_of_range {
if self.config.show_nonprintable {
let line = replace_nonprintable(
line_buffer,
self.config.tab_width,
self.config.nonprintable_notation,
);
write!(handle, "{}", line)?;
} else {
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(())
}
}
struct HighlighterFromSet<'a> {
highlighter: HighlightLines<'a>,
syntax_set: &'a SyntaxSet,
}
impl<'a> HighlighterFromSet<'a> {
fn new(syntax_in_set: SyntaxReferenceInSet<'a>