diff --git a/crates/nu-cli/src/cli.rs b/crates/nu-cli/src/cli.rs index 59e040de70..272a390468 100644 --- a/crates/nu-cli/src/cli.rs +++ b/crates/nu-cli/src/cli.rs @@ -306,6 +306,7 @@ pub fn create_default_context( whole_stream_command(StrCollect), whole_stream_command(BuildString), whole_stream_command(Ansi), + whole_stream_command(Char), // Column manipulation whole_stream_command(Reject), whole_stream_command(Select), diff --git a/crates/nu-cli/src/commands.rs b/crates/nu-cli/src/commands.rs index 6cc89c0ff5..d35f6ee15b 100644 --- a/crates/nu-cli/src/commands.rs +++ b/crates/nu-cli/src/commands.rs @@ -13,6 +13,7 @@ pub(crate) mod build_string; pub(crate) mod cal; pub(crate) mod calc; pub(crate) mod cd; +pub(crate) mod char_; pub(crate) mod classified; #[cfg(feature = "clipboard")] pub(crate) mod clip; @@ -142,6 +143,7 @@ pub(crate) use append::Append; pub(crate) use build_string::BuildString; pub(crate) use cal::Cal; pub(crate) use calc::Calc; +pub(crate) use char_::Char; pub(crate) use compact::Compact; pub(crate) use config::Config; pub(crate) use count::Count; diff --git a/crates/nu-cli/src/commands/char_.rs b/crates/nu-cli/src/commands/char_.rs new file mode 100644 index 0000000000..107bdf462a --- /dev/null +++ b/crates/nu-cli/src/commands/char_.rs @@ -0,0 +1,81 @@ +use crate::commands::WholeStreamCommand; +use crate::prelude::*; +use nu_errors::ShellError; +use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value}; +use nu_source::Tagged; + +pub struct Char; + +#[derive(Deserialize)] +struct CharArgs { + name: Tagged, +} + +#[async_trait] +impl WholeStreamCommand for Char { + fn name(&self) -> &str { + "char" + } + + fn signature(&self) -> Signature { + Signature::build("ansi").required( + "character", + SyntaxShape::Any, + "the name of the character to output", + ) + } + + fn usage(&self) -> &str { + "Output special characters (eg. 'newline')" + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Output newline", + example: r#"char newline"#, + result: Some(vec![Value::from("\n")]), + }] + } + + async fn run( + &self, + args: CommandArgs, + registry: &CommandRegistry, + ) -> Result { + let (CharArgs { name }, _) = args.process(®istry).await?; + + let special_character = str_to_character(&name.item); + + if let Some(output) = special_character { + Ok(OutputStream::one(ReturnSuccess::value( + UntaggedValue::string(output).into_value(name.tag()), + ))) + } else { + Err(ShellError::labeled_error( + "Unknown character", + "unknown character", + name.tag(), + )) + } + } +} + +fn str_to_character(s: &str) -> Option { + match s { + "newline" | "enter" | "nl" => Some("\n".into()), + "tab" => Some("\t".into()), + _ => None, + } +} + +#[cfg(test)] +mod tests { + use super::Char; + + #[test] + fn examples_work_as_expected() { + use crate::examples::test as test_examples; + + test_examples(Char {}) + } +}