From 3f1824111d5d85510010613240eb4567de21fb6e Mon Sep 17 00:00:00 2001 From: Darren Schroeder <343840+fdncred@users.noreply.github.com> Date: Fri, 26 Aug 2022 14:48:48 -0500 Subject: [PATCH] add the ast command to peek at the internals of nushell (#6423) * add the ast command to peak at the internals of nushell * fixed a bug in an example --- crates/nu-command/src/core_commands/ast.rs | 77 ++++++++++++++++++++++ crates/nu-command/src/core_commands/mod.rs | 2 + crates/nu-command/src/default_context.rs | 1 + 3 files changed, 80 insertions(+) create mode 100644 crates/nu-command/src/core_commands/ast.rs diff --git a/crates/nu-command/src/core_commands/ast.rs b/crates/nu-command/src/core_commands/ast.rs new file mode 100644 index 000000000..f61719fde --- /dev/null +++ b/crates/nu-command/src/core_commands/ast.rs @@ -0,0 +1,77 @@ +use nu_engine::CallExt; +use nu_parser::parse; +use nu_protocol::{ + ast::Call, + engine::{Command, EngineState, Stack, StateWorkingSet}, + Category, Example, PipelineData, ShellError, Signature, Spanned, SyntaxShape, +}; + +#[derive(Clone)] +pub struct Ast; + +impl Command for Ast { + fn name(&self) -> &str { + "ast" + } + + fn usage(&self) -> &str { + "Print the abstract syntax tree (ast) for a pipeline." + } + + fn signature(&self) -> Signature { + Signature::build("ast") + .required( + "pipeline", + SyntaxShape::String, + "the pipeline to print the ast for", + ) + .category(Category::Core) + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + _input: PipelineData, + ) -> Result { + let head = call.head; + let pipeline: Spanned = call.req(engine_state, stack, 0)?; + let mut working_set = StateWorkingSet::new(engine_state); + + let (output, err) = parse(&mut working_set, None, pipeline.item.as_bytes(), false, &[]); + eprintln!("output: {:#?}\nerror: {:#?}", output, err); + + Ok(PipelineData::new(head)) + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "Print the ast of a string", + example: "ast 'hello'", + result: None, + }, + Example { + description: "Print the ast of a pipeline", + example: "ast 'ls | where name =~ README'", + result: None, + }, + Example { + description: "Print the ast of a pipeline with an error", + example: "ast 'for x in 1..10 { echo $x '", + result: None, + }, + ] + } +} + +#[cfg(test)] +mod test { + #[test] + fn test_examples() { + use super::Ast; + use crate::test_examples; + test_examples(Ast {}) + } +} diff --git a/crates/nu-command/src/core_commands/mod.rs b/crates/nu-command/src/core_commands/mod.rs index fcdbb545a..08162a805 100644 --- a/crates/nu-command/src/core_commands/mod.rs +++ b/crates/nu-command/src/core_commands/mod.rs @@ -1,4 +1,5 @@ mod alias; +mod ast; mod debug; mod def; mod def_env; @@ -29,6 +30,7 @@ mod use_; mod version; pub use alias::Alias; +pub use ast::Ast; pub use debug::Debug; pub use def::Def; pub use def_env::DefEnv; diff --git a/crates/nu-command/src/default_context.rs b/crates/nu-command/src/default_context.rs index 06e38b925..d35b6e41d 100644 --- a/crates/nu-command/src/default_context.rs +++ b/crates/nu-command/src/default_context.rs @@ -29,6 +29,7 @@ pub fn create_default_context() -> EngineState { // Core bind_command! { Alias, + Ast, Debug, Def, DefEnv,