2018-01-12 03:38:09 -05:00
|
|
|
#! /your/favourite/path/to/ruby
|
|
|
|
# -*- mode: ruby; coding: utf-8; indent-tabs-mode: nil; ruby-indent-level: 2 -*-
|
|
|
|
# -*- frozen_string_literal: true; -*-
|
|
|
|
# -*- warn_indent: true; -*-
|
|
|
|
#
|
|
|
|
# Copyright (c) 2017 Urabe, Shyouhei. All rights reserved.
|
|
|
|
#
|
|
|
|
# This file is a part of the programming language Ruby. Permission is hereby
|
|
|
|
# granted, to either redistribute and/or modify this file, provided that the
|
|
|
|
# conditions mentioned in the file COPYING are met. Consult the file for
|
|
|
|
# details.
|
|
|
|
|
|
|
|
require 'pathname'
|
|
|
|
require 'erb'
|
|
|
|
require_relative 'c_escape'
|
|
|
|
|
|
|
|
class RubyVM::Dumper
|
|
|
|
include RubyVM::CEscape
|
2018-01-12 03:38:11 -05:00
|
|
|
private
|
|
|
|
|
|
|
|
def new_binding
|
|
|
|
# This `eval 'binding'` does not return the current binding
|
|
|
|
# but creates one on top of it.
|
|
|
|
return eval 'binding'
|
|
|
|
end
|
|
|
|
|
|
|
|
def new_erb spec
|
2018-01-12 03:38:12 -05:00
|
|
|
path = Pathname.new(__FILE__).realpath.dirname
|
2018-01-12 03:38:11 -05:00
|
|
|
path += '../views'
|
|
|
|
path += spec
|
|
|
|
src = path.read mode: 'rt:utf-8:utf-8'
|
|
|
|
rescue Errno::ENOENT
|
|
|
|
raise "don't know how to generate #{path}"
|
|
|
|
else
|
2018-02-27 06:12:23 -05:00
|
|
|
if ERB.instance_method(:initialize).parameters.assoc(:key) # Ruby 2.6+
|
2018-02-22 08:28:25 -05:00
|
|
|
erb = ERB.new(src, trim_mode: '%-')
|
|
|
|
else
|
|
|
|
erb = ERB.new(src, nil, '%-')
|
|
|
|
end
|
2018-01-12 03:38:11 -05:00
|
|
|
erb.filename = path.realpath.to_path
|
|
|
|
return erb
|
|
|
|
end
|
2018-01-12 03:38:09 -05:00
|
|
|
|
2018-01-12 03:38:11 -05:00
|
|
|
def finderb spec
|
|
|
|
return @erb.fetch spec do |k|
|
|
|
|
erb = new_erb k
|
|
|
|
@erb[k] = erb
|
2018-01-12 03:38:09 -05:00
|
|
|
end
|
2018-01-12 03:38:11 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def replace_pragma_line str, lineno
|
|
|
|
if str == "#pragma RubyVM reset source\n" then
|
|
|
|
return "#line #{lineno + 2} #{@file}\n"
|
|
|
|
else
|
|
|
|
return str
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def local_variable_set bnd, var, val
|
|
|
|
eval '__locals__ ||= {}', bnd
|
|
|
|
locals = eval '__locals__', bnd
|
|
|
|
locals[var] = val
|
|
|
|
eval "#{var} = __locals__[:#{var}]", bnd
|
|
|
|
test = eval "#{var}", bnd
|
|
|
|
raise unless test == val
|
|
|
|
end
|
|
|
|
|
|
|
|
public
|
|
|
|
|
|
|
|
def do_render source, locals
|
|
|
|
erb = finderb source
|
|
|
|
bnd = @empty.dup
|
|
|
|
locals.each_pair do |k, v|
|
|
|
|
local_variable_set bnd, k, v
|
|
|
|
end
|
|
|
|
return erb.result bnd
|
|
|
|
end
|
|
|
|
|
|
|
|
def replace_pragma str
|
|
|
|
return str \
|
|
|
|
. each_line \
|
|
|
|
. with_index \
|
|
|
|
. map {|i, j| replace_pragma_line i, j } \
|
|
|
|
. join
|
|
|
|
end
|
2018-01-12 03:38:09 -05:00
|
|
|
|
2018-01-26 20:59:08 -05:00
|
|
|
def initialize dst
|
2018-01-12 03:38:09 -05:00
|
|
|
@erb = {}
|
|
|
|
@empty = new_binding
|
|
|
|
@file = cstr dst.realdirpath.to_path
|
|
|
|
end
|
|
|
|
|
2018-01-12 03:38:12 -05:00
|
|
|
def render partial, opts = { :locals => {} }
|
|
|
|
return do_render "_#{partial}.erb", opts[:locals]
|
2018-01-12 03:38:09 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def generate template
|
|
|
|
str = do_render "#{template}.erb", {}
|
|
|
|
return replace_pragma str
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
# view helpers
|
|
|
|
|
|
|
|
alias cstr rstring2cstr
|
|
|
|
alias comm commentify
|
|
|
|
|
|
|
|
def render_c_expr expr
|
|
|
|
render 'c_expr', locals: { expr: expr, }
|
|
|
|
end
|
|
|
|
end
|