diff --git a/src/context/mod.rs b/src/context/mod.rs index 0e66319..74ecf8a 100644 --- a/src/context/mod.rs +++ b/src/context/mod.rs @@ -5,8 +5,8 @@ pub use builder::*; pub use command_group_config::CommandGroupConfig; use nu_protocol::{ ast::{Block, Call}, - engine::{EngineState, Stack}, - PipelineData, Span, + engine::{EngineState, Stack, StateWorkingSet}, + PipelineData, Span, Type, }; use crate::{ @@ -70,6 +70,21 @@ impl Context { self.stack.get_var(*var_id, Span::new(0, 0)).ok() } + /// Define a variable on the stack + pub fn set_var>( + &mut self, + name: S, + value: nu_protocol::Value, + ) -> CrateResult<()> { + let name = name.as_ref(); + let dollar_name = format!("${name}").as_bytes().to_vec(); + let mut state = StateWorkingSet::new(&self.engine_state); + let var_id = state.add_variable(dollar_name, Span::new(0, 0), Type::Any, true); + self.engine_state.merge_delta(state.delta)?; + self.stack.add_var(var_id, value); + Ok(()) + } + /// Returns if the given function exists in the context pub fn has_fn>(&mut self, name: S) -> bool { self.engine_state diff --git a/tests/test_eval.rs b/tests/test_eval.rs index 0940a08..a729a5f 100644 --- a/tests/test_eval.rs +++ b/tests/test_eval.rs @@ -24,6 +24,16 @@ fn it_returns_variables() { assert_eq!(val.as_string().unwrap(), String::from("world")) } +#[test] +fn it_sets_variables() { + let mut ctx = get_context(); + ctx.set_var("world", "world".into_value()).unwrap(); + ctx.eval_raw(r#"let hello = $world"#, PipelineData::empty()) + .unwrap(); + let val = ctx.get_var("hello").expect("No variable returned"); + assert_eq!(val.as_string().unwrap(), String::from("world")) +} + #[derive(RustyValue)] struct TestArg { foo: String, @@ -35,12 +45,12 @@ fn it_executes_functions() { let mut ctx = get_context(); ctx.eval_raw( r#" - + def hello [] { echo "Hello World from this script"; echo # dummy echo so I don't have to print the output - } - + } + "#, PipelineData::empty(), )