I have an rsync-like rust program. The main user interface is something like program src dest.
It needs to invoke itself on another machine over ssh in order to read or write files. This is an implementation detail, and I don't want to really expose it as a subcommand, and risk src being misinterpreted.
I'd like to run these implementation details using flags.
program --read filewould start writing the file to stdout.program --write filewould start writing stdin to the file.program ./local user@remote:remote/filewould write./localto the stdin ofssh user@remote program --write remote/file.program user@remote:remote/file ./localwould write the stdout ofssh user@remote program --read fileto./local.
I've tried using the clap derive API's group feature for its ArgGroups. The derive tutorial example flattens structs.
use std::ffi::OsString;
use clap::{Args, Parser};
#[derive(Parser, Debug)]
struct RsyncExample {
#[command(flatten)]
inner_op: ImplOperation,
#[command(flatten)]
transfer: Option<FileTransfer>,
}
#[derive(Args, Clone, Debug)]
#[group(required = false, multiple = false, conflicts_with = "FileTransfer")]
struct ImplOperation {
#[arg(long)]
read: bool,
#[arg(long)]
write: bool,
}
#[derive(Args, Clone, Debug)]
struct FileTransfer {
from: OsString,
to: OsString,
}
fn main() {
let cli = RsyncExample::parse();
println!("{cli:?}");
}
While the following will rightly disallow specifying both --read --write, and disallow --read file1 file2, the error message is a bit confusing. It still specifies FROM and TO.
$ cargo run -- --read from
error: the argument '--read' cannot be used with:
<FROM>
<TO>
Usage: blktrans --read <FROM> <TO>
For more information, try '--help'.
And even with this, I can't figure out how to allow a single file with those flags.
I have considered linking to this program with a different name, and dispatching based on argv[0]. But I'd like to avoid that if possible.