clive 0.6.2 → 0.7.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.
@@ -6,7 +6,7 @@
6
6
  #
7
7
  #
8
8
 
9
- class Clive
9
+ module Clive
10
10
  module Output
11
11
 
12
12
  end
@@ -68,23 +68,19 @@ class String
68
68
  colour("\e[4#{code}m")
69
69
  end
70
70
 
71
- # Light white doesn't exist
72
- unless name == "white"
73
- # Change name to grey instead of l_black
74
- _name = "l_#{name}"
75
- if name == "black"
76
- _name = "grey"
77
- end
78
-
79
- define_method "#{_name}" do
80
- colour("\e[9#{code}m")
81
- end
82
-
83
- define_method "#{_name}_bg" do
84
- colour("\e[10#{code}m")
85
- end
71
+ # Change name to grey instead of l_black
72
+ l_name = "l_#{name}"
73
+ if name == "black"
74
+ l_name = "grey"
75
+ end
76
+
77
+ define_method "#{l_name}" do
78
+ colour("\e[9#{code}m")
79
+ end
80
+
81
+ define_method "#{l_name}_bg" do
82
+ colour("\e[10#{code}m")
86
83
  end
87
- end
88
84
 
85
+ end
89
86
  end
90
-
@@ -8,7 +8,11 @@ require 'clive/switch'
8
8
  require 'clive/flag'
9
9
  require 'clive/bool'
10
10
 
11
- class Clive
11
+ require 'clive/output'
12
+ require 'clive/formatter'
13
+
14
+
15
+ module Clive
12
16
 
13
17
  # A module wrapping the command line parsing of clive. In the future this
14
18
  # will be the only way of using clive.
@@ -19,11 +23,7 @@ class Clive
19
23
  #
20
24
  # class CLI
21
25
  # include Clive::Parser
22
- #
23
- # @@opts ||= {}
24
- # def self.opts
25
- # @@opts
26
- # end
26
+ # option_hash :opts
27
27
  #
28
28
  # switch :v, :verbose, "Run verbosely" do
29
29
  # opts[:verbose] = true
@@ -34,32 +34,95 @@ class Clive
34
34
  # p CLI.opts
35
35
  #
36
36
  module Parser
37
-
37
+
38
+ # When the module is included we need to keep track of the new class it
39
+ # is now in and we need to create a new base command. So here instance
40
+ # variables are set directly in the new class, and the class is made to
41
+ # extend the methods in Parser so they are available as class methods.
42
+ #
38
43
  def self.included(klass)
39
- @@klass = klass
40
- @@klass.extend(self)
41
- @@base = Clive::Command.new(true)
44
+ klass.instance_variable_set("@klass", klass)
45
+ klass.extend(self)
46
+ klass.instance_variable_set "@base", Clive::Command.new(true)
42
47
  end
43
-
48
+
49
+ # @return [Clive::Command]
50
+ # The base command to forward method calls to.
51
+ #
52
+ def base; @base; end
53
+
54
+ # @see Clive::Command#run
44
55
  def parse(argv)
45
- @@base.run(argv)
56
+ base.run(argv)
46
57
  end
47
58
 
59
+ # @see Clive::Command#flag
48
60
  def flag(*args, &block)
49
- @@base.flag(*args, &block)
61
+ base.flag(*args, &block)
50
62
  end
51
63
 
64
+ # @see Clive::Command#switch
52
65
  def switch(*args, &block)
53
- @@base.switch(*args, &block)
66
+ base.switch(*args, &block)
54
67
  end
55
68
 
69
+ # @see Clive::Command#command
56
70
  def command(*args, &block)
57
- @@base.command(*args, &block)
71
+ base.command(*args, &block)
58
72
  end
59
73
 
74
+ # @see Clive::Command#bool
60
75
  def bool(*args, &block)
