Most crates have relatively minor changes between their major versions. To upgrade a crate, you often just have to check the RELEASES.md
file in its repository, or sometimes the GitHub release list, to see whether there are any API changes that might affect your program or library. The clap
crate in particular is somewhat notorious for how much it changes between its major versions: about half of the argument functions have been replaced since Clap 2.
In this case, the best route is probably to work through the tutorial and reference for the builder functions in Clap 4. Importantly, .min_values(1)
and .takes_value(false)
have been replaced with the ArgAction
system, and .values_of()
and .is_present()
have been replaced with generic .get_many()
and .get_one()
methods, where you have to supply the correct destination type. Overall, a translation of your program might look like this:
use clap::{Arg, ArgAction, Command};
fn main() {
let matches = Command::new("echor")
.author("Me, saadchraibi85@mail.com")
.version("1.0.2")
.about("Get matches of the user")
.arg(
Arg::new("text")
.required(true)
.action(ArgAction::Append)
.value_name("TEXT")
.help("Input Text"),
)
.arg(
Arg::new("omit-newline")
.short('n')
.action(ArgAction::SetTrue)
.help("Don't print newline"),
)
.get_matches();
let text: Vec<&str> = matches
.get_many("text")
.unwrap()
.map(String::as_str)
.collect();
let omit_new_line: bool = *matches.get_one("omit-newline").unwrap();
print!(
"{}{}",
text.join(" "),
if omit_new_line { "" } else { "\n" }
);
}
However, this does not have the exact behavior of values_of_lossy()
on invalid Unicode (which is very rare in practice on the command line). For that, you'd need to retrieve the raw arguments using ValueParser::os_string()
.
Variation with lossy UTF-8 parsing
use clap::{builder::ValueParser, Arg, ArgAction, Command};
use std::ffi::OsString;
fn main() {
let matches = Command::new("echor")
.author("Me, saadchraibi85@mail.com")
.version("1.0.2")
.about("Get matches of the user")
.arg(
Arg::new("text")
.required(true)
.action(ArgAction::Append)
.value_parser(ValueParser::os_string())
.value_name("TEXT")
.help("Input Text"),
)
.arg(
Arg::new("omit-newline")
.short('n')
.action(ArgAction::SetTrue)
.help("Don't print newline"),
)
.get_matches();
let text: Vec<String> = matches
.get_many::<OsString>("text")
.unwrap()
.map(|s| s.to_string_lossy().into_owned())
.collect();
let omit_new_line: bool = *matches.get_one("omit-newline").unwrap();
print!(
"{}{}",
text.join(" "),
if omit_new_line { "" } else { "\n" }
);
}
As a side note, newer versions of Clap have an arg!()
macro which collects the functionality of many of the Arg
methods. The Command
can equivalently be written as (renaming omit-newline
to omit_newline
):
let matches = Command::new("echor")
.author("Me, saadchraibi85@mail.com")
.version("1.0.2")
.about("Get matches of the user")
.args([
arg!(text: <TEXT> ... "Input Text"),
arg!(omit_newline: -n "Don't print newline"),
])
.get_matches();