Class Erubis::Main
In: lib/erubis/main.rb
Parent: Object
Eruby\n[lib/erubis/engine/eruby.rb\nlib/erubis/helpers/rails_helper.rb] PreprocessingEruby XmlEruby HeaderFooterEruby PrintEnabledEruby StdoutEruby FastEruby\n[lib/erubis/engine/eruby.rb\nlib/erubis/helpers/rails_helper.rb] StringBufferEruby BiPatternEruby InterpolationEruby PercentLineEruby PrintOutSimplifiedEruby NoTextEruby ErboutEruby StringIOEruby ArrayEruby PrintOutEruby SimplifiedEruby EscapedEruby DeleteIndentEruby StdoutSimplifiedEruby NoCodeEruby ArrayBufferEruby PreprocessingEruby OptimizedEruby Engine Ejava Ephp Eperl Ec Ejavascript Escheme EscapedEjava EscapedEphp EscapedEc OptimizedXmlEruby EscapedEperl EscapedEjavascript EscapedEscheme ErubisError NotSupportedError CommandOptionError Enumerable Context StandardError RubyEvaluator Eruby RubyGenerator PI::Engine Ejava Eperl Ec Ejavascript Escheme Ephp JavaGenerator Evaluator Engine PI::Converter Generator PerlGenerator CGenerator JavascriptGenerator SchemeGenerator PhpGenerator Basic::Converter Main Engine TinyEruby TinyEruby lib/erubis/engine/escheme.rb lib/erubis/engine/ec.rb lib/erubis/engine/eperl.rb lib/erubis/engine/eruby.rb lib/erubis/engine/ephp.rb lib/erubis/helpers/rails_helper.rb lib/erubis/preprocessing.rb lib/erubis/error.rb lib/erubis/engine/ejava.rb lib/erubis/engine/ejavascript.rb lib/erubis/context.rb lib/erubis/engine/optimized.rb lib/erubis/main.rb lib/erubis/engine/enhanced.rb lib/erubis/engine.rb lib/erubis/tiny.rb NoCodeEnhancer ArrayBufferEnhancer Generator StringBufferEnhancer OptimizedGenerator SchemeGenerator lib/erubis/engine/escheme.rb lib/erubis/engine/ec.rb lib/erubis/engine/eperl.rb lib/erubis/engine/eruby.rb lib/erubis/engine/ephp.rb lib/erubis/engine/ejava.rb lib/erubis/engine/ejavascript.rb lib/erubis/engine.rb lib/erubis/tiny.rb Converter PI SimplifyEnhancer StdoutEnhancer Converter lib/erubis/helpers/rails_helper.rb TemplateConverter RailsHelper RailsFormHelper Helpers XmlHelper HeaderFooterEnhancer RubyGenerator PhpGenerator CGenerator lib/erubis/engine.rb Converter Basic PreprocessingHelper Evaluator BiPatternEnhancer PrintEnabledEnhancer PerlGenerator JavascriptGenerator PercentLineEnhancer NoTextEnhancer ErboutEnhancer PrintOutEnhancer EscapeEnhancer JavaGenerator DeleteIndentEnhancer StringIOEnhancer ArrayEnhancer RubyEvaluator InterpolationEnhancer Erubis dot/m_23_0.png

main class of command

ex.

  Main.main(ARGV)

Methods

Public Class methods

[Source]

    # File lib/erubis/main.rb, line 40
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

[Source]

    # File lib/erubis/main.rb, line 51
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

Public Instance methods

[Source]

     # File lib/erubis/main.rb, line 87
 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:           test(?f, filename)  or raise CommandOptionError.new("#{filename}: file not found.")
170:           engine.filename = filename
171:           engine.convert!(File.read(filename))
172:           val = do_action(action, engine, context, filename, opts)
173:           msg = nil if val
174:         end
175:       else
176:         engine.filename = filename = '(stdin)'
177:         engine.convert!($stdin.read())
178:         val = do_action(action, engine, context, filename, opts)
179:         msg = nil if val
180:       end
181:       print msg if action == 'syntax' && msg
182: 
183:     end

