I don't understand structop basic usage

I'm trying to understand the very basics of structop and I'm struggling. The code that I have now looks like this:

use structopt::StructOpt;

#[derive(StructOpt, Debug)]
#[structopt(name = "weather")]
struct Cli {

    #[structopt(long, required=true, help="The name of the city for which you want to get the weather")]
    city: Vec<String>,

    #[structopt(long, required=true, help="The two-digit abbreviation for the state in which the city is located")]
    state: Vec<String>

}

fn main() {
    let cli = Cli::from_args();
    println!("{:#?}", cli);
}

This produces:

S C:\Users\mthel\Rust\weather_cli> cargo run --city Chicago --state IL
error: Found argument '--city' which wasn't expected, or isn't valid in this context

USAGE:
    cargo.exe run [OPTIONS] [--] [args]...

For more information try --help

However, this works:

PS C:\Users\mthel\Rust\weather_cli> cargo run -- --city Chicago --state IL
    Finished dev [unoptimized + debuginfo] target(s) in 0.03s
     Running `target\debug\weather_cli.exe --city Chicago --state IL`
Cli {
    city: [
        "Chicago",
    ],
    state: [
        "IL",
    ],
}

I don't understand why the 'extra' -- is required at the beginning of the input.

When you use cargo run all the command lines options go to cargo. As they should.

Except if you use the extra --. Then the following options get passed by cargo to the actual program you want to run.

If you run your binary executable directly from targets/debug... then you will not need the extra --.

3 Likes

oh...lol....that makes sense. I've been reading the book for too long and my brain is shot right now :laughing:

One more question...how would you go about making the binary available via PowerShell so that a user can open PowerShell and type: weather --city Chicago --state IL?

This is just installing :slight_smile:

powershell needs the executable to be in its path.

You can copy the binary (target/debug/weather.exe) into somewhere that is in the path, or change the path to include the target directory (I assume?).

The best option is probably to use cargo install:

cargo install --path .

I'm not entirely sure how this works on Windows, but it does (at least in powershell, win10) - EDIT: having rooted around a little, on my box it just installs into a folder in my "home" directory, C://Users/something cargo something :slight_smile:

By default it will install from crates.io but --path will install from your local filesystem, so just run the above in the same folder as Cargo.toml

1 Like

cargo install is okay if you're only distributing to other Rust devs, but if you want to distribute to general users, you'd probably just want to give them the .exe file. After doing a cargo build --release, the executable will be in ./target/release.

Your users can then put that that file somewhere that is on their system PATH and they'll be able to run it from the command line.

2 Likes