clin 0.1.0 → 0.2.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.
- checksums.yaml +4 -4
- data/.gitignore +2 -1
- data/.rubocop.yml +3 -0
- data/CHANGELOG.md +7 -0
- data/README.md +1 -1
- data/examples/dispatcher.rb +22 -50
- data/examples/list_option.rb +27 -0
- data/examples/nested_dispatcher.rb +28 -27
- data/examples/simple.rb +1 -1
- data/examples/test.rb +8 -1
- data/lib/clin/argument.rb +28 -11
- data/lib/clin/command.rb +25 -72
- data/lib/clin/command_dispatcher.rb +2 -1
- data/lib/clin/command_options_mixin.rb +33 -3
- data/lib/clin/command_parser.rb +115 -0
- data/lib/clin/common/help_options.rb +0 -1
- data/lib/clin/errors.rb +7 -2
- data/lib/clin/general_option.rb +5 -5
- data/lib/clin/option.rb +70 -16
- data/lib/clin/option_list.rb +25 -0
- data/lib/clin/version.rb +1 -1
- data/lib/clin.rb +14 -11
- data/spec/clin/command_parser_spec.rb +165 -0
- data/spec/clin/command_spec.rb +112 -0
- data/spec/clin/option_list_spec.rb +32 -0
- data/spec/{cli → clin}/option_spec.rb +10 -2
- data/spec/examples/list_option_spec.rb +20 -0
- data/spec/examples/nested_dispatcher_spec.rb +28 -0
- metadata +26 -14
- data/spec/cli/command_spec.rb +0 -225
- /data/spec/{cli → clin}/argument_spec.rb +0 -0
- /data/spec/{cli → clin}/command_dispacher_spec.rb +0 -0
- /data/spec/{cli → clin}/command_options_mixin_spec.rb +0 -0
- /data/spec/{cli → clin}/common/help_options_spec.rb +0 -0
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Clin::OptionList do
|
4
|
+
describe '#on' do
|
5
|
+
let(:name) { Faker::Lorem.word }
|
6
|
+
let(:description) { Faker::Lorem.sentence }
|
7
|
+
let(:out) { Hash.new }
|
8
|
+
context 'when normal list option' do
|
9
|
+
subject { Clin::OptionList.new(name, description) }
|
10
|
+
before do
|
11
|
+
subject.on('val1', out)
|
12
|
+
subject.on('val2', out)
|
13
|
+
end
|
14
|
+
|
15
|
+
it { expect(out[name]).to be_a Array }
|
16
|
+
it { expect(out[name].size).to be 2 }
|
17
|
+
it { expect(out[name]).to include('val1') }
|
18
|
+
it { expect(out[name]).to include('val2') }
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'when flag list option' do
|
22
|
+
subject { Clin::OptionList.new(name, description, argument: false) }
|
23
|
+
before do
|
24
|
+
subject.on(true, out)
|
25
|
+
subject.on(true, out)
|
26
|
+
end
|
27
|
+
|
28
|
+
it { expect(out[name]).to be_a Integer }
|
29
|
+
it { expect(out[name]).to be 2 }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -68,9 +68,17 @@ RSpec.describe Clin::Option do
|
|
68
68
|
end
|
69
69
|
|
70
70
|
describe '#default_long' do
|
71
|
-
|
71
|
+
context 'simple name' do
|
72
|
+
subject { Clin::Option.new(:echo, Faker::Lorem.sentence) }
|
73
|
+
|
74
|
+
it { expect(subject.default_long).to eq('--echo') }
|
75
|
+
end
|
76
|
+
|
77
|
+
context 'when name contains underscores' do
|
78
|
+
subject { Clin::Option.new(:echo_more, Faker::Lorem.sentence) }
|
72
79
|
|
73
|
-
|
80
|
+
it { expect(subject.default_long.to_s).to eq('--echo-more') }
|
81
|
+
end
|
74
82
|
end
|
75
83
|
|
76
84
|
describe '#default_argument' do
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'examples/list_option'
|
3
|
+
|
4
|
+
RSpec.describe 'list_option.rb' do
|
5
|
+
suppress_puts
|
6
|
+
it { expect(ListCommand.parse('').params).to eq(echo: [], line: 0) }
|
7
|
+
it { expect(ListCommand.parse('--echo msg').params).to eq(echo: ['msg'], line: 0) }
|
8
|
+
it { expect(ListCommand.parse('--line').params).to eq(echo: [], line: 1) }
|
9
|
+
it { expect(ListCommand.parse('--line --line').params).to eq(echo: [], line: 2) }
|
10
|
+
it { expect(ListCommand.parse('-lll').params).to eq(echo: [], line: 3) }
|
11
|
+
it do
|
12
|
+
expect(ListCommand.parse('--echo msg1 --echo msg2').params)
|
13
|
+
.to eq(echo: %w(msg1 msg2), line: 0)
|
14
|
+
end
|
15
|
+
|
16
|
+
it do
|
17
|
+
expect(ListCommand.parse('--echo msg1 --line --echo msg2 -ll').params)
|
18
|
+
.to eq(echo: %w(msg1 msg2), line: 3)
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'examples/nested_dispatcher'
|
3
|
+
|
4
|
+
RSpec.describe 'nested_dispatcher.rb' do
|
5
|
+
suppress_puts
|
6
|
+
it { expect(DispatchCommand.parse('you display Some').params).
|
7
|
+
to eq(you: 'you', display: 'display', message: 'Some') }
|
8
|
+
|
9
|
+
it { expect(DispatchCommand.parse('you display Some -e More').params).
|
10
|
+
to eq(you: 'you', display: 'display', message: 'Some', echo: 'More') }
|
11
|
+
|
12
|
+
it {
|
13
|
+
expect(DispatchCommand.parse('you display Some -e More --times 3').params).
|
14
|
+
to eq(you: 'you', display: 'display', message: 'Some', echo: 'More', times: 3)
|
15
|
+
}
|
16
|
+
|
17
|
+
it { expect(DispatchCommand.parse('you display Some -e More --times 3 -v').params).
|
18
|
+
to eq(you: 'you', display: 'display', message: 'Some', echo: 'More', times: 3) }
|
19
|
+
|
20
|
+
it { expect(DispatchCommand.parse('you display Some --verbose -e More --times 3').params).
|
21
|
+
to eq(you: 'you', display: 'display', message: 'Some', echo: 'More', times: 3) }
|
22
|
+
|
23
|
+
it {
|
24
|
+
expect(DispatchCommand.parse('you --verbose display Some -e More --times 3').params).
|
25
|
+
to eq(you: 'you', display: 'display', message: 'Some', echo: 'More', times: 3) }
|
26
|
+
it { expect { DispatchCommand.parse('').params }.to raise_error(Clin::HelpError) }
|
27
|
+
it { expect { DispatchCommand.parse('-h').params }.to raise_error(Clin::HelpError) }
|
28
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: clin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Timothee Guerin
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-05-
|
11
|
+
date: 2015-05-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -105,12 +105,14 @@ files:
|
|
105
105
|
- ".gitignore"
|
106
106
|
- ".rubocop.yml"
|
107
107
|
- ".travis.yml"
|
108
|
+
- CHANGELOG.md
|
108
109
|
- Gemfile
|
109
110
|
- LICENSE.txt
|
110
111
|
- README.md
|
111
112
|
- Rakefile
|
112
113
|
- clin.gemspec
|
113
114
|
- examples/dispatcher.rb
|
115
|
+
- examples/list_option.rb
|
114
116
|
- examples/nested_dispatcher.rb
|
115
117
|
- examples/optional_argument.rb
|
116
118
|
- examples/simple.rb
|
@@ -120,18 +122,24 @@ files:
|
|
120
122
|
- lib/clin/command.rb
|
121
123
|
- lib/clin/command_dispatcher.rb
|
122
124
|
- lib/clin/command_options_mixin.rb
|
125
|
+
- lib/clin/command_parser.rb
|
123
126
|
- lib/clin/common/help_options.rb
|
124
127
|
- lib/clin/errors.rb
|
125
128
|
- lib/clin/general_option.rb
|
126
129
|
- lib/clin/option.rb
|
130
|
+
- lib/clin/option_list.rb
|
127
131
|
- lib/clin/version.rb
|
128
|
-
- spec/
|
129
|
-
- spec/
|
130
|
-
- spec/
|
131
|
-
- spec/
|
132
|
-
- spec/
|
133
|
-
- spec/
|
132
|
+
- spec/clin/argument_spec.rb
|
133
|
+
- spec/clin/command_dispacher_spec.rb
|
134
|
+
- spec/clin/command_options_mixin_spec.rb
|
135
|
+
- spec/clin/command_parser_spec.rb
|
136
|
+
- spec/clin/command_spec.rb
|
137
|
+
- spec/clin/common/help_options_spec.rb
|
138
|
+
- spec/clin/option_list_spec.rb
|
139
|
+
- spec/clin/option_spec.rb
|
134
140
|
- spec/errors_spec.rb
|
141
|
+
- spec/examples/list_option_spec.rb
|
142
|
+
- spec/examples/nested_dispatcher_spec.rb
|
135
143
|
- spec/examples/simple_spec.rb
|
136
144
|
- spec/spec_helper.rb
|
137
145
|
homepage: ''
|
@@ -159,13 +167,17 @@ signing_key:
|
|
159
167
|
specification_version: 4
|
160
168
|
summary: Clin provide an advance way to define complex command line interface.
|
161
169
|
test_files:
|
162
|
-
- spec/
|
163
|
-
- spec/
|
164
|
-
- spec/
|
165
|
-
- spec/
|
166
|
-
- spec/
|
167
|
-
- spec/
|
170
|
+
- spec/clin/argument_spec.rb
|
171
|
+
- spec/clin/command_dispacher_spec.rb
|
172
|
+
- spec/clin/command_options_mixin_spec.rb
|
173
|
+
- spec/clin/command_parser_spec.rb
|
174
|
+
- spec/clin/command_spec.rb
|
175
|
+
- spec/clin/common/help_options_spec.rb
|
176
|
+
- spec/clin/option_list_spec.rb
|
177
|
+
- spec/clin/option_spec.rb
|
168
178
|
- spec/errors_spec.rb
|
179
|
+
- spec/examples/list_option_spec.rb
|
180
|
+
- spec/examples/nested_dispatcher_spec.rb
|
169
181
|
- spec/examples/simple_spec.rb
|
170
182
|
- spec/spec_helper.rb
|
171
183
|
has_rdoc:
|
data/spec/cli/command_spec.rb
DELETED
@@ -1,225 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'clin/command'
|
3
|
-
|
4
|
-
RSpec.describe Clin::Command do
|
5
|
-
describe '#arguments=' do
|
6
|
-
subject { Class.new(Clin::Command) }
|
7
|
-
let(:args) { %w(fix <var> [opt]) }
|
8
|
-
before do
|
9
|
-
allow(Clin::Argument).to receive(:new)
|
10
|
-
end
|
11
|
-
context 'when using string to set arguments' do
|
12
|
-
before do
|
13
|
-
subject.arguments (args.join(' '))
|
14
|
-
end
|
15
|
-
it { expect(subject.args.size).to eq(args.size) }
|
16
|
-
it { expect(Clin::Argument).to have_received(:new).exactly(args.size).times }
|
17
|
-
end
|
18
|
-
|
19
|
-
context 'when using array to set arguments' do
|
20
|
-
before do
|
21
|
-
subject.arguments (args)
|
22
|
-
end
|
23
|
-
it { expect(subject.args.size).to eq(args.size) }
|
24
|
-
it { expect(Clin::Argument).to have_received(:new).exactly(args.size).times }
|
25
|
-
end
|
26
|
-
|
27
|
-
context 'when using array that contains multiple arguments to set arguments' do
|
28
|
-
before do
|
29
|
-
subject.arguments ([args[0], args[1..-1]])
|
30
|
-
end
|
31
|
-
it { expect(subject.args.size).to eq(args.size) }
|
32
|
-
it { expect(Clin::Argument).to have_received(:new).exactly(args.size).times }
|
33
|
-
end
|
34
|
-
|
35
|
-
end
|
36
|
-
|
37
|
-
describe '#banner' do
|
38
|
-
subject { Class.new(Clin::Command) }
|
39
|
-
context 'when exe is defined' do
|
40
|
-
let(:exe) { Faker::Lorem.word }
|
41
|
-
before do
|
42
|
-
subject.exe_name(exe)
|
43
|
-
end
|
44
|
-
|
45
|
-
it { expect(subject.banner).to eq("Usage: #{exe} [Options]") }
|
46
|
-
end
|
47
|
-
|
48
|
-
context 'when exe is not defined' do
|
49
|
-
it { expect(subject.banner).to eq('Usage: command [Options]') }
|
50
|
-
end
|
51
|
-
|
52
|
-
context 'when arguments are defined' do
|
53
|
-
let(:arguments) { '<some> [Value]' }
|
54
|
-
before do
|
55
|
-
subject.arguments(arguments)
|
56
|
-
end
|
57
|
-
|
58
|
-
it { expect(subject.banner).to eq("Usage: #{Clin.default_exe_name} #{arguments} [Options]") }
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
describe '#parse_arguments' do
|
63
|
-
subject { Class.new(Clin::Command) }
|
64
|
-
let(:args) { %w(fix <var> [opt]) }
|
65
|
-
|
66
|
-
before do
|
67
|
-
subject.arguments(args)
|
68
|
-
end
|
69
|
-
|
70
|
-
it 'raise argument when fixed in different' do
|
71
|
-
expect { subject.parse_arguments(%w(other val opt)) }.to raise_error(Clin::CommandLineError)
|
72
|
-
end
|
73
|
-
it 'raise error when too few arguments' do
|
74
|
-
expect { subject.parse_arguments(['fix']) }.to raise_error(Clin::CommandLineError)
|
75
|
-
end
|
76
|
-
it 'raise error when too much argument' do
|
77
|
-
expect { subject.parse_arguments(%w(other val opt more)) }
|
78
|
-
.to raise_error(Clin::CommandLineError)
|
79
|
-
end
|
80
|
-
|
81
|
-
it 'map arguments' do
|
82
|
-
expect(subject.parse_arguments(%w(fix val opt))).to eq(fix: 'fix', var: 'val', opt: 'opt')
|
83
|
-
end
|
84
|
-
|
85
|
-
it 'opt argument is nil when not provided' do
|
86
|
-
expect(subject.parse_arguments(%w(fix val))).to eq(fix: 'fix', var: 'val')
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
describe '#parse_options' do
|
91
|
-
subject { Class.new(Clin::Command) }
|
92
|
-
let(:opt1) { Clin::Option.new(:name, 'Set name') }
|
93
|
-
let(:opt2) { Clin::Option.new(:verbose, 'Set verbose', argument: false) }
|
94
|
-
let(:opt3) { Clin::Option.new(:echo, 'Set name', optional_argument: true) }
|
95
|
-
before do
|
96
|
-
subject.add_option opt1
|
97
|
-
subject.add_option opt2
|
98
|
-
subject.add_option opt3
|
99
|
-
end
|
100
|
-
|
101
|
-
it 'raise argument when option value is missing' do
|
102
|
-
expect { subject.parse_options(%w(--name)) }.to raise_error(OptionParser::MissingArgument)
|
103
|
-
end
|
104
|
-
it 'raise error when unknown option' do
|
105
|
-
expect { subject.parse_options(%w(--other)) }.to raise_error(OptionParser::InvalidOption)
|
106
|
-
end
|
107
|
-
|
108
|
-
it { expect(subject.parse_options(%w(--name MyName))).to eq(name: 'MyName') }
|
109
|
-
it { expect(subject.parse_options(%w(--name=MyName))).to eq(name: 'MyName') }
|
110
|
-
it { expect(subject.parse_options(%w(-nMyName))).to eq(name: 'MyName') }
|
111
|
-
|
112
|
-
|
113
|
-
it { expect(subject.parse_options(%w(-v))).to eq(verbose: true) }
|
114
|
-
|
115
|
-
it { expect(subject.parse_options(%w(--echo))).to eq(echo: nil) }
|
116
|
-
it { expect(subject.parse_options(%w(-e EchoThis))).to eq(echo: 'EchoThis') }
|
117
|
-
end
|
118
|
-
|
119
|
-
describe '.handle_dispatch' do
|
120
|
-
subject { Class.new(Clin::Command) }
|
121
|
-
let(:args) { [Faker::Lorem.word, Faker::Lorem.word] }
|
122
|
-
before do
|
123
|
-
subject.arguments(%w(remote <args>...))
|
124
|
-
end
|
125
|
-
|
126
|
-
context 'when only dispatching arguments' do
|
127
|
-
before do
|
128
|
-
subject.dispatch :args
|
129
|
-
allow_any_instance_of(Clin::CommandDispatcher).to receive(:parse)
|
130
|
-
end
|
131
|
-
it 'call the command dispatcher with the right arguments' do
|
132
|
-
expect_any_instance_of(Clin::CommandDispatcher).to receive(:parse).once.with(args)
|
133
|
-
subject.handle_dispatch(remote: 'remote', args: args)
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
|
-
context 'when using prefix' do
|
138
|
-
let(:prefix) { 'remote' }
|
139
|
-
before do
|
140
|
-
subject.dispatch :args, prefix: prefix
|
141
|
-
allow_any_instance_of(Clin::CommandDispatcher).to receive(:parse)
|
142
|
-
end
|
143
|
-
it 'call the command dispatcher with the right arguments' do
|
144
|
-
expect_any_instance_of(Clin::CommandDispatcher).to receive(:parse).once.with([prefix] + args)
|
145
|
-
subject.handle_dispatch(remote: 'remote', args: args)
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
context 'when using commands' do
|
150
|
-
let(:cmd1) { double(:command) }
|
151
|
-
let(:cmd2) { double(:command) }
|
152
|
-
before do
|
153
|
-
subject.dispatch :args, commands: [cmd1, cmd2]
|
154
|
-
allow_any_instance_of(Clin::CommandDispatcher).to receive(:initialize)
|
155
|
-
allow_any_instance_of(Clin::CommandDispatcher).to receive(:parse)
|
156
|
-
end
|
157
|
-
it 'call the command dispatcher with the right arguments' do
|
158
|
-
expect_any_instance_of(Clin::CommandDispatcher).to receive(:initialize).once.with([cmd1, cmd2])
|
159
|
-
subject.handle_dispatch(remote: 'remote', args: args)
|
160
|
-
end
|
161
|
-
end
|
162
|
-
|
163
|
-
context 'when dispatcher raise HelpError' do
|
164
|
-
let(:new_message) { Faker::Lorem.sentence }
|
165
|
-
before do
|
166
|
-
subject.dispatch :args
|
167
|
-
allow_any_instance_of(Clin::CommandDispatcher).to receive(:initialize)
|
168
|
-
allow_any_instance_of(Clin::CommandDispatcher).to receive(:parse) do
|
169
|
-
fail Clin::HelpError, 'Dispatcher error'
|
170
|
-
end
|
171
|
-
allow(subject).to receive(:option_parser).and_return(new_message)
|
172
|
-
end
|
173
|
-
it { expect { subject.handle_dispatch(remote: 'remote', args: args) }.to raise_error(Clin::HelpError) }
|
174
|
-
it { expect { subject.handle_dispatch(remote: 'remote', args: args) }.to raise_error(new_message) }
|
175
|
-
end
|
176
|
-
end
|
177
|
-
|
178
|
-
describe '.dispatch_doc' do
|
179
|
-
subject { Class.new(Clin::Command) }
|
180
|
-
before do
|
181
|
-
subject.arguments(%w(remote <args>...))
|
182
|
-
end
|
183
|
-
|
184
|
-
let(:cmd1) { double(:command, usage: 'cmd1') }
|
185
|
-
let(:cmd2) { double(:command, usage: 'cmd2') }
|
186
|
-
let(:cmd3) { double(:command, usage: 'cmd3') }
|
187
|
-
let(:cmds) { [cmd1, cmd2, cmd3] }
|
188
|
-
let(:opts) { double(:option_parser, separator: true) }
|
189
|
-
before do
|
190
|
-
subject.dispatch :args, commands: cmds
|
191
|
-
allow_any_instance_of(Clin::CommandDispatcher).to receive(:initialize)
|
192
|
-
subject.dispatch_doc(opts)
|
193
|
-
end
|
194
|
-
it { expect(opts).to have_received(:separator).at_least(cmds.size).times }
|
195
|
-
end
|
196
|
-
|
197
|
-
describe '.subcommands' do
|
198
|
-
before do
|
199
|
-
@cmd1 = Class.new(Clin::Command)
|
200
|
-
@cmd2 = Class.new(Clin::Command)
|
201
|
-
@abstract_cmd = Class.new(Clin::Command) { abstract true }
|
202
|
-
end
|
203
|
-
|
204
|
-
it { expect(Clin::Command.subcommands).to include(@cmd1) }
|
205
|
-
it { expect(Clin::Command.subcommands).to include(@cmd2) }
|
206
|
-
it { expect(Clin::Command.subcommands).not_to include(@abstract_cmd) }
|
207
|
-
end
|
208
|
-
|
209
|
-
describe '.exe_name' do
|
210
|
-
context 'when not setting the exe_name' do
|
211
|
-
subject { Class.new(Clin::Command) }
|
212
|
-
|
213
|
-
it { expect(subject.exe_name).to eq(Clin.exe_name) }
|
214
|
-
end
|
215
|
-
|
216
|
-
context 'when setting the exe_name' do
|
217
|
-
let(:name) { Faker::Lorem.word }
|
218
|
-
subject { Class.new(Clin::Command) }
|
219
|
-
before do
|
220
|
-
subject.exe_name(name)
|
221
|
-
end
|
222
|
-
it { expect(subject.exe_name).to eq(name) }
|
223
|
-
end
|
224
|
-
end
|
225
|
-
end
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|