rust clap, use enum for separate flags - rust

I have this example:
use clap::Parser;
#[derive(clap::ValueEnum, Clone, Debug)]
enum InfoType {
All,
Headers,
Metadata,
}
#[derive(Parser, Debug)]
#[clap(version)]
#[clap(about = "Prints out metadata for each file")]
struct Args {
#[clap(long)]
#[clap(help = "What to print")]
#[clap(value_enum, default_value_t=InfoType::All)]
info: InfoType,
#[clap(value_parser, required(true))]
#[clap(help = "file(s)")]
files: Vec<String>,
}
fn main() {
let args = Args::parse();
println!("args {:?}", args)
}
Here the cli interface becomes almost but not quite what I want
USAGE:
my_test [OPTIONS] <FILES>...
ARGS:
<FILES>... file(s)
OPTIONS:
-h, --help Print help information
--info <INFO> What to print [default: all] [possible values: all, headers, metadata]
-V, --version Print version information
Now this can be run as e.g.
my_test /path/file1 /path/file2 # enables the --info all by default
my_test --info headers /path/file1 /path/file2
What I would like instead is to have the --info <INFO> flag just as --metadata , --all etc. So I can run
my_test /path/file1 /path/file2 # enables the --all all by default
my_test --info /path/file1 /path/file2
But still parsing those flags to the same enum variable - how would I set up this with clap ?

Related

Compiling bevy_dylib v0.5.0 error: linking with `cc` failed: exit status: 1

