Class: WLang::Dialect

Inherits:
Object
  • Object
show all
Defined in:
lib/wlang/dialect.rb

Direct Known Subclasses

Dummy, Html

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args) ⇒ Dialect

Creates a dialect instance with options



101
102
103
104
105
106
107
108
109
# File 'lib/wlang/dialect.rb', line 101

def initialize(*args)
  template, options = nil, {}
  args.each do |arg|
    options  = arg.to_hash if arg.respond_to?(:to_hash)
    template = arg if Template===arg
  end
  @template = template
  @options  = self.class.default_options.merge(options)
end

Instance Attribute Details

#optionsObject (readonly)

All dialect options



95
96
97
# File 'lib/wlang/dialect.rb', line 95

def options
  @options
end

#templateObject (readonly)

The template that uses this dialect instance to render



98
99
100
# File 'lib/wlang/dialect.rb', line 98

def template
  @template
end

Class Method Details

.compile(source, options = {}) ⇒ Object



13
14
15
# File 'lib/wlang/dialect.rb', line 13

def compile(source, options = {})
  Template.new source, :dialect => self
end

.default_options(options = {}) ⇒ Object

facade



8
9
10
11
# File 'lib/wlang/dialect.rb', line 8

def default_options(options = {})
  @default_options ||= (superclass.default_options.dup rescue {})
  @default_options.merge!(options)
end

.define_tag_method(symbols, dialects, code) ⇒ Object

Binds two methods for the given ‘symbols`:

1) _tag_xx_yy that executes ‘code` 2) _diatag_xx_yy that returns the dialect information of the tag blocks.

‘code` can either be a Symbol (existing method) or a Proc (some explicit code).



74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/wlang/dialect.rb', line 74

def define_tag_method(symbols, dialects, code)
  rulename = tag_dispatching_name(symbols, "_tag")
  case code
  when Symbol
    module_eval %Q{ alias :#{rulename} #{code} }
  when Proc
    define_method(rulename, code)
  else
    raise "Unable to use #{code} for a tag"
  end
  dialects_info_name = tag_dispatching_name(symbols, "_diatag")
  define_method(dialects_info_name) do dialects end
end

.render(source, *args) ⇒ Object



17
18
19
# File 'lib/wlang/dialect.rb', line 17

def render(source, *args)
  compile(source).call(*args)
end

.tag(symbols, dialects = nil, method = nil, &block) ⇒ Object

Install a new tag on the dialect for ‘symbols`.

Optional ‘dialects` can be passed if dialect modulation needs to occur for some blocks. The source code of the tag can either be passed as a `method` Symbol or as a block.

Examples:

# A simple tag with explicit code as a block
tag('$') do |buf,fn| ... end

# A simple tag, reusing a method (better for testing the method easily)
tag('$', :some_existing_method)

# Specifying that the first block of #{...}{...} has to be parsed in the same
# dialect whereas the second has to be parsed in the dummy one.
tag('#', [self, WLang::Dummy], ::some_existing_method)


41
42
43
44
45
46
47
48
# File 'lib/wlang/dialect.rb', line 41

def tag(symbols, dialects = nil, method = nil, &block)
  if block
    tag(symbols, dialects, block)
  else
    dialects, method = nil, dialects if method.nil?
    define_tag_method(symbols, dialects, method)
  end
end

.tag_dispatching_name(symbols, prefix = "_tag") ⇒ Object

Returns the dispatching method name for a given tag symbol and optional prefix (defaults to ‘_tag’).

Example:

Dialect.tag_dispatching_name('!$')
# => :_tag_33_36

Dialect.tag_dispatching_name('!$', "my_prefix")
# => :my_prefix_33_36


61
62
63
64
65
# File 'lib/wlang/dialect.rb', line 61

def tag_dispatching_name(symbols, prefix = "_tag")
  symbols = symbols.chars unless symbols.is_a?(Array)
  chars   = symbols.map{|s| s.ord}.join("_")
  "#{prefix}_#{chars}".to_sym
end

Instance Method Details

#bracesObject

Returns the braces to use, as set in the options



114
115
116
# File 'lib/wlang/dialect.rb', line 114

def braces
  options[:braces]
end

#contextObject

Returns the execution context, defined as the subject of the root scope.



158
159
160
# File 'lib/wlang/dialect.rb', line 158

def context
  scope.root.subject
end

#dialects_for(symbols) ⇒ Object

Returns the dialects used to parse the blocks associated with ‘symbols`, as previously installed by `define_tag_method`.

Raises:

  • (ArgumentError)


120
121
122
123
124
# File 'lib/wlang/dialect.rb', line 120

def dialects_for(symbols)
  info = self.class.tag_dispatching_name(symbols, "_diatag")
  raise ArgumentError, "No tag for #{symbols}" unless respond_to?(info)
  send(info)
end

#evaluate(expr, *default, &bl) ⇒ Object Also known as: value_of

Evaluates ‘expr` in the current scope. `expr` can be either

  • a Symbol or a String, taken as a dot expression to evaluate

  • a Proc or a Template, first rendered and then evaluated

Evaluation is delegated to the scope (@see Scope#evaluate) and the result returned by this method.



183
184
185
186
187
188
189
190
191
192
193
# File 'lib/wlang/dialect.rb', line 183

def evaluate(expr, *default, &bl)
  case expr
  when Symbol, String
    catch(:fail) do
      return scope.evaluate(expr, self, *default, &bl)
    end
    raise NameError, "Unable to find `#{expr}` on #{scope}"
  else
    evaluate(render(expr), *default, &bl)
  end
end

#render(fn, scope = nil, buffer = "") ⇒ Object

Renders ‘fn` to a `buffer`, optionally extending the current scope.

‘fn` can either be a String (immediately pushed on the buffer), a Proc (taken as a tag block to render further), or a Template (taken as a partial to render in the current scope).

Is ‘scope` is specified, the current scope is first branched to use to new one in priority, then rendering applies and the newly created scope if then poped.

Returns the buffer.



139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/wlang/dialect.rb', line 139

def render(fn, scope = nil, buffer = "")
  if scope.nil?
    case fn
      when String       then buffer << fn
      when Proc         then fn.call(self, buffer)
      when Template     then fn.call(@scope, buffer)
      when TiltTemplate then buffer << fn.render(@scope)
      else
        raise ArgumentError, "Unable to render `#{fn}`"
    end
    buffer
  else
    with_scope(scope){ render(fn, nil, buffer) }
  end
end

#scopeObject

Returns the current rendering scope.



163
164
165
# File 'lib/wlang/dialect.rb', line 163

def scope
  @scope || Scope.null
end

#with_scope(x) ⇒ Object

Yields the block with a scope branched with a sub-scope ‘x`.



168
169
170
171
172
173
# File 'lib/wlang/dialect.rb', line 168

def with_scope(x)
  @scope = scope.push(x)
  res    = yield
  @scope = scope.pop
  res
end