180 lines
5.5 KiB
Plaintext
180 lines
5.5 KiB
Plaintext
|
#!/usr/bin/env ruby
|
||
|
|
||
|
###
|
||
|
### inline-require - expand 'require "foo"' into inline code
|
||
|
###
|
||
|
### usage: inline-require [-h] [-I path[,path2,..]] script
|
||
|
###
|
||
|
### copyright(c) 2006-2009 kuwata-lab.com all rights reserved.
|
||
|
### 2.6.5
|
||
|
### $Rev: 10 $
|
||
|
###
|
||
|
|
||
|
|
||
|
class InlineRequire
|
||
|
|
||
|
def initialize(opts={})
|
||
|
@opts = opts.dup
|
||
|
end
|
||
|
attr_accessor :opts
|
||
|
|
||
|
def expand(filename)
|
||
|
sbuf = ''
|
||
|
inlined = []
|
||
|
level = 0
|
||
|
expand_require(filename, sbuf, inlined, level)
|
||
|
return sbuf
|
||
|
end
|
||
|
|
||
|
private
|
||
|
|
||
|
def expand_require(filename, sbuf, inlined, level)
|
||
|
raise "*** assertion error" if inlined.include?(filename)
|
||
|
remove_comment = @opts[:remove_comment]
|
||
|
expand_indented = @opts[:expand_indented]
|
||
|
keep_filename = @opts[:keep_filename]
|
||
|
loaded_features = @opts[:loaded_features]
|
||
|
inlined << filename
|
||
|
prog = File.read(filename)
|
||
|
n = 0
|
||
|
flag_if_file = false
|
||
|
prog.each_line do |line|
|
||
|
n += 1
|
||
|
|
||
|
## comment out from 'if __FILE__ == $0' to 'end'
|
||
|
if level > 0
|
||
|
if flag_if_file
|
||
|
sbuf << "#" << line
|
||
|
flag_if_file = false if line =~ /^end$/
|
||
|
next
|
||
|
end
|
||
|
if line =~ /^if\s+__FILE__\s*==\s*\$0(\s+then)?$/ || line =~ /^if\s+\$0\s*==\s*__FILE__(\s+then)?$/
|
||
|
flag_if_file = true
|
||
|
sbuf << "#" << line
|
||
|
next
|
||
|
end
|
||
|
end
|
||
|
|
||
|
## find 'require "foo"' and expand it to inline code
|
||
|
flag_inline = false
|
||
|
pattern = expand_indented ? /^[ \t]*require ['"](.*)["']\s*$/ \
|
||
|
: /^require ['"](.*)["']\s*$/
|
||
|
if line =~ pattern
|
||
|
libname = $1
|
||
|
libpath = find_library(libname)
|
||
|
$stderr.puts "*** debug: libpath=#{libpath.inspect}" if $debug_mode
|
||
|
unless libpath
|
||
|
#raise "file '#{filename}'(line #{n}): library '#{libname}' not found."
|
||
|
warn "file '#{filename}'(line #{n}): library '#{libname}' not found."
|
||
|
else
|
||
|
flag_inline = true if libpath =~ /\.rb$/ && local_library?(libpath)
|
||
|
end
|
||
|
end
|
||
|
if !flag_inline
|
||
|
sbuf << line unless remove_comment && line =~ /^[ \t]*\#/
|
||
|
elsif inlined.include?(libpath)
|
||
|
sbuf << "#--already included #{line}" unless remove_comment
|
||
|
else
|
||
|
if keep_filename
|
||
|
@n ||= 0; @n += 1; n = @n
|
||
|
end
|
||
|
sbuf << "#--begin of #{line}" unless remove_comment
|
||
|
sbuf << "$LOADED_FEATURES << '#{libname}.rb'\n" if loaded_features
|
||
|
sbuf << "eval <<'END_OF_SCRIPT__#{n}', TOPLEVEL_BINDING, '#{libpath}', 1\n" if keep_filename
|
||
|
expand_require(libpath, sbuf, inlined, level+1)
|
||
|
sbuf << "END_OF_SCRIPT__#{n}\n" if keep_filename
|
||
|
sbuf << "#--end of #{line}" unless remove_comment
|
||
|
end
|
||
|
end
|
||
|
#sbuf << "\n" if sbuf[-1] != ?\n
|
||
|
end
|
||
|
|
||
|
def local_library?(libpath)
|
||
|
return libpath !~ /^\//
|
||
|
end
|
||
|
|
||
|
def find_library(libname)
|
||
|
if libname =~ /^\.rb$/
|
||
|
libname_rb = libname
|
||
|
libname_so = nil
|
||
|
elsif libname =~ /^\.so$/
|
||
|
libname_rb = nil
|
||
|
libname_so = libname
|
||
|
else
|
||
|
libname_rb = libname + ".rb"
|
||
|
libname_so = libname + ".so"
|
||
|
end
|
||
|
$LOAD_PATH.each do |path|
|
||
|
if libname_rb
|
||
|
libpath = path + "/" + libname_rb
|
||
|
return libpath if test(?f, libpath)
|
||
|
end
|
||
|
if libname_so
|
||
|
libpath = path + "/" + libname_so
|
||
|
return libpath if test(?f, libpath)
|
||
|
end
|
||
|
end
|
||
|
return nil
|
||
|
end
|
||
|
|
||
|
end
|
||
|
|
||
|
if __FILE__ == $0
|
||
|
|
||
|
begin
|
||
|
require "optparse"
|
||
|
op = OptionParser.new
|
||
|
options = {}
|
||
|
op.on("-h", "--help") {|v| options[:help] = v }
|
||
|
op.on("-I libpath") {|v| options[:libpath] = v }
|
||
|
op.on("-i") {|v| options[:expand_indented] = v }
|
||
|
op.on("-c") {|v| options[:remove_comment] = v }
|
||
|
op.on("-k") {|v| options[:keep_filename] = v }
|
||
|
op.on("-l") {|v| options[:loaded_features] = v }
|
||
|
op.on("-D") {|v| options[:debug] = v }
|
||
|
op.parse!()
|
||
|
|
||
|
$debug_mode = options[:debug]
|
||
|
|
||
|
if options[:help]
|
||
|
command = File.basename($0)
|
||
|
puts "Usage: #{command} [-h] [-I path[,path2,..]] script"
|
||
|
puts " -h : help"
|
||
|
puts " -i : expand indented require(), too"
|
||
|
puts " -c : remove comment lines start with '#'"
|
||
|
puts " -k : keep filename (for debugging)"
|
||
|
puts " -l : append libs to $LOADED_FEATURES"
|
||
|
puts " -I path[,path2,...] : ruby library path"
|
||
|
exit(0)
|
||
|
end
|
||
|
|
||
|
if options[:libpath]
|
||
|
rubylib_paths = options[:libpath].split(/,/)
|
||
|
else
|
||
|
rubylib_paths = []
|
||
|
end
|
||
|
$stderr.puts "*** debug: rubylib_paths=#{rubylib_paths.inspect}" if $debug_mode
|
||
|
$LOAD_PATH.concat(rubylib_paths)
|
||
|
|
||
|
filenames = ARGV
|
||
|
|
||
|
opts = { :expand_indented => options[:expand_indented],
|
||
|
:remove_comment => options[:remove_comment],
|
||
|
:keep_filename => options[:keep_filename],
|
||
|
:loaded_features => options[:loaded_features] }
|
||
|
inline_require = InlineRequire.new(opts)
|
||
|
filenames.each do |filename|
|
||
|
print inline_require.expand(filename)
|
||
|
end
|
||
|
|
||
|
rescue => ex
|
||
|
if $debug_mode
|
||
|
raise ex
|
||
|
else
|
||
|
$stderr.puts ex.message
|
||
|
end
|
||
|
|
||
|
end
|
||
|
|
||
|
end
|