gli 2.19.2 → 2.20.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/.circleci/config.yml +28 -0
- data/.gitignore +1 -3
- data/Gemfile +0 -6
- data/README.rdoc +2 -12
- data/Rakefile +15 -37
- data/bin/ci +29 -0
- data/bin/gli +25 -64
- data/bin/rake +29 -0
- data/bin/setup +5 -0
- data/exe/gli +68 -0
- data/gli.gemspec +19 -21
- data/gli.rdoc +2 -2
- data/lib/gli/commands/help_modules/command_help_format.rb +1 -1
- data/lib/gli/commands/help_modules/global_help_format.rb +1 -1
- data/lib/gli/commands/scaffold.rb +9 -93
- data/lib/gli/options.rb +2 -2
- data/lib/gli/version.rb +1 -1
- data/object-model.dot +29 -0
- data/object-model.png +0 -0
- data/test/apps/todo/Gemfile +1 -1
- data/test/apps/todo/bin/todo +1 -1
- data/test/integration/gli_cli_test.rb +69 -0
- data/test/integration/gli_powered_app_test.rb +52 -0
- data/test/integration/scaffold_test.rb +30 -0
- data/test/integration/test_helper.rb +52 -0
- data/test/{tc_command_finder.rb → unit/command_finder_test.rb} +6 -6
- data/test/{tc_command.rb → unit/command_test.rb} +4 -4
- data/test/unit/compound_command_test.rb +17 -0
- data/test/{tc_doc.rb → unit/doc_test.rb} +38 -51
- data/test/{tc_flag.rb → unit/flag_test.rb} +19 -25
- data/test/{tc_gli.rb → unit/gli_test.rb} +28 -47
- data/test/{tc_help.rb → unit/help_test.rb} +48 -107
- data/test/{init_simplecov.rb → unit/init_simplecov.rb} +0 -0
- data/test/{tc_options.rb → unit/options_test.rb} +4 -4
- data/test/unit/subcommand_parsing_test.rb +263 -0
- data/test/unit/subcommands_test.rb +245 -0
- data/test/{fake_std_out.rb → unit/support/fake_std_out.rb} +0 -0
- data/test/{config.yaml → unit/support/gli_test_config.yml} +0 -0
- data/test/unit/switch_test.rb +49 -0
- data/test/{tc_terminal.rb → unit/terminal_test.rb} +4 -3
- data/test/unit/test_helper.rb +13 -0
- data/test/unit/verbatim_wrapper_test.rb +24 -0
- metadata +57 -124
- data/.ruby-gemset +0 -1
- data/.ruby-version +0 -1
- data/.travis.yml +0 -11
- data/ObjectModel.graffle +0 -1191
- data/bin/report_on_rake_results +0 -10
- data/bin/test_all_rubies.sh +0 -6
- data/features/gli_executable.feature +0 -90
- data/features/gli_init.feature +0 -236
- data/features/step_definitions/gli_executable_steps.rb +0 -18
- data/features/step_definitions/gli_init_steps.rb +0 -11
- data/features/step_definitions/todo_steps.rb +0 -100
- data/features/support/env.rb +0 -54
- data/features/support/hooks.rb +0 -5
- data/features/todo.feature +0 -579
- data/features/todo_legacy.feature +0 -130
- data/test/option_test_helper.rb +0 -13
- data/test/tc_compound_command.rb +0 -22
- data/test/tc_subcommand_parsing.rb +0 -280
- data/test/tc_subcommands.rb +0 -259
- data/test/tc_switch.rb +0 -55
- data/test/tc_verbatim_wrapper.rb +0 -36
- data/test/test_helper.rb +0 -21
@@ -1,130 +0,0 @@
|
|
1
|
-
Feature: The todo app is backwards compatible with legacy subcommand parsing
|
2
|
-
As a user of GLI
|
3
|
-
My apps with subcommands should support the old, legacy way, by default
|
4
|
-
|
5
|
-
Background:
|
6
|
-
Given I have GLI installed
|
7
|
-
And GLI's libs are in my path
|
8
|
-
And my terminal size is "80x24"
|
9
|
-
And todo_legacy's bin directory is in my path
|
10
|
-
|
11
|
-
Scenario: Help completion mode for subcommands
|
12
|
-
When I successfully run `todo help -c list`
|
13
|
-
Then the output should contain:
|
14
|
-
"""
|
15
|
-
contexts
|
16
|
-
tasks
|
17
|
-
"""
|
18
|
-
|
19
|
-
Scenario: Help completion mode partial match for subcommands
|
20
|
-
When I successfully run `todo help -c list con`
|
21
|
-
Then the output should contain:
|
22
|
-
"""
|
23
|
-
contexts
|
24
|
-
"""
|
25
|
-
|
26
|
-
Scenario Outline: Getting Help for a top level command of todo
|
27
|
-
# No idea why I have to do this again.
|
28
|
-
Given todo_legacy's bin directory is in my path
|
29
|
-
When I successfully run `todo <help_invocation>`
|
30
|
-
Then the output should contain:
|
31
|
-
"""
|
32
|
-
NAME
|
33
|
-
list - List things, such as tasks or contexts
|
34
|
-
|
35
|
-
SYNOPSIS
|
36
|
-
todo [global options] list [command options] [tasks] [--flag arg] [-x arg]
|
37
|
-
todo [global options] list [command options] contexts [--otherflag arg] [-b] [-f|--foobar]
|
38
|
-
|
39
|
-
DESCRIPTION
|
40
|
-
List a whole lot of things that you might be keeping track of in your
|
41
|
-
overall todo list.
|
42
|
-
|
43
|
-
This is your go-to place or finding all of the things that you might have
|
44
|
-
stored in your todo databases.
|
45
|
-
|
46
|
-
COMMAND OPTIONS
|
47
|
-
-l, --[no-]long - Show long form
|
48
|
-
|
49
|
-
COMMANDS
|
50
|
-
contexts - List contexts
|
51
|
-
tasks - List tasks (default)
|
52
|
-
"""
|
53
|
-
|
54
|
-
Examples:
|
55
|
-
| help_invocation |
|
56
|
-
| help list |
|
57
|
-
| list -h |
|
58
|
-
| list --help |
|
59
|
-
|
60
|
-
|
61
|
-
Scenario: Getting Help for a sub command of todo list
|
62
|
-
When I successfully run `todo help list tasks`
|
63
|
-
Then the output should contain:
|
64
|
-
"""
|
65
|
-
NAME
|
66
|
-
tasks - List tasks
|
67
|
-
|
68
|
-
SYNOPSIS
|
69
|
-
todo [global options] list tasks [command options]
|
70
|
-
todo [global options] list tasks [command options] open
|
71
|
-
|
72
|
-
DESCRIPTION
|
73
|
-
Lists all of your tasks that you have, in varying orders, and all that
|
74
|
-
stuff. Yes, this is long, but I need a long description.
|
75
|
-
|
76
|
-
COMMAND OPTIONS
|
77
|
-
--flag=arg - (default: none)
|
78
|
-
-x arg - blah blah crud x whatever (default: none)
|
79
|
-
|
80
|
-
COMMANDS
|
81
|
-
<default> - list all tasks
|
82
|
-
open - list open tasks
|
83
|
-
"""
|
84
|
-
|
85
|
-
Scenario: Getting Help for a sub command with no command options
|
86
|
-
When I successfully run `todo help new`
|
87
|
-
Then the output should contain:
|
88
|
-
"""
|
89
|
-
NAME
|
90
|
-
create - Create a new task or context
|
91
|
-
|
92
|
-
SYNOPSIS
|
93
|
-
todo [global options] create
|
94
|
-
todo [global options] create contexts [context_name]
|
95
|
-
todo [global options] create tasks task_name...
|
96
|
-
|
97
|
-
COMMANDS
|
98
|
-
<default> - Makes a new task
|
99
|
-
contexts - Make a new context
|
100
|
-
tasks - Make a new task
|
101
|
-
"""
|
102
|
-
And the output should not contain "COMMAND OPTIONS"
|
103
|
-
|
104
|
-
Scenario: Running ls w/out subcommand shows help and an error
|
105
|
-
When I run `todo ls`
|
106
|
-
Then the exit status should not be 0
|
107
|
-
And the stderr should contain "error: Command 'ls' requires a subcommand"
|
108
|
-
And the stdout should contain:
|
109
|
-
"""
|
110
|
-
NAME
|
111
|
-
ls - LS things, such as tasks or contexts
|
112
|
-
|
113
|
-
SYNOPSIS
|
114
|
-
todo [global options] ls [command options] contexts [-b] [-f|--foobar]
|
115
|
-
todo [global options] ls [command options] tasks [-x arg]
|
116
|
-
|
117
|
-
DESCRIPTION
|
118
|
-
List a whole lot of things that you might be keeping track of in your
|
119
|
-
overall todo list.
|
120
|
-
|
121
|
-
This is your go-to place or finding all of the things that you might have
|
122
|
-
stored in your todo databases.
|
123
|
-
|
124
|
-
COMMAND OPTIONS
|
125
|
-
-l, --[no-]long - Show long form
|
126
|
-
|
127
|
-
COMMANDS
|
128
|
-
contexts - List contexts
|
129
|
-
tasks - List tasks
|
130
|
-
"""
|
data/test/option_test_helper.rb
DELETED
data/test/tc_compound_command.rb
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
require 'tempfile'
|
3
|
-
|
4
|
-
class TC_testCompounCommand < Clean::Test::TestCase
|
5
|
-
include TestHelper
|
6
|
-
|
7
|
-
test_that "when we create a CompoundCommand where some commands are missing, we get an exception" do
|
8
|
-
Given {
|
9
|
-
@name = any_string
|
10
|
-
@unknown_name = any_string
|
11
|
-
@existing_command = OpenStruct.new(:name => @name)
|
12
|
-
@base = OpenStruct.new( :commands => { @name => @existing_command })
|
13
|
-
}
|
14
|
-
When {
|
15
|
-
@code = lambda { GLI::Commands::CompoundCommand.new(@base,{:foo => [@name,@unknown_name]}) }
|
16
|
-
}
|
17
|
-
Then {
|
18
|
-
ex = assert_raises(RuntimeError,&@code)
|
19
|
-
assert_match /#{@unknown_name}/,ex.message
|
20
|
-
}
|
21
|
-
end
|
22
|
-
end
|
@@ -1,280 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
require 'pp'
|
3
|
-
|
4
|
-
class TC_testSubCommandParsing < Clean::Test::TestCase
|
5
|
-
include TestHelper
|
6
|
-
|
7
|
-
def setup
|
8
|
-
@fake_stdout = FakeStdOut.new
|
9
|
-
@fake_stderr = FakeStdOut.new
|
10
|
-
|
11
|
-
@original_stdout = $stdout
|
12
|
-
$stdout = @fake_stdout
|
13
|
-
@original_stderr = $stderr
|
14
|
-
$stderr = @fake_stderr
|
15
|
-
|
16
|
-
@app = CLIApp.new
|
17
|
-
@app.reset
|
18
|
-
@app.subcommand_option_handling :legacy
|
19
|
-
@app.error_device=@fake_stderr
|
20
|
-
ENV.delete('GLI_DEBUG')
|
21
|
-
|
22
|
-
@results = {}
|
23
|
-
@exit_code = 0
|
24
|
-
end
|
25
|
-
|
26
|
-
def teardown
|
27
|
-
$stdout = @original_stdout
|
28
|
-
$stderr = @original_stderr
|
29
|
-
end
|
30
|
-
|
31
|
-
test_that "commands options may clash with globals and it gets sorted out" do
|
32
|
-
Given :app_with_subcommands_storing_results
|
33
|
-
When {
|
34
|
-
@app.run(%w(-f global command1 -f command -s foo))
|
35
|
-
}
|
36
|
-
Then {
|
37
|
-
assert_equal 'command1',@results[:command_name]
|
38
|
-
assert_equal 'global', @results[:global_options][:f],'global'
|
39
|
-
assert !@results[:global_options][:s]
|
40
|
-
assert_equal 'command', @results[:command_options][:f]
|
41
|
-
assert @results[:command_options][:s]
|
42
|
-
}
|
43
|
-
end
|
44
|
-
|
45
|
-
test_that "in legacy mode, subcommand options all share a namespace" do
|
46
|
-
Given :app_with_subcommands_storing_results
|
47
|
-
When {
|
48
|
-
@app.run(%w(-f global command1 -f command -s subcommand10 -f sub))
|
49
|
-
}
|
50
|
-
Then {
|
51
|
-
with_clue {
|
52
|
-
assert_equal 'subcommand10',@results[:command_name]
|
53
|
-
assert_equal 'global', @results[:global_options][:f],'global'
|
54
|
-
assert !@results[:global_options][:s]
|
55
|
-
assert_equal 'sub', @results[:command_options][:f]
|
56
|
-
assert @results[:command_options][:s]
|
57
|
-
assert_nil @results[:command_options][GLI::Command::PARENT]
|
58
|
-
assert_nil @results[:command_options][GLI::Command::PARENT]
|
59
|
-
}
|
60
|
-
}
|
61
|
-
end
|
62
|
-
|
63
|
-
test_that "in normal mode, each subcommand has its own namespace" do
|
64
|
-
Given :app_with_subcommands_storing_results, :normal
|
65
|
-
When {
|
66
|
-
@app.run(%w(-f global command1 -f command -s subcommand10 -f sub))
|
67
|
-
}
|
68
|
-
Then {
|
69
|
-
with_clue {
|
70
|
-
assert_equal 'subcommand10',@results[:command_name]
|
71
|
-
assert_equal 'global', @results[:global_options][:f],'global'
|
72
|
-
assert !@results[:global_options][:s]
|
73
|
-
assert_equal 'sub', @results[:command_options][:f]
|
74
|
-
assert !@results[:command_options][:s]
|
75
|
-
assert_equal 'command',@results[:command_options][GLI::Command::PARENT][:f]
|
76
|
-
assert @results[:command_options][GLI::Command::PARENT][:s]
|
77
|
-
}
|
78
|
-
}
|
79
|
-
end
|
80
|
-
|
81
|
-
test_that "in loose mode with autocomplete false, it doesn't autocorrect a sub command" do
|
82
|
-
Given :app_with_subcommand_storing_results, :normal, false, :loose
|
83
|
-
When {
|
84
|
-
@app.run(%w(-f global command -f flag -s subcomm -f subflag))
|
85
|
-
}
|
86
|
-
Then {
|
87
|
-
with_clue {
|
88
|
-
assert_equal "command",@results[:command_name]
|
89
|
-
}
|
90
|
-
}
|
91
|
-
end
|
92
|
-
|
93
|
-
test_that "in strict mode with autocomplete false, it doesn't autocorrect a sub command" do
|
94
|
-
Given :app_with_subcommand_storing_results, :normal, false, :strict
|
95
|
-
When {
|
96
|
-
@app.run(%w(-f global command -f flag -s subcomm -f subflag))
|
97
|
-
}
|
98
|
-
Then {
|
99
|
-
with_clue {
|
100
|
-
assert_equal nil,@results[:command_name]
|
101
|
-
assert @fake_stderr.contained?(/error: Too many arguments for command/)
|
102
|
-
}
|
103
|
-
}
|
104
|
-
end
|
105
|
-
|
106
|
-
test_that "in loose mode, argument validation is ignored" do
|
107
|
-
Given :app_with_arguments, 1, 1, false, :loose
|
108
|
-
When :run_app_with_X_arguments, 0
|
109
|
-
Then {
|
110
|
-
with_clue {
|
111
|
-
assert_equal 0, @results[:number_of_args_give_to_action]
|
112
|
-
assert_equal 0, @exit_code
|
113
|
-
}
|
114
|
-
}
|
115
|
-
end
|
116
|
-
|
117
|
-
test_that "in strict mode, subcommand_option_handling must be normal" do
|
118
|
-
Given :app_with_arguments, 1, 1, false, :strict, :legacy
|
119
|
-
When :run_app_with_X_arguments, 1
|
120
|
-
Then {
|
121
|
-
with_clue {
|
122
|
-
assert_nil @results[:number_of_args_give_to_action]
|
123
|
-
assert_equal 1, @exit_code
|
124
|
-
assert @fake_stderr.contained?(/you must enable normal subcommand_option_handling/)
|
125
|
-
}
|
126
|
-
}
|
127
|
-
end
|
128
|
-
|
129
|
-
ix = -1
|
130
|
-
[
|
131
|
-
[1 , 1 , false , 0 , :not_enough] ,
|
132
|
-
[1 , 1 , false , 1 , :success] ,
|
133
|
-
[1 , 1 , false , 2 , :success] ,
|
134
|
-
[1 , 1 , false , 3 , :too_many] ,
|
135
|
-
[1 , 1 , true , 0 , :not_enough] ,
|
136
|
-
[1 , 1 , true , 1 , :success] ,
|
137
|
-
[1 , 1 , true , 2 , :success] ,
|
138
|
-
[1 , 1 , true , 3 , :success] ,
|
139
|
-
[1 , 1 , true , 30 , :success] ,
|
140
|
-
[0 , 0 , false , 0 , :success] ,
|
141
|
-
[0 , 0 , false , 1 , :too_many] ,
|
142
|
-
[0 , 1 , false , 1 , :success] ,
|
143
|
-
[0 , 1 , false , 0 , :success] ,
|
144
|
-
[1 , 0 , false , 1 , :success] ,
|
145
|
-
[1 , 0 , false , 0 , :not_enough] ,
|
146
|
-
[0 , 0 , true , 0 , :success] ,
|
147
|
-
[0 , 0 , true , 10 , :success]
|
148
|
-
|
149
|
-
].each do |number_required, number_optional, has_multiple, number_generated, status|
|
150
|
-
ix = ix + 1
|
151
|
-
test_that "in strict mode, with #{number_required} required, #{number_optional} optional, #{ has_multiple ? 'multiple' : 'not multiple' } and #{number_generated} generated, it should be #{status}" do
|
152
|
-
Given :app_with_arguments, number_required, number_optional, has_multiple, :strict
|
153
|
-
When :run_app_with_X_arguments, number_generated
|
154
|
-
Then {
|
155
|
-
with_clue {
|
156
|
-
if status == :success then
|
157
|
-
assert_equal number_generated, @results[:number_of_args_give_to_action]
|
158
|
-
assert_equal 0, @exit_code
|
159
|
-
assert !@fake_stderr.contained?(/Not enough arguments for command/)
|
160
|
-
assert !@fake_stderr.contained?(/Too many arguments for command/)
|
161
|
-
elsif status == :not_enough then
|
162
|
-
assert_equal nil, @results[:number_of_args_give_to_action]
|
163
|
-
assert_equal 64, @exit_code
|
164
|
-
assert @fake_stderr.contained?(/Not enough arguments for command/)
|
165
|
-
elsif status == :too_many then
|
166
|
-
assert_equal nil, @results[:number_of_args_give_to_action]
|
167
|
-
assert_equal 64, @exit_code
|
168
|
-
assert @fake_stderr.contained?(/Too many arguments for command/)
|
169
|
-
else
|
170
|
-
assert false
|
171
|
-
end
|
172
|
-
}
|
173
|
-
}
|
174
|
-
end
|
175
|
-
end
|
176
|
-
private
|
177
|
-
def with_clue(&block)
|
178
|
-
block.call
|
179
|
-
rescue Exception
|
180
|
-
dump = ""
|
181
|
-
PP.pp "\nRESULTS---#{@results}", dump unless @results.empty?
|
182
|
-
PP.pp "\nSTDERR---\n#{@fake_stderr.to_s}", dump
|
183
|
-
PP.pp "\nSTDOUT---\n#{@fake_stdout.to_s}", dump
|
184
|
-
@original_stdout.puts dump
|
185
|
-
raise
|
186
|
-
end
|
187
|
-
|
188
|
-
def app_with_subcommand_storing_results(subcommand_option_handling_strategy, autocomplete, arguments_handling_strategy)
|
189
|
-
@app.subcommand_option_handling subcommand_option_handling_strategy
|
190
|
-
@app.autocomplete_commands autocomplete
|
191
|
-
@app.arguments arguments_handling_strategy
|
192
|
-
@app.flag ['f','flag']
|
193
|
-
@app.switch ['s','switch']
|
194
|
-
|
195
|
-
@app.command "command" do |c|
|
196
|
-
c.flag ['f','flag']
|
197
|
-
c.switch ['s','switch']
|
198
|
-
c.action do |global,options,args|
|
199
|
-
@results = {
|
200
|
-
:command_name => "command",
|
201
|
-
:global_options => global,
|
202
|
-
:command_options => options,
|
203
|
-
:args => args
|
204
|
-
}
|
205
|
-
end
|
206
|
-
|
207
|
-
c.command "subcommand" do |subcommand|
|
208
|
-
subcommand.flag ['f','flag']
|
209
|
-
subcommand.flag ['foo']
|
210
|
-
subcommand.switch ['s','switch']
|
211
|
-
subcommand.action do |global,options,args|
|
212
|
-
@results = {
|
213
|
-
:command_name => "subcommand",
|
214
|
-
:global_options => global,
|
215
|
-
:command_options => options,
|
216
|
-
:args => args
|
217
|
-
}
|
218
|
-
end
|
219
|
-
end
|
220
|
-
end
|
221
|
-
end
|
222
|
-
|
223
|
-
def app_with_subcommands_storing_results(subcommand_option_handling_strategy = :legacy)
|
224
|
-
@app.subcommand_option_handling subcommand_option_handling_strategy
|
225
|
-
@app.flag ['f','flag']
|
226
|
-
@app.switch ['s','switch']
|
227
|
-
|
228
|
-
2.times do |i|
|
229
|
-
@app.command "command#{i}" do |c|
|
230
|
-
c.flag ['f','flag']
|
231
|
-
c.switch ['s','switch']
|
232
|
-
c.action do |global,options,args|
|
233
|
-
@results = {
|
234
|
-
:command_name => "command#{i}",
|
235
|
-
:global_options => global,
|
236
|
-
:command_options => options,
|
237
|
-
:args => args
|
238
|
-
}
|
239
|
-
end
|
240
|
-
|
241
|
-
2.times do |j|
|
242
|
-
c.command "subcommand#{i}#{j}" do |subcommand|
|
243
|
-
subcommand.flag ['f','flag']
|
244
|
-
subcommand.flag ['foo']
|
245
|
-
subcommand.switch ['s','switch']
|
246
|
-
subcommand.action do |global,options,args|
|
247
|
-
@results = {
|
248
|
-
:command_name => "subcommand#{i}#{j}",
|
249
|
-
:global_options => global,
|
250
|
-
:command_options => options,
|
251
|
-
:args => args
|
252
|
-
}
|
253
|
-
end
|
254
|
-
end
|
255
|
-
end
|
256
|
-
end
|
257
|
-
end
|
258
|
-
end
|
259
|
-
|
260
|
-
def app_with_arguments(number_required_arguments, number_optional_arguments, has_argument_multiple, arguments_handling_strategy = :loose, subcommand_option_handling_strategy = :normal)
|
261
|
-
@app.arguments arguments_handling_strategy
|
262
|
-
@app.subcommand_option_handling subcommand_option_handling_strategy
|
263
|
-
|
264
|
-
number_required_arguments.times { |i| @app.arg("needed#{i}") }
|
265
|
-
number_optional_arguments.times { |i| @app.arg("optional#{i}", :optional) }
|
266
|
-
@app.arg :multiple, [:multiple, :optional] if has_argument_multiple
|
267
|
-
|
268
|
-
@app.command :cmd do |c|
|
269
|
-
c.action do |g,o,a|
|
270
|
-
@results = {
|
271
|
-
:number_of_args_give_to_action => a.size
|
272
|
-
}
|
273
|
-
end
|
274
|
-
end
|
275
|
-
end
|
276
|
-
|
277
|
-
def run_app_with_X_arguments(number_arguments)
|
278
|
-
@exit_code = @app.run [].tap{|args| args << "cmd"; number_arguments.times {|i| args << "arg#{i}"}}
|
279
|
-
end
|
280
|
-
end
|