use std::io::{self, BufRead, BufReader, Read, Write};
use anyhow::{Context, Result};
use yansi::Paint;
use crate::{
config::{Config, PlaceholderFormat, StyleConfig},
formatter::{PageSnippet, highlight_lines},
line_iterator::LineIterator,
};
#[cfg(not(target_os = "windows"))]
fn configure_pager(_: bool) {
use std::sync::Once;
static INIT: Once = Once::new();
INIT.call_once(|| pager::Pager::with_default_pager("less -R").setup());
}
#[cfg(target_os = "windows")]
fn configure_pager(enable_styles: bool) {
use crate::utils::print_warning;
print_warning(enable_styles, "--pager flag not available on Windows!");
}
pub fn print_page(
reader: impl Read,
enable_markdown: bool,
enable_styles: bool,
use_pager: bool,
config: &Config,
) -> Result<()> {
let reader = BufReader::new(reader);
if use_pager || config.display.use_pager {
configure_pager(enable_styles);
}
let stdout = io::stdout();
let mut handle = stdout.lock();
if enable_markdown {
for line in reader.lines() {
let line = line.context("Error while reading from a page")?;
writeln!(handle, "{line}").context("Could not write to stdout")?;
}
} else {
let mut process_snippet = |snip: PageSnippet<&str>| {
if snip.is_empty() {
Ok(())
} else {
print_snippet(
&mut handle,
snip,
&config.style,
config.display.placeholder_format,
)
.context("Failed to print snippet")
}
};
highlight_lines(
LineIterator::new(reader),
&mut process_snippet,
!config.display.compact,
config.display.show_title,
config.display.indent,
)
.context("Could not write to stdout")?;
}
handle.flush().context("Could not flush stdout")?;
Ok(())
}
fn print_snippet(
writer: &mut impl Write,
snip: PageSnippet<&str>,
style: &StyleConfig,
placeholder_format: PlaceholderFormat,
) -> io::Result<()> {
use PageSnippet::*;
match snip {
CommandName(s) | Title(s) => write!(writer, "{}", s.paint(style.command_name)),
Placeholder(s) => write!(writer, "{}", s.paint(style.example_variable)),
PlaceholderVariants { short, long } => match placeholder_format {
PlaceholderFormat::Short => write!(writer, "{}", short.paint(style.example_code)),
PlaceholderFormat::Long => write!(writer, "{}", long.paint(style.example_code)),
PlaceholderFormat::Both => {
write!(
writer,
"{}",
format!("[{short}|{long}]").paint(style.example_code)
)
}
},
NormalCode(s) => write!(writer, "{}", s.paint(style.example_code)),
Description(s) => write!(writer, "{}", s.paint(style.description)),
Text(s) => write!(writer, "{}", s.paint(style.example_text)),
Indent(n) => write!(writer, "{:n$}", ' '),
Linebreak => writeln!(writer),
}
}