On Mac freshly upgraded to Monterey, I'm getting the following when attempting to cargo run a trivial Bevy program. I've reinstalled XCode CLTs like recommended here and other places. I've tried messing around with some of the cargo.yml with no success.
Compiling bevy_dylib v0.5.0
error: linking with `cc` failed: exit status: 1
note: "cc" "-Wl,-exported_symbols_list,/var/folders/rp/lky8r76j5v5dk0rqg_yzk35w0000gn/T/rustcDYBmaq/list"
"-m64" "-arch" "x86_64" <......... many pages of warnings>
ld: warning: object file (/Users/BWStearns/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy-glsl-to-spirv-0.2.1/build/osx/libSPIRV-Tools-opt.glsltospirv.a(const_folding_rules.cpp.o)) was built for newer macOS version (10.13) than being linked (10.7)
<many more pages of warnings>
"_CGDisplayCreateUUIDFromDisplayID", referenced from:
_$LT$winit..platform_impl..platform..monitor..MonitorHandle$u20$as$u20$core..cmp..PartialEq$GT$::eq::h541b069daf520ec9 in libwinit-4f8b93ad49cc21f8.rlib(winit-4f8b93ad49cc21f8.winit.355ded65-cgu.6.rcgu.o)
_$LT$winit..platform_impl..platform..monitor..MonitorHandle$u20$as$u20$core..cmp..Ord$GT$::cmp::h951d61f6bd1d7a5f in libwinit-4f8b93ad49cc21f8.rlib(winit-4f8b93ad49cc21f8.winit.355ded65-cgu.6.rcgu.o)
winit::platform_impl::platform::monitor::MonitorHandle::ns_screen::h3207f8aed4eae22f in libwinit-4f8b93ad49cc21f8.rlib(winit-4f8b93ad49cc21f8.winit.355ded65-cgu.6.rcgu.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
error: could not compile `bevy_dylib` due to previous error
The cargo.yml is like this:
[package]
name = "my_bevy_game"
version = "0.1.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
bevy = { version = "0.5.0", features = ["dynamic"] }
I just ran into this starting this week. I am pretty sure this exact code was compiling fine a couple weeks ago. Any help would be greatly appreciated.
main.rs looks like
use bevy::prelude::*;
struct Person;
struct Name(String);
fn add_people(mut commands: Commands) {
commands.spawn().insert(Person).insert(Name("Elaina Proctor".to_string()));
commands.spawn().insert(Person).insert(Name("Renzo Hume".to_string()));
commands.spawn().insert(Person).insert(Name("Zayna Nieves".to_string()));
}
fn greet_people(query: Query<&Name, With<Person>>) {
for name in query.iter() {
println!("hello {}!", name.0);
}
}
pub struct HelloPlugin;
impl Plugin for HelloPlugin {
fn build(&self, app: &mut AppBuilder) {
app.add_startup_system(add_people.system())
.add_system(greet_people.system());
}
}
fn main() {
App::build()
.add_plugins(DefaultPlugins)
.add_plugin(HelloPlugin)
.run();
}
Update:
Definitely something about the environment on my machine because on a different macbook it worked fine.
So I found a solution if you discover this issue and the code works on other machines. Uninstall rust with rustup self uninstall and then renistall with the standard script curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh and then you should be good.

use of undeclared crate or module in rust [duplicate]

If I define a dependency like foo = { version = "1.0.0", optional = true },
will it be available when I do "cargo run"? Can I check if it is enabled in the code?
if cfg!(feature = "foo") {}
Doesn't seem to be working, like the feature is missing all the time.
Moving answer to 60258216 here:
Optional dependencies do double as features: https://stackoverflow.com/a/39759592/8182118
They will not be enabled by default unless they're listed in the default feature, though you can enable the feature using cargo run --features foo.
For clarity and forward compatibility you may want to create an actual feature which enables the dependency though, that way if you need to "fluff up" the feature in the future and that requires new optional dependencies it's much easier.
In the code, both #[cfg] and cfg! should work depending whether you want to check for it at compile-time or runtime.
It's not hard to test either:
[package]
name = "testx"
version = "0.1.0"
edition = "2018"
[features]
default = ["boolinator"]
magic = ["boolinator"]
empty = []
[dependencies]
boolinator = { version = "*", optional = true }
and a main.rs of:
fn main() {
# macro and attributes would work the same here
if cfg!(feature = "boolinator") {
println!("Hello, bool!");
} else {
println!("Hello, world!");
}
}
you get
$ cargo run -q
Hello, bool!
$ cargo run -q --no-default-features
Hello, world!
$ cargo run -q --no-default-features --features boolinator
Hello, bool!
$ cargo run -q --no-default-features --features magic
Hello, bool!
$ cargo run -q --no-default-features --features empty
Hello, world!
See also https://github.com/rust-lang/edition-guide/issues/96

Why building with rustc command cannot see crates?

Hi I'm trying to explore Rust. What I'm trying to do is using glob module, when i build code with $cargo build and $cargo run it's succesfully builds and runs the executable but if i try it with $rustc main.rs it gives me
error[E0432]: unresolved import `glob`
--> src/main.rs:1:5
|
1 | use glob::glob;
| ^^^^ use of undeclared type or module `glob`
Any ideas?
Version : ╰─ rustc --version rustc 1.43.1 (8d69840ab 2020-05-04)
Code is here:
use glob::glob;
fn main() {
for entry in glob("/home/user/*.jpg").unwrap(){
match entry {
Ok(path) => println!("{:?}", path.display()),
Err(e) => println!("{:?}",e),
}
};
}
My toml
[package]
name = "test1"
version = "0.1.0"
authors = ["ieuD <example#mail.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
glob = "0.3.0"
rustc on its own doesn't handle your dependencies, it just compiles stuff. When you run rustc on your file, it will start compiling it and encounter the unknown glob crate. Dependencies are handled by cargo via Cargo.toml.
Though you could only use rustc (see the answer here) it's a task that's considerably more difficult, that's why cargo is around.

Is there a way to make clap override the [ -h | --help ] flags help text?

I'm following the sample code from Rust Clap Package's docs but can't find any reference regarding help text for auto-generated flags [-h and --help].
extern crate clap;
use clap::{App, Arg, SubCommand};
fn main() {
let matches = App::new("Command One")
.version("1.0")
.author("Some Author <the_account#provider.com>")
.about("Descripción del comando.")
.arg(Arg::with_name("config")
.short("c")
.long("config")
.value_name("FILE")
.help("Sets a custom config file")
.takes_value(true))
.arg(Arg::with_name("INPUT")
.help("Sets the input file to use")
.required(true)
.index(1))
.arg(Arg::with_name("v")
.short("v")
.multiple(true)
.help("Sets the level of verbosity"))
// *** I'm trying this ***
.arg(Arg::with_name("help")
.short("h")
.long("help")
.help("A new help text."))
// ***********
.subcommand(SubCommand::with_name("test")
.about("controls testing features")
.version("1.3")
.author("Someone E. <someone_else#other.com>")
.arg(Arg::with_name("debug")
.short("d")
.help("print debug information verbosely")))
.get_matches();
let config = matches.value_of("config").unwrap_or("default.conf");
println!("Value for config: {}", config);
println!("Using input file: {}", matches.value_of("INPUT").unwrap());
match matches.occurrences_of("v") {
0 => println!("No verbose info"),
1 => println!("Some verbose info"),
2 => println!("Tons of verbose info"),
3 | _ => println!("Don't be crazy"),
}
if let Some(matches) = matches.subcommand_matches("test") {
if matches.is_present("debug") {
println!("Printing debug info...");
} else {
println!("Printing normally...");
}
}
}
To change the description of the -h/--help parameter in the help text, use the help_message method. Likewise, to change the description of -V/--version, use version_message.
extern crate clap;
use clap::App;
fn main() {
let matches = App::new("app")
.help_message("this is the help command")
.version_message("this is the version command")
.get_matches_from(&["app", "--help"]);
}
Output:
app
USAGE:
app
FLAGS:
-h, --help this is the help command
-V, --version this is the version command

How to obtain the value of a configuration flag?

Is there a way of obtaining the value of a configuration flag? For example, I would like to get the value of target_os as str/String, without resorting to the following if-else-if chain:
if cfg!(target_os = "windows") {
"windows"
} else if cfg!(target_os = "linux") {
"linux"
// ...
} else {
"unknown"
}
No. You can get some of them by tricking Cargo into telling you. If you place the following into a build script:
use std::env;
fn main() {
for (key, value) in env::vars() {
if key.starts_with("CARGO_CFG_") {
println!("{}: {:?}", key, value);
}
}
panic!("stop and dump stdout");
}
...it will display the cfg flags Cargo is aware of. The panic! is just there as an easy way to get Cargo to actually show the output instead of hiding it. For reference, the output this produces looks like this:
Compiling dump-cfg v0.1.0 (file:///F:/Programming/Rust/sandbox/cargo-test/dump-cfg)
error: failed to run custom build command for `dump-cfg v0.1.0 (file:///F:/Programming/Rust/sandbox/cargo-test/dump-cfg)`
process didn't exit successfully: `F:\Programming\Rust\sandbox\cargo-test\dump-cfg\target\debug\build\dump-cfg-8b04f9ac3818f82a\build-script-build` (exit code: 101)
--- stdout
CARGO_CFG_TARGET_POINTER_WIDTH: "64"
CARGO_CFG_TARGET_ENV: "msvc"
CARGO_CFG_TARGET_OS: "windows"
CARGO_CFG_TARGET_ENDIAN: "little"
CARGO_CFG_TARGET_FAMILY: "windows"
CARGO_CFG_TARGET_ARCH: "x86_64"
CARGO_CFG_TARGET_HAS_ATOMIC: "16,32,64,8,ptr"
CARGO_CFG_TARGET_FEATURE: "sse,sse2"
CARGO_CFG_WINDOWS: ""
CARGO_CFG_TARGET_VENDOR: "pc"
CARGO_CFG_DEBUG_ASSERTIONS: ""
--- stderr
thread 'main' panicked at 'stop', build.rs:9
note: Run with `RUST_BACKTRACE=1` for a backtrace.
You can extract the values you're interested in from this list, and dump them to a generated source file, which you can then import (using #[path] or include!) into your package's source.
For target_os specifically, and also for just target_family and target_arch, there are corresponding &str constants in std::env::consts::{OS, FAMILY, ARCH}.

Resources