Private Instance methods

[Source]

     # File lib/erubis/main.rb, line 434
434:     def _instance_eval(_context, _str)
435:       _context.instance_eval(_str)
436:     end

[Source]

     # File lib/erubis/main.rb, line 473
473:     def check_syntax(filename, src)
474:       require 'open3'
475:       command = (ENV['_'] || 'ruby') + ' -wc'   # ENV['_'] stores command name
476:       stdin, stdout, stderr = Open3.popen3(command)
477:       stdin.write(src)
478:       stdin.close
479:       result = stdout.read()
480:       stdout.close()
481:       errmsg = stderr.read()
482:       stderr.close()
483:       return nil unless errmsg && !errmsg.empty?
484:       errmsg =~ /\A-:(\d+): /
485:       linenum, message = $1, $'
486:       return "#{filename}:#{linenum}: #{message}"
487:     end

[Source]

     # File lib/erubis/main.rb, line 253
253:     def collect_supported_properties(erubis_klass)
254:       list = []
255:       erubis_klass.ancestors.each do |klass|
256:         if klass.respond_to?(:supported_properties)
257:           list.concat(klass.supported_properties)
258:         end
259:       end
260:       return list
261:     end

[Source]

     # File lib/erubis/main.rb, line 187
187:     def do_action(action, engine, context, filename, opts)
188:       case action
189:       when 'convert'
190:         s = manipulate_src(engine.src, opts)
191:       when nil, 'exec', 'execute'
192:         s = opts.binding ? engine.result(context.to_hash) : engine.evaluate(context)
193:       when 'syntax'
194:         s = check_syntax(filename, engine.src)
195:       else
196:         raise "*** internal error"
197:       end
198:       print s if s
199:       return s
200:     end

[Source]

     # File lib/erubis/main.rb, line 374
374:     def get_classobj(classname, lang, pi)
375:       classname ||= "E#{lang}"
376:       base_module = pi ? Erubis::PI : Erubis
377:       begin
378:         klass = base_module.const_get(classname)
379:       rescue NameError
380:         klass = nil
381:       end
382:       unless klass
383:         if lang
384:           msg = "-l #{lang}: invalid language name (class #{base_module.name}::#{classname} not found)."
385:         else
386:           msg = "-c #{classname}: invalid class name."
387:         end
388:         raise CommandOptionError.new(msg)
389:       end
390:       return klass
391:     end

[Source]

     # File lib/erubis/main.rb, line 393
393:     def get_enhancers(enhancer_names)
394:       return [] unless enhancer_names
395:       enhancers = []
396:       shortname = nil
397:       begin
398:         enhancer_names.split(/,/).each do |shortname|
399:           enhancers << Erubis.const_get("#{shortname}Enhancer")
400:         end
401:       rescue NameError
402:         raise CommandOptionError.new("#{shortname}: no such Enhancer (try '-E' to show all enhancers).")
403:       end
404:       return enhancers
405:     end

[Source]

     # File lib/erubis/main.rb, line 454
454:     def intern_hash_keys(obj, done={})
455:       return if done.key?(obj.__id__)
456:       case obj
457:       when Hash
458:         done[obj.__id__] = obj
459:         obj.keys.each do |key|
460:           obj[key.intern] = obj.delete(key) if key.is_a?(String)
461:         end
462:         obj.values.each do |val|
463:           intern_hash_keys(val, done) if val.is_a?(Hash) || val.is_a?(Array)
464:         end
465:       when Array
466:         done[obj.__id__] = obj
467:         obj.each do |val|
468:           intern_hash_keys(val, done) if val.is_a?(Hash) || val.is_a?(Array)
469:         end
470:       end
471:     end

[Source]

     # File lib/erubis/main.rb, line 407
