use std::io::{self, IsTerminal, Write};
use codespan_reporting::term::termcolor;
use termcolor::{ColorChoice, WriteColor};
use typst::utils::singleton;
use crate::ARGS;
pub fn out() -> TermOut {
TermOut {
inner: singleton!(TermOutInner, TermOutInner::new()),
}
}
struct TermOutInner {
stream: termcolor::StandardStream,
}
impl TermOutInner {
fn new() -> Self {
let color_choice = match ARGS.color {
clap::ColorChoice::Auto if std::io::stderr().is_terminal() => {
ColorChoice::Auto
}
clap::ColorChoice::Always => ColorChoice::Always,
_ => ColorChoice::Never,
};
let stream = termcolor::StandardStream::stderr(color_choice);
TermOutInner { stream }
}
}
#[derive(Clone)]
pub struct TermOut {
inner: &'static TermOutInner,
}
impl TermOut {
pub fn clear_screen(&mut self) -> io::Result<()> {
if self.inner.stream.supports_color() {
let mut stream = self.inner.stream.lock();
write!(stream, "\x1B[2J\x1B[1;1H")?;
stream.flush()?;
}
Ok(())
}
pub fn clear_last_line(&mut self) -> io::Result<()> {
if self.inner.stream.supports_color() {
let mut stream = self.inner.stream.lock();
write!(stream, "\x1B[1F\x1B[0J")?;
stream.flush()?;
}
Ok(())
}
}
impl Write for TermOut {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.inner.stream.lock().write(buf)
}
fn flush(&mut self) -> io::Result<()> {
self.inner.stream.lock().flush()
}
}
impl WriteColor for TermOut {
fn supports_color(&self) -> bool {
self.inner.stream.supports_color()
}
fn set_color(&mut self, spec: &termcolor::ColorSpec) -> io::Result<()> {
self.inner.stream.lock().set_color(spec)
}
fn reset(&mut self) -> io::Result<()> {
self.inner.stream.lock().reset()
}
}