# Author:: The Uttk Team. # Copyright:: Copyright (c) 2004 Uttk team. All rights reserved. # License:: LGPL # $Id: /w/fey/uttk/trunk/bin/getopts/uttk.rb 22244 2006-02-25T10:48:53.146614Z pouillar $ require 'optparse' Hierarchy.import! PpHierarchy.import! module Uttk module Getopts class Uttk def self.head puts "--- |Usage: #{ME} [options] [files...] | |options : use --long-help to see all options | |files : > | by default input files are in Yaml | but you can change the loader (see -L) |".head_cut! end def self.tail puts "strategies : | input files use and compose strategies: | - complete strategy list: --strategy-list | - help on one strategy : --long-help aStrategyName | |documentation: | - introduction, tutorial: http://uttk.org | - api, generated by RDoc: http://api.uttk.org/doc | |bug reports : http://dev.uttk.org | |# Good tests !! |# -- |# The Uttk Team |".head_cut! end def self.usage head puts tail end def self.parse(argv) opts = ::Uttk.default_options.dup optparser = OptionParser.new do |optparser| optparser.banner = '' optparser.summary_indent = ' ' optparser.summary_width = 25 ### Path options optparser.separator 'Path options:' optparser.on('-I', '--include PATH', 'Add PATH to root path (PATH/strategies, ' + 'PATH/filters...)') do |aPath| ::Uttk.load_path += aPath.split(':').map { |x| x.to_path } ::Uttk.setup_autoload_all end ### Strategy options optparser.separator '' optparser.separator 'Strategy options:' optparser.on('--strategy-list', 'List all test strategy classes') do pp_class_hierarchy('Strategies::Strategy') exit end ### Loader options optparser.separator '' optparser.separator 'Loader options:' all_loaders = sub_modules(Loaders) optparser.on('-L', '--loader [TYPE]', all_loaders, 'Select a loader (no argument for the list)') do |aLoader| if aLoader.nil? pp_class_hierarchy('Loaders::Loader') exit else opts[:loader] = Loaders.const_get(aLoader) end end ### Filter options optparser.separator '' optparser.separator 'Filter options:' optparser.on('-F', '--filter [PIPELINE DESCRIPTION]', 'Select a filter pipeline' + '(no argument for the list)') do |desc| if desc.nil? pp_class_hierarchy('Logger::Backend', 'Filters::Filter', 'PathFilters::PathFilter', 'Dumpers::Dumper') exit else begin opts[:observers] << desc rescue ArgumentError => e raise(OptionParser::InvalidArgument, "#{desc}: #{e}") end end end optparser.on('--filter-help', 'More information about filters') do all_filters = sub_modules(Filters) + sub_modules(Dumpers) puts %Q{ |filters: | The --filter (-F) option take a pipeline description which | is a little yaml document. | | The syntax is basic: | | Observer ::= | | ":" Observer | | "[" Observer* "]" | ; | | Filters ::= #{all_filters.join(' | ')} ; | | Examples: | Yaml # Use the Yaml output format on the stdout | Yaml: foo # Use Yaml on file foo | Xml: foo, Yaml: bar # Use Xml on file foo and Yaml on file bar | Xml: [ foo, bar] # Use Xml on files foo and bar | Yaml, Xml: log.xml # Use Yaml on stdout and Xml on log.xml | JustStatus: Yaml # Use the filter JustStatus and display | # its output with Yaml | JustStatus: {Yaml, Xml: log.xml} | # Use Yaml on stdout and Xml on log.xml but trough the | # filter JustStatus. | | Yaml: log.yml, JustStatus: Yaml # This one is usefull | | You can make your own compositions and save them, see the | documentation of the Filters module. | | Warning: | Xml: foo, Xml: bar # Will create only one Xml dumper since | # this is a hash with twice the same key. |}.head_cut! exit end ### Weight options optparser.separator '' optparser.separator 'Weight options:' optparser.on('-W', '--wclass [TYPE]', 'Select the weight class ' + '(no argument for the list)') do |aString| if aString.nil? pp_class_hierarchy('Weights::Weight') exit else opts[:wclass] = Weights.const_get(aString) end end ### Logger options optparser.separator '' optparser.separator 'Logger options:' optparser.on('-l', '--log STRING', 'Set the log base name for log files') do |log| default_filter = STDOUT.tty? ? F::DefaultColor : F::Default opts[:observers] << default_filter.template(log) end optparser.on('-d', '--severity [NAME]', 'Log severity level ' + '(no argument for the list)') do |level| if level.nil? puts 'Log severity level list:' Logger::Severity.labels.each { |l| puts " - #{l}" } exit else begin raise NameError if level.nil? opts[:log_severity] = Logger::Severity.const_get(level.to_s.upcase) rescue NameError raise(OptionParser::InvalidArgument, level) end end end higher_level = Logger::Verbosity.higher_level optparser.on('-v', '--verbosity NUM', "Log verbosity level [0-#{higher_level}]") do |level| ilevel = level.to_i if ilevel.to_s != level raise(OptionParser::InvalidArgument, level) end if 0 <= ilevel and ilevel <= higher_level opts[:log_verbosity] = ilevel else raise(OptionParser::InvalidArgument, level) end end optparser.on('-s', '--log-section [NAME]', 'Active a log section ' + '(no argument for the list)') do |name| if name.nil? #FIXME: print the section tree exit else #FIXME: check the validity of the section opts[:log_section] << name.to_s end end ### Miscellaneous options optparser.separator '' optparser.separator 'Miscellaneous options:' optparser.on('-S', '--symbols symbols', 'Add a hash of symbols to the root test suite') do |str| opts[:symbols] = YAML.load(str) end optparser.on('-A', '--attributes attributes', 'Add a hash of attributes to ' + 'the root test suite') do |aString| opts[:attributes] = YAML.load(aString) end optparser.on('-C', '--[no-]cache', 'Keep the test in cache') do |c| opts[:cache_mode] = c end optparser.on('--cache-dir DIR', 'Use the cache in DIR') do |dir| dir = Pathname.new(dir) unless dir.directory? raise OptionParser::InvalidArgument, 'need a directory' end opts[:cache_dir] = dir end optparser.on('-r', '--cache-proc RUBY_CODE', 'Use this block to skip tests in cache mode') do |code| unless code =~ /^\s*\|[^,]+,[^,]+\|\s*\S+/ raise OptionParser::InvalidArgument, 'need a ruby block with 2 args (e.g |x,y| ...)' end opts[:cache_proc] = DumpableProc.new(code) end optparser.on('--rpath REGEX_PATH', 'Just keep tests with name that matches the REGEX_PATH')\ do |r| opts[:rpath] = RegexPath.new "#{r}/()" end optparser.on('--rpath-exclude REGEX_PATH', 'Skip tests with name that matches the REGEX_PATH')\ do |r| opts[:rpath_exclude] = RegexPath.new "#{r}/()" end optparser.on('-b', '--benchmark', 'Switch on benchmark informations') do opts[:benchmark] = true end optparser.on('--profile', 'Switch on profile informations') do opts[:profile] = true end optparser.on('--dump-status', 'Dump the global status at the end (STDOUT)') do opts[:dump_status] = true end optparser.on('--gen-strategies-hierarchy', 'Generate the strategies hierarchy description') do hsh = Strategies.sub_classes_tree(Strategies::Strategy, true, true) puts "# Uttk's strategies hierarchy generated on #{Time.now}" YAML.dump(hierarchy_to_s(hsh), STDOUT) exit end optparser.on_tail('-h', '--help', 'Show the brief help message') do usage exit 0 end optparser.on_tail('-H', '--long-help [strategy]', 'Show this message') do |aStrategy| if aStrategy.nil? head puts optparser puts tail else Strategies.const_get(aStrategy).help(STDOUT) end exit 0 end optparser.on_tail('--authors', 'Display the AUTHORS file') do puts ::Uttk::AUTHORS_PATH.read exit 0 end optparser.on_tail('--version', 'Show version') do puts ::Uttk::VERSION_TEXT exit 0 end end optparser.parse!(argv) argv << '-' if argv.empty? argv.map! { |x| x == '-' ? STDIN : Pathname.new(x) } opts end protected def self.sub_modules(mod) mod.constants.sort!.map! { |c| c.to_sym } end protected def self.pp_class_hierarchy(name, *others) if name =~ /^(\w+)::(\w+)$/ mod = ::Uttk.const_get($1) klass = mod.const_get($2) puts "#{mod} classes hierarchy:" hsh = mod.sub_classes_tree(klass, true, true) mods = [mod] others.each do |name| if name =~ /^(\w+)::(\w+)$/ mod = ::Uttk.const_get($1) mods << mod klass = mod.const_get($2) hsh[hsh.keys.first].merge! mod.sub_classes_tree(klass, true, true) end end hsh.pp_hierarchy(Regexp.new("^(#{mods.join('|')})::"), true) end end protected def self.hierarchy_to_s(hsh) r = {} hsh.each { |k, v| r[k.to_s] = hierarchy_to_s(v) } r end end # class Uttk end # module Getopts end # module Uttk