class Grizzled::String::Template::UnixShellStringTemplate
A string template that uses the Unix shell-like syntax +${varname}+ (or +$varname+) for variable references. A variable's name typically consists of alphanumerics and underscores, but is controlled by the a supplied regular expression. To include a literal “$” in a string, escape it with a backslash.
For this class, the general form of a variable reference is:
${varname?default}
The +?default+ suffix is optional and specifies a default value to be used if the variable has no value.
A shorthand form of a variable reference is:
$varname
The default capability is not available in the shorthand form.
Constants
- ESCAPED_DOLLAR
- ESCAPED_DOLLAR_PLACEHOLDER
Public Class Methods
Initialize a new UnixShellStringTemplate
. Supports various
hash options.
Parameters:
resolver
-
A hash-like object that can take a variable name (via the +[]+ function) and resolve its value, returning the value (which is converted to string) or
nil
. options
-
hash of options. See below.
Options:
:safe
-
true
for a safe template that substitutes a blank string for a non-existent variable, instead of throwing an exception. Defaults totrue
. :var_pattern
-
Regular expression pattern (as a string, not a Regexp object) to match a variable name. Defaults to “[A-Za-z0-9_]+”
# File lib/grizzled/string/template.rb, line 209 def initialize(resolver, options={}) super(resolver, options) var_re = options.fetch(:var_pattern, "[A-Za-z0-9_]+") @long_var_regexp = %r{\$\{(#{var_re})(\?[^\}]*)?\}} @short_var_regexp = %r{\$(#{var_re})} end
Public Instance Methods
Parse the location of the first variable in the string. Subclasses should override this method.
Parameters:
s
-
the string
Returns a Variable
object, or nil
.
# File lib/grizzled/string/template.rb, line 275 def find_variable_ref(s) def handle_long_match(m) name = m[1] if m[2].nil? default = nil else # Pull off the "?" default = m[2][1..-1] end Variable.new(m.begin(0), m.end(0), name, default) end def handle_no_long_match(s) m = @short_var_regexp.match(s) if m.nil? nil else Variable.new(m.begin(0), m.end(0), m[1], nil) end end m = @long_var_regexp.match(s) if m.nil? handle_no_long_match(s) else handle_long_match(m) end end
# File lib/grizzled/string/template.rb, line 277 def handle_long_match(m) name = m[1] if m[2].nil? default = nil else # Pull off the "?" default = m[2][1..-1] end Variable.new(m.begin(0), m.end(0), name, default) end
# File lib/grizzled/string/template.rb, line 239 def handle_match(m, s) if (m[1].length % 2) == 0 # Odd number of backslashes before "$", including # the one with the dollar token (group 2). Valid escape. b = m.begin(0) start = (b == 0 ? "" : s[0..(b-1)]) start + ESCAPED_DOLLAR_PLACEHOLDER + pre_sub(s[m.end(0)..-1]) else # Even number of backslashes before "$", including the one # with the dollar token (group 2). Not an escape. s end end
# File lib/grizzled/string/template.rb, line 289 def handle_no_long_match(s) m = @short_var_regexp.match(s) if m.nil? nil else Variable.new(m.begin(0), m.end(0), m[1], nil) end end
Kludge to handle escaped “$”. Temporarily replace it with something highly unlikely to be in the string. Then, put a single “$” in its place, after the substitution. Must be sure to handle even versus odd number of backslash characters.
# File lib/grizzled/string/template.rb, line 237 def pre_sub(s) def handle_match(m, s) if (m[1].length % 2) == 0 # Odd number of backslashes before "$", including # the one with the dollar token (group 2). Valid escape. b = m.begin(0) start = (b == 0 ? "" : s[0..(b-1)]) start + ESCAPED_DOLLAR_PLACEHOLDER + pre_sub(s[m.end(0)..-1]) else # Even number of backslashes before "$", including the one # with the dollar token (group 2). Not an escape. s end end # Check for an escaped "$" m = ESCAPED_DOLLAR.match(s) if (m) handle_match(m, s) else s end end
Replace all variable references in the given string. Variable references are recognized per the regular expression passed to the constructor. If a referenced variable is not found in the resolver, this method either:
-
throws a
VariableNotFoundException
(ifsafe
isfalse
). -
substitutes an empty string (if
safe
istrue
)
Recursive references are supported (but beware of infinite recursion).
Parameters:
s
-
the string in which to replace variable references
Returns the substituted result.
# File lib/grizzled/string/template.rb, line 231 def substitute(s) # Kludge to handle escaped "$". Temporarily replace it with # something highly unlikely to be in the string. Then, put a single # "$" in its place, after the substitution. Must be sure to handle # even versus odd number of backslash characters. def pre_sub(s) def handle_match(m, s) if (m[1].length % 2) == 0 # Odd number of backslashes before "$", including # the one with the dollar token (group 2). Valid escape. b = m.begin(0) start = (b == 0 ? "" : s[0..(b-1)]) start + ESCAPED_DOLLAR_PLACEHOLDER + pre_sub(s[m.end(0)..-1]) else # Even number of backslashes before "$", including the one # with the dollar token (group 2). Not an escape. s end end # Check for an escaped "$" m = ESCAPED_DOLLAR.match(s) if (m) handle_match(m, s) else s end end s2 = super(pre_sub(s)) s2.gsub(ESCAPED_DOLLAR_PLACEHOLDER, '$') end