commandable 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. data/README.markdown +91 -57
  2. data/commandable.gemspec +2 -16
  3. data/lib/commandable/app_controller.rb +3 -3
  4. data/lib/commandable/commandable.rb +65 -20
  5. data/lib/commandable/exceptions.rb +4 -1
  6. data/lib/commandable/version.rb +1 -1
  7. data/lib/monkey_patch/os.rb +8 -0
  8. data/spec/commandable/attr_accessor_spec.rb +88 -0
  9. data/spec/commandable/command_line_execution_spec.rb +11 -6
  10. data/spec/commandable/helpers_spec.rb +5 -5
  11. data/spec/commandable/instance_methods_spec.rb +45 -0
  12. data/spec/commandable/required_default_spec.rb +38 -0
  13. data/spec/source_code_examples/attr_accessor.rb +13 -0
  14. data/spec/source_code_examples/attr_accessor_multi.rb +13 -0
  15. data/spec/source_code_examples/class_command_no_command.rb +0 -1
  16. data/spec/source_code_examples/class_methods.rb +0 -1
  17. data/spec/source_code_examples/class_methods_nested.rb +0 -1
  18. data/spec/source_code_examples/command_no_command.rb +0 -1
  19. data/spec/source_code_examples/deep_class.rb +0 -1
  20. data/spec/source_code_examples/default_method.rb +0 -1
  21. data/spec/source_code_examples/default_method_multiparameters.rb +0 -1
  22. data/spec/source_code_examples/default_method_no_params.rb +0 -1
  23. data/spec/source_code_examples/instance_methods.rb +16 -0
  24. data/spec/source_code_examples/instance_methods2.rb +16 -0
  25. data/spec/source_code_examples/multi_line_description.rb +0 -1
  26. data/spec/source_code_examples/multi_line_description_no_params.rb +0 -1
  27. data/spec/source_code_examples/no_description.rb +0 -1
  28. data/spec/source_code_examples/parameter_class.rb +0 -1
  29. data/spec/source_code_examples/parameter_free.rb +0 -1
  30. data/spec/source_code_examples/required_default.rb +11 -0
  31. data/spec/source_code_examples/required_methods.rb +0 -1
  32. data/spec/source_code_examples/super_deep_class.rb +0 -1
  33. data/spec/source_code_examples/test_class.rb +0 -1
  34. data/spec/source_code_examples/xor_class.rb +0 -1
  35. data/spec/source_code_for_errors/class_bad.rb +0 -1
  36. data/spec/source_code_for_errors/default_method_bad.rb +0 -1
  37. data/spec/source_code_for_errors/private_methods_bad.rb +1 -2
  38. data/spec/spec_helper.rb +10 -4
  39. metadata +35 -28
@@ -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 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.
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
- * And finally a call to `Commandable.execute(ARGV)` in your bin file.
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
- 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!)
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
- I have the gem set up to ask if you would like to test on install so please allow the tests to run and upload. This will allow me to find any problems on different platforms.
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
- You can take a look at the test results yourself here:
30
+ $ gem test commandable
24
31
 
25
- <http://test.rubygems.org/gems/hashmodel/v/0.4.0>
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-03-21 - Release Cadidate: 0.2.0.rc1
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
- * *Nix OS (Probably works on Windows but not tested yet)
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. Note that while you can have a method marked as both :default and :required that would be kind of pointless since :required means they have to type out the name of the function and :default means they don't.
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
- The parameter lists for each method that are printed out in the usage/help instructions are built using the names you give them so you should make sure to use descriptive names. 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.
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 disassemble(name)
127
- "No dissaemble #{name}! #{name} is alive!"
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 that call. Keep that in mind if you need to share data between calls. In that case you might want to store your data in a model you create outside the execution queue.
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 it will automatically create usage instructions based on your methods and the descriptions you provide for them. The `help` command is also added for you automatically. If your app has no default 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.
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
- Commandable - The easiest way to add command line control to your app.
189
- Copyrighted free software - Copyright (c) 2011 Mike Bethany.
190
- Version: 0.2.0
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
- Usage: commandable <command> [parameters] [<command> [parameters]...]
211
+ Usage: commandable <command> [parameters] [<command> [parameters]...]
193
212
 
