Skip to content

Commit 339ca87

Browse files
committed
numfmt: fix clippy errors, remove ---debug alias, rename write_line to format_and_write
1 parent 46f0bb1 commit 339ca87

File tree

4 files changed

+113
-6
lines changed

4 files changed

+113
-6
lines changed

src/uu/numfmt/locales/en-US.ftl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,9 @@ numfmt-error-invalid-format-width-overflow = invalid format '{ $format }' (width
7777
numfmt-error-invalid-precision = invalid precision in format '{ $format }'
7878
numfmt-error-format-too-many-percent = format '{ $format }' has too many % directives
7979
numfmt-error-unknown-invalid-mode = Unknown invalid mode: { $mode }
80+
81+
# Debug messages
82+
numfmt-debug-no-conversion = no conversion option specified
83+
numfmt-debug-grouping-no-effect = grouping has no effect in this locale
84+
numfmt-debug-failed-to-convert = failed to convert some of the input numbers
85+
numfmt-debug-header-ignored = --header ignored with command-line input

src/uu/numfmt/locales/fr-FR.ftl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ numfmt-after-help = Options d'UNITÉ :
3636
Une précision optionnelle (%.1f) remplacera la précision déterminée par l'entrée.
3737
3838
# Messages d'aide
39+
numfmt-help-debug = afficher des avertissements sur les entrées invalides
3940
numfmt-help-delimiter = utiliser X au lieu d'espaces pour le délimiteur de champ
4041
numfmt-help-field = remplacer les nombres dans ces champs d'entrée ; voir FIELDS ci-dessous
4142
numfmt-help-format = utiliser le FORMAT à virgule flottante de style printf ; voir FORMAT ci-dessous pour les détails
@@ -75,3 +76,9 @@ numfmt-error-invalid-format-width-overflow = format invalide '{ $format }' (déb
7576
numfmt-error-invalid-precision = précision invalide dans le format '{ $format }'
7677
numfmt-error-format-too-many-percent = le format '{ $format }' a trop de directives %
7778
numfmt-error-unknown-invalid-mode = Mode invalide inconnu : { $mode }
79+
80+
# Messages de débogage
81+
numfmt-debug-no-conversion = aucune option de conversion spécifiée
82+
numfmt-debug-grouping-no-effect = le groupement n'a aucun effet dans cette locale
83+
numfmt-debug-failed-to-convert = échec de conversion d'une partie des nombres en entrée
84+
numfmt-debug-header-ignored = --header ignoré avec une entrée en ligne de commande

src/uu/numfmt/src/format.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// For the full copyright and license information, please view the LICENSE
44
// file that was distributed with this source code.
55

6-
// spell-checker:ignore powf
6+
// spell-checker:ignore powf seps
77

88
use uucore::display::Quotable;
99
use uucore::i18n::decimal::locale_grouping_separator;

src/uu/numfmt/src/numfmt.rs

Lines changed: 99 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,19 +64,20 @@ fn format_and_write<W: std::io::Write>(
6464
}
6565
};
6666

67-
if let Err(error_message) = handled_line {
67+
if let Err(msg) = result {
6868
match options.invalid {
6969
InvalidModes::Abort => {
70-
return Err(Box::new(NumfmtError::FormattingError(error_message)));
70+
return Err(Box::new(NumfmtError::FormattingError(msg)));
7171
}
7272
InvalidModes::Fail => {
73-
show!(NumfmtError::FormattingError(error_message));
73+
show!(NumfmtError::FormattingError(msg));
7474
}
7575
InvalidModes::Warn => {
76-
let _ = writeln!(stderr(), "numfmt: {error_message}");
76+
let _ = writeln!(stderr(), "numfmt: {msg}");
7777
}
7878
InvalidModes::Ignore => {}
7979
}
80+
// On error, echo the original line unchanged.
8081
writer.write_all(input_line)?;
8182
if let Some(eol) = eol {
8283
writer.write_all(&[eol])?;
@@ -90,6 +91,64 @@ fn format_and_write<W: std::io::Write>(
9091
Ok(false)
9192
}
9293

94+
/// Process command-line number arguments.
95+
///
96+
/// Returns `true` if any line contained invalid input.
97+
fn handle_args<'a>(args: impl Iterator<Item = &'a [u8]>, options: &NumfmtOptions) -> UResult<bool> {
98+
let mut stdout = std::io::stdout().lock();
99+
let terminator = if options.zero_terminated { 0u8 } else { b'\n' };
100+
let mut saw_invalid = false;
101+
for l in args {
102+
saw_invalid |= format_and_write(&mut stdout, l, options, Some(terminator))?;
103+
}
104+
Ok(saw_invalid)
105+
}
106+
107+
/// Process lines read from stdin.
108+
///
109+
/// Returns `true` if any line contained invalid input.
110+
fn handle_buffer<R: BufRead>(mut input: R, options: &NumfmtOptions) -> UResult<bool> {
111+
let terminator = if options.zero_terminated { 0u8 } else { b'\n' };
112+
let mut stdout = std::io::stdout().lock();
113+
let mut buf = Vec::new();
114+
let mut line_idx = 0;
115+
let mut saw_invalid = false;
116+
117+
loop {
118+
buf.clear();
119+
let n = input
120+
.read_until(terminator, &mut buf)
121+
.map_err(|e| NumfmtError::IoError(e.to_string()))?;
122+
if n == 0 {
123+
break;
124+
}
125+
126+
let has_terminator = buf.last() == Some(&terminator);
127+
let line = if has_terminator {
128+
&buf[..buf.len() - 1]
129+
} else {
130+
&buf[..]
131+
};
132+
// Emit the terminator only when the input line had one (preserve
133+
// missing final newline).
134+
let eol = has_terminator.then_some(terminator);
135+
136+
if line_idx < options.header {
137+
// Pass header lines through unchanged.
138+
stdout.write_all(line)?;
139+
if let Some(t) = eol {
140+
stdout.write_all(&[t])?;
141+
}
142+
} else {
143+
saw_invalid |= format_and_write(&mut stdout, line, options, eol)?;
144+
}
145+
146+
line_idx += 1;
147+
}
148+
149+
Ok(saw_invalid)
150+
}
151+
93152
fn parse_unit(s: &str) -> Result<Unit> {
94153
match s {
95154
"auto" => Ok(Unit::Auto),
@@ -285,6 +344,34 @@ fn parse_options(args: &ArgMatches) -> Result<NumfmtOptions> {
285344
})
286345
}
287346

347+
fn print_debug_warnings(options: &NumfmtOptions, matches: &ArgMatches) {
348+
fn print_warning(msg_key: &str) {
349+
let _ = writeln!(stderr(), "numfmt: {}", translate!(msg_key));
350+
}
351+
352+
// Warn if no conversion option is specified
353+
// 2>/dev/full does not abort
354+
if options.transform.from == Unit::None
355+
&& options.transform.to == Unit::None
356+
&& options.padding == 0
357+
&& !options.grouping
358+
{
359+
print_warning("numfmt-debug-no-conversion");
360+
}
361+
362+
if options.grouping && locale_grouping_separator().is_empty() {
363+
print_warning("numfmt-debug-grouping-no-effect");
364+
}
365+
366+
// Warn if --header is used with command-line input
367+
if options.header > 0 && matches.get_many::<OsString>(NUMBER).is_some() {
368+
print_warning("numfmt-debug-header-ignored");
369+
}
370+
}
371+
372+
#[uucore::main]
373+
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
374+
let matches = uucore::clap_localization::handle_clap_result(uu_app(), args)?;
288375
let options = parse_options(&matches).map_err(NumfmtError::IllegalArgument)?;
289376

290377
if options.debug {
@@ -296,10 +383,17 @@ fn parse_options(args: &ArgMatches) -> Result<NumfmtOptions> {
296383
.map(|s| os_str_as_bytes(s).map_err(|e| e.to_string()))
297384
.collect::<std::result::Result<Vec<_>, _>>()
298385
.map_err(NumfmtError::IllegalArgument)?;
386+
handle_args(byte_args.into_iter(), &options)
387+
} else {
388+
let stdin = std::io::stdin();
389+
handle_buffer(stdin.lock(), &options)
390+
};
299391

300392
match result {
301393
Err(e) => {
302-
std::io::stdout().flush().expect("error flushing stdout");
394+
// Flush stdout before returning the error so any partial output is
395+
// visible (matches GNU behaviour).
396+
let _ = std::io::stdout().flush();
303397
Err(e)
304398
}
305399
Ok(saw_invalid) => {

0 commit comments

Comments
 (0)