From 4e5d3db9528ea9b611e35f109df73a6b0b4934f7 Mon Sep 17 00:00:00 2001 From: Darren Schroeder <343840+fdncred@users.noreply.github.com> Date: Sat, 3 Feb 2024 10:42:44 -0600 Subject: [PATCH] allow strings with thousands separators to be converted to filesize or ints (#11724) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description This PR changes `into int` and `into filesize` so that they allow thousands separators. ### Before ```nushell ❯ '1,000' | into filesize Error: nu::shell::cant_convert × Can't convert to int. ╭─[entry #1:1:1] 1 │ '1,000' | into filesize · ───┬─── · ╰── can't convert string to int ╰──── ❯ '1,000' | into int Error: nu::shell::cant_convert × Can't convert to int. ╭─[entry #2:1:1] 1 │ '1,000' | into int · ────┬─── · ╰── can't convert string to int ╰──── help: string "1,000" does not represent a valid integer ``` ### After ```nushell ❯ '1,000' | into filesize 1.0 KB ❯ '1,000' | into int 1000 ``` This works by getting the system locale and from that, determining what the thousands separator is. So, hopefully, this will work across locales. # User-Facing Changes # Tests + Formatting # After Submitting --- crates/nu-command/src/conversions/into/filesize.rs | 9 ++++++++- crates/nu-command/src/conversions/into/int.rs | 10 +++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/crates/nu-command/src/conversions/into/filesize.rs b/crates/nu-command/src/conversions/into/filesize.rs index 3920deaed7..967d933b43 100644 --- a/crates/nu-command/src/conversions/into/filesize.rs +++ b/crates/nu-command/src/conversions/into/filesize.rs @@ -5,6 +5,7 @@ use nu_protocol::{ engine::{Command, EngineState, Stack}, record, Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value, }; +use nu_utils::get_system_locale; #[derive(Clone)] pub struct SubCommand; @@ -137,7 +138,13 @@ pub fn action(input: &Value, _args: &CellPathOnlyArgs, span: Span) -> Value { } } fn int_from_string(a_string: &str, span: Span) -> Result { - match a_string.trim().parse::() { + // Get the Locale so we know what the thousands separator is + let locale = get_system_locale(); + + // Now that we know the locale, get the thousands separator and remove it + // so strings like 1,123,456 can be parsed as 1123456 + let no_comma_string = a_string.replace(locale.separator(), ""); + match no_comma_string.trim().parse::() { Ok(n) => Ok(n.0 as i64), Err(_) => Err(ShellError::CantConvert { to_type: "int".into(), diff --git a/crates/nu-command/src/conversions/into/int.rs b/crates/nu-command/src/conversions/into/int.rs index f29288aa0c..afe90f7fcd 100644 --- a/crates/nu-command/src/conversions/into/int.rs +++ b/crates/nu-command/src/conversions/into/int.rs @@ -6,6 +6,7 @@ use nu_protocol::{ engine::{Command, EngineState, Stack}, Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value, }; +use nu_utils::get_system_locale; struct Arguments { radix: u32, @@ -400,7 +401,14 @@ fn convert_int(input: &Value, head: Span, radix: u32) -> Value { } fn int_from_string(a_string: &str, span: Span) -> Result { - let trimmed = a_string.trim(); + // Get the Locale so we know what the thousands separator is + let locale = get_system_locale(); + + // Now that we know the locale, get the thousands separator and remove it + // so strings like 1,123,456 can be parsed as 1123456 + let no_comma_string = a_string.replace(locale.separator(), ""); + + let trimmed = no_comma_string.trim(); match trimmed { b if b.starts_with("0b") => { let num = match i64::from_str_radix(b.trim_start_matches("0b"), 2) {