Expand default values recursively

This commit is contained in:
Sami Samhuri 2026-02-02 20:48:13 -08:00
parent 5172c60910
commit 44dcfa7ba6
No known key found for this signature in database
2 changed files with 20 additions and 6 deletions

View file

@ -3,6 +3,7 @@ require "shellwords"
module Shell
class WordExpander
ENV_VAR_REGEX = /\$(?:\{([^}]+)\}|(\w+)\b)/
DEFAULT_VAR_REGEX = /\A(\w+):-([\s\S]*)\z/
ESCAPED_DOLLAR = "\u0001"
# Splits the given line into multiple words, performing the following transformations:
@ -15,12 +16,7 @@ module Shell
protected_line = protect_escaped_dollars(line)
shellsplit(protected_line)
.map do |word|
word
.gsub(ENV_VAR_REGEX) do
name = Regexp.last_match(2) || Regexp.last_match(1)
ENV.fetch(name)
end
.tr(ESCAPED_DOLLAR, "$")
expand_variables(word).tr(ESCAPED_DOLLAR, "$")
# TODO: expand globs
end
end
@ -98,6 +94,20 @@ module Shell
Dir.glob(word)
end
def expand_variables(value)
value.gsub(ENV_VAR_REGEX) do
raw = Regexp.last_match(2) || Regexp.last_match(1)
if (m = DEFAULT_VAR_REGEX.match(raw))
name = m[1]
fallback = m[2]
env_value = ENV[name]
env_value.nil? || env_value.empty? ? expand_variables(fallback) : env_value
else
ENV.fetch(raw)
end
end
end
def protect_escaped_dollars(line)
output = +""
i = 0

View file

@ -88,6 +88,10 @@ class ShellTest < Minitest::Test
assert_equal "fallback", `#{A1_PATH} -c 'echo ${A1_UNSET_VAR:-fallback}'`.chomp
end
def test_expands_parameter_default_value_with_variable_reference
assert_equal Dir.home, `#{A1_PATH} -c 'echo ${A1_UNSET_VAR:-$HOME}'`.chomp
end
#################################
### Execution and job control ###
#################################