//! Mdbook's configuration system.
//!
//! The main entrypoint of the `config` module is the `Config` struct. This acts
//! essentially as a bag of configuration information, with a couple
//! pre-determined tables ([`BookConfig`] and [`BuildConfig`]) as well as support
//! for arbitrary data which is exposed to plugins and alternative backends.
//!
//!
//! # Examples
//!
//! ```rust
//! # use mdbook::errors::*;
//! use std::path::PathBuf;
//! use std::str::FromStr;
//! use mdbook::Config;
//! use toml::Value;
//!
//! # fn run() -> Result<()> {
//! let src = r#"
//! [book]
//! title = "My Book"
//! authors = ["Michael-F-Bryan"]
//!
//! [build]
//! src = "out"
//!
//! [other-table.foo]
//! bar = 123
//! "#;
//!
//! // load the `Config` from a toml string
//! let mut cfg = Config::from_str(src)?;
//!
//! // retrieve a nested value
//! let bar = cfg.get("other-table.foo.bar").cloned();
//! assert_eq!(bar, Some(Value::Integer(123)));
//!
//! // Set the `output.html.theme` directory
//! assert!(cfg.get("output.html").is_none());
//! cfg.set("output.html.theme", "./themes");
//!
//! // then load it again, automatically deserializing to a `PathBuf`.
//! let got: Option<PathBuf> = cfg.get_deserialized_opt("output.html.theme")?;
//! assert_eq!(got, Some(PathBuf::from("./themes")));
//! # Ok(())
//! # }
//! # run().unwrap()
//! ```
#![deny(missing_docs)]
use log::{debug, trace, warn};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::collections::HashMap;
use std::env;
use std::fs::File;
use std::io::Read;
use std::path::{Path, PathBuf};
use std::str::FromStr;
use toml::value::Table;
use toml::Value;
use crate::errors::*;
use crate::utils::{self, toml_ext::TomlExt};
/// The overall configuration object for MDBook, essentially an in-memory
/// representation of `book.toml`.
#[derive(Debug, Clone, PartialEq)]
pub struct Config {
/// Metadata about the book.
pub book: BookConfig,
/// Information about the build environment.
pub build: BuildConfig,
/// Information about Rust language support.
pub rust: RustConfig,
rest: Value,
}
impl FromStr for Config {
type Err = Error;
/// Load a `Config` from some string.
fn from_str(src: &str) -> Result<Self> {
toml::from_str(src).with_context(|| "Invalid configuration file")
}
}
impl Config {
/// Load the configuration file from disk.
pub fn from_disk<P: AsRef<Path>>(config_file: P) -> Result<Config> {
let mut buffer = String::new();
File::open(config_file)
.with_context(|| "Unable to open the configuration file")?
.read_to_string(&mut buffer)
.with_context(|| "Couldn't read the file")?;
Config::from_str(&