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