Module: Haml::Util

Extended by:
Util
Included in:
Buffer, Precompiler, Util, Version, Sass::Engine, Sass::Plugin, Sass::Script::Color
Defined in:
lib/haml/util.rb

Overview

A module containing various useful functions.

Defined Under Namespace

Classes: StaticConditionalContext

Constant Summary collapse

RUBY_VERSION =

An array of ints representing the Ruby version number.

::RUBY_VERSION.split(".").map {|s| s.to_i}

Instance Method Summary collapse

Instance Method Details

#check_encoding(str) ⇒ Object



132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/haml/util.rb', line 132

def check_encoding(str)
  return if ruby1_8?
  return if str.valid_encoding?
  encoding = str.encoding
  newlines = Regexp.new("\r\n|\r|\n".encode(encoding).force_encoding("binary"))
  str.force_encoding("binary").split(newlines).each_with_index do |line, i|
    begin
      line.encode(encoding)
    rescue Encoding::UndefinedConversionError => e
      yield <<MSG.rstrip, i + 1
Invalid #{encoding.name} character #{e.error_char.dump}
MSG
    end
  end
end

#def_static_method(klass, name, args, *vars, erb) ⇒ Object

This is used for methods in Buffer that need to be very fast, and take a lot of boolean parameters that are known at compile-time. Instead of passing the parameters in normally, a separate method is defined for every possible combination of those parameters; these are then called using #static_method_name.

To define a static method, an ERB template for the method is provided. All conditionals based on the static parameters are done as embedded Ruby within this template. For example:

def_static_method(Foo, :my_static_method, [:foo, :bar], :baz, :bang, <<RUBY)
  <% if baz && bang %>
    return foo + bar
  <% elsif baz || bang %>
    return foo - bar
  <% else %>
    return 17
  <% end %>
RUBY

#static_method_name can be used to call static methods.

