From 2c7d8e78d95e425725b7d95717ce0c0811866c09 Mon Sep 17 00:00:00 2001 From: prsabahrami Date: Sun, 29 Sep 2024 12:23:07 -0400 Subject: [PATCH] Minor fixes along with partial support for variable default to another expression --- crates/deno_task_shell/src/grammar.pest | 4 +-- crates/deno_task_shell/src/parser.rs | 33 +++++++-------------- crates/deno_task_shell/src/shell/execute.rs | 17 ++++++----- 3 files changed, 21 insertions(+), 33 deletions(-) diff --git a/crates/deno_task_shell/src/grammar.pest b/crates/deno_task_shell/src/grammar.pest index 77077db..dd9a693 100644 --- a/crates/deno_task_shell/src/grammar.pest +++ b/crates/deno_task_shell/src/grammar.pest @@ -38,7 +38,7 @@ VARIABLE_EXPANSION = ${ ) } -VARIABLE_MODIFIER = ${ +VARIABLE_MODIFIER = _{ VAR_DEFAULT_VALUE | VAR_ASSIGN_DEFAULT | VAR_ALTERNATE_VALUE | @@ -50,8 +50,6 @@ VAR_ASSIGN_DEFAULT = { ":=" ~ UNQUOTED_PENDING_WORD } VAR_ALTERNATE_VALUE = { ":+" ~ UNQUOTED_PENDING_WORD } VAR_SUBSTRING = { ":" ~ NUMBER ~ (":" ~ NUMBER)? } -NUMBER = @{ "-"? ~ ASCII_DIGIT+ } - TILDE_PREFIX = ${ "~" ~ (!(OPERATOR | WHITESPACE | NEWLINE | "/") ~ ( (!("\"" | "'" | "$" | "\\" | "/") ~ ANY) diff --git a/crates/deno_task_shell/src/parser.rs b/crates/deno_task_shell/src/parser.rs index 550955d..3e7ad7e 100644 --- a/crates/deno_task_shell/src/parser.rs +++ b/crates/deno_task_shell/src/parser.rs @@ -121,16 +121,6 @@ pub struct PipeSequence { pub next: PipelineInner, } -#[cfg_attr(feature = "serialization", derive(serde::Serialize))] -#[cfg_attr(feature = "serialization", serde(rename_all = "camelCase"))] -#[derive(Copy, Clone, Debug, PartialEq, Eq, Error)] -pub enum PipeSequenceOperator { - #[error("Stdout pipe operator")] - Stdout, - #[error("Stdout and stderr pipe operator")] - StdoutStderr, -} - impl From for Sequence { fn from(p: PipeSequence) -> Self { Sequence::Pipeline(Pipeline { @@ -385,12 +375,12 @@ impl Word { pub enum VariableModifier { #[error("Invalid substring")] Substring { - begin: i64, - length: Option, + begin: WordPart, + length: Option, }, - DefaultValue(String), - AssignDefault(String), - AlternateValue(String), + DefaultValue(WordPart), + AssignDefault(WordPart), + AlternateValue(WordPart), } #[cfg_attr(feature = "serialization", derive(serde::Serialize))] @@ -403,7 +393,7 @@ pub enum WordPart { #[error("Invalid text")] Text(String), #[error("Invalid variable")] - Variable(String, Option), + Variable(String, Option>), #[error("Invalid command")] Command(SequentialList), #[error("Invalid quoted string")] @@ -1258,9 +1248,6 @@ fn parse_word(pair: Pair) -> Result { parse_complete_command(part.into_inner().next().unwrap())?; parts.push(WordPart::Command(command)); } - Rule::VARIABLE => { - parts.push(WordPart::Variable(part.as_str().to_string(), None)) - } Rule::VARIABLE_EXPANSION => { let variable_expansion = parse_variable_expansion(part)?; parts.push(variable_expansion); @@ -1513,7 +1500,7 @@ fn parse_variable_expansion(part: Pair) -> Result { .ok_or_else(|| miette!("Expected variable name"))?; let variable_name = variable.as_str().to_string(); - let modifier = inner.next().unwrap().into_inner().next(); + let modifier = inner.next(); let parsed_modifier = if let Some(modifier) = modifier { match modifier.as_rule() { @@ -1521,8 +1508,8 @@ fn parse_variable_expansion(part: Pair) -> Result { let mut numbers = modifier.into_inner(); let begin = numbers .next() - .and_then(|n| n.as_str().parse::().ok()) - .unwrap_or(0); + .and_then(|n| n.as_str()) + .unwrap_or("0"); let length = numbers.next().and_then(|n| n.as_str().parse::().ok()); Some(VariableModifier::Substring { begin, length }) @@ -2020,7 +2007,7 @@ mod test { env_vars: vec![], args: vec![ Word::new_word("echo"), - Word(vec![WordPart::Variable("MY_ENV".to_string())]), + Word(vec![WordPart::Variable("MY_ENV".to_string(), None)]), ], } .into(), diff --git a/crates/deno_task_shell/src/shell/execute.rs b/crates/deno_task_shell/src/shell/execute.rs index 5883815..fea94fb 100644 --- a/crates/deno_task_shell/src/shell/execute.rs +++ b/crates/deno_task_shell/src/shell/execute.rs @@ -1120,13 +1120,16 @@ impl From for EvaluateWordTextError { } impl VariableModifier { - pub fn apply(&self, variable: Option<&String>) -> Option { + pub fn apply(&self, variable: Option<&String>) -> Result, anyhow::Error> { match self { VariableModifier::DefaultValue(default_value) => match variable { - Some(v) => Some(v.to_string()), - None => Some(default_value.clone()), + Some(v) => Ok(Some(v.to_string())), + None => Ok(Some(default_value.clone())), }, VariableModifier::Substring { begin, length } => { + if variable.is_none() { + return Err(anyhow::anyhow!("Variable not found")); + } let variable = variable.unwrap(); let chars: Vec = variable.chars().collect(); let start = usize::try_from(*begin).unwrap(); @@ -1136,9 +1139,9 @@ impl VariableModifier { } None => chars.len(), }; - Some(chars[start..end].iter().collect()) - } - _ => unreachable!("Should not reach"), + Ok(Some(chars[start..end].iter().collect())) + }, + _ => Err(anyhow::anyhow!("Unsupported variable modifier")), } } } @@ -1282,7 +1285,7 @@ fn evaluate_word_parts( WordPart::Variable(name, modifier) => { let value = state.get_var(&name).map(|v| v.to_string()); if let Some(modifier) = modifier { - modifier.apply(value.as_ref()) + modifier.apply(value.as_ref())? } else { value }