clive 0.3.1 → 0.4.0
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/.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
|