argh icon indicating copy to clipboard operation
argh copied to clipboard

Any ability to specify 'raw' greedy args or pass-through?

Open ppearson opened this issue 1 year ago • 0 comments

Is there any way to specify to argh that any:

#[argh(positional, greedy)]
/// command line args
args: Vec<String>,

arg options are expected to be totally "raw" (for lack of a better word), and to no longer try and interpret them, but just collect them?

I'm trying to use argh for an app which allows running other commands with optional args (similar to say gdb, lldb or valgrind) that need to be "passed through", and it looks like argh is attempting to parse any flags it doesn't understand and error, which isn't what I want...

Example here:

use argh::FromArgs;

#[derive(FromArgs)]
/// Main cmd args.
struct MainArgs {
    #[argh(subcommand)]
    command: SubCommandEnum,
}

#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand)]
enum SubCommandEnum {
    // Start the specified process with optional command line args
    Start(SubCommandStart),
    // Attach to a process based off the provided process ID
    Attach(SubCommandAttach),
}

#[derive(FromArgs, PartialEq, Debug)]
/// Run a process with command line args.
#[argh(subcommand, name = "run")]
struct SubCommandStart {
    #[argh(positional)]
    /// command line command to run
    command: String,

    #[argh(positional, greedy)]
    /// command line args
    args: Vec<String>,
}

#[derive(FromArgs, PartialEq, Debug)]
/// Attach to an existing pid.
#[argh(subcommand, name = "attach")]
struct SubCommandAttach {
    #[argh(positional)]
    /// PID of process to attach to
    pid: u32,
}

fn main() {
    let args: MainArgs = argh::from_env();
    if let SubCommandEnum::Attach(attach) = args.command {
        eprintln!("Attaching to process PID: {}...", attach.pid);
    } else if let SubCommandEnum::Start(start) = args.command {
        if start.args.is_empty() {
            eprintln!("Starting process '{}' without args", start.command);
        } else {
            eprintln!("Starting process: '{}' with args: {:?}", start.command, start.args);
        }
    }
}

If you run 'test' (as the compiled binary name) like so:

./test run uptime --version

I'd like '--version' to just be collected into the args Vec<String> without any other processing, but instead it errors, with: Unrecognized argument: --version

For the moment I can work around it to some degree by grouping the 'uptime' and '--version' into a single quoted string which then becomes the 'command' arg, and I can then detect that and separate it out, but it's a bit annoying having to work that way.

Thanks.

ppearson avatar Nov 04 '23 00:11 ppearson