commandable 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +91 -57
- data/commandable.gemspec +2 -16
- data/lib/commandable/app_controller.rb +3 -3
- data/lib/commandable/commandable.rb +65 -20
- data/lib/commandable/exceptions.rb +4 -1
- data/lib/commandable/version.rb +1 -1
- data/lib/monkey_patch/os.rb +8 -0
- data/spec/commandable/attr_accessor_spec.rb +88 -0
- data/spec/commandable/command_line_execution_spec.rb +11 -6
- data/spec/commandable/helpers_spec.rb +5 -5
- data/spec/commandable/instance_methods_spec.rb +45 -0
- data/spec/commandable/required_default_spec.rb +38 -0
- data/spec/source_code_examples/attr_accessor.rb +13 -0
- data/spec/source_code_examples/attr_accessor_multi.rb +13 -0
- data/spec/source_code_examples/class_command_no_command.rb +0 -1
- data/spec/source_code_examples/class_methods.rb +0 -1
- data/spec/source_code_examples/class_methods_nested.rb +0 -1
- data/spec/source_code_examples/command_no_command.rb +0 -1
- data/spec/source_code_examples/deep_class.rb +0 -1
- data/spec/source_code_examples/default_method.rb +0 -1
- data/spec/source_code_examples/default_method_multiparameters.rb +0 -1
- data/spec/source_code_examples/default_method_no_params.rb +0 -1
- data/spec/source_code_examples/instance_methods.rb +16 -0
- data/spec/source_code_examples/instance_methods2.rb +16 -0
- data/spec/source_code_examples/multi_line_description.rb +0 -1
- data/spec/source_code_examples/multi_line_description_no_params.rb +0 -1
- data/spec/source_code_examples/no_description.rb +0 -1
- data/spec/source_code_examples/parameter_class.rb +0 -1
- data/spec/source_code_examples/parameter_free.rb +0 -1
- data/spec/source_code_examples/required_default.rb +11 -0
- data/spec/source_code_examples/required_methods.rb +0 -1
- data/spec/source_code_examples/super_deep_class.rb +0 -1
- data/spec/source_code_examples/test_class.rb +0 -1
- data/spec/source_code_examples/xor_class.rb +0 -1
- data/spec/source_code_for_errors/class_bad.rb +0 -1
- data/spec/source_code_for_errors/default_method_bad.rb +0 -1
- data/spec/source_code_for_errors/private_methods_bad.rb +1 -2
- data/spec/spec_helper.rb +10 -4
- metadata +35 -28
data/README.markdown
CHANGED
@@ -1,45 +1,55 @@
|
|
1
1
|
# Commandable
|
2
|
-
The easiest way to add command line control to your Ruby app.
|
2
|
+
The easiest way to add command line control to your Ruby app.
|
3
3
|
|
4
|
-
Stop wasting time writing WET (Write Everything Twice) command line interpreters, or repeatedly writing code for existing ones like optparser, then writing help/usage methods that you constantly
|
4
|
+
Stop wasting time writing WET (Write Everything Twice) command line interpreters, or repeatedly writing code for existing ones like optparser, then writing help/usage methods that you constantly must update as your code changes. Now you can add a single line above an existing method and that method will be available from the command line.
|
5
5
|
|
6
|
-
Best of all the help/usage instructions are automatically generated using the method itself! When you change your methods the help instructions change automajically! There's no extra effort needed on your part.
|
6
|
+
Best of all the help/usage instructions are automatically generated using the method itself! When you change your methods the help instructions change automajically! There's no extra effort needed on your part.
|
7
7
|
|
8
8
|
The whole process can take as little as four lines of code:
|
9
9
|
|
10
|
-
* You put a `command "I do something!"` line above your method.
|
11
10
|
* Add a `require 'commandable'` line somewhere (I'd put it in my bin).
|
12
11
|
* Then an `extend Commandable` inside your class.
|
13
|
-
*
|
12
|
+
* Put a `command "I do something!"` line above your method.
|
13
|
+
* And finally make a call to `Commandable.execute(ARGV)` in your bin file.
|
14
14
|
|
15
|
-
|
15
|
+
Now any method you want to make accessible from the command line requires just a single line of code and it's right where your method is so it's easy to find when you do want to change some functionality.
|
16
|
+
|
17
|
+
Don't think of **Commandable** as a way to add command line switches, it's much more than that. Think of it as a way to allow your app to be driven directly from the command line.
|
18
|
+
|
19
|
+
You can now "use your words" to let people interact with your apps in a natural way. No more confusing switches that mean one thing in one program and something completely different in another. Can you believe some apps actually use `-v` for something other than "version" and `-h` for something other than "help?" Madness I say! Madness!
|
16
20
|
|
17
|
-
You can now "use your words" to let people interact with your apps in a natural way.
|
18
21
|
|
19
22
|
## Testing for a Better Tomorrow ##
|
20
23
|
|
21
|
-
|
24
|
+
In an effort to make the best possible software I'm asking anyone that would like to help out to run the BDD/TDD tests included with the gem. If you don't already have the `rubygems-test` gem installed please install it:
|
25
|
+
|
26
|
+
$ gem install rubygems-test
|
27
|
+
|
28
|
+
And then run the tests on your machine:
|
22
29
|
|
23
|
-
|
30
|
+
$ gem test commandable
|
24
31
|
|
25
|
-
|
32
|
+
And of course upload them when it asks you if it can. You can take a look at the test results yourself here:
|
33
|
+
|
34
|
+
<http://test.rubygems.org/gems/commandable/v/0.2.0>
|
26
35
|
|
27
36
|
Thanks for your help.
|
28
37
|
|
29
38
|
|
30
39
|
## Status
|
31
40
|
|
32
|
-
2011-
|
41
|
+
2011-04-04 - Version: 0.2.1
|
33
42
|
|
43
|
+
See change history for additions.
|
34
44
|
|
35
45
|
## Principle of Least Surprise
|
36
46
|
|
37
|
-
I've tried to follow the principle of least surprise so Commandable should just work like you would expect it to. As long as you expect it to work the same way as I do.
|
47
|
+
I've tried to follow the principle of least surprise so Commandable should just work like you would expect it to. As long as you expect it to work the same way as I do.
|
38
48
|
|
39
49
|
## Requirements ##
|
40
50
|
|
41
51
|
* Ruby 1.9.2
|
42
|
-
*
|
52
|
+
* Any Posix OS (It works, mostly, on Windows but ironically some of the tests won't run because of some unix commands I use in the tests)
|
43
53
|
|
44
54
|
## Installation
|
45
55
|
From the command line:
|
@@ -49,17 +59,17 @@ From the command line:
|
|
49
59
|
|
50
60
|
## Usage Instructions
|
51
61
|
|
52
|
-
After installing the **Commandable** gem require it somewhere that gets loaded before your class does:
|
62
|
+
After installing the **Commandable** gem require it somewhere that gets loaded before your class does:
|
53
63
|
|
54
64
|
require 'commandable'
|
55
65
|
|
56
|
-
Extend your class with the **Commandable** module:
|
66
|
+
Extend your class with the **Commandable** module:
|
57
67
|
|
58
68
|
class Widget
|
59
69
|
extend Commandable
|
60
70
|
|
61
71
|
Then put `command` and a description above the method you want to make accessible. The description is optional but can be helpful
|
62
|
-
since it's used when automatically building your help/usage instructions.
|
72
|
+
since it's used when automatically building your help/usage instructions.
|
63
73
|
|
64
74
|
command "create a new widget"
|
65
75
|
def new(name)
|
@@ -71,46 +81,48 @@ since it's used when automatically building your help/usage instructions.
|
|
71
81
|
command ["description"], [:required], [:default], [:priority=>(0...n)], [:xor[=>:group_name]]
|
72
82
|
|
73
83
|
_**command**_ _(required)_
|
74
|
-
This is the only thing that's required. It tells **Commandable** to add the method that follows to the list of methods available from the command line.
|
84
|
+
This is the only thing that's required. It tells **Commandable** to add the method that follows to the list of methods available from the command line.
|
75
85
|
|
76
86
|
_**description**_ [optional]
|
77
|
-
As you would imagine this is a short description of what the method does. You can have multiple lines by using a new line, `\n`, in the description and your description will be lined up properly. This prints in the help/usage instructions when a user calls your programing using the command "help" or if they try to issue a command that doesn't exist. Help instructions will also print if they try to use your app without any parameters (if there isn't a default method that doesn't require parameters.).
|
87
|
+
As you would imagine this is a short description of what the method does. You can have multiple lines by using a new line, `\n`, in the description and your description will be lined up properly. This prints in the help/usage instructions when a user calls your programing using the command "help" or if they try to issue a command that doesn't exist. Help instructions will also print if they try to use your app without any parameters (if there isn't a default method that doesn't require parameters.).
|
78
88
|
|
79
89
|
_**:required**_ [optional]
|
80
|
-
You can mark a method as required and the user must specify this command and any required parameters every time they run your app.
|
90
|
+
You can mark a method as required and the user must specify this command and any required parameters every time they run your app. You can also have a method marked as both :default and :required which allows you to run a method with a required parameter but you don't have to type the method name.
|
81
91
|
|
82
92
|
_**:default**_ [optional]
|
83
|
-
You can have one and only one default method. This method will be called if your app is called with just parameters or if the first command line parameter isn't a command. The user can still give more commands after the parameters for the default command too.
|
93
|
+
You can have one and only one default method. This method will be called if your app is called with just parameters or if the first command line parameter isn't a command. The user can still give more commands after the parameters for the default command too.
|
84
94
|
|
85
|
-
For instance say your default method is :foo that takes one parameter and you have another method called :bar that also takes one parameter. A user could do this:
|
95
|
+
For instance say your default method is :foo that takes one parameter and you have another method called :bar that also takes one parameter. A user could do this:
|
86
96
|
|
87
97
|
yourapp "Some Parameter" bar "A parameter for bar"
|
88
98
|
|
89
|
-
Just be aware that if they give an option that has the same name as a function the app will think it's a command.
|
99
|
+
Just be aware that if they give an option that has the same name as a function the app will think it's a command.
|
90
100
|
|
91
101
|
_**priority=>n**_ [optional]
|
92
|
-
This optional setting allows you to assign priorities to your methods so if you need them to be executed in a specific order, regardless of how the user specifies them on the command line, you can use this. Then when you execute the command line or ask for a queue of commands they will be sorted for you by priority.
|
102
|
+
This optional setting allows you to assign priorities to your methods so if you need them to be executed in a specific order, regardless of how the user specifies them on the command line, you can use this. Then when you execute the command line or ask for a queue of commands they will be sorted for you by priority.
|
93
103
|
|
94
|
-
The higher the priority the sooner the method will be executed. If you do not specify a priority a method will have a priority of 0, the lowest priority.
|
104
|
+
The higher the priority the sooner the method will be executed. If you do not specify a priority a method will have a priority of 0, the lowest priority.
|
95
105
|
|
96
|
-
Note that you can have a default method with a lower priority than a non-default method.
|
106
|
+
Note that you can have a default method with a lower priority than a non-default method.
|
97
107
|
|
98
108
|
_**:xor[=>:whatever]**_ [optional]
|
99
|
-
The :xor parameter allows you to configure a group of methods as mutually exclusive, i.e. if method1 and method2 are in the same :xor group the user of your application can only call one of them at a time.
|
109
|
+
The :xor parameter allows you to configure a group of methods as mutually exclusive, i.e. if method1 and method2 are in the same :xor group the user of your application can only call one of them at a time.
|
100
110
|
|
101
|
-
You can use just the :xor symbol and the method will be put into the default XOR group, called :xor so :xor=>:xor, but if you need multiple XOR groups you can specify a group name by using a hash instead of just the :xor symbol.
|
111
|
+
You can use just the :xor symbol and the method will be put into the default XOR group, called :xor so :xor=>:xor, but if you need multiple XOR groups you can specify a group name by using a hash instead of just the :xor symbol.
|
102
112
|
|
103
|
-
The XOR group name will be printed in the front to the description text so it's probably a good idea to use :xor as the prefix.
|
113
|
+
The XOR group name will be printed in the front to the description text so it's probably a good idea to use :xor as the prefix.
|
104
114
|
|
105
115
|
|
106
116
|
### Parameter lists
|
107
|
-
|
117
|
+
When building the help/usage instructions a list of parameters for each command is automatically created using the names you give the parameters in your method; make sure you use descriptive names.
|
118
|
+
|
119
|
+
Also keep in mind that all command line parameters are strings so you need to deal with that inside your methods if what you really want is a number.
|
108
120
|
|
109
|
-
If none of your methods have parameters then there won't be any reference to parameters in the help/usage instructions.
|
121
|
+
If none of your methods have parameters then there won't be any reference to parameters in the help/usage instructions. The description text will be moved over to be closer to your commands.
|
110
122
|
|
111
123
|
### A complete class
|
112
124
|
|
113
|
-
A complete class might look like this:
|
125
|
+
A complete class might look like this:
|
114
126
|
|
115
127
|
require 'commandable'
|
116
128
|
|
@@ -123,8 +135,8 @@ A complete class might look like this:
|
|
123
135
|
end
|
124
136
|
|
125
137
|
command "destroy an existing widget", :xor
|
126
|
-
def
|
127
|
-
"No
|
138
|
+
def delete(name)
|
139
|
+
"No disassemble #{name}! #{name} is alive!"
|
128
140
|
end
|
129
141
|
|
130
142
|
command "spend lots of money to update a widget", :xor
|
@@ -132,10 +144,15 @@ A complete class might look like this:
|
|
132
144
|
"You just gave #{name} a nice new coat of paint!"
|
133
145
|
end
|
134
146
|
|
147
|
+
command "your security key must be entered for every command", :required
|
148
|
+
def key(security)
|
149
|
+
# blah, blah, blah
|
150
|
+
end
|
151
|
+
|
135
152
|
end
|
136
153
|
|
137
154
|
#### Class methods
|
138
|
-
You can also use it on class methods:
|
155
|
+
You can also use it on class methods:
|
139
156
|
|
140
157
|
require "commandable"
|
141
158
|
|
@@ -156,7 +173,7 @@ You can also use it on class methods:
|
|
156
173
|
end
|
157
174
|
end
|
158
175
|
|
159
|
-
If you want to do a block of class commands using `class << self` you need to put `extend Commandable` inside the block:
|
176
|
+
If you want to do a block of class commands using `class << self` you need to put `extend Commandable` inside the block:
|
160
177
|
|
161
178
|
require "commandable"
|
162
179
|
|
@@ -177,31 +194,33 @@ If you want to do a block of class commands using `class << self` you need to pu
|
|
177
194
|
end
|
178
195
|
|
179
196
|
|
180
|
-
Note: Class methods are called directly on the class while instance methods have an instance created for
|
197
|
+
Note: Class methods are called directly on the class while instance methods have an instance created for all calls to that class. This means if you set an instance variable in one method it will be available to any other method calls to that same class; just as if you had created an instance of your class and called methods on it.
|
181
198
|
|
182
199
|
### Automatic usage/help generation ###
|
183
200
|
|
184
|
-
One of the great features of **Commandable** is that
|
201
|
+
One of the great features of **Commandable** is that automatically creates usage instructions based on your methods and the descriptions you provide for them and it adds a `help` command for you.
|
202
|
+
|
203
|
+
If your app has no `:default` method or it has a default command that requires parameters the help/usage instructions will be printed if a user just runs your app without any input.
|
185
204
|
|
186
205
|
A typical help output looks something like this:
|
187
206
|
|
188
|
-
|
189
|
-
|
190
|
-
|
207
|
+
Commandable - The easiest way to add command line control to your app.
|
208
|
+
Copyrighted free software - Copyright (c) 2011 Mike Bethany.
|
209
|
+
Version: 0.2.0
|
191
210
|
|
192
|
-
|
211
|
+
Usage: commandable <command> [parameters] [<command> [parameters]...]
|
193
212
|
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
213
|
+
Command Parameters Description
|
214
|
+
error : Will raise a programmer error, not a user error
|
215
|
+
so you see what happens when you have bad code
|
216
|
+
examples [path] : Copies the test classes to a folder so
|
217
|
+
you can see a bunch of small examples
|
218
|
+
readme : displays the readme file (default)
|
219
|
+
v : <xor> Application Version
|
220
|
+
version : <xor> Application Version
|
221
|
+
widget [path] : Downloads a fully working app demonstrating how
|
222
|
+
to use Commandable with RSpec and Cucumber
|
223
|
+
help : you're looking at it now
|
205
224
|
|
206
225
|
|
207
226
|
|
@@ -210,17 +229,19 @@ For a fully working example with RSpec and Cucumber tests run this command:
|
|
210
229
|
|
211
230
|
$ commandable widget [path]
|
212
231
|
|
213
|
-
|
232
|
+
In addition **Commandable** uses **Commandable** for its own command line options so you can also look at the `lib/commandable/app_controller.rb class` for an example.
|
233
|
+
|
234
|
+
If you would like to see a bunch of simple classes that demonstrate **Commandable**'s uses run:
|
214
235
|
|
215
236
|
$ commandable examples [path]
|
216
237
|
|
217
238
|
### Commandable Options
|
218
239
|
|
219
|
-
These are the basic options you
|
240
|
+
These are the basic options you'll want to be aware of. Specifically you really want to set `Commandable#app_exe` and `Commandable#app_info` so that the help/usage instructions are fully fleshed out.
|
220
241
|
|
221
242
|
**Commandable.app\_exe**
|
222
243
|
_default = ""_
|
223
|
-
This is what a user would type to run your app; don't set it to "My App" set it to "myapp". When this is
|
244
|
+
This is what a user would type to run your app; don't set it to "My App" set it to "myapp". When this is configured the help instructions will include a usage line with your executable's name.
|
224
245
|
|
225
246
|
**Commandable.app\_info**
|
226
247
|
_default = ""_
|
@@ -399,11 +420,24 @@ If you have any questions about how the code works I've tried to give as much in
|
|
399
420
|
Most of all it should be simple to use so if you have any problems please drop me a line. Also if you make any changes please send me a pull request. I hate when people don't respond to them, even to deny them, so I'm pretty good about that sort of thing.
|
400
421
|
|
401
422
|
|
423
|
+
## Version History ##
|
424
|
+
|
425
|
+
2011-04-04 - Version: 0.2.1
|
426
|
+
|
427
|
+
* Added ability to use attr\_accessor and att\_writer as commands. You can only write to them of course but it's an easy way to set values.
|
428
|
+
* Instance methods now retain state between different calls. In other words if you set an instance variable in one method it will be available to any other instance method calls for that class. It's as if you created an instance of your class and called the methods yourself. You can access the class instances using the hash Commandable.class\_cache. It is has the class name, a string, as the key and the instance of the class as the value. {"ClassName"=>#<ClassName:0x00000100b1f188>}
|
429
|
+
* You can now have the execute command work without outputting anything. Just add :silent (or anything other than nil or false) to the execution method. For instance `Commandable.execute(ARGV,:silent)`.
|
430
|
+
* Clarified error message for default methods that are also required. If you don't give anything it tells you you need to give a parameter but you don't specifically have to give the switch.
|
431
|
+
|
432
|
+
2011-03-23 - Version: 0.2.0
|
433
|
+
|
434
|
+
* First public release. It's 0.2.0 because 0.1.0 was called Cloptions and wasn't released.
|
435
|
+
|
402
436
|
## To Do
|
403
437
|
|
404
|
-
|
438
|
+
Nothing in this version.
|
405
439
|
|
406
|
-
###Next version:
|
440
|
+
### Next major version:
|
407
441
|
|
408
442
|
* Add a way to use or discover version numbers. Might have to force standardization and not allow configuration since it should be DRY.
|
409
443
|
* Needs a massive refactoring.
|
data/commandable.gemspec
CHANGED
@@ -13,22 +13,8 @@ Gem::Specification.new do |s|
|
|
13
13
|
s.homepage = "http://mikbe.tk"
|
14
14
|
s.summary = %q{The easiest way to add command line control to your Ruby apps.}
|
15
15
|
s.description = <<EOF
|
16
|
-
The easiest way to add command line control to your Ruby app.
|
17
|
-
|
18
|
-
Stop wasting time writing WET (Write Everything Twice) command line interpreters, or repeatedly writing code for existing ones like optparser, then writing help/usage methods that you constantly have to update as your code changes. Now you can add a single line above an existing method and that method will be available from the command line.
|
19
|
-
|
20
|
-
Best of all the help/usage instructions are automatically generated using the method itself! When you change your methods the help instructions change automajically! There's no extra effort needed on your part.
|
21
|
-
|
22
|
-
The whole process can take as little as four lines of code:
|
23
|
-
|
24
|
-
* You put a `command "I do something!"` line above your method.
|
25
|
-
* Add a `require 'commandable'` line somewhere (I'd put it in my bin).
|
26
|
-
* Then an `extend Commandable` inside your class.
|
27
|
-
* And finally a call to `Commandable.execute(ARGV)` in your bin file.
|
28
|
-
|
29
|
-
Don't think of Commandable as a way to add command line switches to your app but as a way to allow your app to be driven directly from the command line. No more confusing switches that mean one thing in one program and something completely different in another. (Can you believe some apps actually use `-v` for something other than "version" and `-h` for something other than "help?" Madness I say! Madness!)
|
30
|
-
|
31
|
-
You can now "use your words" to let people interact with your apps in a natural way.
|
16
|
+
The easiest way to add command line control to your Ruby app. You can add a single line above an existing method and that method will be available from the command line.
|
17
|
+
Best of all the help/usage instructions are automatically generated using the method definition itself. When you change your methods the help instructions change automajically!
|
32
18
|
EOF
|
33
19
|
|
34
20
|
s.license = 'MIT'
|
@@ -13,7 +13,7 @@ module Commandable
|
|
13
13
|
`open #{File.expand_path((File.dirname(__FILE__) + '/../../readme.markdown'))}`
|
14
14
|
end
|
15
15
|
|
16
|
-
command "
|
16
|
+
command "Downloads a fully working app demonstrating how\nto use Commandable with RSpec and Cucumber"
|
17
17
|
# Creates a simple example app demonstrating a fully working app
|
18
18
|
def widget(path="./widget")
|
19
19
|
# Test for Git
|
@@ -21,7 +21,7 @@ module Commandable
|
|
21
21
|
puts "Git must be installed to download Widget (You're a developer and you don't have Git installed?)"
|
22
22
|
return
|
23
23
|
end
|
24
|
-
# Git already has all of
|
24
|
+
# Git already has all of its own error trapping so
|
25
25
|
# it would be horrible coupling and duplication
|
26
26
|
# of effort to do anything on my end for failures.
|
27
27
|
puts "\nUnable to download Widget. You can find the souce code here:\nhttps#{WIDGET_GITHUB}" unless download_widget(path) == 0
|
@@ -46,7 +46,7 @@ module Commandable
|
|
46
46
|
FileUtils.copy_dir(File.expand_path(File.dirname(__FILE__) + '/../../spec/source_code_examples'),path)
|
47
47
|
end
|
48
48
|
|
49
|
-
command "Will raise a programmer error, not a user error\nso you see what happens when you have bad code"
|
49
|
+
command "Will raise a programmer error, not a user error\nso you can see what happens when you have bad code"
|
50
50
|
# Causes an error so you can see what it will look like if you have an error in your code.
|
51
51
|
def error
|
52
52
|
raise Exception, "An example of a non-user error caused by your bad code trapped in Commandable.execute()"
|
@@ -53,6 +53,12 @@ module Commandable
|
|
53
53
|
@@commands.dup
|
54
54
|
end
|
55
55
|
|
56
|
+
# A hash of instances created when calling instance methods
|
57
|
+
# It's keyed using the class name: {"ClassName"=>#<ClassName:0x00000100b1f188>}
|
58
|
+
def class_cache
|
59
|
+
@@class_cache
|
60
|
+
end
|
61
|
+
|
56
62
|
# Access the command array using the method name (symbol or string)
|
57
63
|
def [](index)
|
58
64
|
raise AccessorError unless index.is_a? String or index.is_a? Symbol
|
@@ -68,8 +74,8 @@ module Commandable
|
|
68
74
|
@app_exe = nil
|
69
75
|
@verbose_parameters = true
|
70
76
|
@@default_method = nil
|
77
|
+
@@class_cache = {}
|
71
78
|
end
|
72
|
-
alias :init :reset_all
|
73
79
|
|
74
80
|
# Clears all methods from the list of available commands
|
75
81
|
# This is mostly useful for testing.
|
@@ -138,11 +144,12 @@ module Commandable
|
|
138
144
|
# A wrapper for the execution_queue that runs the queue and traps errors.
|
139
145
|
# If an error occurs inside this method it will print out a complete.
|
140
146
|
# of availavle methods with usage instructios and exit gracefully.
|
141
|
-
def execute(argv)
|
147
|
+
def execute(argv, silent=false)
|
142
148
|
begin
|
143
149
|
command_queue = execution_queue(argv)
|
144
150
|
command_queue.each do |com|
|
145
|
-
|
151
|
+
return_value = com[:proc].call
|
152
|
+
puts return_value unless silent
|
146
153
|
end
|
147
154
|
rescue Exception => exception
|
148
155
|
if exception.respond_to?(:friendly_name)
|
@@ -170,7 +177,8 @@ module Commandable
|
|
170
177
|
end
|
171
178
|
arguments << "help" if arguments.empty?
|
172
179
|
|
173
|
-
# Parse the
|
180
|
+
# Parse the command line into methods and their parameters
|
181
|
+
|
174
182
|
arguments.each do |arg|
|
175
183
|
if Commandable[arg]
|
176
184
|
last_method = arg.to_sym
|
@@ -190,29 +198,45 @@ module Commandable
|
|
190
198
|
end
|
191
199
|
method_hash[last_method] << arg
|
192
200
|
end
|
193
|
-
|
194
|
-
|
201
|
+
# Test for missing required switches
|
202
|
+
@@commands.select do |key, value|
|
203
|
+
if value[:required] and method_hash[key].nil?
|
204
|
+
# If the required switch is also a default have the error be a missing parameter instead of a missing command
|
205
|
+
if value[:default]
|
206
|
+
method_hash.merge!(key=>[])
|
207
|
+
else
|
208
|
+
raise MissingRequiredCommandError, key
|
209
|
+
end
|
210
|
+
end
|
195
211
|
end
|
196
212
|
end
|
197
|
-
|
213
|
+
#puts "method_hash: #{method_hash}" if method_hash.to_s.include?("required_default")
|
214
|
+
|
198
215
|
# Build an array of procs to be called for each method and its given parameters
|
199
216
|
proc_array = []
|
200
217
|
method_hash.each do |meth, params|
|
201
218
|
command = @@commands[meth]
|
219
|
+
|
220
|
+
if command[:parameters] && !command[:parameters].empty?
|
221
|
+
|
222
|
+
#Change the method name for attr_writers
|
223
|
+
meth = "#{meth}=" if command[:parameters][0][0] == :writer
|
202
224
|
|
203
|
-
|
204
|
-
|
205
|
-
if required
|
225
|
+
# Get a list of required parameters and make sure all of them were provided
|
226
|
+
required = command[:parameters].select{|param| [:req, :writer].include?(param[0])}
|
206
227
|
required.shift(params.count)
|
207
|
-
raise MissingRequiredParameterError, {:method=>meth, :parameters=>required.collect!{|meth| meth[1]}.to_s[1...-1].gsub(":","")} unless required.empty?
|
228
|
+
raise MissingRequiredParameterError, {:method=>meth, :parameters=>required.collect!{|meth| meth[1]}.to_s[1...-1].gsub(":",""), :default=>command[:default]} unless required.empty?
|
208
229
|
end
|
209
|
-
|
230
|
+
|
210
231
|
# Test for duplicate XORs
|
211
232
|
proc_array.select{|x| x[:xor] and x[:xor]==command[:xor] }.each {|bad| raise ExclusiveMethodClashError, "#{meth}, #{bad[:method]}"}
|
212
233
|
|
213
234
|
klass = Object
|
214
235
|
command[:class].split(/::/).each { |name| klass = klass.const_get(name) }
|
215
|
-
|
236
|
+
## Look for class in class cache
|
237
|
+
unless command[:class_method]
|
238
|
+
klass = (@@class_cache[klass.name] ||= klass.new)
|
239
|
+
end
|
216
240
|
proc_array << {:method=>meth, :xor=>command[:xor], :parameters=>params, :priority=>command[:priority], :proc=>lambda{klass.send(meth, *params)}}
|
217
241
|
end
|
218
242
|
proc_array.sort{|a,b| a[:priority] <=> b[:priority]}.reverse
|
@@ -221,8 +245,8 @@ module Commandable
|
|
221
245
|
|
222
246
|
# Set colors to their default values
|
223
247
|
def reset_colors
|
224
|
-
# Colors - off by default
|
225
248
|
@color_output ||= true
|
249
|
+
|
226
250
|
# Build the default colors
|
227
251
|
Term::ANSIColorHI.coloring = color_output
|
228
252
|
c = Term::ANSIColorHI
|
@@ -253,7 +277,7 @@ module Commandable
|
|
253
277
|
def set_colors
|
254
278
|
if color_output
|
255
279
|
@c_app_info = @color_app_info
|
256
|
-
@c_app_exe
|
280
|
+
@c_app_exe = @color_app_exe
|
257
281
|
@c_command = @color_command
|
258
282
|
@c_description = @color_description
|
259
283
|
@c_parameter = @color_parameter
|
@@ -273,7 +297,9 @@ module Commandable
|
|
273
297
|
end
|
274
298
|
|
275
299
|
end
|
276
|
-
|
300
|
+
|
301
|
+
# inititialize the Commandable's settings when it's loaded
|
302
|
+
reset_all
|
277
303
|
|
278
304
|
private
|
279
305
|
|
@@ -281,6 +307,7 @@ module Commandable
|
|
281
307
|
# It lets you add a method to the list of command line methods
|
282
308
|
def command(*cmd_parameters)
|
283
309
|
|
310
|
+
@@attribute = nil
|
284
311
|
@@method_file = nil
|
285
312
|
@@method_line = nil
|
286
313
|
@@command_options = {}
|
@@ -310,6 +337,8 @@ module Commandable
|
|
310
337
|
|
311
338
|
set_trace_func proc { |event, file, line, id, binding, classname|
|
312
339
|
|
340
|
+
@@attribute = id if [:attr_accessor, :attr_writer].include?(id)
|
341
|
+
|
313
342
|
# Traps the line where the method is defined so we can look up
|
314
343
|
# the method source code later if there are optional parameters
|
315
344
|
if event == "line" and !@@method_file
|
@@ -328,8 +357,15 @@ module Commandable
|
|
328
357
|
# Add a method to the list of available command line methods
|
329
358
|
def add_command(meth)
|
330
359
|
@@commands.delete(:help)
|
331
|
-
|
360
|
+
|
361
|
+
if @@attribute
|
362
|
+
argument_list = "value"
|
363
|
+
meth = meth.to_s.delete("=").to_sym if @@attribute == :attr_writer
|
364
|
+
else
|
365
|
+
argument_list = parse_arguments(@@command_options[:parameters])
|
366
|
+
end
|
332
367
|
@@command_options.merge!(:argument_list=>argument_list,:class => self.name)
|
368
|
+
|
333
369
|
@@commands.merge!(meth => @@command_options)
|
334
370
|
@@default_method = {meth => @@command_options} if @@command_options[:default]
|
335
371
|
|
@@ -337,13 +373,22 @@ module Commandable
|
|
337
373
|
|
338
374
|
@@commands.merge!(HELP_COMMAND.dup) # makes sure the help command is always last
|
339
375
|
@@command_options = nil
|
376
|
+
@@attribute = nil
|
340
377
|
end
|
341
378
|
|
342
379
|
# Trap method creation after a command call
|
343
380
|
def method_added(meth)
|
344
381
|
set_trace_func(nil)
|
345
382
|
return super(meth) if meth == :initialize || @@command_options == nil
|
346
|
-
|
383
|
+
|
384
|
+
if @@attribute
|
385
|
+
#synthesize parameter
|
386
|
+
@@command_options.merge!(:parameters=>[[:writer, :value]],:class_method=>false)
|
387
|
+
else
|
388
|
+
# create parameter
|
389
|
+
@@command_options.merge!(:parameters=>self.instance_method(meth).parameters,:class_method=>false)
|
390
|
+
end
|
391
|
+
|
347
392
|
add_command(meth)
|
348
393
|
end
|
349
394
|
|
@@ -386,10 +431,10 @@ module Commandable
|
|
386
431
|
# Reads a line from a source code file.
|
387
432
|
def readline(file, line_number)
|
388
433
|
current_line = 0
|
389
|
-
File.open(file).each
|
434
|
+
File.open(file).each do |line_text|
|
390
435
|
current_line += 1
|
391
436
|
return line_text.strip if current_line == line_number
|
392
|
-
|
437
|
+
end
|
393
438
|
end
|
394
439
|
|
395
440
|
# Parses a method defition for the optional values of given argument.
|
@@ -43,7 +43,10 @@ module Commandable
|
|
43
43
|
end
|
44
44
|
# Create a new instance of the MissingRequiredParameterError class
|
45
45
|
def initialize(msg)
|
46
|
-
super("
|
46
|
+
super("""
|
47
|
+
The #{"default " if msg[:default]}command \"#{msg[:method]}\" is missing the required parameter \"#{msg[:parameters]}\".
|
48
|
+
#{"You don't have to specifically say \"#{msg[:method]}\" but you do have to give the parameter." if msg[:default]}"
|
49
|
+
)
|
47
50
|
end
|
48
51
|
end
|
49
52
|
|
data/lib/commandable/version.rb
CHANGED
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Commandable do
|
4
|
+
|
5
|
+
before(:each) {
|
6
|
+
Commandable.reset_all
|
7
|
+
Commandable.color_output = true
|
8
|
+
Commandable.verbose_parameters = false
|
9
|
+
Commandable.app_exe = "fake_app"
|
10
|
+
Commandable.app_info =
|
11
|
+
"""
|
12
|
+
\e[92mFake App!\e[0m - It's not real!
|
13
|
+
"""
|
14
|
+
}
|
15
|
+
|
16
|
+
|
17
|
+
context "when command is used on an attr_accessor" do
|
18
|
+
|
19
|
+
context 'when there is a single accessor per line' do
|
20
|
+
|
21
|
+
before(:each) { load 'attr_accessor.rb' }
|
22
|
+
|
23
|
+
context "when testing syntax" do
|
24
|
+
|
25
|
+
it "should work with an attr_accessor" do
|
26
|
+
lambda{execute_queue(["some_accesor", "a value"])}.should_not raise_error
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should work with an attr_writer" do
|
30
|
+
lambda{execute_queue(["some_writer", "used the writer"])}.should_not raise_error
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should work with an attr_writer and an attr_accessor" do
|
34
|
+
lambda{execute_queue(["some_accesor", "a value", "some_writer", "used the writer"])}.should_not raise_error
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should raise an error is a value isn't given" do
|
38
|
+
lambda{execute_queue(["some_accesor"])}.should raise_error(Commandable::MissingRequiredParameterError)
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should raise an error is a value isn't given" do
|
42
|
+
lambda{execute_queue(["some_writer"])}.should raise_error(Commandable::MissingRequiredParameterError)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should raise an error is a value isn't given" do
|
46
|
+
lambda{execute_queue(["some_accesor", "some_writer", "used the writer"])}.should raise_error(Commandable::MissingRequiredParameterError)
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should raise an error is a value isn't given" do
|
50
|
+
lambda{execute_queue(["some_accesor", "a value", "some_writer"])}.should raise_error(Commandable::MissingRequiredParameterError)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
it {execute_output_s(["some_accesor", "a value"]).should include("a value")}
|
55
|
+
it {execute_output_s(["some_writer", "blah blah blah"]).should include("blah blah blah")}
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'when there is more than one accessor on the same line' do
|
60
|
+
|
61
|
+
before(:each) { load 'attr_accessor_multi.rb' }
|
62
|
+
|
63
|
+
context "when testing syntax" do
|
64
|
+
it "should use the first accessor" do
|
65
|
+
lambda{execute_queue(["first_accessor", "a value"])}.should_not raise_error
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should ignore the second accessor" do
|
69
|
+
lambda{execute_queue(["second_accessor", "blipidy"])}.should raise_error
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should use the first writer" do
|
73
|
+
lambda{execute_queue(["first_writer", "a value"])}.should_not raise_error
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should ignore the second writer" do
|
77
|
+
lambda{execute_queue(["second_writer", "blipidy"])}.should raise_error
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
it {execute_output_s(["first_accessor", "my very own accessor"]).should include("my very own accessor")}
|
82
|
+
it {execute_output_s(["first_writer", "Look ma! A writer!"]).should include("Look ma! A writer!")}
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
@@ -92,13 +92,18 @@ describe Commandable do
|
|
92
92
|
end
|
93
93
|
|
94
94
|
context "and automatically executing commands" do
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
95
|
+
it {execute_output_ary(["foo", "1", "2.4"]).should == ["1", "2.4"]}
|
96
|
+
it {execute_output_ary(["bar", "234"]).should == ["234", "Number 42"]}
|
97
|
+
it {execute_output_ary(["bar", "39", "potato"]).should == ["39", "potato"]}
|
98
|
+
it {execute_output_ary(["qux"]).should == ["1492", "I'm a tricky one"]}
|
99
|
+
it {execute_output_ary(["qux", "991"]).should == ["991", "I'm a tricky one"]}
|
100
|
+
it {execute_output_ary(["qux", "1821", "Look I've got %special\"characters\" in me"]).should ==
|
101
101
|
["1821", "Look I've got %special\"characters\" in me"]}
|
102
|
+
|
103
|
+
context "when specifying that it should be silent" do
|
104
|
+
it {execute_output_s(["foo", "1", "2.4"], :silent).should be_empty}
|
105
|
+
end
|
106
|
+
|
102
107
|
end
|
103
108
|
|
104
109
|
context "and using the execution_queue command" do
|
@@ -6,11 +6,11 @@ describe Commandable do
|
|
6
6
|
|
7
7
|
before(:each) {load 'private_methods_bad.rb'}
|
8
8
|
|
9
|
-
specify {
|
10
|
-
specify {
|
11
|
-
specify {
|
12
|
-
specify {
|
13
|
-
specify {
|
9
|
+
specify {PrivateMethodsBad.send(:parse_optional, "def bar(x=14243)", "x").should == "14243"}
|
10
|
+
specify {PrivateMethodsBad.send(:parse_optional,"def bar x = 144444", "x").should == "144444"}
|
11
|
+
specify {PrivateMethodsBad.send(:parse_optional,"def bar x=12", "x").should == "12"}
|
12
|
+
specify {PrivateMethodsBad.send(:parse_optional,'def bar (x="42", y)', "x").should == "\"42\""}
|
13
|
+
specify {PrivateMethodsBad.send(:parse_optional,'def bar(y="kjljlj",x="I love Ruby")', "x").should == "\"I love Ruby\""}
|
14
14
|
|
15
15
|
end
|
16
16
|
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Commandable do
|
4
|
+
|
5
|
+
context "when calling instance methods" do
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
@first_value = "the first value saved"
|
9
|
+
@second_value = "the second saved value"
|
10
|
+
end
|
11
|
+
|
12
|
+
it "saves instance variables between method calls" do
|
13
|
+
load 'instance_methods.rb'
|
14
|
+
values = execute_queue(["set_value", @first_value, "get_value"])
|
15
|
+
values[1].should == @first_value
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'when multiple classes are involved' do
|
19
|
+
|
20
|
+
it "saves instance variables between method calls" do
|
21
|
+
load 'instance_methods.rb'
|
22
|
+
load 'instance_methods2.rb'
|
23
|
+
values2 = execute_queue(["set_value2", @second_value, "get_value2"])
|
24
|
+
values2[1].should == values2[0]
|
25
|
+
execute_queue(["get_value"])[0].should == @first_value
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
context "when running the execution queue manually" do
|
31
|
+
|
32
|
+
it "should give a programmer access to any instances created" do
|
33
|
+
Commandable.reset_all
|
34
|
+
load 'instance_methods.rb'
|
35
|
+
load 'instance_methods2.rb'
|
36
|
+
execute_queue(["set_value", @first_value, "get_value"])
|
37
|
+
execute_queue(["set_value2", @second_value, "get_value2"])
|
38
|
+
Commandable.class_cache.keys.should include("InstanceMethods", "InstanceMethods2")
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Commandable do
|
4
|
+
|
5
|
+
before(:each) {
|
6
|
+
Commandable.reset_all
|
7
|
+
Commandable.color_output = true
|
8
|
+
Commandable.verbose_parameters = false
|
9
|
+
Commandable.app_exe = "fake_app"
|
10
|
+
Commandable.app_info =
|
11
|
+
"""
|
12
|
+
\e[92mFake App!\e[0m - It's not real!
|
13
|
+
"""
|
14
|
+
load "required_default.rb"
|
15
|
+
}
|
16
|
+
|
17
|
+
|
18
|
+
context "when there is a required/default command" do
|
19
|
+
|
20
|
+
context "and it has a required parameter" do
|
21
|
+
|
22
|
+
context "but nothing is given on the command line" do
|
23
|
+
|
24
|
+
it "should say a required parameter is missing" do
|
25
|
+
lambda{execute_queue([])}.should raise_error(Commandable::MissingRequiredParameterError)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should say a required parameter is missing" do
|
29
|
+
execute_output_s([]).should include("default command")
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require "commandable"
|
2
|
+
|
3
|
+
class AttrAccessorMulti
|
4
|
+
extend Commandable
|
5
|
+
|
6
|
+
# You can do this just realize the second accessor is ignored
|
7
|
+
command 'only runs the first accessor'
|
8
|
+
attr_accessor :first_accessor, :second_accessor
|
9
|
+
|
10
|
+
command 'only runs the first writer'
|
11
|
+
attr_writer :first_writer, :second_writer
|
12
|
+
|
13
|
+
end
|
@@ -1,10 +1,9 @@
|
|
1
|
-
@@command_options
|
2
1
|
require "commandable"
|
3
2
|
|
4
3
|
# This is just a not so clever way of getting at the instance methods of Commandable
|
5
4
|
# Accessing the private methods of a class/module is a bad idea but I really need to
|
6
5
|
# test them. Plus making a helper module just to test them is also against best practices
|
7
6
|
# so...
|
8
|
-
class
|
7
|
+
class PrivateMethodsBad
|
9
8
|
extend Commandable
|
10
9
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -47,16 +47,22 @@ def capture_output
|
|
47
47
|
end
|
48
48
|
|
49
49
|
# Executes a command capturing STDOUT and STDERR as an array representing each line
|
50
|
-
|
51
|
-
|
50
|
+
# Traps errors so not to be used for testing lambad{}.should_not raise_error
|
51
|
+
# or should raise_error since you won't get the error
|
52
|
+
def execute_output_ary(argv, silent=false)
|
53
|
+
execute_output_s(argv, silent).split(%r{\n})
|
52
54
|
end
|
53
55
|
|
54
56
|
# Executes a command capturing STDOUT and STDERR as one string
|
55
|
-
|
56
|
-
|
57
|
+
# Traps errors so not to be used for testing lambad{}.should_not raise_error
|
58
|
+
# or should raise_error since you won't get the error
|
59
|
+
def execute_output_s(argv, silent=false)
|
60
|
+
output = capture_output{Commandable.execute(argv, silent)}
|
57
61
|
output[:stdout] + output[:stderr]
|
58
62
|
end
|
59
63
|
|
64
|
+
# Exectues a command queue returning the results
|
65
|
+
# Use when you want to make sure you don't raise an error
|
60
66
|
def execute_queue(argv)
|
61
67
|
queue = Commandable.execution_queue(argv)
|
62
68
|
queue.collect{|meth| meth[:proc].call}
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: commandable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,12 +9,12 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-
|
12
|
+
date: 2011-04-04 00:00:00.000000000 -04:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: term-ansicolor-hi
|
17
|
-
requirement: &
|
17
|
+
requirement: &2153496380 !ruby/object:Gem::Requirement
|
18
18
|
none: false
|
19
19
|
requirements:
|
20
20
|
- - ~>
|
@@ -22,10 +22,10 @@ dependencies:
|
|
22
22
|
version: 1.0.7
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
|
-
version_requirements: *
|
25
|
+
version_requirements: *2153496380
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
27
|
name: rspec
|
28
|
-
requirement: &
|
28
|
+
requirement: &2153495800 !ruby/object:Gem::Requirement
|
29
29
|
none: false
|
30
30
|
requirements:
|
31
31
|
- - ~>
|
@@ -33,10 +33,10 @@ dependencies:
|
|
33
33
|
version: '2.5'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
|
-
version_requirements: *
|
36
|
+
version_requirements: *2153495800
|
37
37
|
- !ruby/object:Gem::Dependency
|
38
38
|
name: cucumber
|
39
|
-
requirement: &
|
39
|
+
requirement: &2153495200 !ruby/object:Gem::Requirement
|
40
40
|
none: false
|
41
41
|
requirements:
|
42
42
|
- - ~>
|
@@ -44,10 +44,10 @@ dependencies:
|
|
44
44
|
version: '0.10'
|
45
45
|
type: :development
|
46
46
|
prerelease: false
|
47
|
-
version_requirements: *
|
47
|
+
version_requirements: *2153495200
|
48
48
|
- !ruby/object:Gem::Dependency
|
49
49
|
name: aruba
|
50
|
-
requirement: &
|
50
|
+
requirement: &2153494600 !ruby/object:Gem::Requirement
|
51
51
|
none: false
|
52
52
|
requirements:
|
53
53
|
- - ~>
|
@@ -55,25 +55,15 @@ dependencies:
|
|
55
55
|
version: '0.3'
|
56
56
|
type: :development
|
57
57
|
prerelease: false
|
58
|
-
version_requirements: *
|
59
|
-
description: !
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
can take as little as four lines of code: \n\n* You put a `command \"I do something!\"`
|
68
|
-
line above your method.\n* Add a `require 'commandable'` line somewhere (I'd put
|
69
|
-
it in my bin).\n* Then an `extend Commandable` inside your class.\n* And finally
|
70
|
-
a call to `Commandable.execute(ARGV)` in your bin file. \n\nDon't think of Commandable
|
71
|
-
as a way to add command line switches to your app but as a way to allow your app
|
72
|
-
to be driven directly from the command line. No more confusing switches that mean
|
73
|
-
one thing in one program and something completely different in another. (Can you
|
74
|
-
believe some apps actually use `-v` for something other than \"version\" and `-h`
|
75
|
-
for something other than \"help?\" Madness I say! Madness!)\n\nYou can now \"use
|
76
|
-
your words\" to let people interact with your apps in a natural way.\n"
|
58
|
+
version_requirements: *2153494600
|
59
|
+
description: ! 'The easiest way to add command line control to your Ruby app. You
|
60
|
+
can add a single line above an existing method and that method will be available
|
61
|
+
from the command line.
|
62
|
+
|
63
|
+
Best of all the help/usage instructions are automatically generated using the method
|
64
|
+
definition itself. When you change your methods the help instructions change automajically!
|
65
|
+
|
66
|
+
'
|
77
67
|
email:
|
78
68
|
- mikbe.tk@gmail.com
|
79
69
|
executables:
|
@@ -103,13 +93,19 @@ files:
|
|
103
93
|
- lib/commandable/exceptions.rb
|
104
94
|
- lib/commandable/version.rb
|
105
95
|
- lib/monkey_patch/file_utils.rb
|
96
|
+
- lib/monkey_patch/os.rb
|
106
97
|
- spec/commandable/app_controller_spec.rb
|
98
|
+
- spec/commandable/attr_accessor_spec.rb
|
107
99
|
- spec/commandable/command_line_execution_spec.rb
|
108
100
|
- spec/commandable/commandable_spec.rb
|
109
101
|
- spec/commandable/help_generator_spec.rb
|
110
102
|
- spec/commandable/helpers_spec.rb
|
103
|
+
- spec/commandable/instance_methods_spec.rb
|
104
|
+
- spec/commandable/required_default_spec.rb
|
111
105
|
- spec/commandable/reset_spec.rb
|
112
106
|
- spec/commandable/xor_groups_spec.rb
|
107
|
+
- spec/source_code_examples/attr_accessor.rb
|
108
|
+
- spec/source_code_examples/attr_accessor_multi.rb
|
113
109
|
- spec/source_code_examples/class_command_no_command.rb
|
114
110
|
- spec/source_code_examples/class_methods.rb
|
115
111
|
- spec/source_code_examples/class_methods_nested.rb
|
@@ -118,11 +114,14 @@ files:
|
|
118
114
|
- spec/source_code_examples/default_method.rb
|
119
115
|
- spec/source_code_examples/default_method_multiparameters.rb
|
120
116
|
- spec/source_code_examples/default_method_no_params.rb
|
117
|
+
- spec/source_code_examples/instance_methods.rb
|
118
|
+
- spec/source_code_examples/instance_methods2.rb
|
121
119
|
- spec/source_code_examples/multi_line_description.rb
|
122
120
|
- spec/source_code_examples/multi_line_description_no_params.rb
|
123
121
|
- spec/source_code_examples/no_description.rb
|
124
122
|
- spec/source_code_examples/parameter_class.rb
|
125
123
|
- spec/source_code_examples/parameter_free.rb
|
124
|
+
- spec/source_code_examples/required_default.rb
|
126
125
|
- spec/source_code_examples/required_methods.rb
|
127
126
|
- spec/source_code_examples/super_deep_class.rb
|
128
127
|
- spec/source_code_examples/test_class.rb
|
@@ -160,12 +159,17 @@ summary: The easiest way to add command line control to your Ruby apps.
|
|
160
159
|
test_files:
|
161
160
|
- autotest/discover.rb
|
162
161
|
- spec/commandable/app_controller_spec.rb
|
162
|
+
- spec/commandable/attr_accessor_spec.rb
|
163
163
|
- spec/commandable/command_line_execution_spec.rb
|
164
164
|
- spec/commandable/commandable_spec.rb
|
165
165
|
- spec/commandable/help_generator_spec.rb
|
166
166
|
- spec/commandable/helpers_spec.rb
|
167
|
+
- spec/commandable/instance_methods_spec.rb
|
168
|
+
- spec/commandable/required_default_spec.rb
|
167
169
|
- spec/commandable/reset_spec.rb
|
168
170
|
- spec/commandable/xor_groups_spec.rb
|
171
|
+
- spec/source_code_examples/attr_accessor.rb
|
172
|
+
- spec/source_code_examples/attr_accessor_multi.rb
|
169
173
|
- spec/source_code_examples/class_command_no_command.rb
|
170
174
|
- spec/source_code_examples/class_methods.rb
|
171
175
|
- spec/source_code_examples/class_methods_nested.rb
|
@@ -174,11 +178,14 @@ test_files:
|
|
174
178
|
- spec/source_code_examples/default_method.rb
|
175
179
|
- spec/source_code_examples/default_method_multiparameters.rb
|
176
180
|
- spec/source_code_examples/default_method_no_params.rb
|
181
|
+
- spec/source_code_examples/instance_methods.rb
|
182
|
+
- spec/source_code_examples/instance_methods2.rb
|
177
183
|
- spec/source_code_examples/multi_line_description.rb
|
178
184
|
- spec/source_code_examples/multi_line_description_no_params.rb
|
179
185
|
- spec/source_code_examples/no_description.rb
|
180
186
|
- spec/source_code_examples/parameter_class.rb
|
181
187
|
- spec/source_code_examples/parameter_free.rb
|
188
|
+
- spec/source_code_examples/required_default.rb
|
182
189
|
- spec/source_code_examples/required_methods.rb
|
183
190
|
- spec/source_code_examples/super_deep_class.rb
|
184
191
|
- spec/source_code_examples/test_class.rb
|