Skip to content

Commit

Permalink
fix(expansion): correct length for 1-element arrays (#316)
Browse files Browse the repository at this point in the history
  • Loading branch information
reubeno authored Jan 9, 2025
1 parent a767905 commit 89bb3ce
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 5 deletions.
23 changes: 18 additions & 5 deletions brush-core/src/expansion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use crate::variables::{self, ShellValue};
struct Expansion {
fields: Vec<WordField>,
concatenate: bool,
from_array: bool,
undefined: bool,
}

Expand All @@ -32,6 +33,7 @@ impl Default for Expansion {
Self {
fields: vec![],
concatenate: true,
from_array: false,
undefined: false,
}
}
Expand Down Expand Up @@ -83,11 +85,12 @@ impl Expansion {
fields: vec![WordField::from(String::new())],
concatenate: true,
undefined: true,
from_array: false,
}
}

pub(crate) fn polymorphic_len(&self) -> usize {
if self.fields.len() > 1 {
if self.from_array {
self.fields.len()
} else {
self.fields.iter().fold(0, |acc, field| acc + field.len())
Expand All @@ -97,16 +100,17 @@ impl Expansion {
pub(crate) fn polymorphic_subslice(&self, index: usize, end: usize) -> Self {
let len = end - index;

// If there are multiple fields, then interpret `index` and `end` as indices
// into the vector of fields.
if self.fields.len() > 1 {
// If we came from an array, then interpret `index` and `end` as indices
// into the elements.
if self.from_array {
let actual_len = min(len, self.fields.len() - index);
let fields = self.fields[index..(index + actual_len)].to_vec();

Expansion {
fields,
concatenate: self.concatenate,
undefined: self.undefined,
from_array: self.from_array,
}
} else {
// Otherwise, interpret `index` and `end` as indices into the string contents.
Expand Down Expand Up @@ -176,6 +180,7 @@ impl Expansion {
fields,
concatenate: self.concatenate,
undefined: self.undefined,
from_array: self.from_array,
}
}
}
Expand Down Expand Up @@ -621,7 +626,7 @@ impl<'a> WordExpander<'a> {
let Expansion {
fields: this_fields,
concatenate,
undefined: _undefined,
..
} = self.expand_word_piece(piece.piece).await?;

let fields_to_append = if concatenate {
Expand Down Expand Up @@ -679,6 +684,7 @@ impl<'a> WordExpander<'a> {
fields,
concatenate: false,
undefined: false,
from_array: false,
}
}
brush_parser::word::WordPiece::TildePrefix(prefix) => Expansion::from(
Expand Down Expand Up @@ -1098,6 +1104,7 @@ impl<'a> WordExpander<'a> {
.map(|name| WordField(vec![ExpansionPiece::Splittable(name)]))
.collect(),
concatenate,
from_array: true,
undefined: false,
})
}
Expand All @@ -1118,6 +1125,7 @@ impl<'a> WordExpander<'a> {
.map(|key| WordField(vec![ExpansionPiece::Splittable(key)]))
.collect(),
concatenate,
from_array: true,
undefined: false,
})
}
Expand Down Expand Up @@ -1303,12 +1311,14 @@ impl<'a> WordExpander<'a> {
.map(|value| WordField(vec![ExpansionPiece::Splittable(value)]))
.collect(),
concatenate: *concatenate,
from_array: true,
undefined: false,
})
} else {
Ok(Expansion {
fields: vec![],
concatenate: *concatenate,
from_array: true,
undefined: false,
})
}
Expand Down Expand Up @@ -1348,6 +1358,7 @@ impl<'a> WordExpander<'a> {
.map(|param| WordField(vec![ExpansionPiece::Splittable(param.to_owned())]))
.collect(),
concatenate: *concatenate,
from_array: true,
undefined: false,
})
}
Expand Down Expand Up @@ -1554,6 +1565,7 @@ fn coalesce_expansions(expansions: Vec<Expansion>) -> Expansion {

// TODO: What if expansions have different concatenation values?
acc.concatenate = expansion.concatenate;
acc.from_array = expansion.from_array;

acc
})
Expand Down Expand Up @@ -1600,6 +1612,7 @@ fn transform_expansion(
Ok(Expansion {
fields: transformed_fields,
concatenate: expansion.concatenate,
from_array: expansion.from_array,
undefined: expansion.undefined,
})
}
Expand Down
13 changes: 13 additions & 0 deletions brush-shell/tests/cases/word_expansion.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,13 @@ cases:
echo "len(y[*]) = ${#y[*]}"
echo "len(y[@]) = ${#y[@]}"
- name: "Array length: single item"
stdin: |
z=("something here")
echo "len(z) = ${#z}"
echo "len(z[*]) = ${#z[*]}"
echo "len(z[@]) = ${#z[@]}"
- name: "Parameter expression: default value"
stdin: |
value="value"
Expand Down Expand Up @@ -726,6 +733,12 @@ cases:
echo "\${myarray[@]:2:2}: ${myarray[@]:2:2}"
echo "\${myarray[@]:2}: ${myarray[@]:2}"
- name: "Substring operator on single-element array"
stdin: |
myarray=("abcde fghij klmno pqrst uvwxy z")
echo "\${myarray[@]:0:1}: ${myarray[@]:0:1}"
echo "\${myarray[@]:1}: ${myarray[@]:1}"
- name: "Substring operator past end of array"
stdin: |
set a b c
Expand Down

0 comments on commit 89bb3ce

Please sign in to comment.