Parameters:

  • klass (Module)

    The class on which to define the static method

  • name (#to_s)

    The (base) name of the static method

  • args (Array<Symbol>)

    The names of the arguments to the defined methods (not to the ERB template)

  • vars (Array<Symbol>)

    The names of the static boolean variables to be made available to the ERB template

  • erb (String)

    The template for the method code



223
224
225
226
227
228
229
230
231
232
233
# File 'lib/haml/util.rb', line 223

def def_static_method(klass, name, args, *vars)
  erb = vars.pop
  powerset(vars).each do |set|
    context = StaticConditionalContext.new(set).instance_eval {binding}
    klass.class_eval(<<METHOD)
def #{static_method_name(name, *vars.map {|v| set.include?(v)})}(#{args.join(', ')})
  #{ERB.new(erb).result(context)}
end
METHOD
  end
end

#enum_with_index(enum) ⇒ Enumerator

A version of Enumerable#enum_with_index that works in Ruby 1.8 and 1.9.

Parameters:

  • enum (Enumerable)

    The enumerable to get the enumerator for

Returns:

  • (Enumerator)

    The with-index enumerator



170
171
172
# File 'lib/haml/util.rb', line 170

def enum_with_index(enum)
  ruby1_8? ? enum.enum_with_index : enum.each_with_index
end

#has?(attr, klass, method) ⇒ Boolean

Checks to see if a class has a given method. For example:

Haml::Util.has?(:public_instance_method, String, :gsub) #=> true

Method collections like Class#instance_methods return strings in Ruby 1.8 and symbols in Ruby 1.9 and on, so this handles checking for them in a compatible way.

Parameters:

  • attr (#to_s)

    The (singular) name of the method-collection method (e.g. :instance_methods, :private_methods)

  • klass (Module)

    The class to check the methods of which to check

  • method (String, Symbol)

    The name of the method do check for

Returns:

  • (Boolean)

    Whether or not the given collection has the given method



162
163
164
# File 'lib/haml/util.rb', line 162

def has?(attr, klass, method)
  klass.send("#{attr}s").include?(ruby1_8? ? method.to_s : method.to_sym)
end

#map_hash(hash) {|key, value| ... } ⇒ Hash

Maps the key-value pairs of a hash according to a block. For example:

map_hash({:foo => "bar", :baz => "bang"}) {|k, v| [k.to_s, v.to_sym]}
  #=> {"foo" => :bar, "baz" => :bang}

Parameters:

  • hash (Hash)

    The hash to map

Yields:

  • (key, value)

    A block in which the key-value pairs are transformed

Yield Parameters:

  • The (key)

    hash key

  • The (value)

    hash value

Yield Returns:

  • ((Object, Object))

    The new value for the [key, value] pair

Returns:

  • (Hash)

    The mapped hash

See Also:



81
82
83
# File 'lib/haml/util.rb', line 81

def map_hash(hash, &block)
  to_hash(hash.map(&block))
end

#map_keys(hash) {|key| ... } ⇒ Hash

Maps the keys in a hash according to a block. For example:

map_keys({:foo => "bar", :baz => "bang"}) {|k| k.to_s}
  #=> {"foo" => "bar", "baz" => "bang"}

Parameters:

  • hash (Hash)

    The hash to map

Yields:

  • (key)

    A block in which the keys are transformed

Yield Parameters:

  • key (Object)

    The key that should be mapped

Yield Returns:

  • (Object)

    The new value for the key

Returns:

  • (Hash)

    The mapped hash

See Also:



46
47
48
# File 'lib/haml/util.rb', line 46

def map_keys(hash)
  to_hash(hash.map {|k, v| [yield(k), v]})
end

#map_vals(hash) {|value| ... } ⇒ Hash

Maps the values in a hash according to a block. For example:

map_values({:foo => "bar", :baz => "bang"}) {|v| v.to_sym}
  #=> {:foo => :bar, :baz => :bang}

Parameters:

  • hash (Hash)

    The hash to map

Yields:

  • (value)

    A block in which the values are transformed

Yield Parameters:

  • value (Object)

    The value that should be mapped

Yield Returns:

  • (Object)

    The new value for the value

Returns:

  • (Hash)

    The mapped hash

See Also:



63
64
65
# File 'lib/haml/util.rb', line 63

def map_vals(hash)
  to_hash(hash.map {|k, v| [k, yield(v)]})
end

#merge_adjacent_strings(enum) ⇒ Array

Concatenates all strings that are adjacent in an array, while leaving other elements as they are. For example:

merge_adjacent_strings([1, "foo", "bar", 2, "baz"])
  #=> [1, "foobar", 2, "baz"]

Parameters:

  • enum (Enumerable)

Returns:

  • (Array)

    The enumerable with strings merged



114
115
116
117
118
119
120
121
122
123
# File 'lib/haml/util.rb', line 114

def merge_adjacent_strings(enum)
  e = enum.inject([]) do |a, e|
    if e.is_a?(String) && a.last.is_a?(String)
      a.last << e
    else
      a << e
    end
    a
  end
end

#powerset(arr) ⇒ Set<Set>

Computes the powerset of the given array. This is the set of all subsets of the array. For example:

powerset([1, 2, 3]) #=>
  Set[Set[], Set[1], Set[2], Set[3], Set[1, 2], Set[2, 3], Set[1, 3], Set[1, 2, 3]]

Parameters:

  • arr (Enumerable)

Returns:

  • (Set<Set>)

    The subsets of arr



94
95
96
97
98
99
100
101
102
103
# File 'lib/haml/util.rb', line 94

def powerset(arr)
  arr.inject([Set.new].to_set) do |powerset, el|
    new_powerset = Set.new
    powerset.each do |subset|
      new_powerset << subset
      new_powerset << subset + [el]
    end
    new_powerset
  end
end

#ruby1_8?Boolean

Whether or not this is running under Ruby 1.8 or lower.

Returns:

  • (Boolean)


128
129
130
# File 'lib/haml/util.rb', line 128

def ruby1_8?
  Haml::Util::RUBY_VERSION[0] == 1 && Haml::Util::RUBY_VERSION[1] < 9
end

#scope(file) ⇒ String

Returns the path of a file relative to the Haml root directory.

Parameters:

  • file (String)

    The filename relative to the Haml root

Returns:

  • (String)

    The filename relative to the the working directory



17
18
19
# File 'lib/haml/util.rb', line 17

def scope(file)
  File.join(File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__)))), file)
end

#static_method_name(name, *vars) ⇒ String

Computes the name for a method defined via #def_static_method.

Parameters:

  • name (String)

    The base name of the static method

  • vars (Array<Boolean>)

    The static variable assignment

Returns:

  • (String)

    The real name of the static method



240
241
242
# File 'lib/haml/util.rb', line 240

def static_method_name(name, *vars)
  "#{name}_#{vars.map {|v| !!v}.join('_')}"
end

#to_hash(arr) ⇒ Hash

Converts an array of [key, value] pairs to a hash. For example:

to_hash([[:foo, "bar"], [:baz, "bang"]])
  #=> {:foo => "bar", :baz => "bang"}

Parameters:

Returns:

  • (Hash)

    A hash



29
30
31
# File 'lib/haml/util.rb', line 29

def to_hash(arr)
  arr.compact.inject({}) {|h, (k, v)| h[k] = v; h}
end