JustBash.Interpreter.Expansion (JustBash v0.4.0)

View Source

Handles shell expansion: variables, command substitution, arithmetic.

Delegates to specialized submodules:

  • Parameter - Parameter expansion operations (${VAR:-default}, etc.)
  • Glob - Glob expansion and pattern matching
  • Brace - Brace expansion ({a,b,c}, {1..10})

Summary

Types

A variable assignment from an expansion like ${VAR:=default} or $((x++))

Side effects an expansion hands back to the enclosing command.

What a command substitution did, on its way out to the enclosing command.

Functions

Expand a single array element word, applying IFS splitting to unquoted expansions.

Expand words for a for-loop, applying IFS splitting to unquoted expansions.

Expand a parameter with optional operations. Returns {expanded_value, pending_assignments}.

Expand redirection target.

Expand word parts into a string, handling all substitution types. Returns the expanded string and any side effects — see pending_assignments/0 and take_substitutions/1.

Expand word parts into a string, discarding pending assignments. Use this when you don't need to track variable assignments (e.g., in pattern matching).

Expand word parts with brace and glob expansion, returning a list of strings. Used for command arguments where globs should expand to multiple files.

Split the command-substitution traces out of a list of expansion side effects.

Types

assignment()

@type assignment() :: {String.t(), String.t()}

A variable assignment from an expansion like ${VAR:=default} or $((x++))

pending_assignments()

@type pending_assignments() :: [assignment() | substitution()]

Side effects an expansion hands back to the enclosing command.

substitution()

@type substitution() :: {:substitution, String.t(), non_neg_integer()}

What a command substitution did, on its way out to the enclosing command.

Its diagnostic belongs on the shell's stderr — bash writes it there even when the enclosing command redirects stderr, since the expansion happens before the redirection is performed — and its exit status is what a bare assignment reports as $?.

Functions

expand_array_element(bash, word)

@spec expand_array_element(JustBash.t(), JustBash.AST.Word.t()) :: [String.t()]

Expand a single array element word, applying IFS splitting to unquoted expansions.

Used for array assignment like arr=($(echo "a b c")) where command substitution output should be word-split into multiple array elements.

Returns a list of expanded strings (may be multiple due to IFS splitting or brace expansion).

expand_for_loop_words(bash, words)

@spec expand_for_loop_words(JustBash.t(), [JustBash.AST.Word.t()]) :: [String.t()]

Expand words for a for-loop, applying IFS splitting to unquoted expansions.

In bash, IFS splitting only happens on unquoted variable/command substitution results. Quoted strings (single or double) are not split. Brace expansion produces multiple words directly.

expand_parameter(bash, param)

Expand a parameter with optional operations. Returns {expanded_value, pending_assignments}.

Delegates to JustBash.Interpreter.Expansion.Parameter.

expand_redirect_target(bash, target)

@spec expand_redirect_target(JustBash.t(), JustBash.AST.Word.t() | String.t() | any()) ::
  String.t()

Expand redirection target.

expand_word_parts(bash, parts)

@spec expand_word_parts(JustBash.t(), [JustBash.AST.word_part()]) ::
  {String.t(), pending_assignments()}

Expand word parts into a string, handling all substitution types. Returns the expanded string and any side effects — see pending_assignments/0 and take_substitutions/1.

Examples

iex> expand_word_parts(bash, [%AST.Literal{value: "hello"}])
{"hello", []}

iex> expand_word_parts(bash, [%AST.ParameterExpansion{parameter: "x", operation: %AST.AssignDefault{...}}])
{"default", [{"x", "default"}]}

expand_word_parts_simple(bash, parts)

@spec expand_word_parts_simple(JustBash.t(), [JustBash.AST.word_part()]) :: String.t()

Expand word parts into a string, discarding pending assignments. Use this when you don't need to track variable assignments (e.g., in pattern matching).

expand_word_with_glob(bash, parts)

@spec expand_word_with_glob(JustBash.t(), [JustBash.AST.word_part()]) ::
  {[String.t()], pending_assignments()}

Expand word parts with brace and glob expansion, returning a list of strings. Used for command arguments where globs should expand to multiple files.

Expansion order: brace -> parameter/command -> word splitting (IFS) -> glob

take_substitutions(effects)

@spec take_substitutions(pending_assignments()) ::
  {String.t(), non_neg_integer() | nil, [assignment()]}

Split the command-substitution traces out of a list of expansion side effects.

Returns the accumulated stderr, the exit status of the last substitution that ran (nil when none did — bash reports the last one as $? for a bare assignment), and the assignments left over.