erbse 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGES.txt +828 -0
- data/MIT-LICENSE +20 -0
- data/README.md +51 -0
- data/benchmark/Makefile +6 -0
- data/benchmark/bench.rb +313 -0
- data/benchmark/bench_context.yaml +141 -0
- data/benchmark/templates/_footer.html +4 -0
- data/benchmark/templates/_header.html +52 -0
- data/benchmark/templates/bench_erb.rhtml +29 -0
- data/benchmark/templates/bench_erubis.rhtml +29 -0
- data/benchmark/templates/bench_eruby.rhtml +29 -0
- data/bin/erubis +10 -0
- data/erbse.gemspec +24 -0
- data/lib/erbse.rb +52 -0
- data/lib/erbse/context.rb +83 -0
- data/lib/erbse/converter.rb +357 -0
- data/lib/erbse/engine.rb +114 -0
- data/lib/erbse/engine/ec.rb +117 -0
- data/lib/erbse/engine/ecpp.rb +113 -0
- data/lib/erbse/engine/ejava.rb +110 -0
- data/lib/erbse/engine/ejavascript.rb +119 -0
- data/lib/erbse/engine/enhanced.rb +126 -0
- data/lib/erbse/engine/eperl.rb +95 -0
- data/lib/erbse/engine/ephp.rb +99 -0
- data/lib/erbse/engine/eruby.rb +119 -0
- data/lib/erbse/engine/escheme.rb +114 -0
- data/lib/erbse/engine/optimized.rb +127 -0
- data/lib/erbse/enhancer.rb +723 -0
- data/lib/erbse/error.rb +23 -0
- data/lib/erbse/evaluator.rb +88 -0
- data/lib/erbse/generator.rb +85 -0
- data/lib/erbse/helper.rb +47 -0
- data/lib/erbse/helpers/rails_form_helper.rb +197 -0
- data/lib/erbse/helpers/rails_helper.rb +353 -0
- data/lib/erbse/main.rb +516 -0
- data/lib/erbse/preprocessing.rb +58 -0
- data/lib/erbse/tiny.rb +144 -0
- data/lib/erbse/util.rb +22 -0
- data/lib/erbse/version.rb +3 -0
- data/test/assert-text-equal.rb +44 -0
- data/test/data/users-guide/Example.ejava +55 -0
- data/test/data/users-guide/array_example.result +9 -0
- data/test/data/users-guide/arraybuffer_example.result +9 -0
- data/test/data/users-guide/bipattern-example.rhtml +4 -0
- data/test/data/users-guide/bipattern_example.result +6 -0
- data/test/data/users-guide/bufvar-example.rb +10 -0
- data/test/data/users-guide/bufvar-example.result +17 -0
- data/test/data/users-guide/context.rb +6 -0
- data/test/data/users-guide/context.yaml +8 -0
- data/test/data/users-guide/def_method.rb +14 -0
- data/test/data/users-guide/def_method.result +3 -0
- data/test/data/users-guide/escape_example.result +9 -0
- data/test/data/users-guide/example.ec +27 -0
- data/test/data/users-guide/example.ecpp +30 -0
- data/test/data/users-guide/example.ejs +20 -0
- data/test/data/users-guide/example.eperl +18 -0
- data/test/data/users-guide/example.ephp +18 -0
- data/test/data/users-guide/example.eruby +6 -0
- data/test/data/users-guide/example.escheme +28 -0
- data/test/data/users-guide/example1.eruby +6 -0
- data/test/data/users-guide/example1.rb +17 -0
- data/test/data/users-guide/example1.result +16 -0
- data/test/data/users-guide/example10.rb +4 -0
- data/test/data/users-guide/example10.result +17 -0
- data/test/data/users-guide/example10.xhtml +14 -0
- data/test/data/users-guide/example10_x.result +17 -0
- data/test/data/users-guide/example11.php +20 -0
- data/test/data/users-guide/example11.result +23 -0
- data/test/data/users-guide/example11.rhtml +21 -0
- data/test/data/users-guide/example11_C.result +10 -0
- data/test/data/users-guide/example11_N.result +16 -0
- data/test/data/users-guide/example11_U.result +16 -0
- data/test/data/users-guide/example11_php.result +15 -0
- data/test/data/users-guide/example1_x.result +9 -0
- data/test/data/users-guide/example2.eruby +7 -0
- data/test/data/users-guide/example2.rb +10 -0
- data/test/data/users-guide/example2.result +27 -0
- data/test/data/users-guide/example2_trim.result +10 -0
- data/test/data/users-guide/example2_x.result +10 -0
- data/test/data/users-guide/example3.eruby +6 -0
- data/test/data/users-guide/example3.rb +10 -0
- data/test/data/users-guide/example31.result +22 -0
- data/test/data/users-guide/example32.result +4 -0
- data/test/data/users-guide/example3_e.result +8 -0
- data/test/data/users-guide/example4.eruby +3 -0
- data/test/data/users-guide/example4.rb +11 -0
- data/test/data/users-guide/example4.result +10 -0
- data/test/data/users-guide/example4_x.result +5 -0
- data/test/data/users-guide/example5.eruby +6 -0
- data/test/data/users-guide/example5.rb +16 -0
- data/test/data/users-guide/example5.result +7 -0
- data/test/data/users-guide/example6.rb +12 -0
- data/test/data/users-guide/example6.result +7 -0
- data/test/data/users-guide/example7.eruby +8 -0
- data/test/data/users-guide/example71.result +13 -0
- data/test/data/users-guide/example72.result +13 -0
- data/test/data/users-guide/example8.eruby +6 -0
- data/test/data/users-guide/example8_ruby.result +7 -0
- data/test/data/users-guide/example8_yaml.result +7 -0
- data/test/data/users-guide/example9.eruby +3 -0
- data/test/data/users-guide/example9.rb +8 -0
- data/test/data/users-guide/example9.result +9 -0
- data/test/data/users-guide/example91.result +5 -0
- data/test/data/users-guide/example92.result +4 -0
- data/test/data/users-guide/example_c.result +32 -0
- data/test/data/users-guide/example_java.result +56 -0
- data/test/data/users-guide/example_js.result +22 -0
- data/test/data/users-guide/example_perl.result +20 -0
- data/test/data/users-guide/example_php.result +19 -0
- data/test/data/users-guide/example_scheme.result +30 -0
- data/test/data/users-guide/example_scheme_display.result +29 -0
- data/test/data/users-guide/fasteruby-example.rb +8 -0
- data/test/data/users-guide/fasteruby-example.result +18 -0
- data/test/data/users-guide/fasteruby.rb +11 -0
- data/test/data/users-guide/fasteruby.result +38 -0
- data/test/data/users-guide/fasteruby.rhtml +15 -0
- data/test/data/users-guide/headerfooter-example.eruby +9 -0
- data/test/data/users-guide/headerfooter-example2.rb +8 -0
- data/test/data/users-guide/headerfooter-example2.rhtml +10 -0
- data/test/data/users-guide/headerfooter_example.result +11 -0
- data/test/data/users-guide/headerfooter_example2.result +13 -0
- data/test/data/users-guide/interpolation_example.result +9 -0
- data/test/data/users-guide/main_program1.rb +8 -0
- data/test/data/users-guide/main_program1.result +6 -0
- data/test/data/users-guide/main_program2.rb +8 -0
- data/test/data/users-guide/main_program2.result +6 -0
- data/test/data/users-guide/nocode-example.eruby +14 -0
- data/test/data/users-guide/nocode-php.result +20 -0
- data/test/data/users-guide/nocode_example.result +15 -0
- data/test/data/users-guide/normal-eruby-test.eruby +9 -0
- data/test/data/users-guide/normal_eruby_test.result +11 -0
- data/test/data/users-guide/notext-example.eruby +14 -0
- data/test/data/users-guide/notext-example.php +19 -0
- data/test/data/users-guide/notext-php.result +20 -0
- data/test/data/users-guide/notext_example.result +16 -0
- data/test/data/users-guide/percentline-example.rhtml +6 -0
- data/test/data/users-guide/percentline_example.result +9 -0
- data/test/data/users-guide/prefixedline-example.rb +9 -0
- data/test/data/users-guide/prefixedline-example.rhtml +6 -0
- data/test/data/users-guide/prefixedline_example.result +9 -0
- data/test/data/users-guide/printenable_example.result +4 -0
- data/test/data/users-guide/printenabled-example.eruby +3 -0
- data/test/data/users-guide/printenabled-example.rb +8 -0
- data/test/data/users-guide/printstatement_example.result +8 -0
- data/test/data/users-guide/simplify_example.result +9 -0
- data/test/data/users-guide/stderr.log +3 -0
- data/test/data/users-guide/stdout_exmple.result +9 -0
- data/test/data/users-guide/stringbuffer_example.result +9 -0
- data/test/data/users-guide/tail_260.result +4 -0
- data/test/data/users-guide/tailnewline.rhtml +3 -0
- data/test/data/users-guide/template1.rhtml +4 -0
- data/test/data/users-guide/template2.rhtml +4 -0
- data/test/test-engines.rb +425 -0
- data/test/test-enhancers.rb +646 -0
- data/test/test-erubis.rb +887 -0
- data/test/test-index-cgi.rb +191 -0
- data/test/test-main.rb +752 -0
- data/test/test-users-guide.rb +73 -0
- data/test/test.rb +45 -0
- data/test/testutil.rb +111 -0
- metadata +233 -0
data/lib/erbse/main.rb
ADDED
@@ -0,0 +1,516 @@
|
|
1
|
+
###
|
2
|
+
### $Release: 2.7.0 $
|
3
|
+
### copyright(c) 2006-2011 kuwata-lab.com all rights reserved.
|
4
|
+
###
|
5
|
+
|
6
|
+
require 'yaml'
|
7
|
+
require 'erubis'
|
8
|
+
require 'erubis/tiny'
|
9
|
+
require 'erubis/engine/enhanced'
|
10
|
+
require 'erubis/engine/optimized'
|
11
|
+
require 'erubis/engine/eruby'
|
12
|
+
require 'erubis/engine/ephp'
|
13
|
+
require 'erubis/engine/ec'
|
14
|
+
require 'erubis/engine/ecpp'
|
15
|
+
require 'erubis/engine/ejava'
|
16
|
+
require 'erubis/engine/escheme'
|
17
|
+
require 'erubis/engine/eperl'
|
18
|
+
require 'erubis/engine/ejavascript'
|
19
|
+
|
20
|
+
|
21
|
+
module Erubis
|
22
|
+
|
23
|
+
|
24
|
+
Ejs = Ejavascript
|
25
|
+
EscapedEjs = EscapedEjavascript
|
26
|
+
|
27
|
+
|
28
|
+
class CommandOptionError < ErubisError
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
##
|
33
|
+
## main class of command
|
34
|
+
##
|
35
|
+
## ex.
|
36
|
+
## Main.main(ARGV)
|
37
|
+
##
|
38
|
+
class Main
|
39
|
+
|
40
|
+
def self.main(argv=ARGV)
|
41
|
+
status = 0
|
42
|
+
begin
|
43
|
+
Main.new.execute(ARGV)
|
44
|
+
rescue CommandOptionError => ex
|
45
|
+
$stderr.puts ex.message
|
46
|
+
status = 1
|
47
|
+
end
|
48
|
+
exit(status)
|
49
|
+
end
|
50
|
+
|
51
|
+
def initialize
|
52
|
+
@single_options = "hvxztTSbeBXNUC"
|
53
|
+
@arg_options = "pcrfKIlaE" #C
|
54
|
+
@option_names = {
|
55
|
+
'h' => :help,
|
56
|
+
'v' => :version,
|
57
|
+
'x' => :source,
|
58
|
+
'z' => :syntax,
|
59
|
+
'T' => :unexpand,
|
60
|
+
't' => :untabify, # obsolete
|
61
|
+
'S' => :intern,
|
62
|
+
'b' => :bodyonly,
|
63
|
+
'B' => :binding,
|
64
|
+
'p' => :pattern,
|
65
|
+
'c' => :context,
|
66
|
+
#'C' => :class,
|
67
|
+
'e' => :escape,
|
68
|
+
'r' => :requires,
|
69
|
+
'f' => :datafiles,
|
70
|
+
'K' => :kanji,
|
71
|
+
'I' => :includes,
|
72
|
+
'l' => :lang,
|
73
|
+
'a' => :action,
|
74
|
+
'E' => :enhancers,
|
75
|
+
'X' => :notext,
|
76
|
+
'N' => :linenum,
|
77
|
+
'U' => :unique,
|
78
|
+
'C' => :compact,
|
79
|
+
}
|
80
|
+
assert unless @single_options.length + @arg_options.length == @option_names.length
|
81
|
+
(@single_options + @arg_options).each_byte do |ch|
|
82
|
+
assert unless @option_names.key?(ch.chr)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
|
87
|
+
def execute(argv=ARGV)
|
88
|
+
## parse command-line options
|
89
|
+
options, properties = parse_argv(argv, @single_options, @arg_options)
|
90
|
+
filenames = argv
|
91
|
+
options['h'] = true if properties[:help]
|
92
|
+
opts = Object.new
|
93
|
+
arr = @option_names.collect {|ch, name| "def #{name}; @#{name}; end\n" }
|
94
|
+
opts.instance_eval arr.join
|
95
|
+
options.each do |ch, val|
|
96
|
+
name = @option_names[ch]
|
97
|
+
opts.instance_variable_set("@#{name}", val)
|
98
|
+
end
|
99
|
+
|
100
|
+
## help, version, enhancer list
|
101
|
+
if opts.help || opts.version
|
102
|
+
puts version() if opts.version
|
103
|
+
puts usage() if opts.help
|
104
|
+
puts show_properties() if opts.help
|
105
|
+
puts show_enhancers() if opts.help
|
106
|
+
return
|
107
|
+
end
|
108
|
+
|
109
|
+
## include path
|
110
|
+
opts.includes.split(/,/).each do |path|
|
111
|
+
$: << path
|
112
|
+
end if opts.includes
|
113
|
+
|
114
|
+
## require library
|
115
|
+
opts.requires.split(/,/).each do |library|
|
116
|
+
require library
|
117
|
+
end if opts.requires
|
118
|
+
|
119
|
+
## action
|
120
|
+
action = opts.action
|
121
|
+
action ||= 'syntax' if opts.syntax
|
122
|
+
action ||= 'convert' if opts.source || opts.notext
|
123
|
+
|
124
|
+
## lang
|
125
|
+
lang = opts.lang || 'ruby'
|
126
|
+
action ||= 'convert' if opts.lang
|
127
|
+
|
128
|
+
## class name of Eruby
|
129
|
+
#classname = opts.class
|
130
|
+
classname = nil
|
131
|
+
klass = get_classobj(classname, lang, properties[:pi])
|
132
|
+
|
133
|
+
## kanji code
|
134
|
+
$KCODE = opts.kanji if opts.kanji
|
135
|
+
|
136
|
+
## read context values from yaml file
|
137
|
+
datafiles = opts.datafiles
|
138
|
+
context = load_datafiles(datafiles, opts)
|
139
|
+
|
140
|
+
## parse context data
|
141
|
+
if opts.context
|
142
|
+
context = parse_context_data(opts.context, opts)
|
143
|
+
end
|
144
|
+
|
145
|
+
## properties for engine
|
146
|
+
properties[:escape] = true if opts.escape && !properties.key?(:escape)
|
147
|
+
properties[:pattern] = opts.pattern if opts.pattern
|
148
|
+
#properties[:trim] = false if opts.notrim
|
149
|
+
properties[:preamble] = properties[:postamble] = false if opts.bodyonly
|
150
|
+
properties[:pi] = nil if properties[:pi] == true
|
151
|
+
|
152
|
+
## create engine and extend enhancers
|
153
|
+
engine = klass.new(nil, properties)
|
154
|
+
enhancers = get_enhancers(opts.enhancers)
|
155
|
+
#enhancers.push(Erubis::EscapeEnhancer) if opts.escape
|
156
|
+
enhancers.each do |enhancer|
|
157
|
+
engine.extend(enhancer)
|
158
|
+
engine.bipattern = properties[:bipattern] if enhancer == Erubis::BiPatternEnhancer
|
159
|
+
end
|
160
|
+
|
161
|
+
## no-text
|
162
|
+
engine.extend(Erubis::NoTextEnhancer) if opts.notext
|
163
|
+
|
164
|
+
## convert and execute
|
165
|
+
val = nil
|
166
|
+
msg = "Syntax OK\n"
|
167
|
+
if filenames && !filenames.empty?
|
168
|
+
filenames.each do |filename|
|
169
|
+
File.file?(filename) or
|
170
|
+
raise CommandOptionError.new("#{filename}: file not found.")
|
171
|
+
engine.filename = filename
|
172
|
+
engine.convert!(File.read(filename))
|
173
|
+
val = do_action(action, engine, context, filename, opts)
|
174
|
+
msg = nil if val
|
175
|
+
end
|
176
|
+
else
|
177
|
+
engine.filename = filename = '(stdin)'
|
178
|
+
engine.convert!($stdin.read())
|
179
|
+
val = do_action(action, engine, context, filename, opts)
|
180
|
+
msg = nil if val
|
181
|
+
end
|
182
|
+
print msg if action == 'syntax' && msg
|
183
|
+
|
184
|
+
end
|
185
|
+
|
186
|
+
private
|
187
|
+
|
188
|
+
def do_action(action, engine, context, filename, opts)
|
189
|
+
case action
|
190
|
+
when 'convert'
|
191
|
+
s = manipulate_src(engine.src, opts)
|
192
|
+
when nil, 'exec', 'execute'
|
193
|
+
s = opts.binding ? engine.result(context.to_hash) : engine.evaluate(context)
|
194
|
+
when 'syntax'
|
195
|
+
s = check_syntax(filename, engine.src)
|
196
|
+
else
|
197
|
+
raise "*** internal error"
|
198
|
+
end
|
199
|
+
print s if s
|
200
|
+
return s
|
201
|
+
end
|
202
|
+
|
203
|
+
def manipulate_src(source, opts)
|
204
|
+
flag_linenum = opts.linenum
|
205
|
+
flag_unique = opts.unique
|
206
|
+
flag_compact = opts.compact
|
207
|
+
if flag_linenum
|
208
|
+
n = 0
|
209
|
+
source.gsub!(/^/) { n += 1; "%5d: " % n }
|
210
|
+
source.gsub!(/^ *\d+:\s+?\n/, '') if flag_compact
|
211
|
+
source.gsub!(/(^ *\d+:\s+?\n)+/, "\n") if flag_unique
|
212
|
+
else
|
213
|
+
source.gsub!(/^\s*?\n/, '') if flag_compact
|
214
|
+
source.gsub!(/(^\s*?\n)+/, "\n") if flag_unique
|
215
|
+
end
|
216
|
+
return source
|
217
|
+
end
|
218
|
+
|
219
|
+
def usage(command=nil)
|
220
|
+
command ||= File.basename($0)
|
221
|
+
buf = []
|
222
|
+
buf << "erubis - embedded program converter for multi-language"
|
223
|
+
buf << "Usage: #{command} [..options..] [file ...]"
|
224
|
+
buf << " -h, --help : help"
|
225
|
+
buf << " -v : version"
|
226
|
+
buf << " -x : show converted code"
|
227
|
+
buf << " -X : show converted code, only ruby code and no text part"
|
228
|
+
buf << " -N : numbering: add line numbers (for '-x/-X')"
|
229
|
+
buf << " -U : unique: compress empty lines to a line (for '-x/-X')"
|
230
|
+
buf << " -C : compact: remove empty lines (for '-x/-X')"
|
231
|
+
buf << " -b : body only: no preamble nor postamble (for '-x/-X')"
|
232
|
+
buf << " -z : syntax checking"
|
233
|
+
buf << " -e : escape (equal to '--E Escape')"
|
234
|
+
buf << " -p pattern : embedded pattern (default '<% %>')"
|
235
|
+
buf << " -l lang : convert but no execute (ruby/php/c/cpp/java/scheme/perl/js)"
|
236
|
+
buf << " -E e1,e2,... : enhancer names (Escape, PercentLine, BiPattern, ...)"
|
237
|
+
buf << " -I path : library include path"
|
238
|
+
buf << " -K kanji : kanji code (euc/sjis/utf8) (default none)"
|
239
|
+
buf << " -c context : context data string (yaml inline style or ruby code)"
|
240
|
+
buf << " -f datafile : context data file ('*.yaml', '*.yml', or '*.rb')"
|
241
|
+
#buf << " -t : expand tab characters in YAML file"
|
242
|
+
buf << " -T : don't expand tab characters in YAML file"
|
243
|
+
buf << " -S : convert mapping key from string to symbol in YAML file"
|
244
|
+
buf << " -B : invoke 'result(binding)' instead of 'evaluate(context)'"
|
245
|
+
buf << " --pi=name : parse '<?name ... ?>' instead of '<% ... %>'"
|
246
|
+
#'
|
247
|
+
# -T : don't trim spaces around '<% %>'
|
248
|
+
# -c class : class name (XmlEruby/PercentLineEruby/...) (default Eruby)
|
249
|
+
# -r library : require library
|
250
|
+
# -a : action (convert/execute)
|
251
|
+
return buf.join("\n")
|
252
|
+
end
|
253
|
+
|
254
|
+
def collect_supported_properties(erubis_klass)
|
255
|
+
list = []
|
256
|
+
erubis_klass.ancestors.each do |klass|
|
257
|
+
if klass.respond_to?(:supported_properties)
|
258
|
+
list.concat(klass.supported_properties)
|
259
|
+
end
|
260
|
+
end
|
261
|
+
return list
|
262
|
+
end
|
263
|
+
|
264
|
+
def show_properties
|
265
|
+
s = "supported properties:\n"
|
266
|
+
basic_props = collect_supported_properties(Erubis::Basic::Engine)
|
267
|
+
pi_props = collect_supported_properties(Erubis::PI::Engine)
|
268
|
+
list = []
|
269
|
+
common_props = basic_props & pi_props
|
270
|
+
list << ['(common)', common_props]
|
271
|
+
list << ['(basic)', basic_props - common_props]
|
272
|
+
list << ['(pi)', pi_props - common_props]
|
273
|
+
%w[ruby php c cpp java scheme perl javascript].each do |lang|
|
274
|
+
klass = Erubis.const_get("E#{lang}")
|
275
|
+
list << [lang, collect_supported_properties(klass) - basic_props]
|
276
|
+
end
|
277
|
+
list.each do |lang, props|
|
278
|
+
s << " * #{lang}\n"
|
279
|
+
props.each do |name, default_val, desc|
|
280
|
+
s << (" --%-23s : %s\n" % ["#{name}=#{default_val.inspect}", desc])
|
281
|
+
end
|
282
|
+
end
|
283
|
+
s << "\n"
|
284
|
+
return s
|
285
|
+
end
|
286
|
+
|
287
|
+
def show_enhancers
|
288
|
+
dict = {}
|
289
|
+
ObjectSpace.each_object(Module) do |mod|
|
290
|
+
dict[$1] = mod if mod.name =~ /\AErubis::(.*)Enhancer\z/
|
291
|
+
end
|
292
|
+
s = "enhancers:\n"
|
293
|
+
dict.sort_by {|name, mod| name }.each do |name, mod|
|
294
|
+
s << (" %-13s : %s\n" % [name, mod.desc])
|
295
|
+
end
|
296
|
+
return s
|
297
|
+
end
|
298
|
+
|
299
|
+
def version
|
300
|
+
return Erubis::VERSION
|
301
|
+
end
|
302
|
+
|
303
|
+
def parse_argv(argv, arg_none='', arg_required='', arg_optional='')
|
304
|
+
options = {}
|
305
|
+
context = {}
|
306
|
+
while argv[0] && argv[0][0] == ?-
|
307
|
+
optstr = argv.shift
|
308
|
+
optstr = optstr[1, optstr.length-1]
|
309
|
+
#
|
310
|
+
if optstr[0] == ?- # context
|
311
|
+
optstr =~ /\A\-([-\w]+)(?:=(.*))?/ or
|
312
|
+
raise CommandOptionError.new("-#{optstr}: invalid context value.")
|
313
|
+
name, value = $1, $2
|
314
|
+
name = name.gsub(/-/, '_').intern
|
315
|
+
#value = value.nil? ? true : YAML.load(value) # error, why?
|
316
|
+
value = value.nil? ? true : YAML.load("---\n#{value}\n")
|
317
|
+
context[name] = value
|
318
|
+
#
|
319
|
+
else # options
|
320
|
+
while optstr && !optstr.empty?
|
321
|
+
optchar = optstr[0].chr
|
322
|
+
optstr = optstr[1..-1]
|
323
|
+
if arg_none.include?(optchar)
|
324
|
+
options[optchar] = true
|
325
|
+
elsif arg_required.include?(optchar)
|
326
|
+
arg = optstr.empty? ? argv.shift : optstr or
|
327
|
+
raise CommandOptionError.new("-#{optchar}: #{@option_names[optchar]} required.")
|
328
|
+
options[optchar] = arg
|
329
|
+
optstr = nil
|
330
|
+
elsif arg_optional.include?(optchar)
|
331
|
+
arg = optstr.empty? ? true : optstr
|
332
|
+
options[optchar] = arg
|
333
|
+
optstr = nil
|
334
|
+
else
|
335
|
+
raise CommandOptionError.new("-#{optchar}: unknown option.")
|
336
|
+
end
|
337
|
+
end
|
338
|
+
end
|
339
|
+
#
|
340
|
+
end # end of while
|
341
|
+
|
342
|
+
return options, context
|
343
|
+
end
|
344
|
+
|
345
|
+
|
346
|
+
def untabify(str, width=8)
|
347
|
+
list = str.split(/\t/)
|
348
|
+
last = list.pop
|
349
|
+
sb = ''
|
350
|
+
list.each do |s|
|
351
|
+
column = (n = s.rindex(?\n)) ? s.length - n - 1 : s.length
|
352
|
+
n = width - (column % width)
|
353
|
+
sb << s << (' ' * n)
|
354
|
+
end
|
355
|
+
sb << last
|
356
|
+
return sb
|
357
|
+
end
|
358
|
+
#--
|
359
|
+
#def untabify(str, width=8)
|
360
|
+
# sb = ''
|
361
|
+
# str.scan(/(.*?)\t/m) do |s, |
|
362
|
+
# len = (n = s.rindex(?\n)) ? s.length - n - 1 : s.length
|
363
|
+
# sb << s << (" " * (width - len % width))
|
364
|
+
# end
|
365
|
+
# return $' ? (sb << $') : str
|
366
|
+
#end
|
367
|
+
#++
|
368
|
+
|
369
|
+
|
370
|
+
def get_classobj(classname, lang, pi)
|
371
|
+
classname ||= "E#{lang}"
|
372
|
+
base_module = pi ? Erubis::PI : Erubis
|
373
|
+
begin
|
374
|
+
klass = base_module.const_get(classname)
|
375
|
+
rescue NameError
|
376
|
+
klass = nil
|
377
|
+
end
|
378
|
+
unless klass
|
379
|
+
if lang
|
380
|
+
msg = "-l #{lang}: invalid language name (class #{base_module.name}::#{classname} not found)."
|
381
|
+
else
|
382
|
+
msg = "-c #{classname}: invalid class name."
|
383
|
+
end
|
384
|
+
raise CommandOptionError.new(msg)
|
385
|
+
end
|
386
|
+
return klass
|
387
|
+
end
|
388
|
+
|
389
|
+
def get_enhancers(enhancer_names)
|
390
|
+
return [] unless enhancer_names
|
391
|
+
enhancers = []
|
392
|
+
shortname = nil
|
393
|
+
begin
|
394
|
+
enhancer_names.split(/,/).each do |name|
|
395
|
+
shortname = name
|
396
|
+
enhancers << Erubis.const_get("#{shortname}Enhancer")
|
397
|
+
end
|
398
|
+
rescue NameError
|
399
|
+
raise CommandOptionError.new("#{shortname}: no such Enhancer (try '-h' to show all enhancers).")
|
400
|
+
end
|
401
|
+
return enhancers
|
402
|
+
end
|
403
|
+
|
404
|
+
def load_datafiles(filenames, opts)
|
405
|
+
context = Erubis::Context.new
|
406
|
+
return context unless filenames
|
407
|
+
filenames.split(/,/).each do |filename|
|
408
|
+
filename.strip!
|
409
|
+
test(?f, filename) or raise CommandOptionError.new("#{filename}: file not found.")
|
410
|
+
if filename =~ /\.ya?ml$/
|
411
|
+
if opts.unexpand
|
412
|
+
ydoc = YAML.load_file(filename)
|
413
|
+
else
|
414
|
+
ydoc = YAML.load(untabify(File.read(filename)))
|
415
|
+
end
|
416
|
+
ydoc.is_a?(Hash) or raise CommandOptionError.new("#{filename}: root object is not a mapping.")
|
417
|
+
intern_hash_keys(ydoc) if opts.intern
|
418
|
+
context.update(ydoc)
|
419
|
+
elsif filename =~ /\.rb$/
|
420
|
+
str = File.read(filename)
|
421
|
+
context2 = Erubis::Context.new
|
422
|
+
_instance_eval(context2, str)
|
423
|
+
context.update(context2)
|
424
|
+
else
|
425
|
+
CommandOptionError.new("#{filename}: '*.yaml', '*.yml', or '*.rb' required.")
|
426
|
+
end
|
427
|
+
end
|
428
|
+
return context
|
429
|
+
end
|
430
|
+
|
431
|
+
def _instance_eval(_context, _str)
|
432
|
+
_context.instance_eval(_str)
|
433
|
+
end
|
434
|
+
|
435
|
+
def parse_context_data(context_str, opts)
|
436
|
+
if context_str[0] == ?{
|
437
|
+
require 'yaml'
|
438
|
+
ydoc = YAML.load(context_str)
|
439
|
+
unless ydoc.is_a?(Hash)
|
440
|
+
raise CommandOptionError.new("-c: root object is not a mapping.")
|
441
|
+
end
|
442
|
+
intern_hash_keys(ydoc) if opts.intern
|
443
|
+
return ydoc
|
444
|
+
else
|
445
|
+
context = Erubis::Context.new
|
446
|
+
context.instance_eval(context_str, '-c')
|
447
|
+
return context
|
448
|
+
end
|
449
|
+
end
|
450
|
+
|
451
|
+
def intern_hash_keys(obj, done={})
|
452
|
+
return if done.key?(obj.__id__)
|
453
|
+
case obj
|
454
|
+
when Hash
|
455
|
+
done[obj.__id__] = obj
|
456
|
+
obj.keys.each do |key|
|
457
|
+
obj[key.intern] = obj.delete(key) if key.is_a?(String)
|
458
|
+
end
|
459
|
+
obj.values.each do |val|
|
460
|
+
intern_hash_keys(val, done) if val.is_a?(Hash) || val.is_a?(Array)
|
461
|
+
end
|
462
|
+
when Array
|
463
|
+
done[obj.__id__] = obj
|
464
|
+
obj.each do |val|
|
465
|
+
intern_hash_keys(val, done) if val.is_a?(Hash) || val.is_a?(Array)
|
466
|
+
end
|
467
|
+
end
|
468
|
+
end
|
469
|
+
|
470
|
+
def check_syntax(filename, src)
|
471
|
+
require 'open3'
|
472
|
+
#command = (ENV['_'] || 'ruby') + ' -wc' # ENV['_'] stores command name
|
473
|
+
bin = ENV['_'] && File.basename(ENV['_']) =~ /^ruby/ ? ENV['_'] : 'ruby'
|
474
|
+
command = bin + ' -wc'
|
475
|
+
stdin, stdout, stderr = Open3.popen3(command)
|
476
|
+
stdin.write(src)
|
477
|
+
stdin.close
|
478
|
+
result = stdout.read()
|
479
|
+
stdout.close()
|
480
|
+
errmsg = stderr.read()
|
481
|
+
stderr.close()
|
482
|
+
return nil unless errmsg && !errmsg.empty?
|
483
|
+
errmsg =~ /\A-:(\d+): /
|
484
|
+
linenum, message = $1, $'
|
485
|
+
return "#{filename}:#{linenum}: #{message}"
|
486
|
+
end
|
487
|
+
|
488
|
+
if defined?(RUBY_ENGINE) && RUBY_ENGINE == "rbx"
|
489
|
+
def check_syntax(filename, src)
|
490
|
+
require 'compiler'
|
491
|
+
verbose = $VERBOSE
|
492
|
+
msg = nil
|
493
|
+
begin
|
494
|
+
$VERBOSE = true
|
495
|
+
Rubinius::Compiler.compile_string(src, filename)
|
496
|
+
rescue SyntaxError => ex
|
497
|
+
ex_linenum = ex.line
|
498
|
+
linenum = 0
|
499
|
+
srcline = src.each_line do |line|
|
500
|
+
linenum += 1
|
501
|
+
break line if linenum == ex_linenum
|
502
|
+
end
|
503
|
+
msg = "#{ex.message}\n"
|
504
|
+
msg << srcline
|
505
|
+
msg << "\n" unless srcline =~ /\n\z/
|
506
|
+
msg << (" " * (ex.column-1)) << "^\n"
|
507
|
+
ensure
|
508
|
+
$VERBOSE = verbose
|
509
|
+
end
|
510
|
+
return msg
|
511
|
+
end
|
512
|
+
end
|
513
|
+
|
514
|
+
end
|
515
|
+
|
516
|
+
end
|