Parent

Class Index [+]

Quicksearch

Erubis::Main

main class of command

ex.

  Main.main(ARGV)

Public Class Methods

main(argv=ARGV) click to toggle 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
new() click to toggle 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

execute(argv=ARGV) click to toggle 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:           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

Private Instance Methods

_instance_eval(_context, _str) click to toggle source
     # File lib/erubis/main.rb, line 431
431:     def _instance_eval(_context, _str)
432:       _context.instance_eval(_str)
433:     end
check_syntax(filename, src) click to toggle source
     # File lib/erubis/main.rb, line 470
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
check_syntax(filename, src) click to toggle source
     # File lib/erubis/main.rb, line 489
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
collect_supported_properties(erubis_klass) click to toggle source
     # File lib/erubis/main.rb, line 254
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
do_action(action, engine, context, filename, opts) click to toggle source
     # File lib/erubis/main.rb, line 188
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
get_classobj(classname, lang, pi) click to toggle source
     # File lib/erubis/main.rb, line 370
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
get_enhancers(enhancer_names) click to toggle source
     # File lib/erubis/main.rb, line 389
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
intern_hash_keys(obj, done={}) click to toggle source
     # File lib/erubis/main.rb, line 451
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
load_datafiles(filenames, opts) click to toggle source
     # File lib/erubis/main.rb, line 404
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(ff, 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
manipulate_src(source, opts) click to toggle source
     # File lib/erubis/main.rb, line 203
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
parse_argv(argv, arg_none='', arg_required='', arg_optional='') click to toggle 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:           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
parse_context_data(context_str, opts) click to toggle source
     # File lib/erubis/main.rb, line 435
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
show_enhancers() click to toggle source
     # File lib/erubis/main.rb, line 287
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
show_properties() click to toggle source
     # File lib/erubis/main.rb, line 264
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:       ]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
untabify(str, width=8) click to toggle source
     # File lib/erubis/main.rb, line 346
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
usage(command=nil) click to toggle source
     # File lib/erubis/main.rb, line 219
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
version() click to toggle source
     # File lib/erubis/main.rb, line 299
299:     def version
300:       return Erubis::VERSION
301:     end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.