use std::{
fs,
path::PathBuf,
collections::HashMap
};
use chrono::{Local, Datelike, Timelike};
use super::MONTHS;
pub struct ManpageBuilder {
name: String,
short_desc: String,
desc: String,
author_name: String,
author_email: String,
name_comment: Option<String>,
other_pages: Vec<String>,
other_sections: HashMap<String, String>
}
impl ManpageBuilder {
pub fn new(
name: &str,
short_desc: &str,
author_name: &str,
author_email: &str,
desc: &str
) -> Self {
ManpageBuilder {
name: name.to_string(),
short_desc: short_desc.to_string(),
author_name: author_name.to_string(),
author_email: author_email.to_string(),
desc: desc.replace("\n", "\n.br\n"),
name_comment: None,
other_pages: vec![],
other_sections: HashMap::new()
}
}
pub fn name_comment(mut self, comment: &str) -> Self {
self.name_comment = Some(comment.to_string());
self
}
pub fn other_page(mut self, name: &str) -> Self {
self.other_pages.push(name.to_string());
self
}
pub fn section(mut self, name: &str, text: &str) -> Self {
self.other_sections.insert(name.to_string(), text.replace("\n", "\n.br\n"));
self
}
pub fn build<P: Into<PathBuf>>(&self, app_ver: &str, path: P) {
let date = Local::now().date_naive();
let month = MONTHS[date.month() as usize - 1];
let day = date.day();
let year = date.year();
let date_str = format!("{day} {month} {year}");
let time = Local::now().time();
let hour = time.hour();
let minute = time.minute();
let second = time.second();
let time_str = format!("{hour:02}:{minute:02}:{second:02}");
let syn_str = if let Some(synopsis) = self.other_sections.get("SYNOPSIS") {
format!(
".SH SYNOPSIS\n\
{synopsis}\n"
)
}
else { String::new() };
let examples_str = if let Some(examples) = self.other_sections.get("EXAMPLES") {
format!(
".SH EXAMPLES\n\
{examples}\n"
)
}
else { String::new() };
let name_comment = if let Some(ref comment) = self.name_comment {
format!(" ({comment})")
}
else { String::new() };
let header_str = format!(
".\\\" Manpage for {name}{name_comment}.\n\
.\\\" Created on {month} {day}, {year} at {time_str}\n\
.TH {name} 1 \"{date_str}\" \"{app_ver}\" \"{name} man page\"\n\
.SH NAME\n\
{name} \\- {}\n\
{syn_str}\
.SH DESCRIPTION\n\
{}\n\
{examples_str}",
self.short_desc,
self.desc,
name = self.name,
);
let author_str = format!(
".SH AUTHOR\n\
{} ({})",
self.author_name,
self.author_email
);
let footer_str = if self.other_pages.len() > 0 {
let mut sect_header = String::from(".SH SEE ALSO\n");
for (i, other_page) in self.other_pages.iter().enumerate() {
sect_header.push_str(&format!("{other_page}(1)\n"));
if i < self.other_pages.len() - 1{
sect_header.push_str(".br\n");
}
}
format!("{sect_header}{author_str}")
}
else { author_str };
let mut body_str = String::new();
for (sect_title, sect_body) in &self.other_sections {
if sect_title != "SYNOPSIS" && sect_title != "EXAMPLES" {
body_str.push_str(&format!(
".SH {sect_title}\n\
{sect_body}\n"
));
}
}
let file_str = format!("{header_str}{body_str}{footer_str}");
fs::write(path.into(), &file_str).unwrap();
}
}