61
- @@base.bool(*args, &block)
76
+ base.bool(*args, &block)
77
+ end
78
+
79
+ # @see Clive::Command#desc
80
+ def desc(*args)
81
+ base.desc(*args)
82
+ end
83
+
84
+ # @see Clive::Command#help_formatter
85
+ def help_formatter(*args, &block)
86
+ base.help_formatter(*args, &block)
87
+ end
88
+
89
+
90
+ # @see http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html
91
+ # or because that doesn't exist anymore from this mirror
92
+ # http://viewsourcecode.org/why/hacking/seeingMetaclassesClearly.html
93
+ #
94
+ def meta_def(name, &blk)
95
+ (class << self; self; end).instance_eval { define_method(name, &blk) }
96
+ end
97
+
98
+ def option_var(name, value=nil)
99
+ @klass.meta_def(name) do
100
+ instance_variable_get("@#{name}")
101
+ end
102
+ @klass.meta_def("#{name}=") do |val|
103
+ instance_variable_set("@#{name}", val)
104
+ end
105
+ instance_variable_set("@#{name}", value)
106
+ end
107
+
108
+ # Create a new hash which is accessible to the options in the new class
109
+ # but can also be accessed from outside the class. Defines getters and
110
+ # setters for the symbols given, and sets their initial value to +{}+.
111
+ #
112
+ # @param args [Symbol]
113
+ #
114
+ def option_hash(*args)
115
+ args.each do |arg|
116
+ option_var(arg, {})
117
+ end
118
+ end
119
+
120
+ def option_array(*args)
121
+ args.each do |arg|
122
+ option_var(arg, [])
123
+ end
62
124
  end
125
+ alias_method :option_list, :option_array
63
126
 
64
127
  end
65
128
  end
@@ -1,4 +1,4 @@
1
- class Clive
1
+ module Clive
2
2
 
3
3
  # A string that takes no argument, beginning with one or two dashes
4
4
  # eg. ruby --version
@@ -8,26 +8,17 @@ class Clive
8
8
 
9
9
  # Create a new Switch instance.
10
10
  #
11
- # +short+ _or_ +long+ may be omitted but not both.
11
+ # @param names [Array[Symbol]]
12
+ # An array of names the option can be invoked by.
12
13
  #
13
- # @overload switch(short, long, desc, &block)
14
- # Creates a new switch
15
- # @param [Symbol] short single character for short switch, eg. +:v+ => +-v+
16
- # @param [Symbol] long longer switch to be used, eg. +:verbose+ => +--verbose+
17
- # @param [String] desc the description for the switch
14
+ # @param desc [String]
15
+ # A description of what the option does.
18
16
  #
19
17
  # @yield A block to run if the switch is triggered
20
18
  #
21
- def initialize(*args, &block)
22
- @names = []
23
- args.each do |i|
24
- case i
25
- when Symbol
26
- @names << i.to_s
27
- when String
28
- @desc = i
29
- end
30
- end
19
+ def initialize(names, desc, &block)
20
+ @names = names.map(&:to_s)
21
+ @desc = desc
31
22
  @block = block
32
23
  end
33
24
 
@@ -1,4 +1,4 @@
1
- class Clive
1
+ module Clive
2
2
 
3
3
  # A subclass of Array to allow the creation of arrays that look
4
4
  # like:
@@ -1,3 +1,3 @@
1
- class Clive
2
- VERSION = '0.6.2'
1
+ module Clive
2
+ VERSION = '0.7.0'
3
3
  end
