cli 0.0.4 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,69 @@
1
+
2
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
3
+
4
+ describe CLI do
5
+ describe "name conflict reporting" do
6
+ it "raise error when long names configlict" do
7
+ lambda {
8
+ ps = CLI.new do
9
+ switch :location
10
+ switch :location
11
+ end
12
+ }.should raise_error CLI::ParserError::LongNameSpecifiedTwiceError, 'switch location specified twice'
13
+
14
+ lambda {
15
+ ps = CLI.new do
16
+ option :location
17
+ option :location
18
+ end
19
+ }.should raise_error CLI::ParserError::LongNameSpecifiedTwiceError, 'option location specified twice'
20
+
21
+ lambda {
22
+ ps = CLI.new do
23
+ switch :location
24
+ option :location
25
+ end
26
+ }.should raise_error CLI::ParserError::LongNameSpecifiedTwiceError, 'switch and option location specified twice'
27
+
28
+ lambda {
29
+ ps = CLI.new do
30
+ option :location
31
+ switch :location
32
+ end
33
+ }.should raise_error CLI::ParserError::LongNameSpecifiedTwiceError, 'option and switch location specified twice'
34
+ end
35
+ end
36
+
37
+ describe "short name conflict reporting" do
38
+ it "raise error when short names configlict" do
39
+ lambda {
40
+ ps = CLI.new do
41
+ switch :location, :short => :l
42
+ switch :location2, :short => :l
43
+ end
44
+ }.should raise_error CLI::ParserError::ShortNameSpecifiedTwiceError, 'short switch l specified twice'
45
+
46
+ lambda {
47
+ ps = CLI.new do
48
+ option :location, :short => :l
49
+ option :location2, :short => :l
50
+ end
51
+ }.should raise_error CLI::ParserError::ShortNameSpecifiedTwiceError, 'short option l specified twice'
52
+
53
+ lambda {
54
+ ps = CLI.new do
55
+ switch :location, :short => :l
56
+ option :location2, :short => :l
57
+ end
58
+ }.should raise_error CLI::ParserError::ShortNameSpecifiedTwiceError, 'short switch and option l specified twice'
59
+
60
+ lambda {
61
+ ps = CLI.new do
62
+ option :location2, :short => :l
63
+ switch :location, :short => :l
64
+ end
65
+ }.should raise_error CLI::ParserError::ShortNameSpecifiedTwiceError, 'short option and switch l specified twice'
66
+ end
67
+ end
68
+ end
69
+
@@ -0,0 +1,155 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe CLI do
4
+ describe 'option handling' do
5
+ it "should handle long option names" do
6
+ ps = CLI.new do
7
+ option :location
8
+ end.parse(['--location', 'singapore'])
9
+ ps.location.should be_a String
10
+ ps.location.should == 'singapore'
11
+ end
12
+
13
+ it "should handle short option names" do
14
+ ps = CLI.new do
15
+ option :location, :short => :l
16
+ end.parse(['-l', 'singapore'])
17
+ ps.location.should be_a String
18
+ ps.location.should == 'singapore'
19
+ end
20
+
21
+ it "should support casting" do
22
+ ps = CLI.new do
23
+ option :size, :cast => Integer
24
+ end.parse(['--size', '24'])
25
+ ps.size.should be_a Integer
26
+ ps.size.should == 24
27
+ end
28
+
29
+ it "should support casting with lambda" do
30
+ ps = CLI.new do
31
+ option :size, :cast => lambda{|v| v.to_i + 2}
32
+ end.parse(['--size', '24'])
33
+ ps.size.should be_a Integer
34
+ ps.size.should == 26
35
+ end
36
+
37
+ it "should support casting with class" do
38
+ class Upcaser
39
+ def initialize(string)
40
+ @value = string.upcase
41
+ end
42
+ attr_reader :value
43
+ end
44
+
45
+ ps = CLI.new do
46
+ option :text, :cast => Upcaser
47
+ end.parse(['--text', 'hello world'])
48
+ ps.text.should be_a Upcaser
49
+ ps.text.value.should == 'HELLO WORLD'
50
+ end
51
+
52
+ it "should handle default values" do
53
+ ps = CLI.new do
54
+ option :location, :default => 'singapore'
55
+ option :size, :cast => Integer, :default => 23
56
+ end.parse([])
57
+ ps.location.should be_a String
58
+ ps.location.should == 'singapore'
59
+ ps.size.should be_a Integer
60
+ ps.size.should == 23
61
+ end
62
+
63
+ it "default value is casted" do
64
+ ps = CLI.new do
65
+ option :location, :default => 'singapore'
66
+ option :size, :cast => Integer, :default => 23.99
67
+ end.parse([])
68
+ ps.location.should be_a String
69
+ ps.location.should == 'singapore'
70
+ ps.size.should be_a Integer
71
+ ps.size.should == 23
72
+ end
73
+
74
+ it "not given and not defined options should be nil" do
75
+ ps = CLI.new do
76
+ option :size, :cast => Integer
77
+ end.parse([])
78
+ ps.size.should be_nil
79
+ ps.gold.should be_nil
80
+ end
81
+
82
+ it "should handle multiple long and short intermixed options" do
83
+ ps = CLI.new do
84
+ option :location, :short => :l
85
+ option :group, :default => 'red'
86
+ option :power_up, :short => :p
87
+ option :speed, :short => :s, :cast => Integer
88
+ option :not_given
89
+ option :size
90
+ end.parse(['-l', 'singapore', '--power-up', 'yes', '-s', '24', '--size', 'XXXL'])
91
+ ps.group.should == 'red'
92
+ ps.power_up.should == 'yes'
93
+ ps.speed.should == 24
94
+ ps.not_given.should be_nil
95
+ ps.size.should == 'XXXL'
96
+ ps.gold.should be_nil
97
+ end
98
+
99
+ it "should raise error if not symbol and optional hash is passed" do
100
+ lambda {
101
+ ps = CLI.new do
102
+ option 'number'
103
+ end
104
+ }.should raise_error CLI::ParserError::NameArgumetNotSymbolError, "option name has to be of type Symbol, got String"
105
+
106
+ lambda {
107
+ ps = CLI.new do
108
+ option :number, :test
109
+ end
110
+ }.should raise_error CLI::ParserError::OptionsArgumentNotHashError, "option options has to be of type Hash, got Symbol"
111
+ end
112
+
113
+ it "should raise error on missing option argument" do
114
+ ps = CLI.new do
115
+ option :location
116
+ end
117
+
118
+ lambda {
119
+ ps.parse(['--location'])
120
+ }.should raise_error CLI::ParsingError::MissingOptionValueError, 'missing value for option --location'
121
+ end
122
+
123
+ it "should raise error on missing mandatory option" do
124
+ ps = CLI.new do
125
+ option :location
126
+ option :weight, :required => true
127
+ option :size, :required => true
128
+ option :group, :default => 'red'
129
+ option :speed, :short => :s, :cast => Integer
130
+ end
131
+
132
+ lambda {
133
+ ps.parse([])
134
+ }.should raise_error CLI::ParsingError::MandatoryOptionsNotSpecifiedError, "mandatory options not specified: --size, --weight"
135
+ end
136
+
137
+ it "by default option value should be nil" do
138
+ ps = CLI.new do
139
+ option :location
140
+ option :speed, :short => :s, :cast => Integer
141
+ option :weight, :required => true
142
+ option :group, :default => 'red'
143
+ end
144
+
145
+ o = ps.parse(['--weight', '123'])
146
+
147
+ o.location.should be_nil
148
+ o.speed.should be_nil
149
+
150
+ o.weight.should == '123'
151
+ o.group.should == 'red'
152
+ end
153
+ end
154
+ end
155
+
@@ -0,0 +1,57 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe CLI do
4
+ describe "argument separator" do
5
+ it "should allow separating arguments from switches so that arguments can contain switch like elements" do
6
+ ps = CLI.new do
7
+ option :location, :short => :l
8
+ option :group, :default => 'red'
9
+ switch :debug
10
+ switch :verbose
11
+ argument :test
12
+ end.parse(['-l', 'singapore', '--debug', '--', '--verbose'])
13
+
14
+ ps.help.should be_nil
15
+ ps.location.should == 'singapore'
16
+ ps.group.should == 'red'
17
+ ps.debug.should be_true
18
+ ps.test.should == '--verbose'
19
+ ps.verbose.should be_nil
20
+
21
+ ps = CLI.new do
22
+ option :location, :short => :l
23
+ option :group, :default => 'red'
24
+ switch :debug
25
+ switch :verbose
26
+ argument :test
27
+ end.parse(['-l', 'singapore', '--debug', '--help'])
28
+
29
+ ps.location.should be_nil
30
+ ps.group.should be_nil
31
+ ps.debug.should be_nil
32
+ ps.verbose.should be_nil
33
+ ps.help.should_not be_nil
34
+
35
+ ps = CLI.new do
36
+ option :location, :short => :l
37
+ option :group, :default => 'red'
38
+ switch :debug
39
+ switch :merge, :short => :m
40
+ switch :verbose
41
+ argument :test
42
+ argument :test2
43
+ argument :test3
44
+ end.parse(['-l', 'singapore', '--debug', '--', '--help', '--version', '-m'])
45
+
46
+ ps.help.should be_nil
47
+ ps.location.should == 'singapore'
48
+ ps.group.should == 'red'
49
+ ps.debug.should be_true
50
+ ps.test.should == '--help'
51
+ ps.test2.should == '--version'
52
+ ps.test3.should == '-m'
53
+ ps.verbose.should be_nil
54
+ end
55
+ end
56
+ end
57
+
data/spec/spec_helper.rb CHANGED
@@ -9,3 +9,57 @@ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
9
9
  RSpec.configure do |config|