407:     def load_datafiles(filenames, opts)
408:       context = Erubis::Context.new
409:       return context unless filenames
410:       filenames.split(/,/).each do |filename|
411:         filename.strip!
412:         test(?f, filename) or raise CommandOptionError.new("#{filename}: file not found.")
413:         if filename =~ /\.ya?ml$/
414:           if opts.unexpand
415:             ydoc = YAML.load_file(filename)
416:           else
417:             ydoc = YAML.load(untabify(File.read(filename)))
418:           end
419:           ydoc.is_a?(Hash) or raise CommandOptionError.new("#{filename}: root object is not a mapping.")
420:           intern_hash_keys(ydoc) if opts.intern
421:           context.update(ydoc)
422:         elsif filename =~ /\.rb$/
423:           str = File.read(filename)
424:           context2 = Erubis::Context.new
425:           _instance_eval(context2, str)
426:           context.update(context2)
427:         else
428:           CommandOptionError.new("#{filename}: '*.yaml', '*.yml', or '*.rb' required.")
429:         end
430:       end
431:       return context
432:     end

[Source]

     # File lib/erubis/main.rb, line 202
202:     def manipulate_src(source, opts)
203:       flag_linenum   = opts.linenum
204:       flag_unique    = opts.unique
205:       flag_compact   = opts.compact
206:       if flag_linenum
207:         n = 0
208:         source.gsub!(/^/) { n += 1; "%5d:  " % n }
209:         source.gsub!(/^ *\d+:\s+?\n/, '')      if flag_compact
210:         source.gsub!(/(^ *\d+:\s+?\n)+/, "\n") if flag_unique
211:       else
212:         source.gsub!(/^\s*?\n/, '')      if flag_compact
213:         source.gsub!(/(^\s*?\n)+/, "\n") if flag_unique
214:       end
215:       return source
216:     end

[Source]

     # File lib/erubis/main.rb, line 303
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:           unless optstr =~ /\A\-([-\w]+)(?:=(.*))?/
312:             raise CommandOptionError.new("-#{optstr}: invalid context value.")
313:           end
314:           name = $1;  value = $2
315:           name  = name.gsub(/-/, '_').intern
316:           #value = value.nil? ? true : YAML.load(value)   # error, why?
317:           value = value.nil? ? true : YAML.load("---\n#{value}\n")
318:           context[name] = value
319:           #
320:         else                  # options
321:           while optstr && !optstr.empty?
322:             optchar = optstr[0].chr
323:             optstr[0,1] = ""
324:             if arg_none.include?(optchar)
325:               options[optchar] = true
326:             elsif arg_required.include?(optchar)
327:               arg = optstr.empty? ? argv.shift : optstr
328:               unless arg
329:                 mesg = "-#{optchar.chr}: #{@option_args[optchar]} required."
330:                 raise CommandOptionError.new(mesg)
331:               end
332:               options[optchar] = arg
333:               optstr = nil
334:             elsif arg_optional.include?(optchar)
335:               arg = optstr.empty? ? true : optstr
336:               options[optchar] = arg
337:               optstr = nil
338:             else
339:               raise CommandOptionError.new("-#{optchar.chr}: unknown option.")
340:             end
341:           end
342:         end
343:         #
344:       end  # end of while
345: 
346:       return options, context
347:     end

[Source]

     # File lib/erubis/main.rb, line 438
