commandable 0.2.0.beta01 → 0.2.0.beta2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|