clive 0.8.1 → 1.0.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.
Files changed (52) hide show
  1. data/LICENSE +1 -1
  2. data/README.md +328 -227
  3. data/lib/clive.rb +130 -50
  4. data/lib/clive/argument.rb +170 -0
  5. data/lib/clive/arguments.rb +139 -0
  6. data/lib/clive/arguments/parser.rb +210 -0
  7. data/lib/clive/base.rb +189 -0
  8. data/lib/clive/command.rb +342 -444
  9. data/lib/clive/error.rb +66 -0
  10. data/lib/clive/formatter.rb +57 -141
  11. data/lib/clive/formatter/colour.rb +37 -0
  12. data/lib/clive/formatter/plain.rb +172 -0
  13. data/lib/clive/option.rb +185 -75
  14. data/lib/clive/option/runner.rb +163 -0
  15. data/lib/clive/output.rb +141 -16
  16. data/lib/clive/parser.rb +180 -87
  17. data/lib/clive/struct_hash.rb +109 -0
  18. data/lib/clive/type.rb +117 -0
  19. data/lib/clive/type/definitions.rb +170 -0
  20. data/lib/clive/type/lookup.rb +23 -0
  21. data/lib/clive/version.rb +3 -3
  22. data/spec/clive/a_cli_spec.rb +245 -0
  23. data/spec/clive/argument_spec.rb +148 -0
  24. data/spec/clive/arguments/parser_spec.rb +35 -0
  25. data/spec/clive/arguments_spec.rb +191 -0
  26. data/spec/clive/command_spec.rb +276 -209
  27. data/spec/clive/formatter/colour_spec.rb +129 -0
  28. data/spec/clive/formatter/plain_spec.rb +129 -0
  29. data/spec/clive/option/runner_spec.rb +92 -0
  30. data/spec/clive/option_spec.rb +149 -23
  31. data/spec/clive/output_spec.rb +86 -2
  32. data/spec/clive/parser_spec.rb +201 -81
  33. data/spec/clive/struct_hash_spec.rb +82 -0
  34. data/spec/clive/type/definitions_spec.rb +312 -0
  35. data/spec/clive/type_spec.rb +107 -0
  36. data/spec/clive_spec.rb +60 -0
  37. data/spec/extras/expectations.rb +86 -0
  38. data/spec/extras/focus.rb +22 -0
  39. data/spec/helper.rb +35 -0
  40. metadata +56 -36
  41. data/lib/clive/bool.rb +0 -67
  42. data/lib/clive/exceptions.rb +0 -54
  43. data/lib/clive/flag.rb +0 -199
  44. data/lib/clive/switch.rb +0 -31
  45. data/lib/clive/tokens.rb +0 -141
  46. data/spec/clive/bool_spec.rb +0 -54
  47. data/spec/clive/flag_spec.rb +0 -117
  48. data/spec/clive/formatter_spec.rb +0 -108
  49. data/spec/clive/switch_spec.rb +0 -14
  50. data/spec/clive/tokens_spec.rb +0 -38
  51. data/spec/shared_specs.rb +0 -16
  52. data/spec/spec_helper.rb +0 -12
