From 7eaa6d01ab6e2afee977977cf32bd1c5decc890a Mon Sep 17 00:00:00 2001 From: Ryan Armstrong Date: Sat, 30 Sep 2023 10:04:27 -0400 Subject: [PATCH] Add 'help escapes' command for quick reference of nushell string escapes (#10522) resolves #4869 # Description Adds a `help escape` command that can be used to display a table of string escape sequences and their outputs. ```nu help escapes ``` ```nu help escapes -h ``` The command should also appear in the list displayed when tab autocompleting on `help`. # User-Facing Changes Users can now use a new `help escapes` command to output a table of string escape sequences and their outputs. # Tests + Formatting # After Submitting Need to update docs to reflect existence of the new `help escapes` command. --- crates/nu-command/src/default_context.rs | 3 +- crates/nu-command/src/help/help_escapes.rs | 156 +++++++++++++++++++++ crates/nu-command/src/help/mod.rs | 2 + 3 files changed, 160 insertions(+), 1 deletion(-) create mode 100644 crates/nu-command/src/help/help_escapes.rs diff --git a/crates/nu-command/src/default_context.rs b/crates/nu-command/src/default_context.rs index ac5f7655e..ae23e56e5 100644 --- a/crates/nu-command/src/default_context.rs +++ b/crates/nu-command/src/default_context.rs @@ -1,7 +1,7 @@ use nu_protocol::engine::{EngineState, StateWorkingSet}; use crate::{ - help::{HelpAliases, HelpCommands, HelpExterns, HelpModules, HelpOperators}, + help::{HelpAliases, HelpCommands, HelpEscapes, HelpExterns, HelpModules, HelpOperators}, *, }; pub fn add_shell_command_context(mut engine_state: EngineState) -> EngineState { @@ -127,6 +127,7 @@ pub fn add_shell_command_context(mut engine_state: EngineState) -> EngineState { HelpCommands, HelpModules, HelpOperators, + HelpEscapes, }; // Debug diff --git a/crates/nu-command/src/help/help_escapes.rs b/crates/nu-command/src/help/help_escapes.rs new file mode 100644 index 000000000..5401ac1ba --- /dev/null +++ b/crates/nu-command/src/help/help_escapes.rs @@ -0,0 +1,156 @@ +use nu_protocol::{ + ast::Call, + engine::{Command, EngineState, Stack}, + record, Category, IntoInterruptiblePipelineData, PipelineData, ShellError, Signature, Type, + Value, +}; + +#[derive(Clone)] +pub struct HelpEscapes; + +impl Command for HelpEscapes { + fn name(&self) -> &str { + "help escapes" + } + + fn usage(&self) -> &str { + "Show help on nushell string escapes." + } + + fn signature(&self) -> Signature { + Signature::build("help escapes") + .category(Category::Core) + .input_output_types(vec![(Type::Nothing, Type::Table(vec![]))]) + .allow_variants_without_examples(true) + } + + fn run( + &self, + engine_state: &EngineState, + _stack: &mut Stack, + call: &Call, + _input: PipelineData, + ) -> Result { + let head = call.head; + let escape_info = generate_escape_info(); + let mut recs = vec![]; + + for escape in escape_info { + recs.push(Value::record( + record! { + "sequence" => Value::string(escape.sequence, head), + "output" => Value::string(escape.output, head), + }, + head, + )); + } + + Ok(recs + .into_iter() + .into_pipeline_data(engine_state.ctrlc.clone())) + } +} + +struct EscapeInfo { + sequence: String, + output: String, +} + +fn generate_escape_info() -> Vec { + vec![ + EscapeInfo { + sequence: "\\\"".into(), + output: "\"".into(), + }, + EscapeInfo { + sequence: "\\\'".into(), + output: "\'".into(), + }, + EscapeInfo { + sequence: "\\\\".into(), + output: "\\".into(), + }, + EscapeInfo { + sequence: "\\/".into(), + output: "/".into(), + }, + EscapeInfo { + sequence: "\\(".into(), + output: "(".into(), + }, + EscapeInfo { + sequence: "\\)".into(), + output: ")".into(), + }, + EscapeInfo { + sequence: "\\{".into(), + output: "{".into(), + }, + EscapeInfo { + sequence: "\\}".into(), + output: "}".into(), + }, + EscapeInfo { + sequence: "\\$".into(), + output: "$".into(), + }, + EscapeInfo { + sequence: "\\^".into(), + output: "^".into(), + }, + EscapeInfo { + sequence: "\\#".into(), + output: "#".into(), + }, + EscapeInfo { + sequence: "\\|".into(), + output: "|".into(), + }, + EscapeInfo { + sequence: "\\~".into(), + output: "~".into(), + }, + EscapeInfo { + sequence: "\\a".into(), + output: "alert bell".into(), + }, + EscapeInfo { + sequence: "\\b".into(), + output: "backspace".into(), + }, + EscapeInfo { + sequence: "\\e".into(), + output: "escape".into(), + }, + EscapeInfo { + sequence: "\\f".into(), + output: "form feed".into(), + }, + EscapeInfo { + sequence: "\\n".into(), + output: "newline (line feed)".into(), + }, + EscapeInfo { + sequence: "\\r".into(), + output: "carriage return".into(), + }, + EscapeInfo { + sequence: "\\t".into(), + output: "tab".into(), + }, + EscapeInfo { + sequence: "\\u{X...}".into(), + output: "a single unicode character, where X... is 1-6 digits (0-9, A-F)".into(), + }, + ] +} + +#[cfg(test)] +mod test { + #[test] + fn test_examples() { + use super::HelpEscapes; + use crate::test_examples; + test_examples(HelpEscapes {}) + } +} diff --git a/crates/nu-command/src/help/mod.rs b/crates/nu-command/src/help/mod.rs index ae957b498..0bff55734 100644 --- a/crates/nu-command/src/help/mod.rs +++ b/crates/nu-command/src/help/mod.rs @@ -1,6 +1,7 @@ mod help_; mod help_aliases; mod help_commands; +mod help_escapes; mod help_externs; mod help_modules; mod help_operators; @@ -8,6 +9,7 @@ mod help_operators; pub use help_::Help; pub use help_aliases::HelpAliases; pub use help_commands::HelpCommands; +pub use help_escapes::HelpEscapes; pub use help_externs::HelpExterns; pub use help_modules::HelpModules; pub use help_operators::HelpOperators;