choosy 0.4.9 → 0.4.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile.lock +13 -1
- data/README.md +259 -0
- data/Rakefile +28 -17
- data/lib/VERSION.yml +4 -4
- data/lib/choosy.rb +38 -10
- data/lib/choosy/argument.rb +0 -2
- data/lib/choosy/base_command.rb +9 -8
- data/lib/choosy/command.rb +0 -6
- data/lib/choosy/converter.rb +0 -5
- data/lib/choosy/dsl/argument_builder.rb +0 -5
- data/lib/choosy/dsl/base_builder.rb +0 -2
- data/lib/choosy/dsl/base_command_builder.rb +54 -42
- data/lib/choosy/dsl/command_builder.rb +0 -6
- data/lib/choosy/dsl/option_builder.rb +4 -6
- data/lib/choosy/dsl/super_command_builder.rb +0 -4
- data/lib/choosy/errors.rb +10 -2
- data/lib/choosy/option.rb +0 -3
- data/lib/choosy/parse_result.rb +0 -2
- data/lib/choosy/parser.rb +0 -4
- data/lib/choosy/printing/base_printer.rb +0 -3
- data/lib/choosy/printing/color.rb +21 -33
- data/lib/choosy/printing/erb_printer.rb +0 -2
- data/lib/choosy/printing/formatting_element.rb +0 -2
- data/lib/choosy/printing/help_printer.rb +0 -3
- data/lib/choosy/printing/manpage.rb +5 -2
- data/lib/choosy/printing/manpage_printer.rb +1 -6
- data/lib/choosy/rake.rb +33 -31
- data/lib/choosy/super_command.rb +1 -7
- data/lib/choosy/super_parser.rb +0 -6
- data/lib/choosy/terminal.rb +0 -3
- data/lib/choosy/verifier.rb +0 -3
- data/lib/choosy/version.rb +0 -2
- data/spec/choosy/argument_spec.rb +0 -3
- data/spec/choosy/base_command_spec.rb +0 -3
- data/spec/choosy/command_spec.rb +0 -4
- data/spec/choosy/converter_spec.rb +0 -4
- data/spec/choosy/dsl/argument_builder_spec.rb +0 -3
- data/spec/choosy/dsl/base_builder_spec.rb +0 -3
- data/spec/choosy/dsl/base_command_builder_spec.rb +18 -5
- data/spec/choosy/dsl/commmand_builder_spec.rb +0 -6
- data/spec/choosy/dsl/option_builder_spec.rb +0 -3
- data/spec/choosy/dsl/super_command_builder_spec.rb +0 -4
- data/spec/choosy/option_spec.rb +0 -3
- data/spec/choosy/parser_spec.rb +0 -5
- data/spec/choosy/printing/base_printer_spec.rb +0 -5
- data/spec/choosy/printing/color_spec.rb +1 -4
- data/spec/choosy/printing/help_printer_spec.rb +0 -5
- data/spec/choosy/printing/manpage_printer_spec.rb +0 -4
- data/spec/choosy/printing/manpage_spec.rb +2 -3
- data/spec/choosy/super_command_spec.rb +0 -3
- data/spec/choosy/super_parser_spec.rb +0 -5
- data/spec/choosy/terminal_spec.rb +0 -3
- data/spec/choosy/verifier_spec.rb +0 -7
- data/spec/choosy/version_spec.rb +0 -2
- metadata +127 -121
- data/README.markdown +0 -463
- data/lib/choosy/printing.rb +0 -1
- data/spec/integration/command-A_spec.rb +0 -37
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
choosy (0.4.
|
4
|
+
choosy (0.4.9)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: http://rubygems.org/
|
@@ -11,7 +11,17 @@ GEM
|
|
11
11
|
ZenTest (>= 4.4.1)
|
12
12
|
autotest-notification (2.3.1)
|
13
13
|
autotest (~> 4.3)
|
14
|
+
builder (3.0.0)
|
15
|
+
cucumber (1.1.9)
|
16
|
+
builder (>= 2.1.2)
|
17
|
+
diff-lcs (>= 1.1.2)
|
18
|
+
gherkin (~> 2.9.0)
|
19
|
+
json (>= 1.4.6)
|
20
|
+
term-ansicolor (>= 1.0.6)
|
14
21
|
diff-lcs (1.1.2)
|
22
|
+
gherkin (2.9.3)
|
23
|
+
json (>= 1.4.6)
|
24
|
+
json (1.6.6)
|
15
25
|
rspec (2.5.0)
|
16
26
|
rspec-core (~> 2.5.0)
|
17
27
|
rspec-expectations (~> 2.5.0)
|
@@ -20,6 +30,7 @@ GEM
|
|
20
30
|
rspec-expectations (2.5.0)
|
21
31
|
diff-lcs (~> 1.1.2)
|
22
32
|
rspec-mocks (2.5.0)
|
33
|
+
term-ansicolor (1.0.7)
|
23
34
|
|
24
35
|
PLATFORMS
|
25
36
|
ruby
|
@@ -29,4 +40,5 @@ DEPENDENCIES
|
|
29
40
|
autotest
|
30
41
|
autotest-notification
|
31
42
|
choosy!
|
43
|
+
cucumber
|
32
44
|
rspec
|
data/README.md
ADDED
@@ -0,0 +1,259 @@
|
|
1
|
+
# Choosy: Picking your Arguments Carefully
|
2
|
+
|
3
|
+
This is a small DSL library for creating command line clients in Ruby. It is largely inspired by the <a href="https://github.com/defunkt/choice">choice</a>, <a href="https://github.com/visionmedia/commander">commander</a>, and <a href="http://furius.ca/optcomplete/">optcomplete.py</a> libraries, though it makes some different design decisions than they do. It is opinionated software.
|
4
|
+
|
5
|
+
This library should:
|
6
|
+
|
7
|
+
- Make creating command line clients relatively easy.
|
8
|
+
- Make creating supercommands like git, subversion, and gem easier.
|
9
|
+
- Allow you to add validation logic for your arguments within the parsing phase.
|
10
|
+
- Allowing for dependencies between options, so that you can more easily validate related options (i.e. if the<code>--bold</code> flag requires the <code>--font Arial</code> flag, then you should be able to ask for the <code>--font</code> option to be validated first, and then the <code>--bold</code> option.
|
11
|
+
- Allow you to customize its output using your own formatting system, or provide several convenient defaults when you don't want to provide your own.
|
12
|
+
|
13
|
+
This library should never:
|
14
|
+
|
15
|
+
- Interact with your execution logic. You can attach executors to commands for convenience, but the execution phase should be delegated to you, not the parsing library. Separation of concerns, people.
|
16
|
+
- Rely on display or user interface libraries like Highline, since this is only for parsing command lines.
|
17
|
+
- Pollute your namespaces with my DSL function names. (I really, really hate it when libraries do this.)
|
18
|
+
|
19
|
+
# Examples
|
20
|
+
|
21
|
+
This example is a simple date and time tool.
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
#!/usr/bin/env ruby
|
25
|
+
|
26
|
+
# date-time
|
27
|
+
require 'choosy'
|
28
|
+
require 'time'
|
29
|
+
|
30
|
+
class DateTimeCLI
|
31
|
+
attr_reader :command
|
32
|
+
|
33
|
+
def run!(args)
|
34
|
+
@command = Choosy::Command.new :'date-time' do
|
35
|
+
summary "This is a command that prints out the current time"
|
36
|
+
|
37
|
+
executor do |args, options| # An executor can just be a simple block.
|
38
|
+
if options[:utc]
|
39
|
+
puts Time.now.utc.strftime(options[:format])
|
40
|
+
else
|
41
|
+
puts Time.now.strftime(options[:format])
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
section "Description" do
|
46
|
+
para "This tool prints out the current time, with some added effects"
|
47
|
+
end
|
48
|
+
|
49
|
+
section "Options" do
|
50
|
+
boolean :utc, "Prints it using the UTC format"
|
51
|
+
string :format, "The format of the output" do
|
52
|
+
default "%Y-%m-%d %H:%M:%S %z"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
help # Enables the '-h|--help' option.
|
57
|
+
version "1.0" # Enables the '--version' option.
|
58
|
+
end.execute!(args)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
if __FILE__ == $0
|
63
|
+
DateTimeCLI.new.run!(ARGV)
|
64
|
+
end
|
65
|
+
```
|
66
|
+
|
67
|
+
Another simple tool that lists directories.
|
68
|
+
|
69
|
+
```ruby
|
70
|
+
#!/usr/bin/env ruby
|
71
|
+
|
72
|
+
# list-files
|
73
|
+
require 'choosy'
|
74
|
+
|
75
|
+
class ListFilesCLI
|
76
|
+
attr_reader :command
|
77
|
+
|
78
|
+
def run!(args)
|
79
|
+
exe = self # The following block will change 'self', so we capture context here.
|
80
|
+
|
81
|
+
@command = Choosy::Command.new :'date-time' do
|
82
|
+
summary "This is a command that lists files in directories"
|
83
|
+
executor exe # Commands need executors that implement 'execute!'.
|
84
|
+
# We're using 'self'.
|
85
|
+
|
86
|
+
section "Description" do
|
87
|
+
para "This tool prints out some information about directories"
|
88
|
+
end
|
89
|
+
|
90
|
+
section "Options" do
|
91
|
+
integer :limit, "Limit the printed listing to a given number of files."
|
92
|
+
boolean :dirs_only, "Only print out directories"
|
93
|
+
end
|
94
|
+
|
95
|
+
help # Enables the '-h|--help' option.
|
96
|
+
version "1.0" # Enables the '--version' option.
|
97
|
+
|
98
|
+
arguments do
|
99
|
+
metaname 'PATH' # What to display on the manpage
|
100
|
+
count 0..1 # The number of items allowed, restricted here by a range.
|
101
|
+
end
|
102
|
+
end.execute!(args)
|
103
|
+
end
|
104
|
+
|
105
|
+
# Called by the command at the end of the 'run!'
|
106
|
+
def execute!(args, options)
|
107
|
+
limit = options[:limit] || 0
|
108
|
+
paths = if args.empty?
|
109
|
+
['.']
|
110
|
+
else
|
111
|
+
args
|
112
|
+
end
|
113
|
+
|
114
|
+
paths.each do |path|
|
115
|
+
Dir["#{path}/*"].each do |fname|
|
116
|
+
puts fname
|
117
|
+
|
118
|
+
limit -= 1
|
119
|
+
if limit == 0
|
120
|
+
return
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
if __FILE__ == $0
|
128
|
+
ListFilesCLI.new.run!(ARGV)
|
129
|
+
end
|
130
|
+
```
|
131
|
+
|
132
|
+
### Super Commands
|
133
|
+
|
134
|
+
You can also combine multiple choices into an uber-choice, creating commands that look a lot like git or subversion.
|
135
|
+
|
136
|
+
```ruby
|
137
|
+
#!/usr/bin/env ruby
|
138
|
+
|
139
|
+
# git-wrapper
|
140
|
+
require 'choosy'
|
141
|
+
|
142
|
+
class GitExecutor
|
143
|
+
def initialize(type)
|
144
|
+
@type = type
|
145
|
+
end
|
146
|
+
|
147
|
+
def execute!(args, options)
|
148
|
+
exec("git #{@type}")
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
class GitWrapperCLI
|
153
|
+
attr_reader :command
|
154
|
+
|
155
|
+
def run!(args)
|
156
|
+
exe = self # The following block will change 'self', so we capture context here.
|
157
|
+
|
158
|
+
@command = Choosy::SuperCommand.new :'git-wrapper' do
|
159
|
+
summary "This is a command that lists files in directories"
|
160
|
+
|
161
|
+
section "Description" do
|
162
|
+
para "This tool prints out some information about directories"
|
163
|
+
end
|
164
|
+
|
165
|
+
section "Commands" do
|
166
|
+
command :status do
|
167
|
+
summary "Prints out the 'git status'"
|
168
|
+
executor GitExecutor.new(:status)
|
169
|
+
|
170
|
+
help
|
171
|
+
end
|
172
|
+
|
173
|
+
command :diff do
|
174
|
+
summary "Prints out the 'git diff'"
|
175
|
+
executor GitExecutor.new(:diff)
|
176
|
+
|
177
|
+
help
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
help # Enables the '-h|--help' option.
|
182
|
+
version "1.0" # Enables the '--version' option.
|
183
|
+
end.execute!(args)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
if __FILE__ == $0
|
188
|
+
GitWrapperCLI.new.run!(ARGV)
|
189
|
+
end
|
190
|
+
```
|
191
|
+
|
192
|
+
# Output Printing
|
193
|
+
|
194
|
+
Choosy allows you to customize the output printing of your documentation. It exposes the internal object model to any class that implements a <code>print!(command)</code> method.
|
195
|
+
|
196
|
+
The <code>:standard</code> printer that is the default for any command can also be customized to meet some of your needs:
|
197
|
+
|
198
|
+
``` ruby
|
199
|
+
Choosy::Command.new :foo do
|
200
|
+
printer :standard, # The default printer
|
201
|
+
:max_width => 80, # Defaults to the column witdh of the terminal
|
202
|
+
:color => true, # Default is true
|
203
|
+
:header_styles => [:bold, :green], # Defaults to [:bold, :blue]
|
204
|
+
:indent => ' ', # Defaults to this width
|
205
|
+
:offset => ' ' # Defaults to this width
|
206
|
+
|
207
|
+
help "Show this help command."
|
208
|
+
end
|
209
|
+
```
|
210
|
+
|
211
|
+
This above example sets some useful properties for the printer. First, the <code>:max\_width</code> limits the wrapping size on the console. By default, choosy tries to be smart and wrap to the currend column width, but you can introduce this hash parameter as a default max. Next, you can turn off and on color printing by setting <code>:color</code>. Color is on by default, so it's actually superfluous in this example -- just a demonstration of the syntax. The <code>:header\_styles</code> is an array of styles that will be applied to the headers for this document. By default, headers are <code>[:bold, :blue]</code>. Most of the ANSI colors and codes are supported, but check <code>lib/choosy/printing/color.rb</code> for additional options. The last two options given are actually formatting spacers in the output that you can customize: <code>:indent</code> is the default indent for commands and options; <code>:offset</code> is the distance between the options and commands to their associated descriptive text.
|
212
|
+
|
213
|
+
For those who want the nice, manpage experience, there's also the <code>:manpage</code> printer:
|
214
|
+
|
215
|
+
``` ruby
|
216
|
+
Choosy::Command.new :foo do
|
217
|
+
printer :manpage,
|
218
|
+
:max_width => 80, # Same as :standard
|
219
|
+
:color => true, # Same as :standard
|
220
|
+
:header_styles => [:bold, :green], # Same as :standard
|
221
|
+
:option_sytles => [:bold], # Same as :standard
|
222
|
+
:indent => ' ', # Same as :standard
|
223
|
+
:offset => ' ', # Same as :standard
|
224
|
+
:version => FOO_VERSION, # Will use the version name you specify, see below.
|
225
|
+
:section => 1, # Default is always '1'
|
226
|
+
:date => '03/24/2011', # Date you want displayed
|
227
|
+
:manual => 'Foo Co.' # The manual page group
|
228
|
+
|
229
|
+
version FOO_VERSION # If you don't supply a version above, this will be used
|
230
|
+
end
|
231
|
+
```
|
232
|
+
|
233
|
+
Because the library is super-awesome, the manpage will even be in color when piped to <code>less -R</code> (the default)! If you don't like the format of my manpage, feel free to implement your own using the <code>choosy/printing/manpage</code> class, a useful utility class for formatting manpage output correctly.
|
234
|
+
|
235
|
+
If you already have some templates that you'd like to use, there is also the <code>:erb</code> template that can be customized by writing a template of your choice:
|
236
|
+
|
237
|
+
``` ruby
|
238
|
+
Choosy::Command.new :foo do
|
239
|
+
printer :erb,
|
240
|
+
:color => true, # Defaults to true
|
241
|
+
:template => 'path/to/file.erb' # Required
|
242
|
+
end
|
243
|
+
```
|
244
|
+
|
245
|
+
The ERB printer also accepts the <code>:color</code> option. The color is exposed via a <code>color</code> property in the template; the command is exposed by the <code>command</code> property.
|
246
|
+
|
247
|
+
Finally, because I don't want to tell you how to print your help, I also give you the option of supplying your own printer. Just create a class with a <code>print!(command)</code> method on that class, and it will be passed in the command that it should print the help for. I have supplied some code you may find useful in <code>choosy/terminal</code> that will help with things like finding commands and determining the column width of the terminal.
|
248
|
+
|
249
|
+
``` ruby
|
250
|
+
class CustomPrinter
|
251
|
+
def print!(command)
|
252
|
+
puts "I got called on help for #{command.name}"
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
Choosy::Command.new :foo do
|
257
|
+
printer CustomPrinter.new
|
258
|
+
end
|
259
|
+
```
|
data/Rakefile
CHANGED
@@ -1,35 +1,49 @@
|
|
1
|
-
|
1
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), 'lib')
|
2
|
+
|
2
3
|
require 'rake'
|
3
4
|
require 'rspec/core/rake_task'
|
4
|
-
|
5
|
-
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), 'lib')
|
5
|
+
require 'cucumber/rake/task'
|
6
6
|
require 'choosy/rake'
|
7
7
|
|
8
8
|
desc "Default task"
|
9
9
|
task :default => [:spec]
|
10
10
|
|
11
|
-
desc "Run the
|
12
|
-
|
11
|
+
desc "Run all of the specifications."
|
12
|
+
task :spec => ['spec:default']
|
13
|
+
namespace :spec do
|
14
|
+
task :default => [:rspec, :cucumber]
|
15
|
+
|
16
|
+
desc "Run the RSpec tests."
|
17
|
+
RSpec::Core::RakeTask.new :rspec
|
13
18
|
|
14
|
-
desc "
|
15
|
-
|
16
|
-
|
17
|
-
|
19
|
+
desc "Runs all of the cucumber tasks. Add 'tag=TAG' to run only matching tags."
|
20
|
+
Cucumber::Rake::Task.new :cucumber do |cucumber|
|
21
|
+
cucumber.cucumber_opts = ["-t #{ENV['tag'] || "all"}", "features"]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
desc "Rebuilds the README.md file."
|
26
|
+
task :readme do
|
27
|
+
File.open 'docs/README.md', 'r' do |template|
|
28
|
+
File.open 'README.md', 'w' do |output|
|
18
29
|
template.each do |line|
|
19
|
-
if line =~
|
20
|
-
puts $
|
30
|
+
if line =~ /^INCLUDE\((.*?),\s*(.*?)\)/
|
31
|
+
output.puts " ```#{$2}"
|
32
|
+
|
21
33
|
File.open $1, 'r' do |toinsert|
|
22
34
|
exclude = false
|
23
35
|
toinsert.each_line do |ins|
|
24
|
-
if ins =~
|
36
|
+
if ins =~ /^#=begin/
|
25
37
|
exclude = true
|
26
38
|
end
|
27
39
|
output.puts " #{ins}" unless exclude
|
28
|
-
if ins =~
|
40
|
+
if ins =~ /^#=end/
|
29
41
|
exclude = false
|
30
42
|
end
|
31
43
|
end
|
32
44
|
end
|
45
|
+
|
46
|
+
output.puts " ```"
|
33
47
|
else
|
34
48
|
output.puts line
|
35
49
|
end
|
@@ -38,11 +52,8 @@ task :doc => [ :rdoc ] do
|
|
38
52
|
end
|
39
53
|
end
|
40
54
|
|
41
|
-
desc "Create RDocs: TODO"
|
42
|
-
task :rdoc
|
43
|
-
|
44
55
|
desc "Cleans the generated files."
|
45
56
|
task :clean => ['gem:clean']
|
46
57
|
|
47
58
|
desc "Runs the full deploy"
|
48
|
-
task :push => [:release, :clean]
|
59
|
+
task :push => [:readme, 'choosy:release', :clean]
|
data/lib/VERSION.yml
CHANGED
data/lib/choosy.rb
CHANGED
@@ -1,16 +1,44 @@
|
|
1
|
-
|
1
|
+
require 'tsort'
|
2
|
+
require 'time'
|
3
|
+
require 'date'
|
4
|
+
require 'yaml'
|
2
5
|
|
3
|
-
require 'choosy/command'
|
4
|
-
require 'choosy/super_command'
|
5
|
-
require 'choosy/converter'
|
6
6
|
require 'choosy/errors'
|
7
|
-
require 'choosy/
|
8
|
-
require 'choosy/
|
7
|
+
require 'choosy/base_command'
|
8
|
+
require 'choosy/parse_result'
|
9
9
|
require 'choosy/parser'
|
10
10
|
require 'choosy/verifier'
|
11
|
+
require 'choosy/command'
|
12
|
+
require 'choosy/argument'
|
13
|
+
require 'choosy/option'
|
14
|
+
require 'choosy/terminal'
|
15
|
+
require 'choosy/converter'
|
16
|
+
|
17
|
+
require 'choosy/printing/base_printer'
|
18
|
+
require 'choosy/printing/color'
|
19
|
+
|
20
|
+
require 'choosy/dsl/base_builder'
|
21
|
+
require 'choosy/dsl/argument_builder'
|
22
|
+
require 'choosy/dsl/base_command_builder'
|
11
23
|
require 'choosy/dsl/command_builder'
|
12
|
-
require 'choosy/dsl/super_command_builder'
|
13
24
|
require 'choosy/dsl/option_builder'
|
14
|
-
|
15
|
-
|
16
|
-
|
25
|
+
|
26
|
+
module Choosy
|
27
|
+
autoload :SuperCommand, 'choosy/super_command'
|
28
|
+
autoload :SuperParser, 'choosy/super_parser'
|
29
|
+
autoload :Version, 'choosy/version'
|
30
|
+
|
31
|
+
module Printing
|
32
|
+
autoload :ERBPrinter, 'choosy/printing/erb_printer'
|
33
|
+
autoload :FormattingElement, 'choosy/printing/formatting_element'
|
34
|
+
autoload :HelpPrinter, 'choosy/printing/help_printer'
|
35
|
+
autoload :Manpage, 'choosy/printing/manpage'
|
36
|
+
autoload :ManpageFormatter, 'choosy/printing/manpage'
|
37
|
+
autoload :ManpagePrinter, 'choosy/printing/manpage_printer'
|
38
|
+
end
|
39
|
+
|
40
|
+
module DSL
|
41
|
+
autoload :SuperCommandBuilder, 'choosy/dsl/super_command_builder'
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
data/lib/choosy/argument.rb
CHANGED
data/lib/choosy/base_command.rb
CHANGED
@@ -1,6 +1,3 @@
|
|
1
|
-
require 'choosy/errors'
|
2
|
-
require 'tsort'
|
3
|
-
|
4
1
|
module Choosy
|
5
2
|
class OptionBuilderHash < Hash
|
6
3
|
include TSort
|
@@ -53,12 +50,16 @@ module Choosy
|
|
53
50
|
end
|
54
51
|
end
|
55
52
|
|
56
|
-
def execute!(args)
|
57
|
-
|
53
|
+
def execute!(args, propagate=false)
|
54
|
+
if propagate
|
58
55
|
execute(args)
|
59
|
-
|
60
|
-
|
61
|
-
|
56
|
+
else
|
57
|
+
begin
|
58
|
+
execute(args)
|
59
|
+
rescue Choosy::ClientExecutionError => e
|
60
|
+
$stderr << "#{@name}: #{e.message}\n"
|
61
|
+
exit 1
|
62
|
+
end
|
62
63
|
end
|
63
64
|
end
|
64
65
|
|