/*! This small lib is used to generate README files for the crates in the `sources` workspace. These functions are called in a crate's build.rs file to generate a README from Rust doc comments. !*/ use snafu::ResultExt; use std::fs::File; use std::io::Write; use std::path::{Path, PathBuf}; pub type Result<T> = std::result::Result<T, error::Error>; pub mod error { use snafu::Snafu; use std::path::PathBuf; #[derive(Debug, Snafu)] #[snafu(visibility(pub(super)))] pub enum Error { #[snafu(display("Unable to create the 'README.md' file: {}", source))] ReadmeCreate { source: std::io::Error }, #[snafu(display("Unable to generate the 'README.md' file contents: {}", error))] ReadmeGenerate { error: String }, #[snafu(display("Unable to open '{}': {}", file.display(), source))] ReadmeSourceOpen { file: PathBuf, source: std::io::Error, }, #[snafu(display("Unable to open 'README.tpl': {}", source))] ReadmeTemplateOpen { source: std::io::Error }, #[snafu(display("Unable to write to the 'README.md' file: {}", source))] ReadmeWrite { source: std::io::Error }, } } /// When this function is called in a `build.rs` file, it will generate a `README.md` (as a sibling /// to `build.rs`). It uses the doc comments found in `src/main.rs` and the `cargo-readme` crate to /// do so. The template for `cargo-readme` is expected to be `README.tpl` as a sibling file to /// `build.rs`. pub fn from_main() -> Result<()> { from_file("src/main.rs") } /// When this function is called in a `build.rs` file, it will generate a `README.md` (as a sibling /// to `build.rs`). It uses the doc comments found in `src/lib.rs` and the `cargo-readme` crate to /// do so. The template for `cargo-readme` is expected to be `README.tpl` as a sibling file to /// `build.rs`. pub fn from_lib() -> Result<()> { from_file("src/lib.rs") } /// When this function is called in a `build.rs` file, it will generate a `README.md` (as a sibling /// to `build.rs`). It uses the doc comments found in `rust_file` and the `cargo-readme` crate to do /// so. The template for `cargo-readme` is expected to be `README.tpl` as a sibling file to /// `build.rs`. pub fn from_file<P>(rust_file: P) -> Result<()> where P: AsRef<Path>, { // Check for environment variable "SKIP_README". If it is set, // skip README generation if std::env::var_os("SKIP_README").is_some() { return Ok(()); } let mut source = File::open(rust_file.as_ref()).context(error::ReadmeSourceOpenSnafu { file: rust_file.as_ref(), })?; let mut template = File::open("README.tpl").context(error::ReadmeTemplateOpenSnafu)?; let mut content = cargo_readme::generate_readme( &PathBuf::from("."), // root &mut source, // source Some(&mut template), // template // The "add x" arguments don't apply when using a template. true, // add title false, // add badges false, // add license true, // indent headings ) .map_err(|e| error::ReadmeGenerateSnafu { error: e }.build())?; // Make sure the end of the file has a newline if content.chars().last().unwrap_or_default() != '\n' { content += "\n"; } let mut readme = File::create("README.md").context(error::ReadmeCreateSnafu)?; readme .write_all(content.as_bytes()) .context(error::ReadmeWriteSnafu)?; Ok(()) }