2019-05-26 01:50:41 +07:00
|
|
|
use crate::get_book_dir;
|
2021-05-31 19:43:15 -07:00
|
|
|
use clap::{App, Arg, ArgMatches, SubCommand};
|
2018-07-23 12:45:01 -05:00
|
|
|
use mdbook::config;
|
|
|
|
|
use mdbook::errors::Result;
|
|
|
|
|
use mdbook::MDBook;
|
2017-06-26 01:24:33 +02:00
|
|
|
use std::io;
|
|
|
|
|
use std::io::Write;
|
2018-03-27 01:37:11 +11:00
|
|
|
use std::process::Command;
|
2017-06-26 01:02:32 +02:00
|
|
|
|
2017-06-27 07:59:50 +02:00
|
|
|
// Create clap subcommand arguments
|
|
|
|
|
pub fn make_subcommand<'a, 'b>() -> App<'a, 'b> {
|
|
|
|
|
SubCommand::with_name("init")
|
2018-08-02 15:48:22 -05:00
|
|
|
.about("Creates the boilerplate structure and files for a new book")
|
2017-06-27 07:59:50 +02:00
|
|
|
// the {n} denotes a newline which will properly aligned in all help messages
|
2018-12-04 00:11:41 +01:00
|
|
|
.arg_from_usage(
|
|
|
|
|
"[dir] 'Directory to create the book in{n}\
|
|
|
|
|
(Defaults to the Current Directory when omitted)'",
|
2019-05-05 21:57:43 +07:00
|
|
|
)
|
|
|
|
|
.arg_from_usage("--theme 'Copies the default theme into your source folder'")
|
2018-08-02 15:48:22 -05:00
|
|
|
.arg_from_usage("--force 'Skips confirmation prompts'")
|
2021-05-31 19:43:15 -07:00
|
|
|
.arg(
|
|
|
|
|
Arg::with_name("title")
|
|
|
|
|
.long("title")
|
|
|
|
|
.takes_value(true)
|
|
|
|
|
.help("Sets the book title")
|
|
|
|
|
.required(false),
|
|
|
|
|
)
|
|
|
|
|
.arg(
|
2021-07-04 11:57:46 -07:00
|
|
|
Arg::with_name("ignore")
|
|
|
|
|
.long("ignore")
|
|
|
|
|
.takes_value(true)
|
|
|
|
|
.possible_values(&["none", "git"])
|
|
|
|
|
.help("Creates a VCS ignore file (i.e. .gitignore)")
|
|
|
|
|
.required(false),
|
2021-05-31 19:43:15 -07:00
|
|
|
)
|
2017-06-27 07:59:50 +02:00
|
|
|
}
|
|
|
|
|
|
2017-06-26 01:02:32 +02:00
|
|
|
// Init command implementation
|
2017-06-27 07:59:50 +02:00
|
|
|
pub fn execute(args: &ArgMatches) -> Result<()> {
|
2017-06-26 01:02:32 +02:00
|
|
|
let book_dir = get_book_dir(args);
|
2017-11-18 20:41:04 +08:00
|
|
|
let mut builder = MDBook::init(&book_dir);
|
2018-03-15 02:27:56 +11:00
|
|
|
let mut config = config::Config::default();
|
2017-06-26 01:02:32 +02:00
|
|
|
// If flag `--theme` is present, copy theme to src
|
|
|
|
|
if args.is_present("theme") {
|
2021-01-06 16:29:38 -08:00
|
|
|
let theme_dir = book_dir.join("theme");
|
|
|
|
|
println!();
|
|
|
|
|
println!("Copying the default theme to {}", theme_dir.display());
|
2017-06-26 01:02:32 +02:00
|
|
|
// Skip this if `--force` is present
|
2021-01-06 16:29:38 -08:00
|
|
|
if !args.is_present("force") && theme_dir.exists() {
|
2017-11-18 20:41:04 +08:00
|
|
|
println!("This could potentially overwrite files already present in that directory.");
|
2017-06-26 01:02:32 +02:00
|
|
|
print!("\nAre you sure you want to continue? (y/n) ");
|
|
|
|
|
|
|
|
|
|
// Read answer from user and exit if it's not 'yes'
|
2017-11-18 20:41:04 +08:00
|
|
|
if confirm() {
|
|
|
|
|
builder.copy_theme(true);
|
2017-06-26 01:02:32 +02:00
|
|
|
}
|
2018-03-15 02:27:56 +11:00
|
|
|
} else {
|
|
|
|
|
builder.copy_theme(true);
|
2017-06-26 01:02:32 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-04 11:57:46 -07:00
|
|
|
if let Some(ignore) = args.value_of("ignore") {
|
|
|
|
|
match ignore {
|
|
|
|
|
"git" => builder.create_gitignore(true),
|
|
|
|
|
_ => builder.create_gitignore(false)
|
|
|
|
|
};
|
2021-05-31 19:43:15 -07:00
|
|
|
} else {
|
|
|
|
|
println!("\nDo you want a .gitignore to be created? (y/n)");
|
|
|
|
|
if confirm() {
|
|
|
|
|
builder.create_gitignore(true);
|
|
|
|
|
}
|
2017-06-26 01:02:32 +02:00
|
|
|
}
|
|
|
|
|
|
2021-05-31 19:43:15 -07:00
|
|
|
config.book.title = if args.is_present("title") {
|
|
|
|
|
args.value_of("title").map(String::from)
|
|
|
|
|
} else {
|
|
|
|
|
request_book_title()
|
|
|
|
|
};
|
2018-03-15 02:27:56 +11:00
|
|
|
|
|
|
|
|
if let Some(author) = get_author_name() {
|
|
|
|
|
debug!("Obtained user name from gitconfig: {:?}", author);
|
|
|
|
|
config.book.authors.push(author);
|
|
|
|
|
builder.with_config(config);
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-18 20:41:04 +08:00
|
|
|
builder.build()?;
|
2017-06-26 01:02:32 +02:00
|
|
|
println!("\nAll done, no errors...");
|
|
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-27 01:37:11 +11:00
|
|
|
/// Obtains author name from git config file by running the `git config` command.
|
2018-03-15 02:27:56 +11:00
|
|
|
fn get_author_name() -> Option<String> {
|
2018-03-27 01:37:11 +11:00
|
|
|
let output = Command::new("git")
|
|
|
|
|
.args(&["config", "--get", "user.name"])
|
|
|
|
|
.output()
|
|
|
|
|
.ok()?;
|
|
|
|
|
|
|
|
|
|
if output.status.success() {
|
|
|
|
|
Some(String::from_utf8_lossy(&output.stdout).trim().to_owned())
|
2018-03-15 02:27:56 +11:00
|
|
|
} else {
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Request book title from user and return if provided.
|
|
|
|
|
fn request_book_title() -> Option<String> {
|
|
|
|
|
println!("What title would you like to give the book? ");
|
|
|
|
|
io::stdout().flush().unwrap();
|
|
|
|
|
let mut resp = String::new();
|
|
|
|
|
io::stdin().read_line(&mut resp).unwrap();
|
|
|
|
|
let resp = resp.trim();
|
|
|
|
|
if resp.is_empty() {
|
|
|
|
|
None
|
|
|
|
|
} else {
|
|
|
|
|
Some(resp.into())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Simple function for user confirmation
|
2017-06-26 01:24:33 +02:00
|
|
|
fn confirm() -> bool {
|
|
|
|
|
io::stdout().flush().unwrap();
|
|
|
|
|
let mut s = String::new();
|
|
|
|
|
io::stdin().read_line(&mut s).ok();
|
|
|
|
|
match &*s.trim() {
|
|
|
|
|
"Y" | "y" | "yes" | "Yes" => true,
|
|
|
|
|
_ => false,
|
|
|
|
|
}
|
|
|
|
|
}
|