|
|
@ -1,10 +1,7 @@ |
|
|
|
// TODO: docstrings for everything!!!
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
use clap::{Args, Parser, Subcommand}; |
|
|
|
use clap::{Args, Parser, Subcommand}; |
|
|
|
|
|
|
|
|
|
|
|
#[derive(Parser, Debug)] |
|
|
|
#[derive(Parser, Debug)] |
|
|
|
#[command(name = "cargo")] |
|
|
|
#[command(name = "cargo", bin_name = "cargo")] |
|
|
|
#[command(bin_name = "cargo")] |
|
|
|
|
|
|
|
pub enum Cargo { |
|
|
|
pub enum Cargo { |
|
|
|
#[command(name = "3ds")] |
|
|
|
#[command(name = "3ds")] |
|
|
|
Input(Input), |
|
|
|
Input(Input), |
|
|
@ -13,20 +10,44 @@ pub enum Cargo { |
|
|
|
#[derive(Args, Debug)] |
|
|
|
#[derive(Args, Debug)] |
|
|
|
#[command(version, about)] |
|
|
|
#[command(version, about)] |
|
|
|
pub struct Input { |
|
|
|
pub struct Input { |
|
|
|
|
|
|
|
#[command(subcommand)] |
|
|
|
|
|
|
|
pub cmd: CargoCmd, |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// The cargo command to run. This command will be forwarded to the real
|
|
|
|
/// The cargo command to run. This command will be forwarded to the real
|
|
|
|
/// `cargo` with the appropriate arguments for a 3DS executable.
|
|
|
|
/// `cargo` with the appropriate arguments for a 3DS executable.
|
|
|
|
#[command(subcommand)] |
|
|
|
///
|
|
|
|
pub cmd: CargoCommand, |
|
|
|
/// If another command is passed which is not recognized, it will be passed
|
|
|
|
|
|
|
|
/// through unmodified to `cargo` with RUSTFLAGS set for the 3DS.
|
|
|
|
|
|
|
|
#[derive(Subcommand, Debug)] |
|
|
|
|
|
|
|
#[command(allow_external_subcommands = true)] |
|
|
|
|
|
|
|
pub enum CargoCmd { |
|
|
|
|
|
|
|
/// Builds an executable suitable to run on a 3DS (3dsx).
|
|
|
|
|
|
|
|
Build(CargoArgs), |
|
|
|
|
|
|
|
|
|
|
|
/// Don't actually run any commands, just echo them to the console.
|
|
|
|
/// Builds an executable and sends it to a device with `3dslink`.
|
|
|
|
/// This is mostly intended for testing.
|
|
|
|
Run(Run), |
|
|
|
#[arg(long, hide = true)] |
|
|
|
|
|
|
|
pub dry_run: bool, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Builds a test executable and sends it to a device with `3dslink`.
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
/// This can be used with `--test` for integration tests, or `--lib` for
|
|
|
|
|
|
|
|
/// unit tests (which require a custom test runner).
|
|
|
|
|
|
|
|
Test(Test), |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// NOTE: it seems docstring + name for external subcommands are not rendered
|
|
|
|
|
|
|
|
// in help, but we might as well set them here in case a future version of clap
|
|
|
|
|
|
|
|
// does include them in help text.
|
|
|
|
|
|
|
|
/// Run any other `cargo` command with RUSTFLAGS set for the 3DS.
|
|
|
|
|
|
|
|
#[command(external_subcommand, name = "COMMAND")] |
|
|
|
|
|
|
|
Passthrough(Vec<String>), |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Args, Debug)] |
|
|
|
|
|
|
|
pub struct CargoArgs { |
|
|
|
/// Pass additional options through to the `cargo` command.
|
|
|
|
/// Pass additional options through to the `cargo` command.
|
|
|
|
///
|
|
|
|
///
|
|
|
|
/// To pass flags that start with `-`, you must use `--` to separate `cargo 3ds`
|
|
|
|
/// To pass flags that start with `-`, you must use `--` to separate `cargo 3ds`
|
|
|
|
/// options from cargo options. All args after `--` will be passed through
|
|
|
|
/// options from cargo options. Any argument after `--` will be passed through
|
|
|
|
/// to cargo unmodified.
|
|
|
|
/// to cargo unmodified.
|
|
|
|
///
|
|
|
|
///
|
|
|
|
/// If one of the arguments is itself `--`, the args following that will be
|
|
|
|
/// If one of the arguments is itself `--`, the args following that will be
|
|
|
@ -36,50 +57,31 @@ pub struct Input { |
|
|
|
///
|
|
|
|
///
|
|
|
|
/// > cargo 3ds run -- -- arg1 arg2
|
|
|
|
/// > cargo 3ds run -- -- arg1 arg2
|
|
|
|
#[arg(trailing_var_arg = true)] |
|
|
|
#[arg(trailing_var_arg = true)] |
|
|
|
|
|
|
|
#[arg(allow_hyphen_values = true)] |
|
|
|
#[arg(global = true)] |
|
|
|
#[arg(global = true)] |
|
|
|
cargo_options: Vec<String>, |
|
|
|
#[arg(name = "CARGO_ARGS")] |
|
|
|
} |
|
|
|
args: Vec<String>, |
|
|
|
|
|
|
|
|
|
|
|
#[derive(Subcommand, Debug)] |
|
|
|
|
|
|
|
pub enum CargoCommand { |
|
|
|
|
|
|
|
/// Builds an executable suitable to run on a 3DS (3dsx).
|
|
|
|
|
|
|
|
Build, |
|
|
|
|
|
|
|
/// Equivalent to `cargo check`.
|
|
|
|
|
|
|
|
Check, |
|
|
|
|
|
|
|
/// Equivalent to `cargo clippy`.
|
|
|
|
|
|
|
|
Clippy, |
|
|
|
|
|
|
|
/// Equivalent to `cargo doc`.
|
|
|
|
|
|
|
|
Doc, |
|
|
|
|
|
|
|
/// Builds an executable and sends it to a device with `3dslink`.
|
|
|
|
|
|
|
|
Run(Run), |
|
|
|
|
|
|
|
/// Builds a test executable and sends it to a device with `3dslink`.
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
/// This can be used with `--test` for integration tests, or `--lib` for
|
|
|
|
|
|
|
|
/// unit tests (which require a custom test runner).
|
|
|
|
|
|
|
|
Test(Test), |
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// TODO: this doesn't seem to work for some reason...
|
|
|
|
|
|
|
|
// #[command(external_subcommand)]
|
|
|
|
|
|
|
|
// Other(Vec<String>),
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#[derive(Args, Debug)] |
|
|
|
#[derive(Parser, Debug)] |
|
|
|
pub struct Test { |
|
|
|
pub struct Test { |
|
|
|
/// If set, the built executable will not be sent to the device to run it.
|
|
|
|
/// If set, the built executable will not be sent to the device to run it.
|
|
|
|
#[arg(long)] |
|
|
|
#[arg(long)] |
|
|
|
pub no_run: bool, |
|
|
|
pub no_run: bool, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// The test command uses a superset of the same arguments as Run.
|
|
|
|
#[command(flatten)] |
|
|
|
#[command(flatten)] |
|
|
|
pub run_args: Run, |
|
|
|
pub run_args: Run, |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#[derive(Args, Debug)] |
|
|
|
#[derive(Parser, Debug)] |
|
|
|
pub struct Run { |
|
|
|
pub struct Run { |
|
|
|
/// Specify the IP address of the device to send the executable to.
|
|
|
|
/// Specify the IP address of the device to send the executable to.
|
|
|
|
///
|
|
|
|
///
|
|
|
|
/// Corresponds to 3dslink's `--address` arg, which defaults to automatically
|
|
|
|
/// Corresponds to 3dslink's `--address` arg, which defaults to automatically
|
|
|
|
/// finding the device.
|
|
|
|
/// finding the device.
|
|
|
|
#[arg(long, short = 'a')] |
|
|
|
#[arg(long, short = 'a')] |
|
|
|
pub address: Option<String>, |
|
|
|
pub address: Option<std::net::Ipv4Addr>, |
|
|
|
|
|
|
|
|
|
|
|
/// Set the 0th argument of the executable when running it. Corresponds to
|
|
|
|
/// Set the 0th argument of the executable when running it. Corresponds to
|
|
|
|
/// 3dslink's `--argv0` argument.
|
|
|
|
/// 3dslink's `--argv0` argument.
|
|
|
@ -88,7 +90,7 @@ pub struct Run { |
|
|
|
|
|
|
|
|
|
|
|
/// Start the 3dslink server after sending the executable. Corresponds to
|
|
|
|
/// Start the 3dslink server after sending the executable. Corresponds to
|
|
|
|
/// 3dslink's `--server` argument.
|
|
|
|
/// 3dslink's `--server` argument.
|
|
|
|
#[arg(long, short = 's')] |
|
|
|
#[arg(long, short = 's', default_value_t = false)] |
|
|
|
pub server: bool, |
|
|
|
pub server: bool, |
|
|
|
|
|
|
|
|
|
|
|
/// Set the number of tries when connecting to the device to send the executable.
|
|
|
|
/// Set the number of tries when connecting to the device to send the executable.
|
|
|
@ -96,9 +98,13 @@ pub struct Run { |
|
|
|
// Can't use `short = 'r'` because that would conflict with cargo's `--release/-r`
|
|
|
|
// Can't use `short = 'r'` because that would conflict with cargo's `--release/-r`
|
|
|
|
#[arg(long)] |
|
|
|
#[arg(long)] |
|
|
|
pub retries: Option<usize>, |
|
|
|
pub retries: Option<usize>, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Passthrough cargo options.
|
|
|
|
|
|
|
|
#[command(flatten)] |
|
|
|
|
|
|
|
pub cargo_args: CargoArgs, |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
impl Input { |
|
|
|
impl CargoArgs { |
|
|
|
/// Get the args to be passed to the executable itself (not `cargo`).
|
|
|
|
/// Get the args to be passed to the executable itself (not `cargo`).
|
|
|
|
pub fn cargo_opts(&self) -> &[String] { |
|
|
|
pub fn cargo_opts(&self) -> &[String] { |
|
|
|
self.split_args().0 |
|
|
|
self.split_args().0 |
|
|
@ -110,15 +116,31 @@ impl Input { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fn split_args(&self) -> (&[String], &[String]) { |
|
|
|
fn split_args(&self) -> (&[String], &[String]) { |
|
|
|
if let Some(split) = self.cargo_options.iter().position(|arg| arg == "--") { |
|
|
|
if let Some(split) = self |
|
|
|
let split = if &self.cargo_options[split] == "--" { |
|
|
|
.args |
|
|
|
|
|
|
|
.iter() |
|
|
|
|
|
|
|
.position(|s| s == "--" || !s.starts_with('-')) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
let split = if self.args[split] == "--" { |
|
|
|
split + 1 |
|
|
|
split + 1 |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
split |
|
|
|
split |
|
|
|
}; |
|
|
|
}; |
|
|
|
self.cargo_options.split_at(split) |
|
|
|
self.args.split_at(split) |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
(&self.cargo_options[..], &[]) |
|
|
|
(&self.args[..], &[]) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[cfg(test)] |
|
|
|
|
|
|
|
mod tests { |
|
|
|
|
|
|
|
use super::*; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
use clap::CommandFactory; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[test] |
|
|
|
|
|
|
|
fn verify_app() { |
|
|
|
|
|
|
|
Cargo::command().debug_assert(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|