Ian Chamberlain
2 years ago
3 changed files with 140 additions and 46 deletions
@ -1,36 +1,123 @@
@@ -1,36 +1,123 @@
|
||||
use clap::{AppSettings, Args, Parser, ValueEnum}; |
||||
// TODO: docstrings for everything!!!
|
||||
|
||||
#[derive(Parser)] |
||||
#[clap(name = "cargo")] |
||||
#[clap(bin_name = "cargo")] |
||||
pub enum Cargo { |
||||
#[clap(name = "3ds")] |
||||
Input(Input), |
||||
use clap::{Args, Parser, Subcommand}; |
||||
|
||||
#[derive(Parser, Debug)] |
||||
#[command(name = "cargo")] |
||||
#[command(bin_name = "cargo")] |
||||
pub enum Command { |
||||
#[command(name = "3ds")] |
||||
Root(Root), |
||||
} |
||||
|
||||
#[derive(Args)] |
||||
#[clap(about)] |
||||
#[clap(global_setting(AppSettings::AllowLeadingHyphen))] |
||||
pub struct Input { |
||||
#[clap(value_enum)] |
||||
#[derive(Args, Debug)] |
||||
#[command(version, about)] |
||||
pub struct Root { |
||||
/// The cargo command to run. This command will be forwarded to the real
|
||||
/// `cargo` with the appropriate arguments for a 3DS executable.
|
||||
#[command(subcommand)] |
||||
pub cmd: CargoCommand, |
||||
pub cargo_opts: Vec<String>, |
||||
|
||||
/// Don't actually run any commands, just echo them to the console.
|
||||
/// This is mostly intended for testing.
|
||||
#[arg(hide = true)] |
||||
pub dry_run: bool, |
||||
|
||||
/// Pass additional options through to the `cargo` command.
|
||||
///
|
||||
/// To pass flags that start with `-`, you must use `--` to separate `cargo 3ds`
|
||||
/// options from cargo options. All args after `--` will be passed through
|
||||
/// to cargo unmodified.
|
||||
///
|
||||
/// If one of the arguments is itself `--`, the args following that will be
|
||||
/// considered as args to pass to the executable, rather than to `cargo`
|
||||
/// (only works for the `run` or `test` commands). For example, if you want
|
||||
/// to pass some args to the executable directly it might look like this:
|
||||
///
|
||||
/// > cargo 3ds run -- -- arg1 arg2
|
||||
#[arg(trailing_var_arg = true)] |
||||
#[arg(global = true)] |
||||
cargo_options: Vec<String>, |
||||
} |
||||
|
||||
#[derive(ValueEnum, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)] |
||||
#[derive(Subcommand, Debug)] |
||||
pub enum CargoCommand { |
||||
/// Builds an executable suitable to run on a 3DS (3dsx).
|
||||
Build, |
||||
Run, |
||||
Test, |
||||
/// 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)] |
||||
pub struct Test { |
||||
/// If set, the built executable will not be sent to the device to run it.
|
||||
#[arg(long)] |
||||
pub no_run: bool, |
||||
#[command(flatten)] |
||||
pub run_args: Run, |
||||
} |
||||
|
||||
impl CargoCommand { |
||||
pub fn should_build_3dsx(&self) -> bool { |
||||
matches!( |
||||
self, |
||||
CargoCommand::Build | CargoCommand::Run | CargoCommand::Test |
||||
) |
||||
#[derive(Args, Debug)] |
||||
pub struct Run { |
||||
/// Specify the IP address of the device to send the executable to.
|
||||
///
|
||||
/// Corresponds to 3dslink's `--address` arg, which defaults to automatically
|
||||
/// finding the device.
|
||||
#[arg(long, short = 'a')] |
||||
pub address: Option<String>, |
||||
|
||||
/// Set the 0th argument of the executable when running it. Corresponds to
|
||||
/// 3dslink's `--argv0` argument.
|
||||
#[arg(long, short = '0')] |
||||
pub argv0: Option<String>, |
||||
|
||||
/// Start the 3dslink server after sending the executable. Corresponds to
|
||||
/// 3dslink's `--server` argument.
|
||||
#[arg(long, short = 's')] |
||||
pub server: bool, |
||||
|
||||
/// Set the number of tries when connecting to the device to send the executable.
|
||||
/// Corresponds to 3dslink's `--retries` argument.
|
||||
// Can't use `short = 'r'` because that would conflict with cargo's `--release/-r`
|
||||
#[arg(long)] |
||||
pub retries: Option<usize>, |
||||
} |
||||
|
||||
impl Root { |
||||
/// Get the args to be passed to the executable itself (not `cargo`).
|
||||
pub fn cargo_options(&self) -> &[String] { |
||||
self.split_args().0 |
||||
} |
||||
|
||||
/// Get the args to be passed to the executable itself (not `cargo`).
|
||||
pub fn executable_args(&self) -> &[String] { |
||||
self.split_args().1 |
||||
} |
||||
|
||||
fn split_args(&self) -> (&[String], &[String]) { |
||||
if let Some(split) = self.cargo_options.iter().position(|arg| arg == "--") { |
||||
let split = if &self.cargo_options[split] == "--" { |
||||
split + 1 |
||||
} else { |
||||
split |
||||
}; |
||||
self.cargo_options.split_at(split) |
||||
} else { |
||||
(&self.cargo_options[..], &[]) |
||||
} |
||||
} |
||||
} |
||||
|
Loading…
Reference in new issue