diff --git a/README.md b/README.md index a41b45d2..9345895c 100644 --- a/README.md +++ b/README.md @@ -75,13 +75,13 @@ cargo xtask install-tools Here is a summary of the various commands you can run in the project. -| Command | Description | -| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `cargo install-tools` | Install all the tools the project depends on. | -| `cargo serve` | Start a web server with the course. You'll find the content on http://localhost:3000. | -| `cargo rust-tests` | Test the included Rust snippets. | -| `cargo web-tests` | Run the web driver tests in the tests directory. | -| `cargo build-book` | Create a static version of the course in the `book/` directory. Note that you have to separately build and zip exercises and add them to book/html. To build any of the translated versions of the course, run MDBOOK_BOOK__LANGUAGE=xx mdbook build -d book/xx where xx is the ISO 639 language code (e.g. da for the Danish translation). [TRANSLATIONS.md](TRANSLATIONS.md) contains further instructions. | +| Command | Description | +| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `cargo install-tools` | Install all the tools the project depends on. | +| `cargo serve` | Start a web server with the course. You'll find the content on http://localhost:3000. To serve any of the translated versions of the course, add the language flag (`--language` or `-l`) followed by xx, where xx is the ISO 639 language code (e.g. `cargo xtask serve -l da` for the Danish translation). | +| `cargo rust-tests` | Test the included Rust snippets. | +| `cargo web-tests` | Run the web driver tests in the tests directory. | +| `cargo build-book` | Create a static version of the course in the `book/` directory. Note that you have to separately build and zip exercises and add them to book/html. To build any of the translated versions of the course, add the language flag (`--language` or `-l`) followed by xx, where xx is the ISO 639 language code (e.g. `cargo xtask build -l da` for the Danish translation). [TRANSLATIONS.md](TRANSLATIONS.md) contains further instructions. | > **Note** On Windows, you need to enable symlinks > (`git config --global core.symlinks true`) and Developer Mode. diff --git a/xtask/src/main.rs b/xtask/src/main.rs index b8a64894..f5d9f5cc 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -20,8 +20,8 @@ //! the tools. use anyhow::{Ok, Result, anyhow}; -use clap::{Parser, ValueEnum}; -use std::path::Path; +use clap::{Parser, Subcommand}; +use std::path::{Path, PathBuf}; use std::{env, process::Command}; fn main() -> Result<()> { @@ -38,11 +38,11 @@ fn main() -> Result<()> { )] struct Cli { /// The task to execute - #[arg(value_enum)] + #[command(subcommand)] task: Task, } -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)] +#[derive(Subcommand)] enum Task { /// Installs the tools the project depends on. InstallTools, @@ -51,9 +51,25 @@ enum Task { /// Tests all included Rust snippets. RustTests, /// Starts a web server with the course. - Serve, - /// Create a static version of the course in the `book/` directory. - Build, + Serve { + /// ISO 639 language code (e.g. da for the Danish translation). + #[arg(short, long)] + language: Option, + + /// Directory to place the build. If not provided, defaults to the book/ directory (or the book/xx directory if a language is provided). + #[arg(short, long)] + output: Option, + }, + /// Create a static version of the course. + Build { + /// ISO 639 language code (e.g. da for the Danish translation). + #[arg(short, long)] + language: Option, + + /// Directory to place the build. If not provided, defaults to the book/ directory (or the book/xx directory if a language is provided). + #[arg(short, long)] + output: Option, + }, } fn execute_task() -> Result<()> { @@ -62,15 +78,14 @@ fn execute_task() -> Result<()> { Task::InstallTools => install_tools()?, Task::WebTests => run_web_tests()?, Task::RustTests => run_rust_tests()?, - Task::Serve => start_web_server()?, - Task::Build => build()?, + Task::Serve { language, output } => start_web_server(language, output)?, + Task::Build { language, output } => build(language, output)?, } Ok(()) } fn install_tools() -> Result<()> { println!("Installing project tools..."); - let path_to_mdbook_exerciser = Path::new(env!("CARGO_WORKSPACE_DIR")).join("mdbook-exerciser"); let path_to_mdbook_course = @@ -136,7 +151,6 @@ fn run_web_tests() -> Result<()> { fn run_rust_tests() -> Result<()> { println!("Running rust tests..."); - let path_to_workspace_root = Path::new(env!("CARGO_WORKSPACE_DIR")); let status = Command::new("mdbook") @@ -156,15 +170,26 @@ fn run_rust_tests() -> Result<()> { Ok(()) } -fn start_web_server() -> Result<()> { +fn start_web_server( + language: Option, + output_arg: Option, +) -> Result<()> { println!("Starting web server ..."); let path_to_workspace_root = Path::new(env!("CARGO_WORKSPACE_DIR")); - let status = Command::new("mdbook") - .current_dir(path_to_workspace_root.to_str().unwrap()) - .arg("serve") - .status() - .expect("Failed to execute mdbook serve"); + let mut command = Command::new("mdbook"); + command.current_dir(path_to_workspace_root.to_str().unwrap()); + command.arg("serve"); + + if let Some(language) = &language { + println!("Language: {}", &language); + command.env("MDBOOK_BOOK__LANGUAGE", &language); + } + + command.arg("-d"); + command.arg(get_output_dir(language, output_arg)); + + let status = command.status().expect("Failed to execute mdbook serve"); if !status.success() { let error_message = format!( @@ -176,15 +201,23 @@ fn start_web_server() -> Result<()> { Ok(()) } -fn build() -> Result<()> { +fn build(language: Option, output_arg: Option) -> Result<()> { println!("Building course..."); let path_to_workspace_root = Path::new(env!("CARGO_WORKSPACE_DIR")); - let status = Command::new("mdbook") - .current_dir(path_to_workspace_root.to_str().unwrap()) - .arg("build") - .status() - .expect("Failed to execute mdbook build"); + let mut command = Command::new("mdbook"); + command.current_dir(path_to_workspace_root.to_str().unwrap()); + command.arg("build"); + + if let Some(language) = &language { + println!("Language: {}", &language); + command.env("MDBOOK_BOOK__LANGUAGE", language); + } + + command.arg("-d"); + command.arg(get_output_dir(language, output_arg)); + + let status = command.status().expect("Failed to execute mdbook build"); if !status.success() { let error_message = format!( @@ -195,3 +228,13 @@ fn build() -> Result<()> { } Ok(()) } + +fn get_output_dir(language: Option, output_arg: Option) -> PathBuf { + // If the 'output' arg is specified by the caller, use that, otherwise output to the 'book/' directory + // (or the 'book/xx' directory if a language was specified). + if let Some(d) = output_arg { + d + } else { + Path::new("book").join(language.unwrap_or("".to_string())) + } +}