10
10
 
11
11
  end
12
+
13
+ def stdin_write(data)
14
+ r, w = IO.pipe
15
+ old_stdin = STDIN.clone
16
+ STDIN.reopen r
17
+ Thread.new do
18
+ w.write data
19
+ w.close
20
+ end
21
+ begin
22
+ yield
23
+ ensure
24
+ STDIN.reopen old_stdin
25
+ end
26
+ end
27
+
28
+ def stdout_read
29
+ r, w = IO.pipe
30
+ old_stdout = STDOUT.clone
31
+ STDOUT.reopen(w)
32
+ data = ''
33
+ t = Thread.new do
34
+ data << r.read
35
+ end
36
+ begin
37
+ yield
38
+ ensure
39
+ w.close
40
+ STDOUT.reopen(old_stdout)
41
+ end
42
+ t.join
43
+ data
44
+ end
45
+
46
+ def stderr_read
47
+ r, w = IO.pipe
48
+ old_stdout = STDERR.clone
49
+ STDERR.reopen(w)
50
+ data = ''
51
+ t = Thread.new do
52
+ data << r.read
53
+ end
54
+ begin
55
+ yield
56
+ ensure
57
+ w.close
58
+ STDERR.reopen(old_stdout)
59
+ end
60
+ t.join
61
+ data
62
+ end
63
+
64
+ require 'cli'
65
+
@@ -0,0 +1,74 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe CLI do
4
+ describe 'STDIN handling' do
5
+ before :all do
6
+ @yaml = <<EOF
7
+ ---
8
+ :parser:
9
+ :successes: 41
10
+ :failures: 0
11
+ EOF
12
+ end
13
+
14
+ it "should be nil if not specified" do
15
+ ps = CLI.new.parse
16
+ ps.stdin.should be_nil
17
+ end
18
+
19
+ it "should return IO if stdin is defined" do
20
+ ps = CLI.new do
21
+ stdin
22
+ end.parse
23
+ ps.stdin.should be_a IO
24
+ end
25
+
26
+ it "should support casting to YAML" do
27
+ ps = nil
28
+ ss = CLI.new do
29
+ stdin :log_data, :cast => YAML, :description => 'log statistic data in YAML format'
30
+ end
31
+
32
+ stdin_write(@yaml) do
33
+ ps = ss.parse
34
+ end
35
+
36
+ ps.stdin.should == {:parser=>{:successes=>41, :failures=>0}}
37
+ end
38
+
39
+ it "should support casting with lambda" do
40
+ ps = nil
41
+ ss = CLI.new do
42
+ stdin :log_data, :cast => lambda{|sin| sin.read.upcase}, :description => 'log statistic data in YAML format'
43
+ end
44
+
45
+ stdin_write('hello world') do
46
+ ps = ss.parse
47
+ end
48
+
49
+ ps.stdin.should == 'HELLO WORLD'
50
+ end
51
+
52
+ it "should support casting with custom class" do
53
+ class Upcaser
54
+ def initialize(io)
55
+ @value = io.read.upcase
56
+ end
57
+ attr_reader :value
58
+ end
59
+
60
+ ps = nil
61
+ ss = CLI.new do
62
+ stdin :log_data, :cast => Upcaser, :description => 'log statistic data in YAML format'
63
+ end
64
+
65
+ stdin_write('hello world') do
66
+ ps = ss.parse
67
+ end
68
+
69
+ ps.stdin.should be_a Upcaser
70
+ ps.stdin.value.should == 'HELLO WORLD'
71
+ end
72
+ end
73
+ end
74
+
@@ -0,0 +1,62 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe CLI do
4
+ describe 'switch handling' do
5
+ it "should handle long switch names" do
6
+ ps = CLI.new do
7
+ switch :location
8
+ switch :unset
9
+ end.parse(['--location'])
10
+ ps.location.should be_true
11
+ ps.unset.should be_nil
12
+ end
13
+
14
+ it "should handle short switch names" do
15
+ ps = CLI.new do
16
+ switch :location, :short => :l
17
+ switch :unset, :short => :u
18
+ end.parse(['-l'])
19
+ ps.location.should be_true
20
+ ps.unset.should be_nil
21
+ end
22
+
23
+ it "should raise error if not symbol and optional hash is passed" do
24
+ lambda {
25
+ ps = CLI.new do
26
+ switch 'number'
27
+ end.parse([])
28
+ }.should raise_error CLI::ParserError::NameArgumetNotSymbolError, "switch name has to be of type Symbol, got String"
29
+
30
+ lambda {
31
+ ps = CLI.new do
32
+ switch :number, :test
33
+ end
34
+ }.should raise_error CLI::ParserError::OptionsArgumentNotHashError, "switch options has to be of type Hash, got Symbol"
35
+ end
36
+
37
+ it "shoud raise error is short name is invalid" do
38
+ lambda {
39
+ ps = CLI.new do
40
+ switch :location, :short => "l"
41
+ end
42
+ }.should raise_error CLI::ParserError::ShortNameNotSymbolError, 'short name has to be of type Symbol, got String'
43
+
44
+ lambda {
45
+ ps = CLI.new do
46
+ switch :location, :short => :abc
47
+ end
48
+ }.should raise_error CLI::ParserError::ShortNameIsInvalidError, 'short name has to be one letter symbol, got abc'
49
+ end
50
+
51
+ it "should raise error on unrecognized switch" do
52
+ ps = CLI.new do
53
+ option :location
54
+ end
55
+
56
+ lambda {
57
+ ps.parse(['--xxx'])
58
+ }.should raise_error CLI::ParsingError::UnknownSwitchError, 'unknown switch --xxx'
59
+ end
60
+ end
61
+ end
62
+