From 93521da9d8c64827d950147b4f2138033420f92d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20=C5=BD=C3=A1dn=C3=ADk?= Date: Tue, 28 Sep 2021 21:03:53 +0300 Subject: [PATCH] Add 'export def' command --- crates/nu-command/src/default_context.rs | 10 ++++++- crates/nu-command/src/export_def.rs | 35 ++++++++++++++++++++++++ crates/nu-parser/src/parse_keywords.rs | 35 +++++++++++++++++++++++- 3 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 crates/nu-command/src/export_def.rs diff --git a/crates/nu-command/src/default_context.rs b/crates/nu-command/src/default_context.rs index 609d0cc683..4140ca1a4d 100644 --- a/crates/nu-command/src/default_context.rs +++ b/crates/nu-command/src/default_context.rs @@ -6,7 +6,7 @@ use nu_protocol::{ }; use crate::{ - Alias, Benchmark, BuildString, Def, Do, Each, External, For, From, FromJson, Git, GitCheckout, + Alias, Benchmark, BuildString, Def, Do, Each, ExportDef, External, For, From, FromJson, Git, GitCheckout, If, Length, Let, LetEnv, Lines, ListGitBranches, Ls, Module, Sys, Table, Use, Where, }; @@ -20,12 +20,20 @@ pub fn create_default_context() -> Rc> { Signature::build("where").required("cond", SyntaxShape::RowCondition, "condition"); working_set.add_decl(sig.predeclare()); + working_set.add_decl(Box::new(If)); + + working_set.add_decl(Box::new(Let)); + + working_set.add_decl(Box::new(LetEnv)); + working_set.add_decl(Box::new(Alias)); working_set.add_decl(Box::new(Benchmark)); working_set.add_decl(Box::new(BuildString)); + working_set.add_decl(Box::new(Def)); working_set.add_decl(Box::new(Do)); working_set.add_decl(Box::new(Each)); + working_set.add_decl(Box::new(ExportDef)); working_set.add_decl(Box::new(External)); working_set.add_decl(Box::new(For)); working_set.add_decl(Box::new(From)); diff --git a/crates/nu-command/src/export_def.rs b/crates/nu-command/src/export_def.rs new file mode 100644 index 0000000000..b82418c486 --- /dev/null +++ b/crates/nu-command/src/export_def.rs @@ -0,0 +1,35 @@ +use nu_protocol::ast::Call; +use nu_protocol::engine::{Command, EvaluationContext}; +use nu_protocol::{Signature, SyntaxShape, Value}; + +pub struct ExportDef; + +impl Command for ExportDef { + fn name(&self) -> &str { + "export def" + } + + fn usage(&self) -> &str { + "Define a custom command and export it from a module" + } + + fn signature(&self) -> nu_protocol::Signature { + Signature::build("export def") + .required("target", SyntaxShape::String, "definition name") + .required("params", SyntaxShape::Signature, "parameters") + .required( + "block", + SyntaxShape::Block(Some(vec![])), + "body of the definition", + ) + } + + fn run( + &self, + _context: &EvaluationContext, + call: &Call, + _input: Value, + ) -> Result { + Ok(Value::Nothing { span: call.head }) + } +} diff --git a/crates/nu-parser/src/parse_keywords.rs b/crates/nu-parser/src/parse_keywords.rs index 7c8ed36b6c..787de1b53b 100644 --- a/crates/nu-parser/src/parse_keywords.rs +++ b/crates/nu-parser/src/parse_keywords.rs @@ -235,7 +235,40 @@ pub fn parse_export( let export_name = working_set.get_span_contents(spans[1]); match export_name { - b"def" => parse_def(working_set, &spans[1..]), + b"def" => { + let (stmt, err) = parse_def(working_set, &spans[1..]); + + let export_def_decl_id = working_set + .find_decl(b"export def") + .expect("internal error: missing 'export def' command"); + + // Trying to warp the 'def' call into the 'export def' in a very clumsy way + let stmt = if let Statement::Pipeline(ref pipe) = stmt { + if !pipe.expressions.is_empty() { + if let Expr::Call(ref call) = pipe.expressions[0].expr { + let mut call = call.clone(); + + call.head = span(&spans[0..=1]); + call.decl_id = export_def_decl_id; + + Statement::Pipeline(Pipeline::from_vec(vec![Expression { + expr: Expr::Call(call), + span: span(spans), + ty: Type::Unknown, + custom_completion: None, + }])) + } else { + stmt + } + } else { + stmt + } + } else { + stmt + }; + + (stmt, err) + } _ => ( garbage_statement(spans), Some(ParseError::Expected(