@@ -1,31 +0,0 @@
1
- module Clive
2
-
3
- # A string that takes no argument, beginning with one or two dashes
4
- # eg. ruby --version
5
- # ruby -v
6
- #
7
- class Switch < Option
8
-
9
- # Create a new Switch instance.
10
- #
11
- # @param names [Array[Symbol]]
12
- # An array of names the option can be invoked by.
13
- #
14
- # @param desc [String]
15
- # A description of what the option does.
16
- #
17
- # @yield A block to run if the switch is triggered
18
- #
19
- def initialize(names, desc, &block)
20
- @names = names.map(&:to_s)
21
- @desc = desc
22
- @block = block
23
- end
24
-
25
- # Runs the block that was given
26
- def run
27
- @block.call
28
- end
29
-
30
- end
31
- end
@@ -1,141 +0,0 @@
1
- module Clive
2
-
3
- # A subclass of Array to allow the creation of arrays that look
4
- # like:
5
- #
6
- # [[:word, 'Value'], [:long, 'verbose'], [:short, 'r']]
7
- #
8
- # The tokens are not stored like that but as the string
9
- # representations:
10
- #
11
- # ["Value", "--verbose", "-r"]
12
- #
13
- class Tokens < Array
14
-
15
- TOKEN_KEYS = [:word, :short, :long]
16
-
17
- # Create a new Tokens instance. Pass either an array of tokens
18
- # or a plain array, they will be converted correctly.
19
- #
20
- # @param [Array] args
21
- # pass either
22
- # ["command", "--flag"]
23
- # # or
24
- # [[:word, "command"], [:long, "flag"]]
25
- # @return [Tokens]
26
- #
27
- def initialize(args=[])
28
- if token?(args[0])
29
- r = []
30
- args.each {|i| r << token_to_string(i)}
31
- args = r
32
- end
33
- super(args)
34
- end
35
-
36
- # Turn +@tokens+ into an array, this ensures that shorts are split
37
- # as is expected
38
- #
39
- # @return [Array] array representation of tokens held
40
- def array
41
- return [] unless self.tokens
42
- arr = []
43
- self.tokens.each do |i|
44
- k, v = i[0], i[1]
45
- case k
46
- when :long
47
- arr << "--#{v}"
48
- when :short
49
- arr << "-#{v}"
50
- when :word
51
- arr << v
52
- end
53
- end
54
-
55
- arr
56
- end
57
-
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"].
62
- #
63
- # @return [Array] the tokens that are held
64
- def tokens
65
- t = []
66
- self.each do |i|
67
- case i
68
- when /\-\-.+/
69
- if i.include?('=')
70
- a, b = i[2..i.length].split('=')
71
- t << [:long, a] << [:word, b]
72
- else
73
- t << [:long, i[2..i.length]]
74
- end
75
- when /\-.+/
76
- i[1..i.length].split('').each do |j|
77
- t << [:short, j]
78
- end
79
- else
80
- t << [:word, i]
81
- end
82
- end
83
-
84
- t
85
- end
86
-
87
- # @see #tokens
88
- def self.to_tokens(arr)
89
- Tokens.new(arr).tokens
90
- end
91
-
92
- # @see #array
93
- def self.to_array(tokens)
94
- Tokens.new(tokens).array
95
- end
96
-
97
- # Checks to see if it is a token being added and changes it back
98
- def <<(val)
99
- if token?(val)
100
- super(token_to_string(val))
101
- else
102
- super
103
- end
104
- end
105
-
106
- # Test whether an array is a token
107
- #
108
- # @param [Array]
109
- # @return [Boolean]
110
- #
111
- # @example
112
- #
113
- # t.token?([:word, "something"]) #=> true
114
- # t.token?(["a", "normal", "array"]) #=> false
115
- #
116
- def token?(arr)
117
- return false if arr.nil?
118
- TOKEN_KEYS.include?(arr[0])
119
- end
120
-
121
- # Convert a tokens to its string representation
122
- def token_to_string(token)
123
- k, v = token[0], token[1]
124
- case k
125
- when :long
126
- "--#{v}"
127
- when :short
128
- "-#{v}"
129
- when :word
130
- v
131
- end
132
- end
133
-
134
- # This is here to force the use of #tokens and #array when
135
- # accessing the contents
136
- def inspect
137
- "#<Clive::Tokens:0x#{'%x' % (self.object_id << 1)} #{self.tokens}>"
138
- end
139
-
140
- end
141
- end
@@ -1,54 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Clive::Bool do
4
-
5
- subject { Clive::Bool.new([:n, :name], "A test", true) {|arg| $stdout.puts arg } }
6
- let(:falsey) { Clive::Bool.new([:n, :name], "A test", false) {|arg| $stdout.puts arg } }
7
-
8
- describe "#truth" do
9
- it "returns the truth" do
10
- subject.truth.should == true
11
- end
12
- end
13
-
14
- it_behaves_like "an option"
15
-
16
- context "when no long name is given" do
17
- it "raises an error" do
18
- expect {
19
- Clive::Bool.new([:n], "Short test", true) {}
20
- }.should raise_error Clive::MissingLongName
21
- end
22
- end
23
-
24
- describe "#run" do
25
- context "when truth is true" do
26
- it "passes true to the block" do
27
- $stdout.should_receive(:puts).with(true)
28
- subject.run
29
- end
30
- end
31
-
32
- context "when truth is false" do
33
- it "passes false to the block" do
34
- $stdout.should_receive(:puts).with(false)
35
- falsey.run
36
- end
37
- end
38
- end
39
-
40
- describe "#to_h" do
41
- context "when truth is true" do
42
- it "returns hash for help formatter" do
43
- hsh = {'names' => subject.names_to_strings(true),
44
- 'desc' => subject.desc}
45
- subject.to_h.should == hsh
46
- end
47
- end
48
-
49
- context "when truth is false" do
50
- specify { falsey.to_h.should be_nil }
51
- end
52
- end
53
-
54
- end
@@ -1,117 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Clive::Flag do
4
-
5
- subject { Clive::Flag.new([:S, :say], "Say something", "WORD(S)") {|i| $stdout.puts i } }
6
-
7
- it_behaves_like "an option"
8
-
9
- describe "#run" do
10
- it "calls the block with the argument" do
11
- $stdout.should_receive(:puts).with("hey")
12
- subject.run(["hey"])
13
- end
14
- end
15
-
16
- describe "#arg_size" do
17
- context "when choice is available" do
18
- it "returns 1" do
19
- subject.args = 1..5
20
- subject.arg_size.should == 1
21
- end
22
- end
23
-
24
- context "when arguments are required" do
25
- subject { Clive::Flag.new([:n], "Description", "REQ [OPT] REQ2 [OPT2] [OPT3]") }
26
-
27
- it "returns the number of all arguments" do
28
- subject.arg_size(:all).should == 5
29
- end
30
-
31
- it "returns the number of optional arguments" do
32
- subject.arg_size(:optional).should == 3
33
- end
34
-
35
- it "returns the number of mandatory arguments" do
36
- subject.arg_size(:mandatory).should == 2
37
- end
38
- end
39
- end
40
-
41
- describe "#args_to_string" do
42
-
43
- context "when a list of options" do
44
- it "returns the arguments as a string" do
45
- subject.args = "first [second]"
46
- subject.args_to_string.should == "<first> [second]"
47
- end
48
- end
49
-
50
- context "when a splat as option" do
51
- it "returns the argument and ellipsis" do
52
- subject.args = "arg..."
53
- subject.args_to_string.should == "<arg1> ..."
54
- end
55
- end
56
-
57
- context "when a choice of options" do
58
- it "returns an empty string" do
59
- subject.args = %w(a b c)
60
- subject.args_to_string.should == ""
61
- end
62
- end
63
-
64
- context "when a range of options" do
65
- it "returns an empty string" do
66
- subject.args = 1..5
67
- subject.args_to_string.should == ""
68
- end
69
- end
70
-
71
- end
72
-
73
- describe "#options_to_string" do
74
-
75
- context "when a list of options" do
76
- it "returns an empty string" do
77
- subject.args = "first [second]"
78
- subject.options_to_string.should == ""
79
- end
80
- end
81
-
82
- context "when a splat as option" do
83
- it "returns an empty string" do
84
- subject.args = "arg..."
85
- subject.options_to_string.should == ""
86
- end
87
- end
88
-
89
- context "when a choice of options" do
90
- it "returns the choices joined" do
91
- subject.args = %w(a b c)
92
- subject.options_to_string.should == "(a, b, c)"
93
- end
94
- end
95
-
96
- context "when a range of options" do
97
- it "returns a string representation of the range" do
98
- subject.args = 1..5
99
- subject.options_to_string.should == "(1..5)"
100
- end
101
- end
102
-
103
- end
104
-
105
- describe "#to_h" do
106
- it "returns a hash" do
107
- hsh = {
108
- "names" => %w(-S --say),
109
- "desc" => "Say something",
110
- "args" => "<WORD(S)>",
111
- "options" => ""
112
- }
113
- subject.to_h.should == hsh
114
- end
115
- end
116
-
117
- end
@@ -1,108 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Clive::Formatter do
4
-
5
- describe Clive::Formatter::Obj do
6
- subject { Clive::Formatter::Obj.new({:test => 5}) }
7
-
8
- describe "#initialize" do
9
- it "defines methods given by hash" do
10
- subject.test.should == 5
11
- end
12
- end
13
-
14
- describe "#evaluate" do
15
- it "evaluates code within the object" do
16
- $stdout.should_receive(:puts).with(5)
17
- subject.evaluate("$stdout.puts test")
18
- end
19
- end
20
- end
21
-
22
-
23
- subject { Clive::Formatter.new(30, 5) }
24
-
25
-
26
- describe "#switch" do
27
- it "sets format for switches" do
28
- subject.switch("{desc}")
29
- subject.instance_variable_get("@switch").should == "{desc}"
30
- end
31
- end
32
-
33
- describe "#bool" do
34
- it "sets format for bools" do
35
- subject.bool "{desc}"
36
- subject.instance_variable_get("@bool").should == "{desc}"
37
- end
38
- end
39
-
40
- describe "#flag" do
41
- it "sets format for flags" do
42
- subject.flag "{desc}"
43
- subject.instance_variable_get("@flag").should == "{desc}"
44
- end
45
- end
46
-
47
- describe "#command" do
48
- it "sets format for commands" do
49
- subject.command "{desc}"
50
- subject.instance_variable_get("@command").should == "{desc}"
51
- end
52
- end
53
-
54
-
55
- describe "#format" do
56
- it "generates the help" do
57
- formatter = Clive::Command.setup(Class.new).help_formatter(:white)
58
- options = [
59
- Clive::Switch.new([:t, :test], "A test switch"),
60
- Clive::Bool.new([:boolean], "A bool", true),
61
- Clive::Bool.new([:boolean], "A bool", false),
62
- Clive::Flag.new([:args], "With args", "ARG [OPT]"),
63
- Clive::Flag.new([:choose], "With options", ["a", "b", "c"])
64
- ]
65
- command = Clive::Command.new([:command], "A command", Class.new)
66
- result = <<EOS
67
- head
68
-
69
- Commands:
70
- command A command
71
-
72
- Options:
73
- -t, --test A test switch
74
- --[no-]boolean A bool
75
- --args <ARG> [OPT] With args \e[1m\e[0m
76
- --choose With options \e[1m(a, b, c)\e[0m
77
-
78
- foot
79
- EOS
80
-
81
- formatter.format("head", "foot", [command], options).should == result
82
- end
83
- end
84
-
85
-
86
- describe "#parse" do
87
- it "parses before and after '{spaces}' separately" do
88
- args = {"name" => "a", "desc" => "something"}
89
- subject.should_receive(:parse_format).with("{name}", args).and_return("")
90
- subject.should_receive(:parse_format).with("{desc}", args).and_return("")
91
- subject.parse("{name}{spaces}{desc}", args)
92
- end
93
-
94
- it "calculates the correct number of spaces" do
95
- args = {"name" => "a long name", "desc" => "|a short desc"}
96
- subject.parse("{name}{spaces}{desc}", args).split('|')[0].size.should == 30
97
- end
98
- end
99
-
100
- describe "#parse_format" do
101
- it "inserts the arguments into the format" do
102
- subject.parse_format(
103
- "{desc}{name}", {'desc' => 'a', 'name' => 'b'}
104
- ).should == "ab"
105
- end
106
- end
107
-
108
- end