use camino::{Utf8Path, Utf8PathBuf};
use cap_std::ambient_authority;
use cap_std::fs_utf8::{Dir, OpenOptions};
use std::io::Write;
use crate::error::OrthohelpError;
use super::types::ManSection;
pub struct ManPageInfo<'a> {
pub name: &'a str,
pub subcommand: Option<&'a str>,
pub section: ManSection,
}
impl<'a> ManPageInfo<'a> {
#[must_use]
pub const fn new(name: &'a str, section: ManSection) -> Self {
Self {
name,
subcommand: None,
section,
}
}
#[must_use]
pub const fn with_subcommand(name: &'a str, subcommand: &'a str, section: ManSection) -> Self {
Self {
name,
subcommand: Some(subcommand),
section,
}
}
}
pub fn write_man_page(
out_dir: &Utf8Path,
info: &ManPageInfo<'_>,
content: &str,
) -> Result<Utf8PathBuf, OrthohelpError> {
let dir = ensure_dir(out_dir)?;
let section = info.section.as_u8();
let section_dir = format!("man/man{section}");
dir.create_dir_all(§ion_dir)
.map_err(|io_err| OrthohelpError::Io {
path: out_dir.join(§ion_dir),
source: io_err,
})?;
let section_dir_handle = dir
.open_dir(§ion_dir)
.map_err(|io_err| OrthohelpError::Io {
path: out_dir.join(§ion_dir),
source: io_err,
})?;
let filename = info.subcommand.map_or_else(
|| format!("{}.{section}", info.name),
|sub| format!("{}-{sub}.{section}", info.name),
);
let file_path = out_dir.join(§ion_dir).join(&filename);
let mut file = section_dir_handle
.open_with(
&filename,
OpenOptions::new().write(true).create(true).truncate(true),
)
.map_err(|io_err| OrthohelpError::Io {
path: file_path.clone(),
source: io_err,
})?;
file.write_all(content.as_bytes())
.map_err(|io_err| OrthohelpError::Io {
path: file_path.clone(),
source: io_err,
})?;
Ok(file_path)
}
fn ensure_dir(path: &Utf8Path) -> Result<Dir, OrthohelpError> {
match Dir::open_ambient_dir(path, ambient_authority()) {
Ok(dir) => Ok(dir),
Err(open_err) if open_err.kind() == std::io::ErrorKind::NotFound => {
Dir::create_ambient_dir_all(path, ambient_authority()).map_err(|io_err| {
OrthohelpError::Io {
path: path.to_path_buf(),
source: io_err,
}
})?;
Dir::open_ambient_dir(path, ambient_authority()).map_err(|io_err| OrthohelpError::Io {
path: path.to_path_buf(),
source: io_err,
})
}
Err(open_err) => Err(OrthohelpError::Io {
path: path.to_path_buf(),
source: open_err,
}),
}
}