mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 19:47:45 +00:00
false,true: Implement custom help, version
This avoids hacking around the short options of these command line arguments that have been introduced by clap. Additionally, we test and correctly handle the combination of both version and help. The GNU binary will ignore both arguments in this case while clap would perform the first one. A test for this edge case was added.
This commit is contained in:
parent
c1e108933f
commit
23a544c485
4 changed files with 69 additions and 38 deletions
|
@ -4,7 +4,7 @@
|
||||||
// *
|
// *
|
||||||
// * For the full copyright and license information, please view the LICENSE
|
// * For the full copyright and license information, please view the LICENSE
|
||||||
// * file that was distributed with this source code.
|
// * file that was distributed with this source code.
|
||||||
use clap::{App, Arg, ArgSettings, ErrorKind};
|
use clap::{App, AppSettings, Arg};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use uucore::error::{set_exit_code, UResult};
|
use uucore::error::{set_exit_code, UResult};
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ static ABOUT: &str = "
|
||||||
|
|
||||||
#[uucore::main]
|
#[uucore::main]
|
||||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
let app = uu_app();
|
let mut app = uu_app();
|
||||||
|
|
||||||
// Mirror GNU options, always return `1`. In particular even the 'successful' cases of no-op,
|
// Mirror GNU options, always return `1`. In particular even the 'successful' cases of no-op,
|
||||||
// and the interrupted display of help and version should return `1`. Also, we return Ok in all
|
// and the interrupted display of help and version should return `1`. Also, we return Ok in all
|
||||||
|
@ -26,12 +26,19 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
// and unwind through the standard library allocation handling machinery.
|
// and unwind through the standard library allocation handling machinery.
|
||||||
set_exit_code(1);
|
set_exit_code(1);
|
||||||
|
|
||||||
if let Err(err) = app.try_get_matches_from(args) {
|
if let Ok(matches) = app.try_get_matches_from_mut(args) {
|
||||||
if let ErrorKind::DisplayHelp | ErrorKind::DisplayVersion = err.kind {
|
let error = if matches.index_of("help").is_some() {
|
||||||
if let Err(print_fail) = err.print() {
|
app.print_long_help()
|
||||||
// Try to display this error.
|
} else if matches.index_of("version").is_some() {
|
||||||
let _ = writeln!(std::io::stderr(), "{}: {}", uucore::util_name(), print_fail);
|
writeln!(std::io::stdout(), "{}", app.render_version())
|
||||||
}
|
} else {
|
||||||
|
Ok(())
|
||||||
|
};
|
||||||
|
|
||||||
|
// Try to display this error.
|
||||||
|
if let Err(print_fail) = error {
|
||||||
|
// Completely ignore any error here, no more failover and we will fail in any case.
|
||||||
|
let _ = writeln!(std::io::stderr(), "{}: {}", uucore::util_name(), print_fail);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,16 +49,17 @@ pub fn uu_app<'a>() -> App<'a> {
|
||||||
App::new(uucore::util_name())
|
App::new(uucore::util_name())
|
||||||
.version(clap::crate_version!())
|
.version(clap::crate_version!())
|
||||||
.about(ABOUT)
|
.about(ABOUT)
|
||||||
// Hide the default -V and -h for version and help.
|
// We provide our own help and version options, to ensure maximum compatibility with GNU.
|
||||||
// This requires us to overwrite short, not short_aliases.
|
.setting(AppSettings::DisableHelpFlag | AppSettings::DisableVersionFlag)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new("dummy-help")
|
Arg::new("help")
|
||||||
.short('h')
|
.long("help")
|
||||||
.setting(ArgSettings::Hidden),
|
.help("Print help information")
|
||||||
|
.exclusive(true),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new("dummy-version")
|
Arg::new("version")
|
||||||
.short('V')
|
.long("version")
|
||||||
.setting(ArgSettings::Hidden),
|
.help("Print version information"),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
// *
|
// *
|
||||||
// * For the full copyright and license information, please view the LICENSE
|
// * For the full copyright and license information, please view the LICENSE
|
||||||
// * file that was distributed with this source code.
|
// * file that was distributed with this source code.
|
||||||
use clap::{App, Arg, ArgSettings, ErrorKind};
|
use clap::{App, AppSettings, Arg};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use uucore::error::{set_exit_code, UResult};
|
use uucore::error::{set_exit_code, UResult};
|
||||||
|
|
||||||
|
@ -18,18 +18,24 @@ static ABOUT: &str = "
|
||||||
|
|
||||||
#[uucore::main]
|
#[uucore::main]
|
||||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
let app = uu_app();
|
let mut app = uu_app();
|
||||||
|
|
||||||
if let Err(err) = app.try_get_matches_from(args) {
|
if let Ok(matches) = app.try_get_matches_from_mut(args) {
|
||||||
if let ErrorKind::DisplayHelp | ErrorKind::DisplayVersion = err.kind {
|
let error = if matches.index_of("help").is_some() {
|
||||||
if let Err(print_fail) = err.print() {
|
app.print_long_help()
|
||||||
// Try to display this error.
|
} else if matches.index_of("version").is_some() {
|
||||||
let _ = writeln!(std::io::stderr(), "{}: {}", uucore::util_name(), print_fail);
|
writeln!(std::io::stdout(), "{}", app.render_version())
|
||||||
// Mirror GNU options. When failing to print warnings or version flags, then we exit
|
} else {
|
||||||
// with FAIL. This avoids allocation some error information which may result in yet
|
Ok(())
|
||||||
// other types of failure.
|
};
|
||||||
set_exit_code(1);
|
|
||||||
}
|
if let Err(print_fail) = error {
|
||||||
|
// Try to display this error.
|
||||||
|
let _ = writeln!(std::io::stderr(), "{}: {}", uucore::util_name(), print_fail);
|
||||||
|
// Mirror GNU options. When failing to print warnings or version flags, then we exit
|
||||||
|
// with FAIL. This avoids allocation some error information which may result in yet
|
||||||
|
// other types of failure.
|
||||||
|
set_exit_code(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,16 +46,17 @@ pub fn uu_app<'a>() -> App<'a> {
|
||||||
App::new(uucore::util_name())
|
App::new(uucore::util_name())
|
||||||
.version(clap::crate_version!())
|
.version(clap::crate_version!())
|
||||||
.about(ABOUT)
|
.about(ABOUT)
|
||||||
// Hide the default -V and -h for version and help.
|
// We provide our own help and version options, to ensure maximum compatibility with GNU.
|
||||||
// This requires us to overwrite short, not short_aliases.
|
.setting(AppSettings::DisableHelpFlag | AppSettings::DisableVersionFlag)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new("dummy-help")
|
Arg::new("help")
|
||||||
.short('h')
|
.long("help")
|
||||||
.setting(ArgSettings::Hidden),
|
.help("Print help information")
|
||||||
|
.exclusive(true),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new("dummy-version")
|
Arg::new("version")
|
||||||
.short('V')
|
.long("version")
|
||||||
.setting(ArgSettings::Hidden),
|
.help("Print version information"),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,11 +25,19 @@ fn test_help() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_short_options() {
|
fn test_short_options() {
|
||||||
for option in ["-h", "-v"] {
|
for option in ["-h", "-V"] {
|
||||||
new_ucmd!().arg(option).fails().stdout_is("");
|
new_ucmd!().arg(option).fails().stdout_is("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_conflict() {
|
||||||
|
new_ucmd!()
|
||||||
|
.args(&["--help", "--version"])
|
||||||
|
.fails()
|
||||||
|
.stdout_is("");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "netbsd"))]
|
#[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "netbsd"))]
|
||||||
fn test_full() {
|
fn test_full() {
|
||||||
|
|
|
@ -25,11 +25,19 @@ fn test_help() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_short_options() {
|
fn test_short_options() {
|
||||||
for option in ["-h", "-v"] {
|
for option in ["-h", "-V"] {
|
||||||
new_ucmd!().arg(option).succeeds().stdout_is("");
|
new_ucmd!().arg(option).succeeds().stdout_is("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_conflict() {
|
||||||
|
new_ucmd!()
|
||||||
|
.args(&["--help", "--version"])
|
||||||
|
.succeeds()
|
||||||
|
.stdout_is("");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "netbsd"))]
|
#[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "netbsd"))]
|
||||||
fn test_full() {
|
fn test_full() {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue