27: def parse(args, err, out, warn_if_no_files)
28: options = OpenStruct.new
29: options.out = out == STDOUT ? Kernel : out
30: options.formatter_type = Formatter::ProgressBarFormatter
31: options.backtrace_tweaker = QuietBacktraceTweaker.new
32: options.spec_name = nil
33:
34: opts = ::OptionParser.new do |opts|
35: opts.banner = "Usage: spec [options] (FILE|DIRECTORY|GLOB)+"
36: opts.separator ""
37:
38: opts.on("-D", "--diff [FORMAT]", "Show diff of objects that are expected to be equal when they are not",
39: "Builtin formats: unified|u|context|c",
40: "You can also specify a custom differ class",
41: "(in which case you should also specify --require)") do |format|
42: require 'spec/expectations/diff'
43:
44:
45: options.context_lines = 3
46:
47: case format
48: when 'context', 'c'
49: options.diff_format = :context
50: when 'unified', 'u', '', nil
51: options.diff_format = :unified
52: end
53:
54: if [:context,:unified].include? options.diff_format
55: require 'spec/expectations/differs/default'
56: options.differ_class = Spec::Expectations::Differs::Default
57: else
58: begin
59: options.diff_format = :custom
60: options.differ_class = eval(format)
61: rescue NameError
62: err.puts "Couldn't find differ class #{format}"
63: err.puts "Make sure the --require option is specified *before* --diff"
64: exit if out == $stdout
65: end
66: end
67:
68: end
69:
70: opts.on("-c", "--colour", "--color", "Show coloured (red/green) output") do
71: options.colour = true
72: end
73:
74: opts.on("-s", "--spec SPECIFICATION_NAME", "Execute context or specification with matching name") do |spec_name|
75: options.spec_name = spec_name
76: end
77:
78: opts.on("-l", "--line LINE_NUMBER", Integer, "Execute context or specification at given line") do |line_number|
79: options.line_number = line_number.to_i
80: end
81:
82: opts.on("-f", "--format FORMAT", "Builtin formats: specdoc|s|rdoc|r|html|h",
83: "You can also specify a custom formatter class",
84: "(in which case you should also specify --require)") do |format|
85: case format
86: when 'specdoc', 's'
87: options.formatter_type = Formatter::SpecdocFormatter
88: when 'html', 'h'
89: options.formatter_type = Formatter::HtmlFormatter
90: when 'rdoc', 'r'
91: options.formatter_type = Formatter::RdocFormatter
92: options.dry_run = true
93: else
94: begin
95: options.formatter_type = eval(format)
96: rescue NameError
97: err.puts "Couldn't find formatter class #{format}"
98: err.puts "Make sure the --require option is specified *before* --format"
99: exit if out == $stdout
100: end
101: end
102: end
103:
104: opts.on("-r", "--require FILE", "Require FILE before running specs",
105: "Useful for loading custom formatters or other extensions",
106: "If this option is used it must come before the others") do |req|
107: require req
108: end
109:
110: opts.on("-b", "--backtrace", "Output full backtrace") do
111: options.backtrace_tweaker = NoisyBacktraceTweaker.new
112: end
113:
114: opts.on("-H", "--heckle CODE", "If all specs pass, this will run your specs many times, mutating",
115: "the specced code a little each time. The intent is that specs",
116: "*should* fail, and RSpec will tell you if they don't.",
117: "CODE should be either Some::Module, Some::Class or Some::Fabulous#method}") do |heckle|
118: require 'spec/runner/heckle_runner'
119: options.heckle_runner = HeckleRunner.new(heckle)
120: end
121:
122: opts.on("-d", "--dry-run", "Don't execute specs") do
123: options.dry_run = true
124: end
125:
126: opts.on("-o", "--out OUTPUT_FILE", "Path to output file (defaults to STDOUT)") do |outfile|
127: options.out = File.new(outfile, 'w')
128: end
129:
130: opts.on("-v", "--version", "Show version") do
131: out.puts ::Spec::VERSION::DESCRIPTION
132: exit if out == $stdout
133: end
134:
135: opts.on_tail("-h", "--help", "You're looking at it") do
136: out.puts opts
137: exit if out == $stdout
138: end
139:
140: end
141: opts.parse!(args)
142:
143: if args.empty? && warn_if_no_files
144: err.puts opts
145: exit(1) if err == $stderr
146: end
147:
148: if options.line_number
149: set_spec_from_line_number(options, args, err)
150: end
151:
152: options
153: end