clive 0.3.1 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -1
- data/VERSION +1 -1
- data/clive.gemspec +2 -2
- data/lib/clive.rb +46 -1
- data/lib/clive/bool.rb +7 -2
- data/lib/clive/command.rb +12 -4
- data/lib/clive/exceptions.rb +10 -4
- data/lib/clive/ext.rb +34 -1
- data/lib/clive/flag.rb +78 -22
- data/lib/clive/option.rb +9 -6
- data/lib/clive/tokens.rb +12 -3
- data/test/bin_test +1 -0
- data/test/helper.rb +4 -1
- data/test/test_clive.rb +6 -0
- data/test/test_flag.rb +109 -7
- metadata +5 -5
data/.gitignore
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.4.0
|
data/clive.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{clive}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.4.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Joshua Hawxwell"]
|
12
|
-
s.date = %q{2010-
|
12
|
+
s.date = %q{2010-09-19}
|
13
13
|
s.description = %q{Clive is a DSL for creating a command line interface. It is for people who, like me, love OptionParser's syntax and love GLI's commands.}
|
14
14
|
s.email = %q{m@hawx.me}
|
15
15
|
s.extra_rdoc_files = [
|
data/lib/clive.rb
CHANGED
@@ -22,30 +22,75 @@ require 'clive/bool'
|
|
22
22
|
# end
|
23
23
|
# c.parse(ARGV)
|
24
24
|
#
|
25
|
+
# @example Non-simple Example
|
26
|
+
#
|
27
|
+
# opts = {}
|
28
|
+
# c = Clive.new do
|
29
|
+
# bool(:v, :verbose, "Run verbosely") {|i| opts[:verbose] = i}
|
30
|
+
#
|
31
|
+
# command :add, "Add a new project" do
|
32
|
+
# opts[:add] = {}
|
33
|
+
#
|
34
|
+
# switch(:force, "Force overwrite") {opts[:add][:force] = true}
|
35
|
+
# flag :framework, "Add framework" do |i|
|
36
|
+
# opts[:add][:framework] ||= []
|
37
|
+
# opts[:add][:framework] << i
|
38
|
+
# end
|
39
|
+
#
|
40
|
+
# command :init, "Initialize the project after creating" do
|
41
|
+
# switch(:m, :minimum, "Use minimum settings") {opts[:add][:min] = true}
|
42
|
+
# flag(:w, :width) {|i| opts[:add][:width] = i.to_i}
|
43
|
+
# end
|
44
|
+
#
|
45
|
+
# end
|
46
|
+
#
|
47
|
+
# switch :version, "Show version" do
|
48
|
+
# puts "1.0.0"
|
49
|
+
# exit
|
50
|
+
# end
|
51
|
+
# end
|
52
|
+
# ARGV = c.parse(ARGV)
|
53
|
+
#
|
25
54
|
class Clive
|
26
|
-
|
55
|
+
|
56
|
+
# This is the base command, the only way it differs from a normal command
|
57
|
+
# is that it has no name and it's block is executed immediately on creation.
|
58
|
+
#
|
59
|
+
# @return [Command] the base command
|
60
|
+
#
|
27
61
|
attr_accessor :base
|
28
62
|
|
29
63
|
def initialize(&block)
|
30
64
|
@base = Command.new(true, &block)
|
31
65
|
end
|
32
66
|
|
67
|
+
# Parse the base command
|
33
68
|
def parse(argv)
|
34
69
|
@base.run(argv)
|
35
70
|
end
|
36
71
|
|
72
|
+
# @group Base Proxy Methods
|
73
|
+
|
74
|
+
# @see Command#switches
|
75
|
+
# @return [Array] switches in +base+
|
37
76
|
def switches
|
38
77
|
@base.switches
|
39
78
|
end
|
40
79
|
|
80
|
+
# @see Command#commands
|
81
|
+
# @return [Array] commands in +base+
|
41
82
|
def commands
|
42
83
|
@base.commands
|
43
84
|
end
|
44
85
|
|
86
|
+
# @see Command#flags
|
87
|
+
# @return [Array] flags in +base+
|
45
88
|
def flags
|
46
89
|
@base.flags
|
47
90
|
end
|
48
91
|
|
92
|
+
# @see Command#bools
|
93
|
+
# @return [Array] bools in +base+
|
49
94
|
def bools
|
50
95
|
@base.bools
|
51
96
|
end
|
data/lib/clive/bool.rb
CHANGED
@@ -1,13 +1,14 @@
|
|
1
1
|
class Clive
|
2
2
|
|
3
|
-
# A switch which can be triggered with either --no-
|
4
|
-
#
|
3
|
+
# A switch which can be triggered with either --no-[name] and --[name].
|
4
|
+
# The 'truthness' of this is then passed to the block.
|
5
5
|
class Bool < Option
|
6
6
|
attr_accessor :truth
|
7
7
|
|
8
8
|
# Creates a new Bool switch instance. A boolean switch has a truth,
|
9
9
|
# this determines what is passed to the block. They should be created
|
10
10
|
# in pairs so one can be +--something+ the other +--no-something+.
|
11
|
+
# NOTE: this does not happen within this class!
|
11
12
|
#
|
12
13
|
# +short+ and/or +desc+ can be omitted when creating a Boolean, all
|
13
14
|
# other arguments must be present.
|
@@ -19,6 +20,7 @@ class Clive
|
|
19
20
|
# @param [String] desc description of use/purpose
|
20
21
|
#
|
21
22
|
# @yield [Boolean] A block to be run when the switch is triggered
|
23
|
+
# @raise [MissingLongName] raises when a long name is not given
|
22
24
|
#
|
23
25
|
def initialize(*args, truth, &block)
|
24
26
|
@names = []
|
@@ -35,6 +37,7 @@ class Clive
|
|
35
37
|
end
|
36
38
|
end
|
37
39
|
|
40
|
+
# booleans require a long name to add --no- to
|
38
41
|
unless @names.find_all {|i| i.length > 1}.length > 0
|
39
42
|
raise MissingLongName, @names[0]
|
40
43
|
end
|
@@ -48,6 +51,8 @@ class Clive
|
|
48
51
|
@block.call(@truth)
|
49
52
|
end
|
50
53
|
|
54
|
+
# @param [Integer] width the total ideal width of help
|
55
|
+
# @param [Integer] prepend the number of spaces to add before each line
|
51
56
|
# @return [String] summary for help or nil if +@truth = false+
|
52
57
|
def summary(width=30, prepend=5)
|
53
58
|
return nil unless @truth
|
data/lib/clive/command.rb
CHANGED
@@ -98,8 +98,15 @@ class Clive
|
|
98
98
|
when :switch
|
99
99
|
v.run
|
100
100
|
when :flag
|
101
|
-
|
102
|
-
v.
|
101
|
+
args = i[2..-1]
|
102
|
+
opt_args = v.arg_num(true)
|
103
|
+
nec_args = v.arg_num(false)
|
104
|
+
# check for missing args
|
105
|
+
if args.size < nec_args
|
106
|
+
raise MissingArgument.new(v.sort_name)
|
107
|
+
end
|
108
|
+
|
109
|
+
v.run(args)
|
103
110
|
when :argument
|
104
111
|
r << v
|
105
112
|
end
|
@@ -170,8 +177,8 @@ class Clive
|
|
170
177
|
else
|
171
178
|
if k == :word
|
172
179
|
# add to last flag?
|
173
|
-
if r.last && r.last[0] == :flag && r.last[
|
174
|
-
r.last
|
180
|
+
if r.last && r.last[0] == :flag && r.last.size - 2 < r.last[1].args.size
|
181
|
+
r.last.push(v)
|
175
182
|
else
|
176
183
|
r << [:argument, v]
|
177
184
|
end
|
@@ -261,6 +268,7 @@ class Clive
|
|
261
268
|
if @options.length > 0
|
262
269
|
summary << "\n Options:\n"
|
263
270
|
@options.sort.each do |i|
|
271
|
+
next if i.names.include?("help")
|
264
272
|
summary << i.summary(width, prepend) << "\n" if i.summary
|
265
273
|
end
|
266
274
|
end
|
data/lib/clive/exceptions.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
class Clive
|
2
2
|
|
3
|
-
#
|
3
|
+
# General problem
|
4
4
|
class CliveError < StandardError
|
5
5
|
attr_accessor :args
|
6
6
|
|
@@ -26,21 +26,27 @@ class Clive
|
|
26
26
|
|
27
27
|
end
|
28
28
|
|
29
|
-
#
|
29
|
+
# General problem with input
|
30
30
|
class ParseError < CliveError
|
31
31
|
def reason; "parse error"; end
|
32
32
|
end
|
33
33
|
|
34
|
-
#
|
34
|
+
# A flag has a missing argument
|
35
35
|
class MissingArgument < ParseError
|
36
36
|
def reason; "missing argument"; end
|
37
37
|
end
|
38
38
|
|
39
|
-
#
|
39
|
+
# A flag has a wrong argument
|
40
|
+
class InvalidArgument < ParseError
|
41
|
+
def reason; "invalid argument"; end
|
42
|
+
end
|
43
|
+
|
44
|
+
# An option that wasn't defined has been found
|
40
45
|
class InvalidOption < ParseError
|
41
46
|
def reason; "invalid option"; end
|
42
47
|
end
|
43
48
|
|
49
|
+
# Long name is missing for bool
|
44
50
|
class MissingLongName < CliveError
|
45
51
|
def reason; "missing long name"; end
|
46
52
|
end
|
data/lib/clive/ext.rb
CHANGED
@@ -2,7 +2,7 @@ class Clive
|
|
2
2
|
|
3
3
|
class Array < ::Array
|
4
4
|
|
5
|
-
# If passed a Symbol or String will get the
|
5
|
+
# If passed a Symbol or String will get the option or command with that name.
|
6
6
|
# Otherwise does what you expect of an Array (see ::Array#[])
|
7
7
|
#
|
8
8
|
# @param [Symbol, String, Integer, Range] val name or index of item to return
|
@@ -16,5 +16,38 @@ class Clive
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
+
# Attempts to fill +self+ with values from +input+, giving priority to
|
20
|
+
# true, then false. If insufficient input to fill all false will use nil.
|
21
|
+
#
|
22
|
+
# @param [Array] input array of values to fill +self+ with
|
23
|
+
# @return [Array] filled array
|
24
|
+
#
|
25
|
+
# @example
|
26
|
+
#
|
27
|
+
# [true, false, false, true].optimise_fill(["a", "b", "c"])
|
28
|
+
# #=> ["a", "b", nil, "c"]
|
29
|
+
#
|
30
|
+
#
|
31
|
+
def optimise_fill(input)
|
32
|
+
match = self
|
33
|
+
diff = input.size - match.reject{|i| i == false}.size
|
34
|
+
|
35
|
+
result = []
|
36
|
+
match.each_index do |i|
|
37
|
+
curr_item = match[i]
|
38
|
+
if curr_item == true
|
39
|
+
result << input.shift
|
40
|
+
else
|
41
|
+
if diff > 0
|
42
|
+
result << input.shift
|
43
|
+
diff -= 1
|
44
|
+
else
|
45
|
+
result << nil
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
result
|
50
|
+
end
|
51
|
+
|
19
52
|
end
|
20
53
|
end
|
data/lib/clive/flag.rb
CHANGED
@@ -1,44 +1,75 @@
|
|
1
1
|
class Clive
|
2
2
|
|
3
|
-
# A switch that takes
|
3
|
+
# A switch that takes one or more arguments.
|
4
4
|
# eg. wget --tries=10
|
5
5
|
# wget -t 10
|
6
6
|
#
|
7
7
|
class Flag < Option
|
8
|
-
attr_accessor :
|
8
|
+
attr_accessor :args
|
9
9
|
|
10
|
-
# Creates a new Flag instance.
|
10
|
+
# Creates a new Flag instance. A flag is a switch that can take one or more
|
11
|
+
# arguments.
|
11
12
|
#
|
12
|
-
# +short+
|
13
|
+
# +short+ *or* +long+ can be omitted but not both.
|
14
|
+
# +args+ can also be omitted (is "ARG" by default)
|
13
15
|
#
|
14
|
-
# @overload flag(short, long, desc, &block)
|
15
|
-
# Creates a new flag
|
16
|
+
# @overload flag(short, long, args, desc, &block)
|
16
17
|
# @param [Symbol] short single character for short flag, eg. +:t+ => +-t 10+
|
17
18
|
# @param [Symbol] long longer switch to be used, eg. +:tries+ => +--tries=10+
|
19
|
+
# @param [String, Array] args
|
20
|
+
# either a string showing the arguments to be given, eg.
|
21
|
+
#
|
22
|
+
# "FROM" # single arg, or
|
23
|
+
# "FROM TO" # two args, or
|
24
|
+
# "[VIA]" # optional arg surrounded by square brackets
|
25
|
+
#
|
26
|
+
# or an array of acceptable inputs, eg.
|
27
|
+
#
|
28
|
+
# ["large", "medium", "small"] # will only accept these args
|
29
|
+
#
|
18
30
|
# @param [String] desc the description for the flag
|
19
31
|
#
|
20
32
|
# @yield [String] A block to be run if switch is triggered
|
21
33
|
#
|
22
34
|
def initialize(*args, &block)
|
23
|
-
@names
|
24
|
-
@
|
25
|
-
@arg_name = "ARG"
|
35
|
+
@names = []
|
36
|
+
@args = []
|
26
37
|
|
38
|
+
# Need to be able to make each arg_name optional or not
|
39
|
+
# and allow for type in future
|
27
40
|
args.each do |i|
|
28
41
|
if i.is_a? String
|
29
|
-
if i =~
|
30
|
-
|
42
|
+
if i =~ /\A(([A-Z0-9\[\]]+)\s?)+\Z/
|
43
|
+
i.split(' ').each do |arg|
|
44
|
+
type = String
|
45
|
+
if arg[0] == "["
|
46
|
+
@args << {
|
47
|
+
:name => arg[1..arg.length-2],
|
48
|
+
:optional => true,
|
49
|
+
:type => type
|
50
|
+
}
|
51
|
+
else
|
52
|
+
@args << {
|
53
|
+
:name => arg,
|
54
|
+
:optional => false,
|
55
|
+
:type => type
|
56
|
+
}
|
57
|
+
end
|
58
|
+
end
|
31
59
|
else
|
32
60
|
@desc = i
|
33
61
|
end
|
34
62
|
else
|
35
|
-
|
63
|
+
if i.class == Symbol
|
64
|
+
@names << i.to_s
|
65
|
+
else
|
66
|
+
@args = i
|
67
|
+
end
|
36
68
|
end
|
37
69
|
end
|
38
70
|
|
39
|
-
if @
|
40
|
-
@
|
41
|
-
@optional = true
|
71
|
+
if @args == []
|
72
|
+
@args = [{:name => "ARG", :optional => false, :type => String}]
|
42
73
|
end
|
43
74
|
|
44
75
|
@block = block
|
@@ -46,20 +77,45 @@ class Clive
|
|
46
77
|
|
47
78
|
# Runs the block that was given with an argument
|
48
79
|
#
|
49
|
-
# @param [
|
50
|
-
|
51
|
-
|
80
|
+
# @param [Array] args arguments to pass to the block
|
81
|
+
# @raise [InvalidArgument] only if +args+ is an array of acceptable inputs
|
82
|
+
# and a match is not found.
|
83
|
+
def run(args)
|
84
|
+
if @args[0].is_a? Hash
|
85
|
+
args = Clive::Array.new(@args.collect {|i| !i[:optional]}).optimise_fill(args)
|
86
|
+
else # list
|
87
|
+
unless @args.include? args[0]
|
88
|
+
raise InvalidArgument.new(args)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
@block.call(*args)
|
92
|
+
end
|
93
|
+
|
94
|
+
# @param [Boolean] optional whether to include optional arguments
|
95
|
+
# @return [Integer] number of arguments this takes
|
96
|
+
def arg_num(optional)
|
97
|
+
if @args[0].is_a? Hash
|
98
|
+
@args.find_all {|i| i[:optional] == optional }.size
|
99
|
+
else
|
100
|
+
1
|
101
|
+
end
|
52
102
|
end
|
53
103
|
|
54
104
|
# @return [String] summary for help
|
55
105
|
def summary(width=30, prepend=5)
|
56
106
|
n = names_to_strings.join(', ')
|
57
|
-
|
58
|
-
|
107
|
+
a = nil
|
108
|
+
if @args[0].is_a? Hash
|
109
|
+
a = @args.map {|i| i[:name]}.join(' ')
|
110
|
+
if @optional
|
111
|
+
n << " [#{a}]"
|
112
|
+
else
|
113
|
+
n << " #{a}"
|
114
|
+
end
|
59
115
|
else
|
60
|
-
n << "
|
116
|
+
n << " {" << @args.join(', ') << "}"
|
61
117
|
end
|
62
|
-
|
118
|
+
|
63
119
|
spaces = width-n.length
|
64
120
|
spaces = 1 if spaces < 1
|
65
121
|
s = spaces(spaces)
|
data/lib/clive/option.rb
CHANGED
@@ -1,16 +1,17 @@
|
|
1
1
|
class Clive
|
2
2
|
|
3
|
+
# @abstract Subclass and override {#initialize} and {#run} to create a new Option class.
|
3
4
|
class Option
|
4
5
|
attr_accessor :names, :desc, :block
|
5
6
|
|
6
|
-
def initialize(
|
7
|
-
|
8
|
-
@
|
9
|
-
@block = block
|
7
|
+
def initialize(*args, &block)
|
8
|
+
# assign name and description
|
9
|
+
# @block = block
|
10
10
|
end
|
11
11
|
|
12
12
|
def run
|
13
|
-
|
13
|
+
# call the block!
|
14
|
+
# @block.call
|
14
15
|
end
|
15
16
|
|
16
17
|
def summary(width=30, prepend=5)
|
@@ -22,7 +23,8 @@ class Clive
|
|
22
23
|
"#{p}#{n}#{s}#{@desc}"
|
23
24
|
end
|
24
25
|
|
25
|
-
# Convert the names to strings,
|
26
|
+
# Convert the names to strings, if name is single character appends
|
27
|
+
# +-+, else appends +--+.
|
26
28
|
#
|
27
29
|
# @param [Boolean] bool whether to add [no-] to long
|
28
30
|
#
|
@@ -69,6 +71,7 @@ class Clive
|
|
69
71
|
r
|
70
72
|
end
|
71
73
|
|
74
|
+
# Compare options based on Option#sort_name
|
72
75
|
def <=>(other)
|
73
76
|
self.sort_name <=> other.sort_name
|
74
77
|
end
|
data/lib/clive/tokens.rb
CHANGED
@@ -11,13 +11,17 @@ class Clive
|
|
11
11
|
# ["Value", "--verbose", "-r"]
|
12
12
|
#
|
13
13
|
class Tokens < Array
|
14
|
-
|
14
|
+
|
15
15
|
TOKEN_KEYS = [:word, :short, :long]
|
16
16
|
|
17
17
|
# Create a new Tokens instance. Pass either an array of tokens
|
18
18
|
# or a plain array, they will be converted correctly.
|
19
19
|
#
|
20
|
-
# @param [
|
20
|
+
# @param [Array] args
|
21
|
+
# pass either
|
22
|
+
# ["command", "--flag"]
|
23
|
+
# # or
|
24
|
+
# [[:word, "command"], [:long, "flag"]]
|
21
25
|
# @return [Tokens]
|
22
26
|
#
|
23
27
|
def initialize(args=[])
|
@@ -51,7 +55,10 @@ class Clive
|
|
51
55
|
arr
|
52
56
|
end
|
53
57
|
|
54
|
-
# Creates an array of tokens based on +self
|
58
|
+
# Creates an array of tokens based on +self+.
|
59
|
+
# Strings beginning with a -, eg. -n become [:short, "n"].
|
60
|
+
# Strings beginning with --, eg. --verbose become [:long, "verbose"].
|
61
|
+
# Strings which begin with neither become [:word, "value"].
|
55
62
|
#
|
56
63
|
# @return [::Array] the tokens that are held
|
57
64
|
def tokens
|
@@ -78,10 +85,12 @@ class Clive
|
|
78
85
|
t
|
79
86
|
end
|
80
87
|
|
88
|
+
# @see #tokens
|
81
89
|
def self.to_tokens(arr)
|
82
90
|
Tokens.new(arr).tokens
|
83
91
|
end
|
84
92
|
|
93
|
+
# @see #array
|
85
94
|
def self.to_array(tokens)
|
86
95
|
Tokens.new(tokens).array
|
87
96
|
end
|
data/test/bin_test
CHANGED
data/test/helper.rb
CHANGED
@@ -1,10 +1,13 @@
|
|
1
|
+
require 'duvet'
|
2
|
+
Duvet.start :filter => 'clive/lib'
|
3
|
+
|
1
4
|
require 'test/unit'
|
2
5
|
require 'shoulda'
|
3
6
|
require 'rr'
|
4
7
|
|
5
8
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
6
9
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
7
|
-
require 'clive'
|
10
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'clive')
|
8
11
|
|
9
12
|
class Test::Unit::TestCase
|
10
13
|
include RR::Adapters::TestUnit
|
data/test/test_clive.rb
CHANGED
@@ -155,6 +155,12 @@ class TestClive < Test::Unit::TestCase
|
|
155
155
|
assert_equal ["argument"], args
|
156
156
|
end
|
157
157
|
|
158
|
+
should "recognise a quoted argument" do
|
159
|
+
c = Clive.new {}
|
160
|
+
args = c.parse ['a quoted argument']
|
161
|
+
assert_equal ["a quoted argument"], args
|
162
|
+
end
|
163
|
+
|
158
164
|
should "recognise multiple arguments" do
|
159
165
|
c = Clive.new do
|
160
166
|
bool(:v, :verbose, "Run verbosely") {}
|
data/test/test_flag.rb
CHANGED
@@ -6,7 +6,7 @@ class TestFlag < Test::Unit::TestCase
|
|
6
6
|
|
7
7
|
setup do
|
8
8
|
@c = Clive.new do
|
9
|
-
flag(:t, :type, "TEXT", "Change type to TYPE") {|i|
|
9
|
+
flag(:t, :type, "TEXT", "Change type to TYPE") {|i| puts(i)}
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
@@ -15,14 +15,14 @@ class TestFlag < Test::Unit::TestCase
|
|
15
15
|
@c.parse(["--type", "text"])
|
16
16
|
end
|
17
17
|
|
18
|
-
should "have
|
19
|
-
|
18
|
+
should "have a arguments" do
|
19
|
+
r = {:name => "TEXT", :optional => false, :type => String}
|
20
|
+
assert_equal r, @c.flags["t"].args[0]
|
20
21
|
end
|
21
22
|
|
22
23
|
should "not be optional" do
|
23
|
-
assert_equal false, @c.flags["t"].optional
|
24
|
+
assert_equal false, @c.flags["t"].args[0][:optional]
|
24
25
|
end
|
25
|
-
|
26
26
|
end
|
27
27
|
|
28
28
|
context "A new flag with default" do
|
@@ -37,11 +37,12 @@ class TestFlag < Test::Unit::TestCase
|
|
37
37
|
end
|
38
38
|
|
39
39
|
should "have an arg name" do
|
40
|
-
|
40
|
+
r = {:name => "TEXT", :optional => true, :type => String}
|
41
|
+
assert_equal r, @c.flags["t"].args[0]
|
41
42
|
end
|
42
43
|
|
43
44
|
should "be optional" do
|
44
|
-
assert_equal true, @c.flags["t"].optional
|
45
|
+
assert_equal true, @c.flags["t"].args[0][:optional]
|
45
46
|
end
|
46
47
|
|
47
48
|
should "pass an argument to block" do
|
@@ -55,4 +56,105 @@ class TestFlag < Test::Unit::TestCase
|
|
55
56
|
end
|
56
57
|
end
|
57
58
|
|
59
|
+
context "A new flag with multiple arguments" do
|
60
|
+
|
61
|
+
setup do
|
62
|
+
@c = Clive.new do
|
63
|
+
flag(:s, :send, "FROM TO", "Send the message from FROM to TO") do |from, to|
|
64
|
+
puts from
|
65
|
+
puts to
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
should "pass two arguments to the block" do
|
71
|
+
mock($stdout).puts("John")
|
72
|
+
mock($stdout).puts("Dave")
|
73
|
+
@c.parse(["--send", "John", "Dave"])
|
74
|
+
end
|
75
|
+
|
76
|
+
should "have a useful summary" do
|
77
|
+
s = "-s, --send FROM TO Send the message from FROM to TO"
|
78
|
+
assert_equal s, @c.flags['s'].summary(0, 0)
|
79
|
+
end
|
80
|
+
|
81
|
+
should "work for more than two arguments" do
|
82
|
+
mock($stdout).puts("from: Josh, to: John, via: Hong Kong, because: It's far away")
|
83
|
+
c = Clive.new do
|
84
|
+
flag(:s, :send, "FROM TO VIA BECAUSE", "Send the message...etc") do |f, t, v, b|
|
85
|
+
puts "from: #{f}, to: #{t}, via: #{v}, because: #{b}"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
c.parse ['-s', 'Josh', 'John', "Hong Kong", "It's far away"]
|
89
|
+
end
|
90
|
+
|
91
|
+
context "and optional arguments" do
|
92
|
+
setup do
|
93
|
+
@c = Clive.new do
|
94
|
+
flag(:s, :send, "FROM [VIA] TO [BECAUSE]", "Send the message...etc") do |f, v, t, b|
|
95
|
+
s = "from: #{f}"
|
96
|
+
s << ", via: #{v}" if v
|
97
|
+
s << ", to: #{t}"
|
98
|
+
s << ", because: #{b}" if b
|
99
|
+
puts s
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
should "correctly parse argument string" do
|
105
|
+
r = [
|
106
|
+
{:name => "FROM", :optional => false, :type => String},
|
107
|
+
{:name => "VIA", :optional => true, :type => String},
|
108
|
+
{:name => "TO", :optional => false, :type => String},
|
109
|
+
{:name => "BECAUSE", :optional => true, :type => String}
|
110
|
+
]
|
111
|
+
assert_equal r, @c.flags[:s].args
|
112
|
+
end
|
113
|
+
|
114
|
+
should "give all arguments when found in input" do
|
115
|
+
mock($stdout).puts("from: Josh, via: Hong Kong, to: John, because: It's far away")
|
116
|
+
@c.parse ["-s", "Josh", "Hong Kong", "John", "It's far away"]
|
117
|
+
end
|
118
|
+
|
119
|
+
should "try to give only needed arguments if some missing" do
|
120
|
+
mock($stdout).puts("from: Josh, to: John")
|
121
|
+
@c.parse ["-s", "Josh", "John"]
|
122
|
+
end
|
123
|
+
|
124
|
+
should "fill optional arguments starting from left" do
|
125
|
+
mock($stdout).puts("from: Josh, via: Hong Kong, to: John")
|
126
|
+
@c.parse ["-s", "Josh", "Hong Kong", "John"]
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
context "A new flag with a list of acceptable arguments" do
|
133
|
+
|
134
|
+
setup do
|
135
|
+
@c = Clive.new do
|
136
|
+
flag(:t, :type, ["large", "medium", "small"], "Choose the type to use") {}
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
should "raise error when correct argument not found" do
|
141
|
+
assert_raise Clive::InvalidArgument do
|
142
|
+
@c.parse(["--type", "apple"])
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
should "not raise error when correct argument given" do
|
147
|
+
@c.parse(["--type", "large"])
|
148
|
+
end
|
149
|
+
|
150
|
+
should "make list arguments" do
|
151
|
+
r = ["large", "medium", "small"]
|
152
|
+
assert_equal r, @c.flags['t'].args
|
153
|
+
end
|
154
|
+
|
155
|
+
should "have a useful summary" do
|
156
|
+
s = "-t, --type {large, medium, small} Choose the type to use"
|
157
|
+
assert_equal s, @c.flags['t'].summary(0, 0)
|
158
|
+
end
|
159
|
+
end
|
58
160
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: clive
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 15
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 4
|
9
|
+
- 0
|
10
|
+
version: 0.4.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Joshua Hawxwell
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-
|
18
|
+
date: 2010-09-19 00:00:00 +01:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|