diff --git a/crates/nu-cmd-extra/src/extra/conversions/fmt.rs b/crates/nu-cmd-extra/src/extra/conversions/fmt.rs index 5bf2ae47a4..0626698fc6 100644 --- a/crates/nu-cmd-extra/src/extra/conversions/fmt.rs +++ b/crates/nu-cmd-extra/src/extra/conversions/fmt.rs @@ -1,5 +1,5 @@ -use nu_cmd_base::input_handler::{operate, CellPathOnlyArgs}; use nu_engine::command_prelude::*; +use nu_protocol::{report_parse_warning, ParseWarning}; #[derive(Clone)] pub struct Fmt; @@ -16,11 +16,11 @@ impl Command for Fmt { fn signature(&self) -> nu_protocol::Signature { Signature::build("fmt") .input_output_types(vec![(Type::Number, Type::record())]) - .category(Category::Conversions) + .category(Category::Deprecated) } fn search_terms(&self) -> Vec<&str> { - vec!["display", "render", "format"] + vec![] } fn examples(&self) -> Vec { @@ -47,72 +47,20 @@ impl Command for Fmt { call: &Call, input: PipelineData, ) -> Result { - fmt(engine_state, stack, call, input) - } -} - -fn fmt( - engine_state: &EngineState, - stack: &mut Stack, - call: &Call, - input: PipelineData, -) -> Result { - let cell_paths: Vec = call.rest(engine_state, stack, 0)?; - let args = CellPathOnlyArgs::from(cell_paths); - operate(action, args, input, call.head, engine_state.signals()) -} - -fn action(input: &Value, _args: &CellPathOnlyArgs, span: Span) -> Value { - match input { - Value::Float { val, .. } => fmt_it_64(*val, span), - Value::Int { val, .. } => fmt_it(*val, span), - Value::Filesize { val, .. } => fmt_it(val.get(), span), - // Propagate errors by explicitly matching them before the final case. - Value::Error { .. } => input.clone(), - other => Value::error( - ShellError::OnlySupportsThisInputType { - exp_input_type: "float, int, or filesize".into(), - wrong_type: other.get_type().to_string(), - dst_span: span, - src_span: other.span(), + let head = call.head; + report_parse_warning( + &StateWorkingSet::new(engine_state), + &ParseWarning::DeprecatedWarning { + old_command: "fmt".into(), + new_suggestion: "use `format number`".into(), + span: head, + url: "`help format number`".into(), }, - span, - ), + ); + crate::extra::strings::format::format_number(engine_state, stack, call, input) } } -fn fmt_it(num: i64, span: Span) -> Value { - Value::record( - record! { - "binary" => Value::string(format!("{num:#b}"), span), - "debug" => Value::string(format!("{num:#?}"), span), - "display" => Value::string(format!("{num}"), span), - "lowerexp" => Value::string(format!("{num:#e}"), span), - "lowerhex" => Value::string(format!("{num:#x}"), span), - "octal" => Value::string(format!("{num:#o}"), span), - "upperexp" => Value::string(format!("{num:#E}"), span), - "upperhex" => Value::string(format!("{num:#X}"), span), - }, - span, - ) -} - -fn fmt_it_64(num: f64, span: Span) -> Value { - Value::record( - record! { - "binary" => Value::string(format!("{:b}", num.to_bits()), span), - "debug" => Value::string(format!("{num:#?}"), span), - "display" => Value::string(format!("{num}"), span), - "lowerexp" => Value::string(format!("{num:#e}"), span), - "lowerhex" => Value::string(format!("{:0x}", num.to_bits()), span), - "octal" => Value::string(format!("{:0o}", num.to_bits()), span), - "upperexp" => Value::string(format!("{num:#E}"), span), - "upperhex" => Value::string(format!("{:0X}", num.to_bits()), span), - }, - span, - ) -} - #[cfg(test)] mod test { use super::*; diff --git a/crates/nu-cmd-extra/src/extra/mod.rs b/crates/nu-cmd-extra/src/extra/mod.rs index 0874824ac5..f2a457222a 100644 --- a/crates/nu-cmd-extra/src/extra/mod.rs +++ b/crates/nu-cmd-extra/src/extra/mod.rs @@ -47,6 +47,7 @@ pub fn add_extra_command_context(mut engine_state: EngineState) -> EngineState { bind_command!( strings::format::FormatPattern, strings::format::FormatBits, + strings::format::FormatNumber, strings::str_::case::Str, strings::str_::case::StrCamelCase, strings::str_::case::StrKebabCase, diff --git a/crates/nu-cmd-extra/src/extra/strings/format/mod.rs b/crates/nu-cmd-extra/src/extra/strings/format/mod.rs index 8b8f45f188..9f1ed1e997 100644 --- a/crates/nu-cmd-extra/src/extra/strings/format/mod.rs +++ b/crates/nu-cmd-extra/src/extra/strings/format/mod.rs @@ -1,6 +1,9 @@ mod bits; mod command; +mod number; pub(crate) use command::FormatPattern; // TODO remove `format_bits` visibility after removal of into bits pub(crate) use bits::{format_bits, FormatBits}; +// TODO remove `format_number` visibility after removal of into bits +pub(crate) use number::{format_number, FormatNumber}; diff --git a/crates/nu-cmd-extra/src/extra/strings/format/number.rs b/crates/nu-cmd-extra/src/extra/strings/format/number.rs new file mode 100644 index 0000000000..e99d19606d --- /dev/null +++ b/crates/nu-cmd-extra/src/extra/strings/format/number.rs @@ -0,0 +1,126 @@ +use nu_cmd_base::input_handler::{operate, CellPathOnlyArgs}; +use nu_engine::command_prelude::*; + +#[derive(Clone)] +pub struct FormatNumber; + +impl Command for FormatNumber { + fn name(&self) -> &str { + "format number" + } + + fn description(&self) -> &str { + "Format a number." + } + + fn signature(&self) -> nu_protocol::Signature { + Signature::build("format number") + .input_output_types(vec![(Type::Number, Type::record())]) + .category(Category::Conversions) + } + + fn search_terms(&self) -> Vec<&str> { + vec!["display", "render", "format"] + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Get a record containing multiple formats for the number 42", + example: "42 | format number", + result: Some(Value::test_record(record! { + "binary" => Value::test_string("0b101010"), + "debug" => Value::test_string("42"), + "display" => Value::test_string("42"), + "lowerexp" => Value::test_string("4.2e1"), + "lowerhex" => Value::test_string("0x2a"), + "octal" => Value::test_string("0o52"), + "upperexp" => Value::test_string("4.2E1"), + "upperhex" => Value::test_string("0x2A"), + })), + }] + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + format_number(engine_state, stack, call, input) + } +} + +pub(crate) fn format_number( + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + input: PipelineData, +) -> Result { + let cell_paths: Vec = call.rest(engine_state, stack, 0)?; + let args = CellPathOnlyArgs::from(cell_paths); + operate(action, args, input, call.head, engine_state.signals()) +} + +fn action(input: &Value, _args: &CellPathOnlyArgs, span: Span) -> Value { + match input { + Value::Float { val, .. } => format_f64(*val, span), + Value::Int { val, .. } => format_i64(*val, span), + Value::Filesize { val, .. } => format_i64(val.get(), span), + // Propagate errors by explicitly matching them before the final case. + Value::Error { .. } => input.clone(), + other => Value::error( + ShellError::OnlySupportsThisInputType { + exp_input_type: "float, int, or filesize".into(), + wrong_type: other.get_type().to_string(), + dst_span: span, + src_span: other.span(), + }, + span, + ), + } +} + +fn format_i64(num: i64, span: Span) -> Value { + Value::record( + record! { + "binary" => Value::string(format!("{num:#b}"), span), + "debug" => Value::string(format!("{num:#?}"), span), + "display" => Value::string(format!("{num}"), span), + "lowerexp" => Value::string(format!("{num:#e}"), span), + "lowerhex" => Value::string(format!("{num:#x}"), span), + "octal" => Value::string(format!("{num:#o}"), span), + "upperexp" => Value::string(format!("{num:#E}"), span), + "upperhex" => Value::string(format!("{num:#X}"), span), + }, + span, + ) +} + +fn format_f64(num: f64, span: Span) -> Value { + Value::record( + record! { + "binary" => Value::string(format!("{:b}", num.to_bits()), span), + "debug" => Value::string(format!("{num:#?}"), span), + "display" => Value::string(format!("{num}"), span), + "lowerexp" => Value::string(format!("{num:#e}"), span), + "lowerhex" => Value::string(format!("{:0x}", num.to_bits()), span), + "octal" => Value::string(format!("{:0o}", num.to_bits()), span), + "upperexp" => Value::string(format!("{num:#E}"), span), + "upperhex" => Value::string(format!("{:0X}", num.to_bits()), span), + }, + span, + ) +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(FormatNumber {}) + } +}