use crate::Env;
use crate::source::Location;
use crate::source::pretty::{Report, ReportType, Snippet};
use crate::system::concurrency::WriteAll;
use crate::system::{Close, Dup, FdFlag, Isatty};
use annotate_snippets::Renderer;
use std::borrow::Cow;
#[cfg(unix)]
pub(crate) use std::os::unix::io::RawFd;
#[cfg(not(unix))]
pub(crate) type RawFd = i32;
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[repr(transparent)]
pub struct Fd(pub RawFd);
impl Fd {
pub const STDIN: Fd = Fd(0);
pub const STDOUT: Fd = Fd(1);
pub const STDERR: Fd = Fd(2);
}
impl From<RawFd> for Fd {
fn from(raw_fd: RawFd) -> Fd {
Fd(raw_fd)
}
}
impl std::fmt::Display for Fd {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.0.fmt(f)
}
}
pub const MIN_INTERNAL_FD: Fd = Fd(10);
pub fn move_fd_internal<S>(system: &S, from: Fd) -> crate::system::Result<Fd>
where
S: Dup + Close + ?Sized,
{
if from >= MIN_INTERNAL_FD {
return Ok(from);
}
let new = system.dup(from, MIN_INTERNAL_FD, FdFlag::CloseOnExec.into());
system.close(from).ok();
new
}
#[must_use]
pub fn report_to_string<S: Isatty>(env: &Env<S>, report: &Report<'_>) -> String {
let renderer = if env.should_print_error_in_color() {
Renderer::styled()
} else {
Renderer::plain()
};
format!("{}\n", renderer.render(&[report.into()]))
}
pub async fn print_report<S: Isatty + WriteAll>(env: &mut Env<S>, report: &Report<'_>) {
let report_str = report_to_string(env, report);
env.system.print_error(&report_str).await;
}
pub async fn print_error<S: Isatty + WriteAll>(
env: &mut Env<S>,
title: Cow<'_, str>,
label: Cow<'_, str>,
location: &Location,
) {
let mut report = Report::new();
report.r#type = ReportType::Error;
report.title = title;
report.snippets = Snippet::with_primary_span(location, label);
print_report(env, &report).await;
}