cli 0.0.4 → 0.1.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.
@@ -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
+