bales 0.1.1 → 0.1.2
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.
- checksums.yaml +4 -4
- data/lib/bales/application.rb +8 -4
- data/lib/bales/command/help.rb +7 -2
- data/lib/bales/version.rb +1 -1
- metadata +5 -10
- data/lib/bales.rb~ +0 -236
- data/lib/bales/application.rb~ +0 -71
- data/lib/bales/command.rb~ +0 -189
- data/lib/bales/command/help.rb~ +0 -37
- data/lib/bales/version.rb~ +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 17750f3056694dcabc3be1c2ac111978e179043f
|
4
|
+
data.tar.gz: b6087e538fd4eccb2e614b1dbd539cf4058b5e90
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 05e0241f93ac005d784ca7d66bc806de2e5ef609c947bf69c1cdbbd338512f6c6170697f47561a6476ac40084e02a958caf1f3da1cba73fb230a575de5347c51
|
7
|
+
data.tar.gz: 31421e16c924c9dfc59318117c9c597f51a31925c7b75bc43248613fa4505f57888cdb0f33e7eb456ab7c5fcdac76f416e5ca158404836e99ae3d20a978b8511
|
data/lib/bales/application.rb
CHANGED
@@ -174,10 +174,14 @@ module Bales
|
|
174
174
|
.map { |p| p.capitalize }
|
175
175
|
.join
|
176
176
|
name = "#{const}::#{part}"
|
177
|
-
|
178
|
-
const
|
179
|
-
|
180
|
-
|
177
|
+
begin
|
178
|
+
if const.const_defined? name
|
179
|
+
const = eval(name)
|
180
|
+
depth += 1
|
181
|
+
else
|
182
|
+
break
|
183
|
+
end
|
184
|
+
rescue NameError
|
181
185
|
break
|
182
186
|
end
|
183
187
|
end
|
data/lib/bales/command/help.rb
CHANGED
@@ -41,8 +41,13 @@ class Bales::Command::Help < Bales::Command
|
|
41
41
|
end
|
42
42
|
|
43
43
|
ns.constants
|
44
|
-
.select { |c|
|
45
|
-
|
44
|
+
.select { |c|
|
45
|
+
begin
|
46
|
+
ns.const_defined? "#{ns}::#{c}"
|
47
|
+
rescue NameError
|
48
|
+
false
|
49
|
+
end
|
50
|
+
}.select { |c| eval("#{ns}::#{c}").class == Class }
|
46
51
|
.select { |c| eval("#{ns}::#{c}") <= Bales::Command }
|
47
52
|
.map { |c| eval "#{ns}::#{c}" }
|
48
53
|
end
|
data/lib/bales/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bales
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan S. Northrup
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-09-05 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: A framework for building command-line applications
|
14
14
|
email:
|
@@ -19,15 +19,10 @@ extra_rdoc_files: []
|
|
19
19
|
files:
|
20
20
|
- README.md
|
21
21
|
- lib/bales.rb
|
22
|
-
- lib/bales.rb~
|
23
22
|
- lib/bales/application.rb
|
24
|
-
- lib/bales/application.rb~
|
25
23
|
- lib/bales/command.rb
|
26
|
-
- lib/bales/command.rb~
|
27
24
|
- lib/bales/command/help.rb
|
28
|
-
- lib/bales/command/help.rb~
|
29
25
|
- lib/bales/version.rb
|
30
|
-
- lib/bales/version.rb~
|
31
26
|
homepage: http://github.com/YellowApple/bales
|
32
27
|
licenses:
|
33
28
|
- MIT
|
@@ -38,17 +33,17 @@ require_paths:
|
|
38
33
|
- lib
|
39
34
|
required_ruby_version: !ruby/object:Gem::Requirement
|
40
35
|
requirements:
|
41
|
-
- -
|
36
|
+
- - '>='
|
42
37
|
- !ruby/object:Gem::Version
|
43
38
|
version: '0'
|
44
39
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
45
40
|
requirements:
|
46
|
-
- -
|
41
|
+
- - '>='
|
47
42
|
- !ruby/object:Gem::Version
|
48
43
|
version: '0'
|
49
44
|
requirements: []
|
50
45
|
rubyforge_project:
|
51
|
-
rubygems_version: 2.4.
|
46
|
+
rubygems_version: 2.4.8
|
52
47
|
signing_key:
|
53
48
|
specification_version: 4
|
54
49
|
summary: Ruby on Bales
|
data/lib/bales.rb~
DELETED
@@ -1,236 +0,0 @@
|
|
1
|
-
# :main: README.md
|
2
|
-
|
3
|
-
##
|
4
|
-
# Ruby on Bales (or just "Bales" for short) is to command-line apps what
|
5
|
-
# Ruby on Rails (or just "Rails" for short) is to websites/webapps.
|
6
|
-
#
|
7
|
-
# The name (and concept) was shamelessly stolen from Jason R. Clark's
|
8
|
-
# "Testing the Multiverse" talk at Ruby on Ales 2015. Here's to hoping that
|
9
|
-
# we, as a Ruby programming community, can get a headstart on a command-line
|
10
|
-
# app framework *before* the Puma-Unicorn Wars ravage the Earth.
|
11
|
-
module Bales
|
12
|
-
##
|
13
|
-
# Base class for Bales apps. Your command-line program should create a
|
14
|
-
# subclass of this, then call said subclass' #parse_and_run instance
|
15
|
-
# method, like so:
|
16
|
-
#
|
17
|
-
# ```ruby
|
18
|
-
# class MyApp::Application < Bales::Application
|
19
|
-
# # insert customizations here
|
20
|
-
# end
|
21
|
-
#
|
22
|
-
# MyApp::Application.parse_and_run
|
23
|
-
# ```
|
24
|
-
class Application
|
25
|
-
##
|
26
|
-
# Runs the specified command (should be a valid class; preferably, should
|
27
|
-
# be a subclass of Bales::Command). Takes a list of positional args
|
28
|
-
# followed by named options.
|
29
|
-
def self.run(command=Bales::Command::Help, *args, **opts)
|
30
|
-
command.run *args, **opts
|
31
|
-
end
|
32
|
-
|
33
|
-
##
|
34
|
-
# Parses ARGV (or some other array if you specify one), returning the
|
35
|
-
# class of the identified command, a hash containing the passed-in
|
36
|
-
# options, and a list of any remaining arguments
|
37
|
-
def self.parse(argv=ARGV)
|
38
|
-
command, result = parse_command_name argv.dup
|
39
|
-
opts, args = command.parse_opts result
|
40
|
-
return command, args, opts
|
41
|
-
end
|
42
|
-
|
43
|
-
##
|
44
|
-
# Parses ARGV (or some other array if you specify one) for a command to
|
45
|
-
# run and its arguments/options, then runs the command.
|
46
|
-
def self.parse_and_run(argv=ARGV)
|
47
|
-
command, args, opts = parse argv
|
48
|
-
run command, *args, **opts
|
49
|
-
end
|
50
|
-
|
51
|
-
private
|
52
|
-
|
53
|
-
def parse_command_name(argv)
|
54
|
-
command_name_parts = []
|
55
|
-
argv.each do |arg|
|
56
|
-
last if arg.match(/^-/)
|
57
|
-
test = args_to_constant [*command_name_parts, arg]
|
58
|
-
if eval("defined? #{test}") == "constant"
|
59
|
-
command_name_parts.push argv.shift
|
60
|
-
else
|
61
|
-
last
|
62
|
-
end
|
63
|
-
end
|
64
|
-
command = args_to_constant [*command_name_parts, arg]
|
65
|
-
command, argv
|
66
|
-
end
|
67
|
-
|
68
|
-
def args_to_constant(argv)
|
69
|
-
result = argv.dup
|
70
|
-
result.map! do |arg|
|
71
|
-
arg.capitalize
|
72
|
-
arg.gsub('-','_').split('_').map { |e| e.capitalize}.join
|
73
|
-
end
|
74
|
-
result.join('::')
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
##
|
79
|
-
# Base class for all Bales commands. Subclass this class to create your
|
80
|
-
# own command, like so:
|
81
|
-
#
|
82
|
-
# ```ruby
|
83
|
-
# class MyApp::Command::Hello < Bales::Command
|
84
|
-
# def self.run(*args, **opts)
|
85
|
-
# puts "Hello, world!"
|
86
|
-
# end
|
87
|
-
# end # produces a `my-app hello` command that prints "Hello, world!"
|
88
|
-
# ```
|
89
|
-
#
|
90
|
-
# Note that the above will accept any number of arguments (including none
|
91
|
-
# at all!). If you want to change this behavior, change `self.run`'s
|
92
|
-
# signature, like so:
|
93
|
-
#
|
94
|
-
# ```ruby
|
95
|
-
# class MyApp::Command::Smack < Bales::Command
|
96
|
-
# def self.run(target, **opts)
|
97
|
-
# puts "#{target} has been smacked with a large trout"
|
98
|
-
# end
|
99
|
-
# end
|
100
|
-
# ```
|
101
|
-
#
|
102
|
-
# Subcommands are automatically derived from namespacing, like so:
|
103
|
-
#
|
104
|
-
# ```ruby
|
105
|
-
# class MyApp::Command::Foo::Bar < Bales::Command
|
106
|
-
# def self.run(*args, **opts)
|
107
|
-
# # ...
|
108
|
-
# end
|
109
|
-
# end # produces `my-app foo bar`
|
110
|
-
# ```
|
111
|
-
#
|
112
|
-
# Camel-cased command classes can be accessed using either hyphenation or
|
113
|
-
# underscores, like so:
|
114
|
-
#
|
115
|
-
# ```ruby
|
116
|
-
# class MyApp::Command::FooBarBaz < Bales::Command
|
117
|
-
# # ...
|
118
|
-
# end
|
119
|
-
# # valid result: "my-app foo-bar-baz"
|
120
|
-
# # also valid: "my-app foo_bar_baz"
|
121
|
-
# ```
|
122
|
-
class Command
|
123
|
-
@options = {}
|
124
|
-
|
125
|
-
##
|
126
|
-
# Runs the command with the provided list of arguments and named options.
|
127
|
-
# Your command should override this method (which by default does
|
128
|
-
# nothing), since this is the method that `Bales::Application.run` calls
|
129
|
-
# in order to actually run your command.
|
130
|
-
#
|
131
|
-
# For example:
|
132
|
-
#
|
133
|
-
# ```ruby
|
134
|
-
# class MyApp::Command::Hello < Bales::Command
|
135
|
-
# def self.run(*args, **opts)
|
136
|
-
# puts "Hello, world!"
|
137
|
-
# end
|
138
|
-
# end
|
139
|
-
# ```
|
140
|
-
def self.run(*args, **opts)
|
141
|
-
end
|
142
|
-
|
143
|
-
##
|
144
|
-
# Defines a named option that the command will accept, along with some
|
145
|
-
# named arguments:
|
146
|
-
#
|
147
|
-
# `:short_form` (optional)
|
148
|
-
# : A shorthand flag to use for the option (like `-v`). This should be a
|
149
|
-
# string, like `"-v"`.
|
150
|
-
#
|
151
|
-
# `:long_form` (optional)
|
152
|
-
# : A longhand flag to use for the option (like `--verbose`). This is
|
153
|
-
# derived from the name of the option if not specified. This should be
|
154
|
-
# a string, like `"--verbose"`
|
155
|
-
#
|
156
|
-
# `:type` (optional)
|
157
|
-
# : The type that this option represents. Defaults to `TrueClass` if
|
158
|
-
# `:arg` is not specified; else, defaults to `String`. This must be a
|
159
|
-
# valid class name.
|
160
|
-
#
|
161
|
-
# A special note on boolean options: if you want your boolean to
|
162
|
-
# default to `true`, set `:type` to `TrueClass`. Likewise, if you want
|
163
|
-
# it to default to `false`, set `:type` to `FalseClass`.
|
164
|
-
#
|
165
|
-
# `:arg` (required unless `:type` is `TrueClass` or `FalseClass`)
|
166
|
-
# : The name of the argument this option accepts. This must not be
|
167
|
-
# defined if `:type` is either `TrueClass` or `FalseClass`; for all
|
168
|
-
# other types, this must be specified. As mentioned above, though, if
|
169
|
-
# `:type` is unspecified, the existence of `:arg` then determines
|
170
|
-
# whether the option's `:type` should default to `TrueClass` or
|
171
|
-
# `String`. This should be a symbol, like `:level`.
|
172
|
-
#
|
173
|
-
# Aside from the hash of option-options, `option` takes a single `name`
|
174
|
-
# argument, which should be a symbol representing the name of the option
|
175
|
-
# to be set, like `:verbose`.
|
176
|
-
def self.option(name, **opts)
|
177
|
-
name = name.to_sym
|
178
|
-
opts[:long_form] ||= "--#{name.to_s}".gsub("_","-")
|
179
|
-
|
180
|
-
unless opts[:type].class == Class
|
181
|
-
raise ArgumentError, ":type option should be a valid class"
|
182
|
-
end
|
183
|
-
|
184
|
-
if opts[:type] == TrueClass or opts[:type] == FalseClass
|
185
|
-
raise ArgumentError, ":arg in boolean opt" unless opts[:arg].nil?
|
186
|
-
else
|
187
|
-
raise ArgumentError, "missing :arg" if opts[:arg].nil?
|
188
|
-
end
|
189
|
-
|
190
|
-
@options[name] = opts
|
191
|
-
end
|
192
|
-
|
193
|
-
##
|
194
|
-
# Takes an ARGV-like array and returns a hash of options and what's left
|
195
|
-
# of the original array. This is rarely needed for normal use, but is
|
196
|
-
# an integral part of how a Bales::Application parses the ARGV it
|
197
|
-
# receives.
|
198
|
-
#
|
199
|
-
# Normally, this should be perfectly fine to leave alone, but if you
|
200
|
-
# prefer to define your own parsing method (e.g. if you want to specify
|
201
|
-
# an alternative format for command-line options, or you are otherwise
|
202
|
-
# dissatisfied with the default approach of wrapping OptionParser), this
|
203
|
-
# is the method you'd want to override.
|
204
|
-
def self.parse_opts(argv)
|
205
|
-
optparser = OptionParser.new
|
206
|
-
result = {}
|
207
|
-
@options.each do |name, opts|
|
208
|
-
result[name] = opts[:default]
|
209
|
-
parser_args = []
|
210
|
-
parser_args.push opts[:short_form]
|
211
|
-
parser_args.push opts[:long_form]
|
212
|
-
unless opts[:type] == TrueClass or opts[:type] == FalseClass
|
213
|
-
parser_args.push opts[:type]
|
214
|
-
end
|
215
|
-
parser_args.push opts[:description]
|
216
|
-
|
217
|
-
if opts[:type] == FalseClass
|
218
|
-
optparser.on(*parser_args) do |value|
|
219
|
-
result[name] = !value
|
220
|
-
end
|
221
|
-
else
|
222
|
-
optparser.on(*parser_args) do |value|
|
223
|
-
result[name] = value
|
224
|
-
end
|
225
|
-
end
|
226
|
-
end
|
227
|
-
end
|
228
|
-
end
|
229
|
-
|
230
|
-
class Command::Help < Command
|
231
|
-
def self.run(*args, **opts)
|
232
|
-
puts "This will someday output some help text"
|
233
|
-
|
234
|
-
end
|
235
|
-
end
|
236
|
-
end
|
data/lib/bales/application.rb~
DELETED
@@ -1,71 +0,0 @@
|
|
1
|
-
##
|
2
|
-
# Base class for Bales apps. Your command-line program should create a
|
3
|
-
# subclass of this, then call said subclass' #parse_and_run instance
|
4
|
-
# method, like so:
|
5
|
-
#
|
6
|
-
# ```ruby
|
7
|
-
# class MyApp::Application < Bales::Application
|
8
|
-
# # insert customizations here
|
9
|
-
# end
|
10
|
-
#
|
11
|
-
# MyApp::Application.parse_and_run
|
12
|
-
# ```
|
13
|
-
class Bales::Application
|
14
|
-
@default_command = Bales::Command::Help
|
15
|
-
def self.default(command=Bales::Command::Help)
|
16
|
-
@default_command = command
|
17
|
-
end
|
18
|
-
|
19
|
-
##
|
20
|
-
# Runs the specified command (should be a valid class; preferably, should
|
21
|
-
# be a subclass of Bales::Command). Takes a list of positional args
|
22
|
-
# followed by named options.
|
23
|
-
def self.run(command, *args, **opts)
|
24
|
-
command.run *args, **opts
|
25
|
-
end
|
26
|
-
|
27
|
-
##
|
28
|
-
# Parses ARGV (or some other array if you specify one), returning the
|
29
|
-
# class of the identified command, a hash containing the passed-in
|
30
|
-
# options, and a list of any remaining arguments
|
31
|
-
def self.parse(argv=ARGV)
|
32
|
-
command, result = parse_command_name argv.dup
|
33
|
-
command ||= @default_command
|
34
|
-
opts, args = command.parse_opts result
|
35
|
-
return command, args, opts
|
36
|
-
end
|
37
|
-
|
38
|
-
##
|
39
|
-
# Parses ARGV (or some other array if you specify one) for a command to
|
40
|
-
# run and its arguments/options, then runs the command.
|
41
|
-
def self.parse_and_run(argv=ARGV)
|
42
|
-
command, args, opts = parse argv
|
43
|
-
run command, *args, **opts
|
44
|
-
end
|
45
|
-
|
46
|
-
private
|
47
|
-
|
48
|
-
def self.parse_command_name(argv)
|
49
|
-
command_name_parts = []
|
50
|
-
argv.each do |arg|
|
51
|
-
last if arg.match(/^-/)
|
52
|
-
test = args_to_constant [*command_name_parts, arg]
|
53
|
-
if eval("defined? #{test}") == "constant"
|
54
|
-
command_name_parts.push argv.shift
|
55
|
-
else
|
56
|
-
last
|
57
|
-
end
|
58
|
-
end
|
59
|
-
command = args_to_constant [*command_name_parts]
|
60
|
-
return command, argv
|
61
|
-
end
|
62
|
-
|
63
|
-
def self.args_to_constant(argv)
|
64
|
-
result = argv.dup
|
65
|
-
result.map! do |arg|
|
66
|
-
arg.capitalize
|
67
|
-
arg.gsub('-','_').split('_').map { |e| e.capitalize}.join
|
68
|
-
end
|
69
|
-
eval result.join('::')
|
70
|
-
end
|
71
|
-
end
|
data/lib/bales/command.rb~
DELETED
@@ -1,189 +0,0 @@
|
|
1
|
-
##
|
2
|
-
# Base class for all Bales commands. Subclass this class to create your
|
3
|
-
# own command, like so:
|
4
|
-
#
|
5
|
-
# ```ruby
|
6
|
-
# class MyApp::Command::Hello < Bales::Command
|
7
|
-
# def self.run(*args, **opts)
|
8
|
-
# puts "Hello, world!"
|
9
|
-
# end
|
10
|
-
# end # produces a `my-app hello` command that prints "Hello, world!"
|
11
|
-
# ```
|
12
|
-
#
|
13
|
-
# Note that the above will accept any number of arguments (including none
|
14
|
-
# at all!). If you want to change this behavior, change `self.run`'s
|
15
|
-
# signature, like so:
|
16
|
-
#
|
17
|
-
# ```ruby
|
18
|
-
# class MyApp::Command::Smack < Bales::Command
|
19
|
-
# def self.run(target, **opts)
|
20
|
-
# puts "#{target} has been smacked with a large trout"
|
21
|
-
# end
|
22
|
-
# end
|
23
|
-
# ```
|
24
|
-
#
|
25
|
-
# Subcommands are automatically derived from namespacing, like so:
|
26
|
-
#
|
27
|
-
# ```ruby
|
28
|
-
# class MyApp::Command::Foo::Bar < Bales::Command
|
29
|
-
# def self.run(*args, **opts)
|
30
|
-
# # ...
|
31
|
-
# end
|
32
|
-
# end # produces `my-app foo bar`
|
33
|
-
# ```
|
34
|
-
#
|
35
|
-
# Camel-cased command classes can be accessed using either hyphenation or
|
36
|
-
# underscores, like so:
|
37
|
-
#
|
38
|
-
# ```ruby
|
39
|
-
# class MyApp::Command::FooBarBaz < Bales::Command
|
40
|
-
# # ...
|
41
|
-
# end
|
42
|
-
# # valid result: "my-app foo-bar-baz"
|
43
|
-
# # also valid: "my-app foo_bar_baz"
|
44
|
-
# ```
|
45
|
-
class Bales::Command
|
46
|
-
@options = {}
|
47
|
-
def self.options
|
48
|
-
@options
|
49
|
-
end
|
50
|
-
def self.options=(new)
|
51
|
-
@options = new
|
52
|
-
end
|
53
|
-
|
54
|
-
##
|
55
|
-
# Assigns an action to this command. Said action is represented as a
|
56
|
-
# block, which should accept an array of arguments and a hash of options.
|
57
|
-
# For example:
|
58
|
-
#
|
59
|
-
# ```ruby
|
60
|
-
# class MyApp::Hello < Bales::Command
|
61
|
-
# action do |args, opts|
|
62
|
-
# puts "Hello, world!"
|
63
|
-
# end
|
64
|
-
# end
|
65
|
-
# ```
|
66
|
-
def self.action(&code)
|
67
|
-
@action = code
|
68
|
-
end
|
69
|
-
|
70
|
-
def self.run(*args, **opts)
|
71
|
-
@action.call(args, opts)
|
72
|
-
end
|
73
|
-
|
74
|
-
##
|
75
|
-
# Defines a named option that the command will accept, along with some
|
76
|
-
# named arguments:
|
77
|
-
#
|
78
|
-
# `:short_form` (optional)
|
79
|
-
# : A shorthand flag to use for the option (like `-v`). This should be a
|
80
|
-
# string, like `"-v"`.
|
81
|
-
#
|
82
|
-
# `:long_form` (optional)
|
83
|
-
# : A longhand flag to use for the option (like `--verbose`). This is
|
84
|
-
# derived from the name of the option if not specified. This should be
|
85
|
-
# a string, like `"--verbose"`
|
86
|
-
#
|
87
|
-
# `:type` (optional)
|
88
|
-
# : The type that this option represents. Defaults to `TrueClass`.
|
89
|
-
# Should be a valid class name, like `String` or `Integer`
|
90
|
-
#
|
91
|
-
# A special note on boolean options: if you want your boolean to
|
92
|
-
# default to `true`, set `:type` to `TrueClass`. Likewise, if you want
|
93
|
-
# it to default to `false`, set `:type` to `FalseClass`.
|
94
|
-
#
|
95
|
-
# `:arg` (optional)
|
96
|
-
# : The name of the argument this option accepts. This should be a
|
97
|
-
# symbol (like :level) or `false` (if the option is a boolean flag).
|
98
|
-
# Defaults to the name of the option or (if the option's `:type` is
|
99
|
-
# `TrueClass` or `FalseClass`) `false`.
|
100
|
-
#
|
101
|
-
# If this is an array, and `:type` is set to `Enumerable` or some
|
102
|
-
# subclass thereof, this will instead be interpreted as a list of
|
103
|
-
# sample arguments during option parsing. It's recommended you set
|
104
|
-
# this accordingly if `:type` is `Enumerable` or any of its subclasses.
|
105
|
-
#
|
106
|
-
# `:required` (optional)
|
107
|
-
# : Whether or not the option is required. This should be a boolean
|
108
|
-
# (`true` or `false`). Default is `false`.
|
109
|
-
#
|
110
|
-
# Aside from the hash of option-options, `option` takes a single `name`
|
111
|
-
# argument, which should be a symbol representing the name of the option
|
112
|
-
# to be set, like `:verbose`.
|
113
|
-
def self.option(name, **opts)
|
114
|
-
name = name.to_sym
|
115
|
-
opts[:long_form] ||= "--#{name.to_s}".gsub("_","-")
|
116
|
-
|
117
|
-
unless opts[:type].is_a? Class
|
118
|
-
raise ArgumentError, ":type option should be a valid class"
|
119
|
-
end
|
120
|
-
|
121
|
-
unless opts[:type].is_a?(TrueClass) or opts[:type].is_a?(FalseClass)
|
122
|
-
opts[:arg] ||= name
|
123
|
-
end
|
124
|
-
|
125
|
-
# if opts[:type] == TrueClass or opts[:type] == FalseClass
|
126
|
-
# raise ArgumentError, ":arg in boolean opt" unless opts[:arg].nil?
|
127
|
-
# else
|
128
|
-
# raise ArgumentError, "missing :arg" if opts[:arg].nil?
|
129
|
-
# end
|
130
|
-
|
131
|
-
result = {}
|
132
|
-
result[name] = opts
|
133
|
-
self.options = result
|
134
|
-
end
|
135
|
-
|
136
|
-
##
|
137
|
-
# Takes an ARGV-like array and returns a hash of options and what's left
|
138
|
-
# of the original array. This is rarely needed for normal use, but is
|
139
|
-
# an integral part of how a Bales::Application parses the ARGV it
|
140
|
-
# receives.
|
141
|
-
#
|
142
|
-
# Normally, this should be perfectly fine to leave alone, but if you
|
143
|
-
# prefer to define your own parsing method (e.g. if you want to specify
|
144
|
-
# an alternative format for command-line options, or you are otherwise
|
145
|
-
# dissatisfied with the default approach of wrapping OptionParser), this
|
146
|
-
# is the method you'd want to override.
|
147
|
-
def self.parse_opts(argv)
|
148
|
-
optparser = OptionParser.new
|
149
|
-
result = {}
|
150
|
-
@options.each do |name, opts|
|
151
|
-
result[name] = opts[:default]
|
152
|
-
parser_args = []
|
153
|
-
parser_args.push opts[:short_form]
|
154
|
-
if opts[:type].is_a?(TrueClass) or opts[:type].is_a?(FalseClass)
|
155
|
-
parser_args.push opts[:long_form]
|
156
|
-
else
|
157
|
-
argstring = opts[:arg].to_s.upcase
|
158
|
-
if opts[:required]
|
159
|
-
parser_args.push "#{opts[:long_form]} #{argstring}"
|
160
|
-
else
|
161
|
-
parser_args.push "#{opts[:long_form]} [#{argstring}]"
|
162
|
-
parser_args.push opts[:type]
|
163
|
-
end
|
164
|
-
parser_args.push opts[:description]
|
165
|
-
|
166
|
-
if opts[:type].is_a? FalseClass
|
167
|
-
optparser.on(*parser_args) do |value|
|
168
|
-
result[name] = !value
|
169
|
-
end
|
170
|
-
else
|
171
|
-
optparser.on(*parser_args) do |value|
|
172
|
-
result[name] = value
|
173
|
-
end
|
174
|
-
end
|
175
|
-
end
|
176
|
-
|
177
|
-
opt_parser.parse! argv
|
178
|
-
return result, argv
|
179
|
-
end
|
180
|
-
end
|
181
|
-
end
|
182
|
-
|
183
|
-
##
|
184
|
-
# Default help command. You'll probably use your own...
|
185
|
-
class Bales::Command::Help < Bales::Command
|
186
|
-
action do |args, opts|
|
187
|
-
puts "This will someday output some help text"
|
188
|
-
end
|
189
|
-
end
|
data/lib/bales/command/help.rb~
DELETED
@@ -1,37 +0,0 @@
|
|
1
|
-
##
|
2
|
-
# Prints help text for a given namespace
|
3
|
-
class Bales::Command::Help < Bales::Command
|
4
|
-
action do |args, opts|
|
5
|
-
puts "This will someday output some help text"
|
6
|
-
end
|
7
|
-
|
8
|
-
private
|
9
|
-
|
10
|
-
def commands(ns)
|
11
|
-
unless eval("defined? #{ns}") == "constant"
|
12
|
-
raise ArgumentError, "expected a constant, but got a #{ns.class}"
|
13
|
-
end
|
14
|
-
|
15
|
-
ns.constants
|
16
|
-
.select { |c| eval("#{ns}::#{c}") <= Bales::Command }
|
17
|
-
.map { |c| eval "#{ns}::#{c}" }
|
18
|
-
end
|
19
|
-
|
20
|
-
def format_option(name, opts, width=72)
|
21
|
-
long = "#{opts[:long_form]}"
|
22
|
-
if opts[:type] <= TrueClass or opts[:type] <= FalseClass
|
23
|
-
if opts[:required]
|
24
|
-
long << " #{opts[:arg]}"
|
25
|
-
else
|
26
|
-
long << " [#{opts[:arg]}]"
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
output = "#{name} (#{opts[:type]}): "
|
31
|
-
output << "#{opts[:short_form]} / " if opts[:short_form]
|
32
|
-
output << long
|
33
|
-
output << "\n"
|
34
|
-
output << opts[:description]
|
35
|
-
output
|
36
|
-
end
|
37
|
-
end
|
data/lib/bales/version.rb~
DELETED