diff --git a/crates/deno_task_shell/src/shell/execute.rs b/crates/deno_task_shell/src/shell/execute.rs index ea4adea..167286a 100644 --- a/crates/deno_task_shell/src/shell/execute.rs +++ b/crates/deno_task_shell/src/shell/execute.rs @@ -1210,13 +1210,13 @@ impl From for EvaluateWordTextError { impl VariableModifier { pub async fn apply( &self, - variable: Option<&String>, + name: &str, state: &mut ShellState, stdin: ShellPipeReader, stderr: ShellPipeWriter, ) -> Result<(Text, Option>), miette::Report> { match self { - VariableModifier::DefaultValue(default_value) => match variable { + VariableModifier::DefaultValue(default_value) => match state.get_var(name) { Some(v) => Ok((v.clone().into(), None)), None => { let v = evaluate_word(default_value.clone(), state, stdin, stderr) @@ -1225,6 +1225,18 @@ impl VariableModifier { Ok((v.value.into(), Some(v.changes))) } }, + VariableModifier::AssignDefault(default_value) => match state.get_var(name) { + Some(v) => Ok((v.clone().into(), None)), + None => { + let v = evaluate_word(default_value.clone(), state, stdin, stderr) + .await + .into_diagnostic()?; + state.apply_env_var(name, &v.value); + let mut changes = v.changes; + changes.push(EnvChange::SetShellVar(name.to_string(), v.value.clone())); + Ok((v.value.into(), Some(changes))) + } + }, // VariableModifier::Substring { begin, length } => { // if variable.is_none() { // return Err(miette::miette!("Variable not found")); @@ -1365,16 +1377,15 @@ fn evaluate_word_parts( continue; } WordPart::Variable(name, modifier) => { - let value = state.get_var(&name).map(|v| v.to_string()); if let Some(modifier) = modifier { let (text, env_changes) = modifier - .apply(value.as_ref(), state, stdin.clone(), stderr.clone()) + .apply(&name, state, stdin.clone(), stderr.clone()) .await?; if let Some(env_changes) = env_changes { result.with_changes(env_changes); } Ok(Some(text)) - } else if let Some(val) = value { + } else if let Some(val) = state.get_var(&name).map(|v| v.to_string()) { Ok(Some(val.into())) } else { Err(miette::miette!("Undefined variable: {}", name)) diff --git a/crates/tests/src/lib.rs b/crates/tests/src/lib.rs index 40f160e..936ca3c 100644 --- a/crates/tests/src/lib.rs +++ b/crates/tests/src/lib.rs @@ -1066,6 +1066,7 @@ async fn touch() { #[tokio::test] async fn variable_expansion() { + // DEFAULT VALUE EXPANSION TestBuilder::new() .command("echo ${FOO:-5}") .assert_stdout("5\n") @@ -1089,6 +1090,26 @@ async fn variable_expansion() { .assert_stdout("2\n") .run() .await; + + // ASSIGN DEFAULT EXPANSION + TestBuilder::new() + .command("echo ${FOO:=5} && echo $FOO") + .assert_stdout("5\n5\n") + .run() + .await; + + TestBuilder::new() + .command(r#"FOO=1 && echo ${FOO:=5} && echo $FOO"#) + .assert_stdout("1\n1\n") + .run() + .await; + + TestBuilder::new() + .command(r#"echo ${FOO:=${BAR:=5}} && echo $FOO && echo $BAR"#) + .assert_stdout("5\n5\n5\n") + .run() + .await; + } #[cfg(test)]