1 use clap::crate_version;
4 use std::path::{Path, PathBuf};
6 use clap::{App, AppSettings, ArgMatches, SubCommand};
8 use mdbook::errors::Result as Result3;
11 #[cfg(feature = "linkcheck")]
13 #[cfg(feature = "linkcheck")]
14 use mdbook::renderer::RenderContext;
17 let d_message = "-d, --dest-dir=[dest-dir]
18 'The output directory for your book{n}(Defaults to ./book when omitted)'";
19 let dir_message = "[dir]
20 'A directory for your book{n}(Defaults to Current Directory when omitted)'";
22 let matches = App::new("rustbook")
23 .about("Build a book with mdBook")
24 .author("Steve Klabnik <steve@steveklabnik.com>")
25 .version(&*format!("v{}", crate_version!()))
26 .setting(AppSettings::SubcommandRequired)
28 SubCommand::with_name("build")
29 .about("Build the book from the markdown files")
30 .arg_from_usage(d_message)
31 .arg_from_usage(dir_message),
34 SubCommand::with_name("linkcheck")
35 .about("Run linkcheck with mdBook 3")
36 .arg_from_usage(dir_message),
40 // Check which subcomamnd the user ran...
41 match matches.subcommand() {
42 ("build", Some(sub_matches)) => {
43 if let Err(e) = build(sub_matches) {
44 eprintln!("Error: {}", e);
46 for cause in e.iter().skip(1) {
47 eprintln!("\tCaused By: {}", cause);
50 ::std::process::exit(101);
53 ("linkcheck", Some(sub_matches)) => {
54 #[cfg(feature = "linkcheck")]
56 if let Err(err) = linkcheck(sub_matches) {
57 eprintln!("Error: {}", err);
58 std::process::exit(101);
62 #[cfg(not(feature = "linkcheck"))]
64 // This avoids the `unused_binding` lint.
66 "mdbook-linkcheck is disabled, but arguments were passed: {:?}",
71 (_, _) => unreachable!(),
75 #[cfg(feature = "linkcheck")]
76 pub fn linkcheck(args: &ArgMatches<'_>) -> Result<(), Error> {
77 let book_dir = get_book_dir(args);
78 let book = MDBook::load(&book_dir).unwrap();
79 let cfg = book.config;
80 let render_ctx = RenderContext::new(&book_dir, book.book, cfg, &book_dir);
81 let cache_file = render_ctx.destination.join("cache.json");
82 let color = codespan_reporting::term::termcolor::ColorChoice::Auto;
83 mdbook_linkcheck::run(&cache_file, color, &render_ctx)
86 // Build command implementation
87 pub fn build(args: &ArgMatches<'_>) -> Result3<()> {
88 let book_dir = get_book_dir(args);
89 let mut book = MDBook::load(&book_dir)?;
91 // Set this to allow us to catch bugs in advance.
92 book.config.build.create_missing = false;
94 if let Some(dest_dir) = args.value_of("dest-dir") {
95 book.config.build.build_dir = PathBuf::from(dest_dir);
103 fn get_book_dir(args: &ArgMatches<'_>) -> PathBuf {
104 if let Some(dir) = args.value_of("dir") {
105 // Check if path is relative from current dir, or absolute...
106 let p = Path::new(dir);
107 if p.is_relative() { env::current_dir().unwrap().join(dir) } else { p.to_path_buf() }
109 env::current_dir().unwrap()