Module: Wip::VariableInterpolation

Defined in:
lib/wip/variable_interpolation.rb

Overview

Interpolates $VAR references the way docker compose does when reading compose.yml: $VAR, $VAR:-default/$VAR-default, bare $VAR, and $$ as an escaped literal dollar sign. $VAR:?err/$VAR:+alt aren't recognized by PATTERN at all, so — unlike an unset $VAR/$VAR, which this resolves to an empty string — they pass through completely unchanged, "$..." and all.

Constant Summary collapse

PATTERN =
/\$\$|\$\{([A-Za-z_][A-Za-z0-9_]*)((:-|-)([^}]*))?\}|\$([A-Za-z_][A-Za-z0-9_]*)/

Class Method Summary collapse

Class Method Details

.call(text, env) ⇒ Object



12
13
14
15
16
17
18
19
# File 'lib/wip/variable_interpolation.rb', line 12

def self.call(text, env)
  text.gsub(PATTERN) do |matched|
    next '$' if matched == '$$'

    name, _, operator, default, bare_name = Regexp.last_match.captures
    resolve(env[name || bare_name], operator, default)
  end
end

.tree(value, env, seen = {}.compare_by_identity) ⇒ Object

Walks an already-parsed YAML structure and interpolates string values only — real Compose interpolates YAML values, never mapping keys (its docs call this out explicitly), and doing this after parsing means a substituted value can't introduce YAML syntax (e.g. a literal "#" turning into a comment marker).

seen tracks Hash/Array objects on the current recursion path (by identity, not #==) so a self-referential YAML alias — ComposeFile.load parses with aliases: true — raises instead of recursing until SystemStackError. The same object reached again from a different branch (an anchor reused, not a cycle) is fine: it's removed from seen once its own subtree finishes.



31
32
33
34
35
36
37
# File 'lib/wip/variable_interpolation.rb', line 31

def self.tree(value, env, seen = {}.compare_by_identity)
  case value
  when String then call(value, env)
  when Hash, Array then walk_container(value, env, seen)
  else value
  end
end