diff --git a/src/cli.rs b/src/cli.rs index 902b54f..d3cffca 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -13,7 +13,7 @@ pub struct Args { /// Enable tracing output /// /// When specified without a value, defaults to `info`. - #[clap( + #[arg( long, global = true, default_missing_value = "info", diff --git a/src/subcommands/build.rs b/src/subcommands/build.rs index 976750d..bdaa391 100644 --- a/src/subcommands/build.rs +++ b/src/subcommands/build.rs @@ -16,21 +16,21 @@ use std::{ #[derive(Debug, clap::Args, Clone)] pub struct BuildArgs { /// The path of the project to build. - #[clap(default_value = ".")] + #[arg(default_value = ".")] pub path: PathBuf, /// Path of output directory /// /// The path of the directory to place the compiled datapack. - #[clap(short, long, env = "DATAPACK_DIR")] + #[arg(short, long, env = "DATAPACK_DIR")] pub output: Option, /// Path of the assets folder /// /// The path of a folder which files and subfolders will be copied to the root of the datapack. /// Overrides the `assets` field in the pack.toml file. - #[clap(short, long)] + #[arg(short, long)] pub assets: Option, /// Package the project to a zip file. - #[clap(short, long)] + #[arg(short, long)] pub zip: bool, } diff --git a/src/subcommands/clean.rs b/src/subcommands/clean.rs index cb01f9e..83d6f34 100644 --- a/src/subcommands/clean.rs +++ b/src/subcommands/clean.rs @@ -8,19 +8,19 @@ use crate::terminal_output::{print_error, print_info, print_success}; #[derive(Debug, clap::Args, Clone)] pub struct CleanArgs { /// The path of the project to clean. - #[clap(default_value = ".")] + #[arg(default_value = ".")] pub path: PathBuf, /// The path of the directory where the compiled datapacks are placed. - #[clap(short, long, env = "DATAPACK_DIR")] + #[arg(short, long, env = "DATAPACK_DIR")] pub output: Option, /// Clean the whole output folder - #[clap(short, long)] + #[arg(short, long)] pub all: bool, /// Force clean - #[clap(short, long)] + #[arg(short, long)] pub force: bool, /// Enable verbose output. - #[clap(short, long)] + #[arg(short, long)] verbose: bool, } diff --git a/src/subcommands/init.rs b/src/subcommands/init.rs index b684485..08e6f32 100644 --- a/src/subcommands/init.rs +++ b/src/subcommands/init.rs @@ -19,25 +19,25 @@ use crate::{ #[derive(Debug, clap::Args, Clone)] pub struct InitArgs { /// The path of the folder to initialize in. - #[clap(default_value = ".")] + #[arg(default_value = ".")] pub path: PathBuf, /// The name of the project. - #[clap(short, long)] + #[arg(short, long)] pub name: Option, /// The description of the project. - #[clap(short, long)] + #[arg(short, long)] pub description: Option, /// The pack format version. - #[clap(short, long, value_name = "FORMAT")] + #[arg(short, long, value_name = "FORMAT")] pub pack_format: Option, /// Force initialization even if the directory is not empty. - #[clap(short, long)] + #[arg(short, long)] pub force: bool, /// The version control system to initialize. - #[clap(long, default_value = "git")] + #[arg(long, default_value = "git")] pub vcs: VersionControlSystem, /// Enable verbose output. - #[clap(short, long)] + #[arg(short, long)] verbose: bool, } diff --git a/src/subcommands/lang_debug.rs b/src/subcommands/lang_debug.rs index e676d64..c7105e1 100644 --- a/src/subcommands/lang_debug.rs +++ b/src/subcommands/lang_debug.rs @@ -6,15 +6,15 @@ use std::path::PathBuf; #[derive(Debug, clap::Args, Clone)] pub struct LangDebugArgs { /// The path of the project to compile. - #[clap(default_value = ".")] + #[arg(default_value = ".")] pub path: PathBuf, /// The state to dump. /// /// Output can be the raw tokens, the abstract syntax tree, or the transpiled datapack. - #[clap(short, long, value_name = "STATE", default_value = "ast")] + #[arg(short, long, value_name = "STATE", default_value = "ast")] pub dump: DumpState, /// Pretty-print the output. - #[clap(short, long)] + #[arg(short, long)] pub pretty: bool, } diff --git a/src/subcommands/watch.rs b/src/subcommands/watch.rs index 9baf84f..f42977a 100644 --- a/src/subcommands/watch.rs +++ b/src/subcommands/watch.rs @@ -18,33 +18,42 @@ use crate::{ #[derive(Debug, clap::Args, Clone)] pub struct WatchArgs { /// The path of the project to watch. - #[clap(default_value = ".")] + #[arg(default_value = ".")] pub path: PathBuf, /// Only run after changes are detected. /// /// Skips the initial run of the commands. - #[clap(short, long)] + #[arg(short, long)] pub no_inital: bool, /// The time to wait in ms before running the command after changes are detected. - #[clap(short, long, value_name = "TIME_IN_MS", default_value = "2000")] + #[arg(short, long, value_name = "TIME_IN_MS", default_value = "2000")] pub debounce_time: u64, /// Additional paths to watch for changes. /// /// By default, the `src` directory, `pack.png`, and `pack.toml` as well as the defined /// assets directory in the config are watched. - #[clap(short, long, value_name = "PATH")] + #[arg(short, long, value_name = "PATH")] pub watch: Vec, - /// The commands to run in the project directory when changes are detected. + /// The shulkerscript commands to run in the project directory when changes are detected. /// /// Use multiple times to run multiple commands. - #[clap(short = 'x', long, value_name = "COMMAND", default_value = "build .")] + /// Internal commands will always run before shell commands and a command will only run if the + /// previous one exited successfully. + /// + /// Use the `--no-execute` flag to disable running these commands, useful when only wanting to + /// run shell commands and not default build command. + #[arg(short = 'x', long, value_name = "COMMAND", default_value = "build .")] pub execute: Vec, -} - -#[derive(Debug, Clone)] -enum WatchCommand { - Internal(Args), - External(String), + /// Do not run the internal shulkerscript commands specified by `--execute` (and the default one). + #[arg(short = 'X', long)] + pub no_execute: bool, + /// The shell commands to run in the project directory when changes are detected. + /// + /// Use multiple times to run multiple commands. + /// Shell commands will always run after shulkerscript commands and a command will only run + /// if the previous one exited successfully. + #[arg(short, long, value_name = "COMMAND")] + pub shell: Vec, } pub fn watch(args: &WatchArgs) -> Result<()> { @@ -58,13 +67,7 @@ pub fn watch(args: &WatchArgs) -> Result<()> { let prog_name = std::env::args() .next() .unwrap_or(env!("CARGO_PKG_NAME").to_string()); - if let Ok(args) = - Args::try_parse_from(iter::once(prog_name.as_str()).chain(split.clone())) - { - WatchCommand::Internal(args) - } else { - WatchCommand::External(cmd.to_owned()) - } + Args::parse_from(iter::once(prog_name.as_str()).chain(split.clone())) }) .collect::>(); @@ -83,7 +86,7 @@ pub fn watch(args: &WatchArgs) -> Result<()> { #[allow(clippy::collapsible_if)] if !args.no_inital { - run_cmds(&commands, true); + run_cmds(&commands, args.no_execute, &args.shell, true); } ctrlc::set_handler(move || { @@ -92,11 +95,14 @@ pub fn watch(args: &WatchArgs) -> Result<()> { }) .expect("Error setting Ctrl-C handler"); + let shell_commands = args.shell.clone(); + let no_execute = args.no_execute; + let mut debouncer = new_debouncer( Duration::from_millis(args.debounce_time), move |res: DebounceEventResult| { if res.is_ok() { - run_cmds(&commands, false) + run_cmds(&commands, no_execute, &shell_commands, false) } else { process::exit(1); } @@ -160,40 +166,38 @@ pub fn watch(args: &WatchArgs) -> Result<()> { } } -fn run_cmds(cmds: &[WatchCommand], initial: bool) { +fn run_cmds(cmds: &[Args], no_execute: bool, shell_cmds: &[String], initial: bool) { if initial { print_info("Running commands initially..."); } else { print_info("Changes have been detected. Running commands..."); } - for (index, cmd) in cmds.iter().enumerate() { - match cmd { - WatchCommand::Internal(args) => { - if args.run().is_err() { - print_error(format!("Error running command: {}", index + 1)); - print_error("Not running further commands."); - break; - } + if !no_execute { + for (index, args) in cmds.iter().enumerate() { + if args.run().is_err() { + print_error(format!("Error running command: {}", index + 1)); + print_error("Not running further commands."); + return; } - WatchCommand::External(cmd) => { - let status = run_shell_cmd(cmd); - match status { - Ok(status) if !status.success() => { - print_error(format!( - "Command {} exited unsuccessfully with status code {}", - index + 1, - status.code().unwrap_or(1) - )); - print_error("Not running further commands."); - break; - } - Ok(_) => {} - Err(_) => { - print_error(format!("Error running command: {}", index + 1)); - print_error("Not running further commands."); - break; - } - } + } + } + for (index, cmd) in shell_cmds.iter().enumerate() { + let status = run_shell_cmd(cmd); + match status { + Ok(status) if !status.success() => { + print_error(format!( + "Shell command {} exited unsuccessfully with status code {}", + index + 1, + status.code().unwrap_or(1) + )); + print_error("Not running further shell commands."); + return; + } + Ok(_) => {} + Err(_) => { + print_error(format!("Error running shell command: {}", index + 1)); + print_error("Not running further shell commands."); + return; } } }