bales 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8545457d99fcc8ad1f955a400e85117f9232bafb
4
- data.tar.gz: 6b071c4698777e472fbced6eac86c5c4ecf398c4
3
+ metadata.gz: 17750f3056694dcabc3be1c2ac111978e179043f
4
+ data.tar.gz: b6087e538fd4eccb2e614b1dbd539cf4058b5e90
5
5
  SHA512:
6
- metadata.gz: e993e329e43ce41ee9388ccc0e6fe4170df541b0545a699bbfdab237768e69bace8b8e1b8198756403d387430b897d4ea0ffbaff0c80e5b842b70cf7b8d4df39
7
- data.tar.gz: 0c8ae1f87771e60d703be9338c8438bc529acfd85ed2bb43b5f5fd706ac08c0ba397f14bcd2ee7093742ec0557398a4995b5ad4ca2fdd323bae35e8c6e25bab0
6
+ metadata.gz: 05e0241f93ac005d784ca7d66bc806de2e5ef609c947bf69c1cdbbd338512f6c6170697f47561a6476ac40084e02a958caf1f3da1cba73fb230a575de5347c51
7
+ data.tar.gz: 31421e16c924c9dfc59318117c9c597f51a31925c7b75bc43248613fa4505f57888cdb0f33e7eb456ab7c5fcdac76f416e5ca158404836e99ae3d20a978b8511
@@ -174,10 +174,14 @@ module Bales
174
174
  .map { |p| p.capitalize }
175
175
  .join
176
176
  name = "#{const}::#{part}"
177
- if const.const_defined? name
178
- const = eval(name)
179
- depth += 1
180
- else
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
@@ -41,8 +41,13 @@ class Bales::Command::Help < Bales::Command
41
41
  end
42
42
 
43
43
  ns.constants
44
- .select { |c| ns.const_defined? "#{ns}::#{c}" }
45
- .select { |c| eval("#{ns}::#{c}").class == Class }
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
@@ -1,3 +1,3 @@
1
1
  module Bales
2
- VERSION="0.1.1"
2
+ VERSION="0.1.2"
3
3
  end
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.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-08-18 00:00:00.000000000 Z
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.6
46
+ rubygems_version: 2.4.8
52
47
  signing_key:
53
48
  specification_version: 4
54
49
  summary: Ruby on Bales
@@ -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
@@ -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
@@ -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
@@ -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
@@ -1,3 +0,0 @@
1
- module Bales
2
- VERSION="0.0.0"
3
- end