commandable 0.2.0.beta01 → 0.2.0.beta2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/BUGS.txt +2 -0
- data/README.markdown +11 -2
- data/bin/commandable +1 -1
- data/commandable.gemspec +3 -2
- data/features/ansicolor.feature +11 -0
- data/features/setup/env.rb +3 -0
- data/features/step-definitions/step-definitions.rb +7 -0
- data/lib/commandable/app_controller.rb +2 -2
- data/lib/commandable/commandable.rb +25 -19
- data/lib/commandable/exceptions.rb +14 -0
- data/lib/commandable/version.rb +1 -1
- data/lib/monkey_patch/file_utils.rb +1 -1
- data/spec/commandable/command_line_execution_spec.rb +31 -8
- data/spec/commandable/commandable_spec.rb +3 -4
- data/spec/commandable/help_generator_spec.rb +1 -1
- data/spec/commandable/reset_spec.rb +1 -1
- data/spec/source_code_examples/default_method.rb +1 -1
- data/spec/source_code_examples/default_method_multiparameters.rb +17 -0
- data/spec/source_code_examples/parameter_class.rb +5 -0
- data/spec/source_code_examples/test_class.rb +0 -3
- data/spec/spec_helper.rb +6 -0
- metadata +28 -10
data/BUGS.txt
ADDED
data/README.markdown
CHANGED
@@ -16,7 +16,16 @@ You can now "use your words" to let people interact with your apps in a natural
|
|
16
16
|
|
17
17
|
## Status
|
18
18
|
|
19
|
-
2011-03-
|
19
|
+
2011-03-18 - Final testing and building the example app. I'd wait to use it till I finish the example app. I'm finding new use cases as I do this and correcting some omissions of logic.
|
20
|
+
|
21
|
+
## Principle of Least Surprise
|
22
|
+
|
23
|
+
I've tried to honestly follow the theory of the principle of least surprise so it should just work like you would expect it to.
|
24
|
+
|
25
|
+
## Requirements ##
|
26
|
+
|
27
|
+
* Ruby 1.9.2
|
28
|
+
* *Nix OS (Probably works on Windows but not tested yet)
|
20
29
|
|
21
30
|
## Installation
|
22
31
|
From the command line:
|
@@ -226,7 +235,7 @@ Then you can do something like this:
|
|
226
235
|
|
227
236
|
require 'term/ansicolor'
|
228
237
|
|
229
|
-
c = Term::
|
238
|
+
c = Term::ANSIColorHI
|
230
239
|
|
231
240
|
Commandable.color_app_info = c.intense_white + c.bold
|
232
241
|
Commandable.color_app_name = c.intense_green + c.bold
|
data/bin/commandable
CHANGED
@@ -4,7 +4,7 @@ require 'commandable'
|
|
4
4
|
Commandable.color_output = true
|
5
5
|
Commandable.verbose_parameters = false
|
6
6
|
Commandable.app_name = "commandable"
|
7
|
-
Commandable.app_info =
|
7
|
+
Commandable.app_info =
|
8
8
|
"""
|
9
9
|
\e[92mCommandable\e[0m - The easiest way to add command line control to your app.
|
10
10
|
Copyrighted free software - Copyright (c) 2011 Mike Bethany.
|
data/commandable.gemspec
CHANGED
@@ -11,11 +11,12 @@ Gem::Specification.new do |s|
|
|
11
11
|
s.email = ["mikbe.tk@gmail.com"]
|
12
12
|
s.homepage = "http://mikbe.tk"
|
13
13
|
s.summary = %q{The easiest way to add command line control to your app.}
|
14
|
-
s.description = %q{
|
14
|
+
s.description = %q{The easiest way to add command line control to your app.\nAdding command line control to your app is as easy as putting 'command "this command does xyz"' above a method.\nParameter lists and a help command are automatically built for you.}
|
15
15
|
|
16
|
-
s.add_dependency("term-ansicolor-hi", "~>1.0.
|
16
|
+
s.add_dependency("term-ansicolor-hi", "~>1.0.7")
|
17
17
|
|
18
18
|
s.add_development_dependency("rspec", "~>2.5")
|
19
|
+
s.add_development_dependency("cucumber")
|
19
20
|
|
20
21
|
s.files = `git ls-files`.split("\n")
|
21
22
|
s.test_files = `git ls-files -- {spec,autotest}/*`.split("\n")
|
@@ -0,0 +1,11 @@
|
|
1
|
+
Feature: Ansicolor
|
2
|
+
In order to not have horrible looking colors
|
3
|
+
As a programmer
|
4
|
+
I want to make sure I'm using ANSIColorHI
|
5
|
+
And it doesn't conflict with the original ANSIColor
|
6
|
+
|
7
|
+
|
8
|
+
Scenario: Run a feature
|
9
|
+
When I run cucumber
|
10
|
+
Then it doesn't give an error
|
11
|
+
|
@@ -12,13 +12,13 @@ module Commandable
|
|
12
12
|
`open #{File.expand_path((File.dirname(__FILE__) + '/../../readme.markdown'))}`
|
13
13
|
end
|
14
14
|
|
15
|
-
command "Copies a fully working app demonstrating how\
|
15
|
+
command "Copies a fully working app demonstrating how\nto use Commandable with RSpec and Cucumber"
|
16
16
|
# Creates a simple example app demonstrating a fully working app
|
17
17
|
def widget(path="./widget")
|
18
18
|
puts "This feature hasn't been added yet. I'm working on it now and it will be in the release version."
|
19
19
|
end
|
20
20
|
|
21
|
-
command "Copies the test classes to a folder so\
|
21
|
+
command "Copies the test classes to a folder so\nyou can see a bunch of small examples"
|
22
22
|
# Copies the test classes to a folder so you can see a bunch of small examples
|
23
23
|
def examples(path="./example_classes")
|
24
24
|
FileUtils.copy_dir(File.expand_path(File.dirname(__FILE__) + '/../../spec/source_code_examples'),path)
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'term/
|
1
|
+
require 'term/ansicolorhi'
|
2
2
|
require 'set'
|
3
3
|
|
4
4
|
# This library allows you to incredibly easily make
|
@@ -19,13 +19,13 @@ module Commandable
|
|
19
19
|
|
20
20
|
# Describes your application, printed at the top of help/usage messages
|
21
21
|
attr_accessor :app_info
|
22
|
-
|
22
|
+
|
23
23
|
# Used when building the usage line, e.g. Usage: app_name [command] [parameters]
|
24
24
|
attr_accessor :app_name
|
25
|
-
|
25
|
+
|
26
26
|
# If optional parameters show default values, true by default
|
27
27
|
attr_accessor :verbose_parameters
|
28
|
-
|
28
|
+
|
29
29
|
# Boolean: If help/usage messages will print in color
|
30
30
|
attr_accessor :color_output
|
31
31
|
# What color the app_info text will be in the help message
|
@@ -40,7 +40,7 @@ module Commandable
|
|
40
40
|
attr_accessor :color_parameter
|
41
41
|
# What color the word "Usage:" will be in the help message
|
42
42
|
attr_accessor :color_usage
|
43
|
-
|
43
|
+
|
44
44
|
# What color the word "Error:" text will be in error messages
|
45
45
|
attr_accessor :color_error_word
|
46
46
|
# What color the friendly name of the error will be in error messages
|
@@ -145,18 +145,16 @@ module Commandable
|
|
145
145
|
puts com[:proc].call
|
146
146
|
end
|
147
147
|
rescue Exception => exception
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
puts
|
159
|
-
end
|
148
|
+
if exception.respond_to?(:friendly_name)
|
149
|
+
set_colors
|
150
|
+
puts help("\n #{@c_error_word}Error:#{@c_reset} #{@c_error_name}#{exception.friendly_name}#{@c_reset}\n #{@c_error_description}#{exception.message}#{@c_reset}\n\n")
|
151
|
+
else
|
152
|
+
puts "\n Bleep, bloop, bleep! Danger Will Robinson! Danger!"
|
153
|
+
puts "\n Error: #{exception.inspect}"
|
154
|
+
puts "\n Backtrace:"
|
155
|
+
puts exception.backtrace.collect{|line| " #{line}"}
|
156
|
+
puts
|
157
|
+
end
|
160
158
|
end
|
161
159
|
end
|
162
160
|
|
@@ -202,6 +200,13 @@ module Commandable
|
|
202
200
|
method_hash.each do |meth, params|
|
203
201
|
command = @@commands[meth]
|
204
202
|
|
203
|
+
# Test for missing parameters
|
204
|
+
required = command[:parameters].select{|param| param[0]==:req} if command[:parameters]
|
205
|
+
if required
|
206
|
+
required.shift(params.count)
|
207
|
+
raise MissingRequiredParameterError, {:method=>meth, :parameters=>required.collect!{|meth| meth[1]}.to_s[1...-1].gsub(":","")} unless required.empty?
|
208
|
+
end
|
209
|
+
|
205
210
|
# Test for duplicate XORs
|
206
211
|
proc_array.select{|x| x[:xor] and x[:xor]==command[:xor] }.each {|bad| raise ExclusiveMethodClashError, "#{meth}, #{bad[:method]}"}
|
207
212
|
|
@@ -211,6 +216,7 @@ module Commandable
|
|
211
216
|
proc_array << {:method=>meth, :xor=>command[:xor], :parameters=>params, :priority=>command[:priority], :proc=>lambda{klass.send(meth, *params)}}
|
212
217
|
end
|
213
218
|
proc_array.sort{|a,b| a[:priority] <=> b[:priority]}.reverse
|
219
|
+
|
214
220
|
end
|
215
221
|
|
216
222
|
# Set colors to their default values
|
@@ -218,8 +224,8 @@ module Commandable
|
|
218
224
|
# Colors - off by default
|
219
225
|
@color_output ||= false
|
220
226
|
# Build the default colors
|
221
|
-
Term::
|
222
|
-
c = Term::
|
227
|
+
Term::ANSIColorHI.coloring = true
|
228
|
+
c = Term::ANSIColorHI
|
223
229
|
@color_app_info = c.intense_white + c.bold
|
224
230
|
@color_app_name = c.intense_green + c.bold
|
225
231
|
@color_command = c.intense_yellow
|
@@ -34,6 +34,20 @@ module Commandable
|
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
|
+
|
38
|
+
# An error raised if a user does not provide a required command
|
39
|
+
class MissingRequiredParameterError < ScriptError
|
40
|
+
# Returns a more print friendly error name
|
41
|
+
def friendly_name
|
42
|
+
"Missing Required Parmeter"
|
43
|
+
end
|
44
|
+
# Create a new instance of the MissingRequiredParameterError class
|
45
|
+
def initialize(msg)
|
46
|
+
super("The command \"#{msg[:method]}\" is missing the required parameter \"#{msg[:parameters]}\".")
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
|
37
51
|
# This error is raised if a user gives two or more commands from the same exclusive group
|
38
52
|
class ExclusiveMethodClashError < ScriptError
|
39
53
|
# Returns a more print friendly error name
|
data/lib/commandable/version.rb
CHANGED
@@ -6,10 +6,10 @@ describe Commandable do
|
|
6
6
|
Commandable.reset_all
|
7
7
|
Commandable.app_name = "mycoolapp"
|
8
8
|
Commandable.app_info =
|
9
|
-
"""
|
10
|
-
|
11
|
-
|
12
|
-
"""
|
9
|
+
"""
|
10
|
+
My Cool App - It does stuff and things!
|
11
|
+
Copyright (c) 2011 Acme Inc.
|
12
|
+
"""
|
13
13
|
|
14
14
|
load 'parameter_class.rb'
|
15
15
|
}
|
@@ -17,13 +17,29 @@ describe Commandable do
|
|
17
17
|
context "when parsing arguments" do
|
18
18
|
|
19
19
|
context "and there is an error in the command line" do
|
20
|
-
|
20
|
+
|
21
|
+
context "because a required parameter is not given" do
|
22
|
+
|
23
|
+
context "with a class that doesn't have a default method" do
|
24
|
+
specify{lambda{execute_queue(["zaz"]).should raise_error(MissingRequiredParameterError)}}
|
25
|
+
specify{lambda{execute_output_s(["zaz"]).should include(/Missing Required/)}}
|
26
|
+
specify{lambda{execute_queue(["zaz", "potato"]).should raise_error(MissingRequiredParameterError)}}
|
27
|
+
specify{lambda{execute_output_s(["zaz", "potato"]).should include(/Missing Required/)}}
|
28
|
+
specify{lambda{execute_queue(["zaz", "potato", "gump"]).should_not raise_error}}
|
29
|
+
specify{lambda{execute_output_s(["zaz", "potato", "gump"]).should_not include(/Missing Required/)}}
|
30
|
+
end
|
31
|
+
|
32
|
+
# When a default method has a required parameter and nothing is given on the command
|
33
|
+
# line Commandable will run help so you won't get a MissingRequiredParameterError
|
34
|
+
|
35
|
+
end
|
36
|
+
|
21
37
|
context "and the default method does not accept parameters" do
|
22
38
|
|
23
39
|
before(:each) {load 'default_method_no_params.rb'}
|
24
40
|
|
25
41
|
context "but something that isn't a method is the first thing on the command line" do
|
26
|
-
specify {lambda{
|
42
|
+
specify {lambda{execute_queue(["potato"])}.should raise_error(Commandable::UnknownCommandError)}
|
27
43
|
specify { execute_output_s(["potato"]).should match(/Unknown Command/)}
|
28
44
|
end
|
29
45
|
|
@@ -31,7 +47,7 @@ describe Commandable do
|
|
31
47
|
|
32
48
|
context "and running procs from the execution queue" do
|
33
49
|
it "raises an error if there is an invalid command given" do
|
34
|
-
lambda{
|
50
|
+
lambda{execute_queue(["fly", "navy"])}.should raise_error(Commandable::UnknownCommandError)
|
35
51
|
end
|
36
52
|
end
|
37
53
|
|
@@ -146,9 +162,16 @@ describe Commandable do
|
|
146
162
|
|
147
163
|
end
|
148
164
|
|
165
|
+
context "when a default method name isn't specified but the required switch is properly given" do
|
166
|
+
before(:each){load "default_method.rb"}
|
167
|
+
specify{lambda{execute_queue(["phish"])}.should_not raise_error}
|
168
|
+
specify{lambda{execute_output_s(["phish"]).should include(/default method called with: phish/)}}
|
169
|
+
specify{execute_queue(["not_a_default_method", "potato"]).should include("not a default method, called with: Cleveland, potato") }
|
170
|
+
specify{execute_output_s(["not_a_default_method", "phish"]).should include("not a default method, called with: Cleveland, phish")}
|
171
|
+
end
|
172
|
+
|
149
173
|
end
|
150
174
|
|
151
|
-
|
152
175
|
end
|
153
176
|
|
154
177
|
end
|
@@ -188,14 +188,13 @@ describe Commandable do
|
|
188
188
|
end
|
189
189
|
|
190
190
|
it "executes the default command if no command is given" do
|
191
|
-
execute_output_ary(["Klaatu"]).should
|
191
|
+
execute_output_ary(["Klaatu"]).should include("default method called with: Klaatu")
|
192
192
|
end
|
193
193
|
|
194
194
|
it "executes a default method and a second command" do
|
195
|
-
execute_output_ary(["Klaatu", "not_a_default_method", "28"]).
|
195
|
+
execute_output_ary(["Klaatu", "not_a_default_method", "28"]).should include(
|
196
196
|
"default method called with: Klaatu",
|
197
|
-
"not a default method, called with: Cleveland"
|
198
|
-
"28"].sort
|
197
|
+
"not a default method, called with: Cleveland, 28")
|
199
198
|
end
|
200
199
|
|
201
200
|
end
|
@@ -18,7 +18,7 @@ describe Commandable do
|
|
18
18
|
from(%{ My Cool App - It does stuff and things!\n Copyright (c) 2011 Acme Inc.}).
|
19
19
|
to(nil)
|
20
20
|
}
|
21
|
-
specify {lambda{Commandable.reset_all}.should change{Commandable.commands.length}.from(
|
21
|
+
specify {lambda{Commandable.reset_all}.should change{Commandable.commands.length}.from(6).to(1)}
|
22
22
|
|
23
23
|
|
24
24
|
|
@@ -0,0 +1,17 @@
|
|
1
|
+
@@command_options
|
2
|
+
require "commandable"
|
3
|
+
|
4
|
+
class DefaultMethodsMultiParameters
|
5
|
+
extend Commandable
|
6
|
+
|
7
|
+
command 'the default method', :default
|
8
|
+
def default_method_multi(name, optional="optional")
|
9
|
+
"multi default method called with: #{name}, #{optional}"
|
10
|
+
end
|
11
|
+
|
12
|
+
command 'does other stuff'
|
13
|
+
def not_a_default_method_multi(name="Cleveland", age)
|
14
|
+
["multi not a default method, called with: #{name}", age]
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -3,6 +3,7 @@ $:.unshift File.expand_path((File.dirname(__FILE__) + '/source_code_examples'))
|
|
3
3
|
$:.unshift File.expand_path((File.dirname(__FILE__) + '/source_code_for_errors'))
|
4
4
|
$:.unshift File.expand_path(File.dirname(__FILE__))
|
5
5
|
|
6
|
+
require 'pp'
|
6
7
|
require 'term/ansicolor'
|
7
8
|
require 'rspec'
|
8
9
|
require 'commandable'
|
@@ -53,3 +54,8 @@ def execute_output_s(argv)
|
|
53
54
|
output = capture_output{Commandable.execute(argv)}
|
54
55
|
output[:stdout] + output[:stderr]
|
55
56
|
end
|
57
|
+
|
58
|
+
def execute_queue(argv)
|
59
|
+
queue = Commandable.execution_queue(argv)
|
60
|
+
queue.collect{|meth| meth[:proc].call}
|
61
|
+
end
|
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.0.beta2
|
5
5
|
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,23 +9,23 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-03-
|
12
|
+
date: 2011-03-21 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: &2154879100 !ruby/object:Gem::Requirement
|
18
18
|
none: false
|
19
19
|
requirements:
|
20
20
|
- - ~>
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: 1.0.
|
22
|
+
version: 1.0.7
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
|
-
version_requirements: *
|
25
|
+
version_requirements: *2154879100
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
27
|
name: rspec
|
28
|
-
requirement: &
|
28
|
+
requirement: &2154878600 !ruby/object:Gem::Requirement
|
29
29
|
none: false
|
30
30
|
requirements:
|
31
31
|
- - ~>
|
@@ -33,10 +33,22 @@ dependencies:
|
|
33
33
|
version: '2.5'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
|
-
version_requirements: *
|
37
|
-
|
38
|
-
|
39
|
-
|
36
|
+
version_requirements: *2154878600
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: cucumber
|
39
|
+
requirement: &2154878200 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ! '>='
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
type: :development
|
46
|
+
prerelease: false
|
47
|
+
version_requirements: *2154878200
|
48
|
+
description: The easiest way to add command line control to your app.\nAdding command
|
49
|
+
line control to your app is as easy as putting 'command "this command does xyz"'
|
50
|
+
above a method.\nParameter lists and a help command are automatically built for
|
51
|
+
you.
|
40
52
|
email:
|
41
53
|
- mikbe.tk@gmail.com
|
42
54
|
executables:
|
@@ -45,6 +57,7 @@ extensions: []
|
|
45
57
|
extra_rdoc_files: []
|
46
58
|
files:
|
47
59
|
- .gitignore
|
60
|
+
- BUGS.txt
|
48
61
|
- Gemfile
|
49
62
|
- LICENCE
|
50
63
|
- README.markdown
|
@@ -53,6 +66,9 @@ files:
|
|
53
66
|
- autotest/discover.rb
|
54
67
|
- bin/commandable
|
55
68
|
- commandable.gemspec
|
69
|
+
- features/ansicolor.feature
|
70
|
+
- features/setup/env.rb
|
71
|
+
- features/step-definitions/step-definitions.rb
|
56
72
|
- lib/commandable.rb
|
57
73
|
- lib/commandable/app_controller.rb
|
58
74
|
- lib/commandable/commandable.rb
|
@@ -71,6 +87,7 @@ files:
|
|
71
87
|
- spec/source_code_examples/command_no_command.rb
|
72
88
|
- spec/source_code_examples/deep_class.rb
|
73
89
|
- spec/source_code_examples/default_method.rb
|
90
|
+
- spec/source_code_examples/default_method_multiparameters.rb
|
74
91
|
- spec/source_code_examples/default_method_no_params.rb
|
75
92
|
- spec/source_code_examples/multi_line_description.rb
|
76
93
|
- spec/source_code_examples/multi_line_description_no_params.rb
|
@@ -124,6 +141,7 @@ test_files:
|
|
124
141
|
- spec/source_code_examples/command_no_command.rb
|
125
142
|
- spec/source_code_examples/deep_class.rb
|
126
143
|
- spec/source_code_examples/default_method.rb
|
144
|
+
- spec/source_code_examples/default_method_multiparameters.rb
|
127
145
|
- spec/source_code_examples/default_method_no_params.rb
|
128
146
|
- spec/source_code_examples/multi_line_description.rb
|
129
147
|
- spec/source_code_examples/multi_line_description_no_params.rb
|