@@ -0,0 +1,54 @@
1
+ require 'spec_helper'
2
+
3
+ describe Clive::Bool do
4
+
5
+ subject { Clive::Bool.new([:n, :name], "A test", true) {|arg| puts arg } }
6
+ let(:falsey) { Clive::Bool.new([:n, :name], "A test", false) {|arg| 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
@@ -0,0 +1,260 @@
1
+ require 'spec_helper'
2
+
3
+ describe Clive::Command do
4
+
5
+ context "when creating a base command" do
6
+ subject { Clive::Command.new(true) {} }
7
+ end
8
+
9
+ subject {
10
+ Clive::Command.new(:co, :comm, "A command") do
11
+ bool(:boo) {}
12
+ switch(:swi) {}
13
+ flag(:fla) {}
14
+ command(:com) {}
15
+ end
16
+ }
17
+
18
+ it_behaves_like "an option"
19
+
20
+ describe "#initialize" do
21
+ subject {
22
+ Clive::Command.new(:com, "A command") do
23
+ flag(:test)
24
+ end
25
+ }
26
+
27
+ it "generates a help header" do
28
+ File.stub!(:basename).and_return("test")
29
+ subject.instance_variable_get("@header").should == "Usage: test com [options]"
30
+ end
31
+
32
+ it "generates an option missing proc" do
33
+ proc = subject.instance_variable_get("@option_missing")
34
+ expect {
35
+ proc.call("hey")
36
+ }.should raise_error Clive::NoOptionError
37
+ end
38
+
39
+ it "sets the help formatter to :default" do
40
+ formatter = subject.instance_variable_get("@help_formatter")
41
+ formatter.should == subject.help_formatter(:default)
42
+ end
43
+
44
+ it "doesn't run the block given" do
45
+ subject.flags.size.should == 0
46
+ end
47
+
48
+ it "generates a help switch" do
49
+ subject.switches.map {|i| i.names}.should include ["h", "help"]
50
+ end
51
+ end
52
+
53
+ describe "#bools" do
54
+ it "returns an array of bools" do
55
+ subject.find
56
+ subject.bools.each do |i|
57
+ i.should be_kind_of Clive::Bool
58
+ end
59
+ end
60
+ end
61
+
62
+ describe "#switches" do
63
+ it "returns an array of switches" do
64
+ subject.find
65
+ subject.switches.each do |i|
66
+ i.should be_kind_of Clive::Switch
67
+ end
68
+ end
69
+ end
70
+
71
+ describe "#flags" do
72
+ it "returns an array of flags" do
73
+ subject.find
74
+ subject.flags.each do |i|
75
+ i.should be_kind_of Clive::Flag
76
+ end
77
+ end
78
+ end
79
+
80
+ describe "#find" do
81
+ it "runs the block for the command" do
82
+ subject.flags.size.should == 0
83
+ subject.find
84
+ subject.flags.size.should == 1
85
+ end
86
+
87
+ it "sets the block to nil" do
88
+ subject.find
89
+ subject.block.should be_nil
90
+ end
91
+ end
92
+
93
+ describe "#run" do
94
+ it "returns an array of unused arguments" do
95
+ subject.find
96
+ subject.run(%w(--swi what)).should == ['what']
97
+ end
98
+ end
99
+
100
+ describe "#tokenize" do
101
+ it "returns an array of tokens" do
102
+ subject.find
103
+ res = [
104
+ [:switch, subject.bools.find {|i| i.names == ["boo"] }],
105
+ [:argument, "what"]
106
+ ]
107
+ subject.tokenize(%w(--boo what)).should == res
108
+ end
109
+ end
110
+
111
+ describe "#parse" do
112
+ it "returns an array of tokens"
113
+ end
114
+
115
+ describe "#to_h" do
116
+ it "returns a hash of data for help formatting" do
117
+ hsh = {'names' => subject.names, 'desc' => subject.desc}
118
+ subject.to_h.should == hsh
119
+ end
120
+ end
121
+
122
+ describe "#command" do
123
+ it "creates a new command" do
124
+ expect {
125
+ subject.command(:comm)
126
+ }.should change {subject.commands.size}.by(1)
127
+ end
128
+
129
+ it "resets the current description" do
130
+ subject.desc 'A command'
131
+ subject.command(:comm)
132
+ subject.current_desc.should == ""
133
+ end
134
+ end
135
+
136
+ describe "#switch" do
137
+ it "creates a new switch" do
138
+ expect {
139
+ subject.switch(:s, :switch)
140
+ }.should change {subject.switches.size}.by(1)
141
+ end
142
+
143
+ it "resets the current description" do
144
+ subject.desc 'A switch'
145
+ subject.switch(:s, :switch)
146
+ subject.current_desc.should == ""
147
+ end
148
+ end
149
+
150
+ describe "#flag" do
151
+ it "creates a new flag" do
152
+ expect {
153
+ subject.flag(:f, :flag)
154
+ }.should change {subject.flags.size}.by(1)
155
+ end
156
+
157
+ it "resets the current description" do
158
+ subject.desc 'A flag'
159
+ subject.flag(:f, :flag)
160
+ subject.current_desc.should == ""
161
+ end
162
+ end
163
+
164
+ describe "#bool" do
165
+ it "creates two bool switches" do
166
+ expect {
167
+ subject.bool(:b, :bool)
168
+ }.should change {subject.bools.size}.by(2)
169
+ end
170
+
171
+ it "resets the current description" do
172
+ subject.desc 'A bool'
173
+ subject.bool(:b, :bool)
174
+ subject.current_desc.should == ""
175
+ end
176
+ end
177
+
178
+ describe "#desc" do
179
+ context "when called with no arguments" do
180
+ it "returns the description for the command" do
181
+ subject.desc.should == "A command"
182
+ end
183
+ end
184
+
185
+ context "when called with an argument" do
186
+ it "sets the current description" do
187
+ subject.desc "A new desc"
188
+ subject.instance_variable_get("@current_desc").should == "A new desc"
189
+ end
190
+ end
191
+ end
192
+
193
+ describe "#option_missing" do
194
+ it "sets the option missing proc" do
195
+ proc = lambda {|n| puts "What? #{name} doesn't exist" }
196
+ subject.option_missing(&proc)
197
+ subject.instance_variable_get("@option_missing").should == proc
198
+ end
199
+ end
200
+
201
+ describe "#header" do
202
+ it "sets the header" do
203
+ subject.header "A header"
204
+ subject.instance_variable_get("@header").should == "A header"
205
+ end
206
+ end
207
+
208
+ describe "#footer" do
209
+ it "sets the footer" do
210
+ subject.footer "A footer"
211
+ subject.instance_variable_get("@footer").should == "A footer"
212
+ end
213
+ end
214
+
215
+ describe "#build_help" do
216
+ it "adds a switch for help" do
217
+ subject.options = Clive::Array.new
218
+ subject.options.should be_empty
219
+ subject.build_help
220
+ subject.options.map(&:names).should include ['h', 'help']
221
+ end
222
+ end
223
+
224
+ describe "#help" do
225
+ it "returns a string of help" do
226
+ help = <<EOS
227
+ Usage: rspec co, comm [options]
228
+
229
+ Options:
230
+ -h, --help \e[90mDisplay help\e[0m
231
+ EOS
232
+
233
+ subject.help.should == help
234
+ end
235
+ end
236
+
237
+ describe "#help_formatter" do
238
+ context "when called with a symbol" do
239
+ it "uses the named formatter" do
240
+ before = subject.instance_variable_get("@formatter")
241
+ subject.help_formatter(:white)
242
+ subject.instance_variable_get("@formatter").should_not == before
243
+ end
244
+ end
245
+
246
+ context "when called with argumentss and a block" do
247
+ it "creates a new help formatter" do
248
+ subject.help_formatter :width => 40, :prepend => 5 do |h|
249
+ h.switch "switch"
250
+ h.bool "bool"
251
+ h.flag "flag"
252
+ h.command "command"
253
+ end
254
+ formatter = subject.instance_variable_get("@formatter")
255
+ formatter.width.should == 40
256
+ end
257
+ end
258
+ end
259
+
260
+ end