]>
Commit | Line | Data |
---|---|---|
dc9dc135 | 1 | use crate::get_book_dir; |
9fa01778 | 2 | use clap::{App, ArgMatches, SubCommand}; |
9fa01778 XL |
3 | use mdbook::config; |
4 | use mdbook::errors::Result; | |
5 | use mdbook::MDBook; | |
ea8adc8c XL |
6 | use std::io; |
7 | use std::io::Write; | |
83c7162d | 8 | use std::process::Command; |
ea8adc8c XL |
9 | |
10 | // Create clap subcommand arguments | |
11 | pub fn make_subcommand<'a, 'b>() -> App<'a, 'b> { | |
12 | SubCommand::with_name("init") | |
9fa01778 | 13 | .about("Creates the boilerplate structure and files for a new book") |
ea8adc8c | 14 | // the {n} denotes a newline which will properly aligned in all help messages |
9fa01778 XL |
15 | .arg_from_usage( |
16 | "[dir] 'Directory to create the book in{n}\ | |
17 | (Defaults to the Current Directory when omitted)'", | |
dc9dc135 XL |
18 | ) |
19 | .arg_from_usage("--theme 'Copies the default theme into your source folder'") | |
9fa01778 | 20 | .arg_from_usage("--force 'Skips confirmation prompts'") |
ea8adc8c XL |
21 | } |
22 | ||
23 | // Init command implementation | |
24 | pub fn execute(args: &ArgMatches) -> Result<()> { | |
ea8adc8c | 25 | let book_dir = get_book_dir(args); |
2c00a5a8 | 26 | let mut builder = MDBook::init(&book_dir); |
83c7162d | 27 | let mut config = config::Config::default(); |
ea8adc8c XL |
28 | |
29 | // If flag `--theme` is present, copy theme to src | |
30 | if args.is_present("theme") { | |
5869c6ff XL |
31 | let theme_dir = book_dir.join("theme"); |
32 | println!(); | |
33 | println!("Copying the default theme to {}", theme_dir.display()); | |
ea8adc8c | 34 | // Skip this if `--force` is present |
5869c6ff | 35 | if !args.is_present("force") && theme_dir.exists() { |
2c00a5a8 | 36 | println!("This could potentially overwrite files already present in that directory."); |
ea8adc8c XL |
37 | print!("\nAre you sure you want to continue? (y/n) "); |
38 | ||
39 | // Read answer from user and exit if it's not 'yes' | |
2c00a5a8 XL |
40 | if confirm() { |
41 | builder.copy_theme(true); | |
ea8adc8c | 42 | } |
83c7162d XL |
43 | } else { |
44 | builder.copy_theme(true); | |
ea8adc8c | 45 | } |
ea8adc8c XL |
46 | } |
47 | ||
2c00a5a8 | 48 | println!("\nDo you want a .gitignore to be created? (y/n)"); |
ea8adc8c | 49 | |
2c00a5a8 XL |
50 | if confirm() { |
51 | builder.create_gitignore(true); | |
ea8adc8c XL |
52 | } |
53 | ||
83c7162d XL |
54 | config.book.title = request_book_title(); |
55 | ||
56 | if let Some(author) = get_author_name() { | |
57 | debug!("Obtained user name from gitconfig: {:?}", author); | |
58 | config.book.authors.push(author); | |
59 | builder.with_config(config); | |
60 | } | |
61 | ||
2c00a5a8 | 62 | builder.build()?; |
ea8adc8c XL |
63 | println!("\nAll done, no errors..."); |
64 | ||
65 | Ok(()) | |
66 | } | |
67 | ||
83c7162d XL |
68 | /// Obtains author name from git config file by running the `git config` command. |
69 | fn get_author_name() -> Option<String> { | |
70 | let output = Command::new("git") | |
71 | .args(&["config", "--get", "user.name"]) | |
72 | .output() | |
73 | .ok()?; | |
74 | ||
75 | if output.status.success() { | |
76 | Some(String::from_utf8_lossy(&output.stdout).trim().to_owned()) | |
77 | } else { | |
78 | None | |
79 | } | |
80 | } | |
81 | ||
82 | /// Request book title from user and return if provided. | |
83 | fn request_book_title() -> Option<String> { | |
84 | println!("What title would you like to give the book? "); | |
85 | io::stdout().flush().unwrap(); | |
86 | let mut resp = String::new(); | |
87 | io::stdin().read_line(&mut resp).unwrap(); | |
88 | let resp = resp.trim(); | |
89 | if resp.is_empty() { | |
90 | None | |
91 | } else { | |
92 | Some(resp.into()) | |
93 | } | |
94 | } | |
95 | ||
96 | // Simple function for user confirmation | |
ea8adc8c XL |
97 | fn confirm() -> bool { |
98 | io::stdout().flush().unwrap(); | |
99 | let mut s = String::new(); | |
100 | io::stdin().read_line(&mut s).ok(); | |
101 | match &*s.trim() { | |
102 | "Y" | "y" | "yes" | "Yes" => true, | |
103 | _ => false, | |
104 | } | |
105 | } |