Class: Grizzled::String::Template::WindowsCmdStringTemplate

Inherits:
TemplateBase
  • Object
show all
Defined in:
lib/grizzled/string/template.rb

Overview

A string template that uses the Windows cmd.exe syntax %varname% for variable references. A variable’s name may consist of alphanumerics and underscores. To include a literal “%” in a string, escape it with a backslash (“%”).

Constant Summary collapse

ESCAPED_PERCENT =
%r{(\\*)(%)}
ESCAPED_PERCENT_PLACEHOLDER =
'\001'

Instance Attribute Summary

Attributes inherited from TemplateBase

#resolver, #safe

Instance Method Summary collapse

Methods inherited from TemplateBase

#get_variable, #handle_no_value, #substitute_variable

Constructor Details

#initialize(resolver, options = {}) ⇒ WindowsCmdStringTemplate

Initialize a new WindowsCmdStringTemplate. 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 to true.

:var_pattern

Regular expression pattern (as a string, not a Regexp object) to match a variable name. Defaults to “[A-Za-z0-9_]+”



335
336
337
338
339
# File 'lib/grizzled/string/template.rb', line 335

def initialize(resolver, options={})
  super(resolver, options)
  var_pat = options.fetch(:var_pattern, "[A-Za-z0-9_]+")
  @var_re = %r{%(#{var_pat})%}
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.



398
399
400
401
402
403
404
405
# File 'lib/grizzled/string/template.rb', line 398

def find_variable_ref(s)
  m = @var_re.match(s)
  if m.nil?
    nil
  else
    Variable.new(m.begin(0), m.end(0), m[1], nil)
  end
end

#handle_match(m, s) ⇒ Object



364
365
366
367
368
369
370
371
372
373
374
375
# File 'lib/grizzled/string/template.rb', line 364

def handle_match(m, s)
  if (m[1].length % 2) == 1
    # Odd number of backslashes before "%". Valid escape.

    b = m.begin(0)
    start = (b == 0 ? "" : s[0..(b-1)])
    start + ESCAPED_PERCENT_PLACEHOLDER + pre_sub(s[m.end(0)..-1])
  else
    # Even number of backslashes before "%". Not an escape.
    s
  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.



362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
# File 'lib/grizzled/string/template.rb', line 362

def pre_sub(s)

  def handle_match(m, s)
    if (m[1].length % 2) == 1
      # Odd number of backslashes before "%". Valid escape.

      b = m.begin(0)
      start = (b == 0 ? "" : s[0..(b-1)])
      start + ESCAPED_PERCENT_PLACEHOLDER + pre_sub(s[m.end(0)..-1])
    else
      # Even number of backslashes before "%". Not an escape.
      s
    end
  end

  # Check for an escaped "%"
  m = ESCAPED_PERCENT.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 (if safe is false).

  • substitutes an empty string (if safe is true)

Recursive references are supported (but beware of infinite recursion).

Parameters:

s

the string in which to replace variable references

Returns the substituted result.



356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
# File 'lib/grizzled/string/template.rb', line 356

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) == 1
        # Odd number of backslashes before "%". Valid escape.

        b = m.begin(0)
        start = (b == 0 ? "" : s[0..(b-1)])
        start + ESCAPED_PERCENT_PLACEHOLDER + pre_sub(s[m.end(0)..-1])
      else
        # Even number of backslashes before "%". Not an escape.
        s
      end
    end

    # Check for an escaped "%"
    m = ESCAPED_PERCENT.match(s)
    if (m)
      handle_match(m, s)
    else
      s
    end
  end

  s2 = super(pre_sub(s))
  s2.gsub(ESCAPED_PERCENT_PLACEHOLDER, '%')
end