Class: Grizzled::String::Template::UnixShellStringTemplate
- Inherits:
-
TemplateBase
- Object
- TemplateBase
- Grizzled::String::Template::UnixShellStringTemplate
- Defined in:
- lib/grizzled/string/template.rb
Overview
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.
Constant Summary collapse
- ESCAPED_DOLLAR_PLACEHOLDER =
"\001"
- ESCAPED_DOLLAR =
%r{(\\*)(\\\$)}
Instance Attribute Summary
Attributes inherited from TemplateBase
Instance Method Summary collapse
-
#find_variable_ref(s) ⇒ Object
Parse the location of the first variable in the string.
- #handle_long_match(m) ⇒ Object
- #handle_match(m, s) ⇒ Object
- #handle_no_long_match(s) ⇒ Object
-
#initialize(resolver, options = {}) ⇒ UnixShellStringTemplate
constructor
Initialize a new
UnixShellStringTemplate
. -
#pre_sub(s) ⇒ Object
Kludge to handle escaped “$”.
-
#substitute(s) ⇒ Object
Replace all variable references in the given string.
Methods inherited from TemplateBase
#get_variable, #handle_no_value, #substitute_variable
Constructor Details
#initialize(resolver, options = {}) ⇒ UnixShellStringTemplate
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) ornil
. 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_]+”
209 210 211 212 213 214 |
# File 'lib/grizzled/string/template.rb', line 209 def initialize(resolver, ={}) super(resolver, ) var_re = .fetch(:var_pattern, "[A-Za-z0-9_]+") @long_var_regexp = %r{\$\{(#{var_re})(\?[^\}]*)?\}} @short_var_regexp = %r{\$(#{var_re})} end |
Instance Method Details
#find_variable_ref(s) ⇒ Object
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
.
275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 |
# 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 |
#handle_long_match(m) ⇒ Object
277 278 279 280 281 282 283 284 285 286 287 |
# 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 |
#handle_match(m, s) ⇒ Object
239 240 241 242 243 244 245 246 247 248 249 250 251 252 |
# 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 |
#handle_no_long_match(s) ⇒ Object
289 290 291 292 293 294 295 296 |
# 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 |
#pre_sub(s) ⇒ Object
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.
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 |
# 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 |
#substitute(s) ⇒ Object
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.
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 |
# 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 |