use std::io::{BufRead, BufReader, Read};
use std::path::Path;
mod extract;
mod process;
mod template;
use crate::config;
#[derive(Debug, Clone, Copy)]
pub struct ReadmeOptions {
pub add_title: bool,
pub add_badges: bool,
pub add_license: bool,
pub indent_headings: bool,
pub extract_from_comment: bool,
}
impl Default for ReadmeOptions {
fn default() -> Self {
ReadmeOptions {
add_title: true,
add_badges: true,
add_license: true,
indent_headings: true,
extract_from_comment: true,
}
}
}
pub fn generate_readme<T: Read>(
project_root: &Path,
source: &mut T,
template: Option<&mut T>,
options: ReadmeOptions,
) -> Result<String, String> {
let lines = if options.extract_from_comment {
extract::extract_docs(source).map_err(|e| format!("{}", e))?
} else {
BufReader::new(source)
.lines()
.collect::<Result<Vec<_>, _>>()
.map_err(|e| format!("{}", e))?
};
let readme = process::process_docs(lines, options.indent_headings).join("\n");
let template = if let Some(template) = template {
Some(get_template_string(template)?)
} else {
None
};
let cargo = config::get_manifest(project_root)?;
template::render(template, readme, &cargo, options)
}
fn get_template_string<T: Read>(template: &mut T) -> Result<String, String> {
let mut template_string = String::new();
if let Err(e) = template.read_to_string(&mut template_string) {
return Err(format!("Error: {}", e));
}
Ok(template_string)
}