438:     def parse_context_data(context_str, opts)
439:       if context_str[0] == ?{
440:         require 'yaml'
441:         ydoc = YAML.load(context_str)
442:         unless ydoc.is_a?(Hash)
443:           raise CommandOptionError.new("-c: root object is not a mapping.")
444:         end
445:         intern_hash_keys(ydoc) if opts.intern
446:         return ydoc
447:       else
448:         context = Erubis::Context.new
449:         context.instance_eval(context_str, '-c')
450:         return context
451:       end
452:     end

[Source]

     # File lib/erubis/main.rb, line 286
286:     def show_enhancers
287:       s = "enhancers:\n"
288:       list = []
289:       ObjectSpace.each_object(Module) do |m| list << m end
290:       list.sort_by { |m| m.name.to_s }.each do |m|
291:         next unless m.name =~ /\AErubis::(.*)Enhancer\z/
292:         name = $1
293:         desc = m.desc
294:         s << ("  %-13s : %s\n" % [name, desc])
295:       end
296:       return s
297:     end

[Source]

     # File lib/erubis/main.rb, line 263
263:     def show_properties
264:       s = "supported properties:\n"
265:       basic_props = collect_supported_properties(Erubis::Basic::Engine)
266:       pi_props    = collect_supported_properties(Erubis::PI::Engine)
267:       list = []
268:       common_props = basic_props & pi_props
269:       list << ['(common)', common_props]
270:       list << ['(basic)',  basic_props - common_props]
271:       list << ['(pi)',     pi_props    - common_props]
272:       %w[ruby php c java scheme perl javascript].each do |lang|
273:         klass = Erubis.const_get("E#{lang}")
274:         list << [lang, collect_supported_properties(klass) - basic_props]
275:       end
276:       list.each do |lang, props|
277:         s << "  * #{lang}\n"
278:         props.each do |name, default_val, desc|
279:           s << ("     --%-23s : %s\n" % ["#{name}=#{default_val.inspect}", desc])
280:         end
281:       end
282:       s << "\n"
283:       return s
284:     end

[Source]

     # File lib/erubis/main.rb, line 350
350:     def untabify(str, width=8)
351:       list = str.split(/\t/)
352:       last = list.pop
353:       sb = ''
354:       list.each do |s|
355:         column = (n = s.rindex(?\n)) ? s.length - n - 1 : s.length
356:         n = width - (column % width)
357:         sb << s << (' ' * n)
358:       end
359:       sb << last
360:       return sb
361:     end

[Source]

     # File lib/erubis/main.rb, line 218
218:     def usage(command=nil)
219:       command ||= File.basename($0)
220:       buf = []
221:       buf << "erubis - embedded program converter for multi-language"
222:       buf << "Usage: #{command} [..options..] [file ...]"
223:       buf << "  -h, --help    : help"
224:       buf << "  -v            : version"
225:       buf << "  -x            : show converted code"
226:       buf << "  -X            : show converted code, only ruby code and no text part"
227:       buf << "  -N            : numbering: add line numbers            (for '-x/-X')"
228:       buf << "  -U            : unique: compress empty lines to a line (for '-x/-X')"
229:       buf << "  -C            : compact: remove empty lines            (for '-x/-X')"
230:       buf << "  -b            : body only: no preamble nor postamble   (for '-x/-X')"
231:       buf << "  -z            : syntax checking"
232:       buf << "  -e            : escape (equal to '--E Escape')"
233:       buf << "  -p pattern    : embedded pattern (default '<% %>')"
234:       buf << "  -l lang       : convert but no execute (ruby/php/c/java/scheme/perl/js)"
235:       buf << "  -E e1,e2,...  : enhancer names (Escape, PercentLine, BiPattern, ...)"
236:       buf << "  -I path       : library include path"
237:       buf << "  -K kanji      : kanji code (euc/sjis/utf8) (default none)"
238:       buf << "  -c context    : context data string (yaml inline style or ruby code)"
239:       buf << "  -f datafile   : context data file ('*.yaml', '*.yml', or '*.rb')"
240:       #buf << "  -t            : expand tab characters in YAML file"
241:       buf << "  -T            : don't expand tab characters in YAML file"
242:       buf << "  -S            : convert mapping key from string to symbol in YAML file"
243:       buf << "  -B            : invoke 'result(binding)' instead of 'evaluate(context)'"
244:       buf << "  --pi=name     : parse '<?name ... ?>' instead of '<% ... %>'"
245:       #'
246:       #  -T            : don't trim spaces around '<% %>'
247:       #  -c class      : class name (XmlEruby/PercentLineEruby/...) (default Eruby)
248:       #  -r library    : require library
249:       #  -a            : action (convert/execute)
250:       return buf.join("\n")
251:     end

[Source]

     # File lib/erubis/main.rb, line 299
299:     def version
300:       return Erubis::VERSION
301:     end

[Validate]