Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/uu/cut/locales/en-US.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ cut-error-invalid-field-value = invalid field value { $value }
cut-error-invalid-position-value = invalid byte/character position { $value }
cut-error-field-number-too-large = field number { $value } is too large
cut-error-position-too-large = byte/character offset { $value } is too large
cut-error-invalid-whitespace-delimited-choice = invalid argument '{ $arg }' for '--whitespace-delimited'
Valid arguments are:
{ $choices }
Try 'cut --help' for more information.
cut-error-ambiguous-whitespace-delimited-choice = ambiguous argument '{ $arg }' for '--whitespace-delimited'
Valid arguments are:
{ $choices }
Try 'cut --help' for more information.

# Diagnostic labels: what the caret points at in a list of ranges
cut-diag-label-zero-bound = counting starts at 1
Expand Down
8 changes: 8 additions & 0 deletions src/uu/cut/locales/fr-FR.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,14 @@ cut-error-invalid-field-value = valeur de champ invalide { $value }
cut-error-invalid-position-value = position d'octet/caractère invalide { $value }
cut-error-field-number-too-large = le numéro de champ { $value } est trop grand
cut-error-position-too-large = le décalage d'octet/caractère { $value } est trop grand
cut-error-invalid-whitespace-delimited-choice = argument '{ $arg }' invalide pour '--whitespace-delimited'
Les arguments valides sont :
{ $choices }
Essayez 'cut --help' pour plus d'informations.
cut-error-ambiguous-whitespace-delimited-choice = argument '{ $arg }' ambigu pour '--whitespace-delimited'
Les arguments valides sont :
{ $choices }
Essayez 'cut --help' pour plus d'informations.

# Étiquettes de diagnostic : ce que le caret désigne dans une liste d'intervalles
cut-diag-label-zero-bound = le décompte commence à 1
Expand Down
37 changes: 34 additions & 3 deletions src/uu/cut/src/cut.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// spell-checker:ignore (ToDO) delim foxjumping sourcefiles undelimited xacfoxjumping

use bstr::io::BufReadExt;
use clap::builder::{PossibleValue, ValueParser};
use clap::builder::ValueParser;
use clap::{Arg, ArgAction, ArgMatches, Command};
use std::ffi::OsString;
use std::fs::File;
Expand All @@ -17,7 +17,6 @@ use uucore::error::{FromIo, UResult, USimpleError, UUsageError, set_exit_code, s
use uucore::i18n::charmap::{Encoding, locale_encoding, mb_char_len};
use uucore::line_ending::LineEnding;
use uucore::os_str_as_bytes;
use uucore::parser::shortcut_value_parser::ShortcutValueParser;

use self::searcher::Searcher;
use matcher::{ExactMatcher, Matcher, MbExactMatcher, WhitespaceMatcher};
Expand Down Expand Up @@ -968,6 +967,37 @@ where
);
}

/// The choices `--whitespace-delimited`'s value accepts.
const WHITESPACE_DELIMITED_CHOICES: &[&str] = &["trimmed"];

/// The choice `value` names among `WHITESPACE_DELIMITED_CHOICES`, accepting
/// any unambiguous abbreviation the way GNU does -- including the empty
/// string, which (like everywhere else here) is a prefix of every choice
/// but, with only one choice to begin with, names it unambiguously.
fn resolve_whitespace_delimited_choice(value: &str) -> UResult<&'static str> {
let list = || {
WHITESPACE_DELIMITED_CHOICES
.iter()
.map(|name| format!(" - '{name}'"))
.collect::<Vec<_>>()
.join("\n")
};
let mut named = WHITESPACE_DELIMITED_CHOICES
.iter()
.filter(|name| name.starts_with(value));
match (named.next(), named.next()) {
(Some(name), None) => Ok(*name),
(Some(_), Some(_)) => Err(USimpleError::new(
1,
translate!("cut-error-ambiguous-whitespace-delimited-choice", "arg" => value.to_string(), "choices" => list()),
)),
_ => Err(USimpleError::new(
1,
translate!("cut-error-invalid-whitespace-delimited-choice", "arg" => value.to_string(), "choices" => list()),
)),
}
}

/// Get delimiter and output delimiter from `-d`/`--delimiter` and `--output-delimiter` options respectively
/// Allow either delimiter to have a value that is neither UTF-8 nor ASCII to align with GNU behavior
fn get_delimiters(matches: &ArgMatches) -> UResult<(Delimiter<'_>, Option<&[u8]>)> {
Expand Down Expand Up @@ -1065,6 +1095,8 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
// `--whitespace-delimited[=trimmed]` (`-w`): the optional value selects trimming.
let whitespace_trimmed = matches
.get_one::<String>(options::WHITESPACE_DELIMITED)
.map(|value| resolve_whitespace_delimited_choice(value))
.transpose()?
.is_some();

let mode_arg = get_mode_arg(&matches)?;
Expand Down Expand Up @@ -1276,7 +1308,6 @@ pub fn uu_app() -> Command {
.long(options::WHITESPACE_DELIMITED)
.help(translate!("cut-help-whitespace-delimited"))
.value_name("trimmed")
.value_parser(ShortcutValueParser::new([PossibleValue::new("trimmed")]))
.num_args(0..=1)
.require_equals(true)
.action(ArgAction::Set),
Expand Down
8 changes: 7 additions & 1 deletion tests/by-util/test_cut.rs
Original file line number Diff line number Diff line change
Expand Up @@ -746,7 +746,13 @@ fn test_whitespace_delimited_long_and_trimmed() {
// Only `trimmed` is a valid value.
new_ucmd!()
.args(&["--whitespace-delimited=middle", "-f1"])
.fails_with_code(1);
.fails_with_code(1)
.stderr_is(concat!(
"cut: invalid argument 'middle' for '--whitespace-delimited'\n",
"Valid arguments are:\n",
" - 'trimmed'\n",
"Try 'cut --help' for more information.\n",
));
}

#[test]
Expand Down
Loading