### subst_simple
# Simple command substitution
echo $(echo hello)
### expect
hello
### end

### subst_in_string
# Command substitution in string
echo "result: $(echo 42)"
### expect
result: 42
### end

### subst_pipeline
# Command substitution with pipeline
echo $(echo hello | cat)
### expect
hello
### end

### subst_assign
# Assign command substitution to variable
VAR=$(echo test); echo $VAR
### expect
test
### end

### subst_nested
# Nested command substitution
echo $(echo $(echo deep))
### expect
deep
### end

### subst_multiline
# Multi-line output
echo "$(printf 'a\nb\nc')"
### expect
a
b
c
### end

### subst_with_args
# Command with arguments
echo $(printf '%s %s' hello world)
### expect
hello world
### end

### subst_arithmetic
# Command in arithmetic context
X=$(echo 5); echo $((X + 3))
### expect
8
### end

### subst_in_condition
# Command substitution in condition
if [ "$(echo yes)" = "yes" ]; then echo matched; fi
### expect
matched
### end

### subst_exit_code
# Exit code from command substitution
result=$(false); echo $?
### expect
1
### end

### subst_backtick
echo `echo hello`
### expect
hello
### end

### subst_multiple
# Multiple substitutions
echo $(echo a) $(echo b) $(echo c)
### expect
a b c
### end

### subst_with_variable
# Substitution using variable
NAME=test; echo $(echo $NAME)
### expect
test
### end

### subst_strip_trailing_newlines
# Command substitution strips trailing newlines
VAR=$(printf 'hello\n\n\n'); echo "x${VAR}y"
### expect
xhelloy
### end

### subst_nested_quotes
# Nested double quotes inside $() inside double quotes
echo "$(echo "hello world")"
### expect
hello world
### end

### subst_nested_quotes_var
# Variable expansion in nested quoted $()
x="John"; echo "Hello, $(echo "$x")!"
### expect
Hello, John!
### end

### subst_deeply_nested_quotes
# Deeply nested $() with quotes
echo "nested: $(echo "$(echo "deep")")"
### expect
nested: deep
### end

### subst_nested_single_quotes
# Single quotes inside $() inside double quotes
echo "$(echo 'single quoted')"
### expect
single quoted
### end

### subst_nested_quotes_no_expand
# Nested quotes without variable (literal string)
echo "result=$(echo "done")"
### expect
result=done
### end

### subst_nested_quotes_empty
# Nested quotes with empty inner string
echo "x$(echo "")y"
### expect
xy
### end

### subst_nested_quotes_multiple
# Multiple nested $() in same double-quoted string
echo "$(echo "a") and $(echo "b")"
### expect
a and b
### end

### subst_nested_quotes_escape
# Escaped characters inside nested $()
echo "$(echo "hello\"world")"
### expect
hello"world
### end

### subst_word_split_for_loop
# Command substitution output is word-split in for-loop list context
count=0
for f in $(printf '/src/one.txt\n/src/two.txt\n/src/three.txt\n'); do
  count=$((count + 1))
done
echo "$count"
### expect
3
### end

### subst_word_split_echo_multiword
# Command substitution producing space-separated words splits in for-loop
result=""
for w in $(echo "alpha beta gamma"); do
  result="${result}[${w}]"
done
echo "$result"
### expect
[alpha][beta][gamma]
### end

### subst_word_split_newlines
# Command substitution with newline-separated output splits on newlines
result=""
for line in $(printf 'x\ny\nz'); do
  result="${result}(${line})"
done
echo "$result"
### expect
(x)(y)(z)
### end

### subst_exit_trap_captured
# EXIT trap output should be captured inside $(), not leak to parent
result="$(trap 'echo TRAPPED' EXIT; echo hello)"
echo "captured=[${result}]"
### expect
captured=[hello
TRAPPED]
### end

### subst_exit_trap_with_explicit_exit
# EXIT trap fires on explicit exit inside $()
result="$(trap 'echo CLEANUP' EXIT; echo data; exit 0)"
echo "captured=[${result}]"
### expect
captured=[data
CLEANUP]
### end

### subst_exit_trap_no_leak
# Trap output must not leak to parent stdout
out="$(trap 'echo INSIDE' EXIT; echo body)"
echo "out=[${out}]"
### expect
out=[body
INSIDE]
### end

### subst_exit_trap_isolation
# EXIT trap in $() should not affect parent traps
trap 'echo PARENT' EXIT
result="$(trap 'echo CHILD' EXIT; echo inner)"
echo "result=[${result}]"
trap - EXIT
### expect
result=[inner
CHILD]
### end

### subst_function_isolation
# Functions defined in $() should not leak to parent shell
x=$(function foo() { echo "sub"; }; echo "ok")
echo "$x"
foo 2>/dev/null
echo "exit=$?"
### expect
ok
exit=127
### end

### subst_variable_isolation
# Variables set in $() should not leak to parent shell
myvar="before"
x=$(myvar="inside"; echo "ok")
echo "$x"
echo "$myvar"
### expect
ok
before
### end

### subst_alias_isolation
# Aliases set in $() should not leak to parent shell
x=$(alias myalias='echo aliased' 2>/dev/null; echo "ok")
echo "$x"
### expect
ok
### end

### subst_file_read_shorthand
# $(<file) reads the file like $(cat file) (issue #2448)
echo hi > /tmp/cs_read
x=$(</tmp/cs_read)
echo "[$x]"
### expect
[hi]
### end

### subst_file_read_shorthand_space
# $(< file) with a space and multi-line content; trailing newlines trimmed
printf 'a\nb\n\n' > /tmp/cs_read2
x=$(< /tmp/cs_read2)
echo "[$x]"
### expect
[a
b]
### end

### subst_file_read_shorthand_var_target
# $(<"$f") expands the target word
f=/tmp/cs_read3
echo value > "$f"
echo "[$(<"$f")]"
### expect
[value]
### end

### subst_file_read_shorthand_missing
# $(<missing) is empty and sets $? to 1
{ x=$(</tmp/cs_no_such_file); } 2>/dev/null
echo "rc=$? [$x]"
### expect
rc=1 []
### end

### subst_file_read_backticks
# `<file` is the backtick spelling of $(<file)
echo tick > /tmp/cs_tick
x=`</tmp/cs_tick`
echo "[$x]"
### expect
[tick]
### end

### subst_file_read_in_arithmetic
# $(<file) and $(cat file) inside $(( )) read the file
echo 5 > /tmp/cs_num
echo $(( $(</tmp/cs_num) + 1 ))
echo $(( $(cat /tmp/cs_num) * 2 ))
### expect
6
10
### end

### subst_file_read_word_split
# Unquoted $(<file) word-splits like any substitution
printf 'a b\nc\n' > /tmp/cs_words
set -- $(</tmp/cs_words)
echo "$#"
### expect
3
### end

### subst_backtick_after_quoted_prefix
# Backquotes glued to a quoted segment, like "a"$(cmd)
echo 'b='`echo X`
echo "b="`echo X`
for u in 'a' 'b='`echo 42`; do echo $u; done
echo 'a'`echo X`'c'
### expect
b=X
b=X
a
b=42
aXc
### end

### subst_backtick_after_quoted_prefix_splits
# The unquoted result still word-splits
printf '[%s]' 'x'`echo "1 2"`; echo
### expect
[x1][2]
### end
