class Dslh
Constants
- INDENT_SPACES
- VALID_OPTIONS
- VERSION
Public Class Methods
deval(hash, options = {}, &block)
click to toggle source
# File lib/dslh.rb, line 66 def deval(hash, options = {}, &block) if [hash, options].any? {|i| not i.kind_of?(Hash) } raise TypeError, "wrong argument type #{options.class} (expected Hash)" end self.new(options).deval(hash, &block) end
eval(expr_or_options = nil, options = nil, &block)
click to toggle source
# File lib/dslh.rb, line 44 def eval(expr_or_options = nil, options = nil, &block) if options and not options.kind_of?(Hash) raise TypeError, "wrong argument type #{options.class} (expected Hash)" end expr = nil options ||= {} if expr_or_options case expr_or_options when String expr = expr_or_options when Hash options.update(expr_or_options) else raise TypeError, "wrong argument type #{expr_or_options.class} (expected String or Hash)" end end self.new(options).eval(expr, &block) end
new(options = {})
click to toggle source
# File lib/dslh.rb, line 75 def initialize(options = {}) invlid_options = options.keys - VALID_OPTIONS unless invlid_options.empty? raise ArgumentError, 'invalid option ' + invlid_options.map {|i| i.inspect }.join(',') end @options = { :time_inspecter => method(:inspect_time), :dump_old_hash_array_format => false, :force_dump_braces => false, :use_braces_instead_of_do_end => false, :use_heredoc_for_multi_line => false, }.merge(options) @options[:key_conv] ||= (@options[:conv] || proc {|i| i.to_s }) @options[:value_conv] ||= @options[:conv] end
Public Instance Methods
deval(hash)
click to toggle source
# File lib/dslh.rb, line 182 def deval(hash) buf = StringIO.new depth = @options[:initial_depth] || 0 deval0(hash, depth, buf, true) buf.string end
eval(expr = nil, &block)
click to toggle source
# File lib/dslh.rb, line 94 def eval(expr = nil, &block) retval = {} scope = Scope.new scope.instance_variable_set(:@__options__, @options) scope.instance_variable_set(:@__hash__, retval) @options[:scope_hook].call(scope) if @options[:scope_hook] (@options[:scope_vars] || {}).each do |name, value| scope.instance_variable_set("@#{name}", value) end if @options[:ignore_methods] ignore_methods = Array(@options[:ignore_methods]) ignore_methods.each do |method_name| scope.instance_eval(<<-EOS) def #{method_name}(*args, &block) method_missing(#{method_name.to_s.inspect}, *args, &block) end EOS end end if expr eval_args = [expr] [:filename, :lineno].each do |k| eval_args << @options[k] if @options[k] end scope.instance_eval(*eval_args) else scope.instance_eval(&block) end if (schema = @options[:schema] || schema_path = @options[:schema_path]) begin require 'kwalify' rescue LoadError raise 'cannot load "kwalify". please install "kwalify"' end if schema and not schema.kind_of?(String) raise TypeError, "wrong schema type #{schema.class} (expected String)" end if schema_path and not schema_path.kind_of?(String) raise TypeError, "wrong schema_path type #{schema_path.class} (expected String)" end schema = schema_path ? Kwalify::Yaml.load_file(schema_path) : Kwalify::Yaml.load(schema) validator = Kwalify::Validator.new(schema) if @options[:root_identify] new_retval = {} retval.each do |k, v| new_retval[k] = v.map {|_id, attrs| attrs.merge('_id' => _id) } end errors = validator.validate(new_retval) errors.each do |e| path = e.path.split('/', 4)[1..-1] root_key = path.shift _id = path.shift.to_i if _id_orig = new_retval.fetch(root_key, {})[_id] _id = _id_orig['_id'] || _id end path = '/' + ([root_key, _id] + path).join('/') e.path.replace(path) end else errors = validator.validate(retval) end unless errors.empty? raise ValidationError.new(errors, retval) end end return retval end
Private Instance Methods
deval0(hash, depth, buf, root = false)
click to toggle source
# File lib/dslh.rb, line 191 def deval0(hash, depth, buf, root = false) indent = (INDENT_SPACES * depth) key_conv = @options[:key_conv] if exclude_keys?(hash.keys) buf.puts(<<-EOS ( #{hash.pretty_inspect.strip.gsub("\n", "\n" + indent)} ) EOS ) return end hash.each do |key, value| key = key_conv.call(key) if key_conv if key.kind_of?(Proc) tmp_buf = StringIO.new nested = value_proc(value, depth, tmp_buf) key_value = case key.arity when 0 key.call when 1 key.call(tmp_buf.string.strip) else key.call(tmp_buf.string.strip, nested) end buf.puts(indent + key_value) else if root and @options[:root_identify] and value.kind_of?(Hash) value.each do |k, v| buf.print(indent + key + ' ' + k.inspect) value_proc(v, depth, buf, true, key) end else buf.print(indent + key) value_proc(value, depth, buf, true, key) end end end end
exclude_keys?(keys)
click to toggle source
# File lib/dslh.rb, line 345 def exclude_keys?(keys) key_conv = @options[:key_conv] exclude_key = @options[:exclude_key] || proc {|k| k = key_conv.call(k) if key_conv k.to_s !~ /\A[_a-z]\w+\Z/i } keys.any? {|k| exclude_key.call(k) } end
inspect_time(time)
click to toggle source
# File lib/dslh.rb, line 356 def inspect_time(time) if Time.respond_to?(:parse) "Time.parse(#{time.to_s.inspect})" else "Time.at(#{time.tv_sec}, #{time.tv_usec})" end end
value_proc(value, depth, value_buf, newline = true, curr_key = nil)
click to toggle source
# File lib/dslh.rb, line 236 def value_proc(value, depth, value_buf, newline = true, curr_key = nil) indent = (INDENT_SPACES * depth) next_indent = (INDENT_SPACES * (depth + 1)) value_conv = @options[:value_conv] nested = false case value when Hash if exclude_keys?(value.keys) value_buf.puts(<<-EOS ( #{next_indent}#{value.pretty_inspect.strip.gsub("\n", "\n" + next_indent)} #{indent}) EOS ) else nested = true value_buf.puts(@options[:use_braces_instead_of_do_end] ? ' {' : ' do') deval0(value, depth + 1, value_buf) value_buf.puts(indent + (@options[:use_braces_instead_of_do_end] ? '}' : 'end')) end when Array if value.empty? value_buf.puts(" []") elsif value.any? {|v| [Array, Hash].any? {|c| v.kind_of?(c) }} nested = true if not @options[:dump_old_hash_array_format] and value.all? {|i| i.kind_of?(Hash) and not exclude_keys?(i.keys) } value_buf.puts(@options[:use_braces_instead_of_do_end] ? ' {|*|' : ' do |*|') value.each_with_index do |v, i| deval0(v, depth + 1, value_buf) if i < (value.length - 1) if @options[:use_braces_instead_of_do_end] value_buf.puts(indent + "}\n" + indent + curr_key + ' {|*|') else value_buf.puts(indent + "end\n" + indent + curr_key + ' do |*|') end end end if newline value_buf.puts(indent + (@options[:use_braces_instead_of_do_end] ? '}' : 'end')) else value_buf.print(indent + (@options[:use_braces_instead_of_do_end] ? '}' : 'end')) end else value_buf.puts(' [') value.each_with_index do |v, i| case v when Hash if exclude_keys?(v.keys) value_buf.print(INDENT_SPACES * (depth + 1) + v.pretty_inspect.strip) else value_buf.puts(next_indent + '_{') deval0(v, depth + 2, value_buf) value_buf.print(next_indent + '}') end when Array value_buf.print(next_indent.slice(0...-1)) value_proc(v, depth + 1, value_buf, false) else value_buf.print(next_indent + v.pretty_inspect.strip.gsub("\n", "\n" + next_indent)) end value_buf.puts(i < (value.length - 1) ? ',' : '') end if newline value_buf.puts(indent + ']') else value_buf.print(indent + ']') end end elsif @options[:force_dump_braces] or value.length == 1 value_buf.puts(' ' + value.inspect) else value_buf.puts(' ' + value.map {|v| v = value_conv.call(v) if value_conv if v.kind_of?(Hash) '(' + v.inspect + ')' else v.inspect end }.join(', ')) end else value = value_conv.call(value) if value_conv if @options[:time_inspecter] and value.kind_of?(Time) value = @options[:time_inspecter].call(value) value_buf.puts(' ' + value) else if @options[:use_heredoc_for_multi_line] \ and value.kind_of?(String) \ and value.match(/\R/) value_buf.puts(' ' + "<<-'EOS'\n#{value}\nEOS") else value_buf.puts(' ' + value.inspect) end end end return nested end