Skip to content

Commit

Permalink
Minor fixes along with partial support for variable default to anothe…
Browse files Browse the repository at this point in the history
…r expression
  • Loading branch information
prsabahrami committed Sep 29, 2024
1 parent 65c4822 commit 2c7d8e7
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 33 deletions.
4 changes: 1 addition & 3 deletions crates/deno_task_shell/src/grammar.pest
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ VARIABLE_EXPANSION = ${
)
}

VARIABLE_MODIFIER = ${
VARIABLE_MODIFIER = _{
VAR_DEFAULT_VALUE |
VAR_ASSIGN_DEFAULT |
VAR_ALTERNATE_VALUE |
Expand All @@ -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)
Expand Down
33 changes: 10 additions & 23 deletions crates/deno_task_shell/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<PipeSequence> for Sequence {
fn from(p: PipeSequence) -> Self {
Sequence::Pipeline(Pipeline {
Expand Down Expand Up @@ -385,12 +375,12 @@ impl Word {
pub enum VariableModifier {
#[error("Invalid substring")]
Substring {
begin: i64,
length: Option<i64>,
begin: WordPart,
length: Option<WordPart>,
},
DefaultValue(String),
AssignDefault(String),
AlternateValue(String),
DefaultValue(WordPart),
AssignDefault(WordPart),
AlternateValue(WordPart),
}

#[cfg_attr(feature = "serialization", derive(serde::Serialize))]
Expand All @@ -403,7 +393,7 @@ pub enum WordPart {
#[error("Invalid text")]
Text(String),
#[error("Invalid variable")]
Variable(String, Option<VariableModifier>),
Variable(String, Option<Box<VariableModifier>>),
#[error("Invalid command")]
Command(SequentialList),
#[error("Invalid quoted string")]
Expand Down Expand Up @@ -1258,9 +1248,6 @@ fn parse_word(pair: Pair<Rule>) -> Result<Word> {
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);
Expand Down Expand Up @@ -1513,16 +1500,16 @@ fn parse_variable_expansion(part: Pair<Rule>) -> Result<WordPart> {
.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() {
Rule::VAR_SUBSTRING => {
let mut numbers = modifier.into_inner();
let begin = numbers
.next()
.and_then(|n| n.as_str().parse::<i64>().ok())
.unwrap_or(0);
.and_then(|n| n.as_str())
.unwrap_or("0");
let length =
numbers.next().and_then(|n| n.as_str().parse::<i64>().ok());
Some(VariableModifier::Substring { begin, length })
Expand Down Expand Up @@ -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(),
Expand Down
17 changes: 10 additions & 7 deletions crates/deno_task_shell/src/shell/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1120,13 +1120,16 @@ impl From<anyhow::Error> for EvaluateWordTextError {
}

impl VariableModifier {
pub fn apply(&self, variable: Option<&String>) -> Option<String> {
pub fn apply(&self, variable: Option<&String>) -> Result<Option<String>, 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<char> = variable.chars().collect();
let start = usize::try_from(*begin).unwrap();
Expand All @@ -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")),
}
}
}
Expand Down Expand Up @@ -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
}
Expand Down

0 comments on commit 2c7d8e7

Please sign in to comment.