Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions crates/bashkit/src/interpreter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3168,7 +3168,9 @@ impl Interpreter {
expanded_values.push((value, has_command_subst));
}

let arr = self.arrays.entry(assignment.name.clone()).or_default();
// Resolve nameref for array assignments
let arr_name = self.resolve_nameref(&assignment.name).to_string();
let arr = self.arrays.entry(arr_name).or_default();
let mut idx = if assignment.append {
arr.keys().max().map(|k| k + 1).unwrap_or(0)
} else {
Expand Down Expand Up @@ -5921,9 +5923,10 @@ impl Interpreter {
result.push_str(&names.join(" "));
}
WordPart::ArrayLength(name) => {
if let Some(arr) = self.assoc_arrays.get(name) {
let resolved = self.resolve_nameref(name);
if let Some(arr) = self.assoc_arrays.get(resolved) {
result.push_str(&arr.len().to_string());
} else if let Some(arr) = self.arrays.get(name) {
} else if let Some(arr) = self.arrays.get(resolved) {
result.push_str(&arr.len().to_string());
} else {
result.push('0');
Expand Down Expand Up @@ -6028,12 +6031,13 @@ impl Interpreter {
}
// "${!arr[@]}" - array keys/indices as separate fields
if let WordPart::ArrayIndices(name) = &word.parts[0] {
if let Some(arr) = self.assoc_arrays.get(name) {
let resolved = self.resolve_nameref(name);
if let Some(arr) = self.assoc_arrays.get(resolved) {
let mut keys: Vec<_> = arr.keys().cloned().collect();
keys.sort();
return Ok(keys);
}
if let Some(arr) = self.arrays.get(name) {
if let Some(arr) = self.arrays.get(resolved) {
let mut indices: Vec<_> = arr.keys().collect();
indices.sort();
return Ok(indices.iter().map(|i| i.to_string()).collect());
Expand Down
98 changes: 98 additions & 0 deletions crates/bashkit/tests/spec_cases/bash/nameref-assoc.test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
### nameref_assign_key_to_assoc
# Nameref assign key to caller's associative array
add_entry() {
local -n ref="$1"
ref["hello"]="world"
ref["foo"]="bar"
}
declare -A mymap
add_entry mymap
echo "${mymap[hello]}"
echo "${mymap[foo]}"
### expect
world
bar
### end

### nameref_iterate_assoc_keys
# Nameref iterate keys of associative array
show_keys() {
local -n ref="$1"
for key in "${!ref[@]}"; do
echo "${key}=${ref[$key]}"
done | sort
}
declare -A colors=([red]=ff0000 [green]=00ff00 [blue]=0000ff)
show_keys colors
### expect
blue=0000ff
green=00ff00
red=ff0000
### end

### nameref_append_indexed_array
# Nameref append to caller's indexed array
collect() {
local -n arr_ref="$1"
arr_ref+=("alpha")
arr_ref+=("beta")
arr_ref+=("gamma")
}
items=()
collect items
echo "${#items[@]}"
echo "${items[0]} ${items[1]} ${items[2]}"
### expect
3
alpha beta gamma
### end

### nameref_two_refs_same_function
# Two namerefs in same function (harness pattern)
collect_from() {
local dir="$1"
local -n map_ref="$2"
local -n order_ref="$3"
map_ref["key-a"]="${dir}/file-a"
map_ref["key-b"]="${dir}/file-b"
order_ref+=("key-a")
order_ref+=("key-b")
}
declare -A my_map
my_order=()
collect_from "/src" my_map my_order
echo "${my_map[key-a]}"
echo "${my_map[key-b]}"
echo "${my_order[0]} ${my_order[1]}"
### expect
/src/file-a
/src/file-b
key-a key-b
### end

### nameref_assoc_length
# Nameref with associative array length
count_entries() {
local -n ref="$1"
echo "${#ref[@]}"
}
declare -A data=([x]=1 [y]=2 [z]=3)
count_entries data
### expect
3
### end

### nameref_overwrite_assoc_key
# Nameref overwrite existing key in associative array
update() {
local -n ref="$1"
ref["name"]="updated"
}
declare -A record=([name]=original [age]=30)
update record
echo "${record[name]}"
echo "${record[age]}"
### expect
updated
30
### end
Loading