194
- Command Parameters Description
195
- error : Will raise a programmer error, not a user error
196
- so you see what happens when you have bad code
197
- examples [path] : Copies the test classes to a folder so
198
- you can see a bunch of small examples
199
- readme : displays the readme file (default)
200
- v : <xor> Application Version
201
- version : <xor> Application Version
202
- widget [path] : Copies a fully working app demonstrating how
203
- to use Commandable with RSpec and Cucumber
204
- help : you're looking at it now
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
- If you would like to see a bunch of simple classes that demonstrate its uses run:
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 will 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.
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 set the help instructions will include a usage line with your executables name.
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
- All done... for now.
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.
@@ -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 "Copies a fully working app demonstrating how\nto use Commandable with RSpec and Cucumber"
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 it's own error trapping
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
- puts com[:proc].call
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 commad line into methods and their parameters
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
- @@commands.select do |key, value|
194
- raise MissingRequiredCommandError, key if value[:required] and method_hash[key].nil?
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
- # Test for missing parameters
204
- required = command[:parameters].select{|param| param[0]==:req} if command[:parameters]
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
- klass = klass.new unless command[:class_method]
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 = @color_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
- init # automatically configure the module when it's loaded
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
- argument_list = parse_arguments(@@command_options[:parameters])
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
- @@command_options.merge!(:parameters=>self.instance_method(meth).parameters,:class_method=>false)
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 { |line_text|
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("The command \"#{msg[:method]}\" is missing the required parameter \"#{msg[:parameters]}\".")
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
 
@@ -2,7 +2,7 @@ module Commandable
2
2
  module VERSION # :nodoc:
3
3
  MAJOR = 0
4
4
  MINOR = 2
5
- TINY = 0
5
+ TINY = 1
6
6
  PRE = nil
7
7
 
8
8
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
@@ -0,0 +1,8 @@
1
+ require 'sys/uname'
2
+ include Sys
3
+
4
+ module Kernel
5
+ def is_windows?
6
+ Uname.sysname.downcase.include?('windows')
7
+ end
8
+ end
@@ -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
- specify {execute_output_ary(["foo", "1", "2.4"]).should == ["1", "2.4"]}
96
- specify {execute_output_ary(["bar", "234"]).should == ["234", "Number 42"]}
97
- specify {execute_output_ary(["bar", "39", "potato"]).should == ["39", "potato"]}
98
- specify {execute_output_ary(["qux"]).should == ["1492", "I'm a tricky one"]}
99
- specify {execute_output_ary(["qux", "991"]).should == ["991", "I'm a tricky one"]}
100
- specify {execute_output_ary(["qux", "1821", "Look I've got %special\"characters\" in me"]).should ==
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 {PrivateMethods.send(:parse_optional, "def bar(x=14243)", "x").should == "14243"}
10
- specify {PrivateMethods.send(:parse_optional,"def bar x = 144444", "x").should == "144444"}
11
- specify {PrivateMethods.send(:parse_optional,"def bar x=12", "x").should == "12"}
12
- specify {PrivateMethods.send(:parse_optional,'def bar (x="42", y)', "x").should == "\"42\""}
13
- specify {PrivateMethods.send(:parse_optional,'def bar(y="kjljlj",x="I love Ruby")', "x").should == "\"I love Ruby\""}
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 AttrAccessor
4
+ extend Commandable
5
+
6
+ command 'uses an attr_accessor'
7
+ attr_accessor :some_accesor
8
+
9
+ command 'uses an attr_writer'
10
+ attr_writer :some_writer
11
+
12
+
13
+ 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,4 +1,3 @@
1
- @@command_options
2
1
  require "commandable"
3
2
 
4
3
  class ClassCommandNoCommand
@@ -1,4 +1,3 @@
1
- @@command_options
2
1
  require "commandable"
3
2
 
4
3
  class ClassMethods
@@ -1,4 +1,3 @@
1
- @@command_options
2
1
  require "commandable"
3
2
 
4
3
  class ClassMethodsNested
@@ -1,4 +1,3 @@
1
- @@command_options
2
1
  require "commandable"
3
2
 
4
3
  class CommandNoCommand
@@ -1,4 +1,3 @@
1
- @@command_options
2
1
  require "commandable"
3
2
 
4
3
  module TopModule
@@ -1,4 +1,3 @@
1
- @@command_options
2
1
  require "commandable"
3
2
 
4
3
  class DefaultMethods
@@ -1,4 +1,3 @@
1
- @@command_options
2
1
  require "commandable"
3
2
 
4
3
  class DefaultMethodsMultiParameters
@@ -1,4 +1,3 @@
1
- @@command_options
2
1
  require "commandable"
3
2
 
4
3
  class DefaultMethodNoParams
@@ -0,0 +1,16 @@
1
+ require "commandable"
2
+
3
+ class InstanceMethods
4
+ extend Commandable
5
+
6
+ command "save a value", :priority=>2
7
+ def set_value(value)
8
+ @value = value
9
+ end
10
+
11
+ command "retreive a value"
12
+ def get_value
13
+ @value
14
+ end
15
+
16
+ end
@@ -0,0 +1,16 @@
1
+ require "commandable"
2
+
3
+ class InstanceMethods2
4
+ extend Commandable
5
+
6
+ command "save a value", :priority=>2
7
+ def set_value2(value)
8
+ @value = value
9
+ end
10
+
11
+ command "retreive a value"
12
+ def get_value2
13
+ @value
14
+ end
15
+
16
+ end
@@ -1,4 +1,3 @@
1
- @@command_options
2
1
  require "commandable"
3
2
 
4
3
  class MultiLineDescription
@@ -1,4 +1,3 @@
1
- @@command_options
2
1
  require "commandable"
3
2
 
4
3
  class MultiLineDescriptionNoParams
@@ -1,4 +1,3 @@
1
- @@command_options
2
1
  require "commandable"
3
2
 
4
3
  class NoDescription
@@ -1,4 +1,3 @@
1
- @@command_options
2
1
  require "commandable"
3
2
 
4
3
  class ParameterClass
@@ -1,4 +1,3 @@
1
- @@command_options
2
1
  require "commandable"
3
2
 
4
3
  class ParameterFree
@@ -0,0 +1,11 @@
1
+ require "commandable"
2
+
3
+ class RequiredDefault
4
+ extend Commandable
5
+
6
+ command "the default action", :default, :required
7
+ def required_default(required_value)
8
+ value
9
+ end
10
+
11
+ end
@@ -1,4 +1,3 @@
1
- @@command_options
2
1
  require "commandable"
3
2
 
4
3
  class RequiredMethods
@@ -1,4 +1,3 @@
1
- @@command_options
2
1
  require "commandable"
3
2
 
4
3
  module TopModule
@@ -1,4 +1,3 @@
1
- @@command_options
2
1
  require "commandable"
3
2
 
4
3
  class TestClass
@@ -1,4 +1,3 @@
1
- @@command_options
2
1
  require "commandable"
3
2
 
4
3
  class XorClass
@@ -1,4 +1,3 @@
1
- @@command_options
2
1
  require "commandable"
3
2
 
4
3
  class ClassBad
@@ -1,4 +1,3 @@
1
- @@command_options
2
1
  require "commandable"
3
2
 
4
3
  class DefaultMethodsBad
@@ -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 PrivateMethods
7
+ class PrivateMethodsBad
9
8
  extend Commandable
10
9
  end
@@ -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
- def execute_output_ary(argv)
51
- execute_output_s(argv).split(%r{\n})
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
- def execute_output_s(argv)
56
- output = capture_output{Commandable.execute(argv)}
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.0
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-03-23 00:00:00.000000000 -04:00
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: &2158240980 !ruby/object:Gem::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: *2158240980
25
+ version_requirements: *2153496380
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: rspec
28
- requirement: &2158240520 !ruby/object:Gem::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: *2158240520
36
+ version_requirements: *2153495800
37
37
  - !ruby/object:Gem::Dependency
38
38
  name: cucumber
39
- requirement: &2158240040 !ruby/object:Gem::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: *2158240040
47
+ version_requirements: *2153495200
48
48
  - !ruby/object:Gem::Dependency
49
49
  name: aruba
50
- requirement: &2158230600 !ruby/object:Gem::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: *2158230600
59
- description: ! "The easiest way to add command line control to your Ruby app.\n\nStop
60
- wasting time writing WET (Write Everything Twice) command line interpreters, or
61
- repeatedly writing code for existing ones like optparser, then writing help/usage
62
- methods that you constantly have to update as your code changes. Now you can add
63
- a single line above an existing method and that method will be available from the
64
- command line.\n\nBest of all the help/usage instructions are automatically generated
65
- using the method itself! When you change your methods the help instructions change
66
- automajically! There's no extra effort needed on your part.\n\nThe whole process
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