gli 2.11.0 → 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.
Files changed (92) hide show
  1. checksums.yaml +5 -5
  2. data/.circleci/config.yml +28 -0
  3. data/.gitignore +3 -3
  4. data/.tool-versions +1 -0
  5. data/Gemfile +0 -2
  6. data/README.rdoc +29 -19
  7. data/Rakefile +15 -37
  8. data/bin/ci +29 -0
  9. data/bin/gli +24 -54
  10. data/bin/rake +29 -0
  11. data/bin/setup +5 -0
  12. data/exe/gli +68 -0
  13. data/gli.gemspec +20 -24
  14. data/gli.rdoc +9 -9
  15. data/lib/gli/app.rb +31 -8
  16. data/lib/gli/app_support.rb +15 -3
  17. data/lib/gli/command.rb +24 -2
  18. data/lib/gli/command_finder.rb +42 -25
  19. data/lib/gli/command_support.rb +7 -6
  20. data/lib/gli/commands/doc.rb +9 -3
  21. data/lib/gli/commands/help.rb +2 -1
  22. data/lib/gli/commands/help_modules/arg_name_formatter.rb +2 -2
  23. data/lib/gli/commands/help_modules/command_help_format.rb +19 -1
  24. data/lib/gli/commands/help_modules/full_synopsis_formatter.rb +3 -2
  25. data/lib/gli/commands/help_modules/global_help_format.rb +1 -1
  26. data/lib/gli/commands/help_modules/options_formatter.rb +4 -6
  27. data/lib/gli/commands/initconfig.rb +3 -6
  28. data/lib/gli/commands/rdoc_document_listener.rb +2 -1
  29. data/lib/gli/commands/scaffold.rb +71 -142
  30. data/lib/gli/dsl.rb +2 -1
  31. data/lib/gli/flag.rb +23 -2
  32. data/lib/gli/gli_option_parser.rb +66 -15
  33. data/lib/gli/option_parser_factory.rb +9 -2
  34. data/lib/gli/options.rb +2 -2
  35. data/lib/gli/switch.rb +4 -0
  36. data/lib/gli/terminal.rb +6 -2
  37. data/lib/gli/version.rb +1 -1
  38. data/lib/gli.rb +1 -0
  39. data/object-model.dot +29 -0
  40. data/object-model.png +0 -0
  41. data/test/apps/todo/Gemfile +1 -1
  42. data/test/apps/todo/bin/todo +12 -6
  43. data/test/apps/todo/lib/todo/commands/create.rb +42 -41
  44. data/test/apps/todo/lib/todo/commands/list.rb +48 -36
  45. data/test/apps/todo/lib/todo/commands/ls.rb +25 -24
  46. data/test/apps/todo/lib/todo/commands/make.rb +42 -39
  47. data/test/apps/todo/todo.gemspec +1 -2
  48. data/test/apps/todo_legacy/todo.gemspec +1 -2
  49. data/test/apps/todo_plugins/commands/third.rb +2 -0
  50. data/test/integration/gli_cli_test.rb +69 -0
  51. data/test/integration/gli_powered_app_test.rb +52 -0
  52. data/test/integration/scaffold_test.rb +30 -0
  53. data/test/integration/test_helper.rb +52 -0
  54. data/test/unit/command_finder_test.rb +54 -0
  55. data/test/{tc_command.rb → unit/command_test.rb} +20 -7
  56. data/test/unit/compound_command_test.rb +17 -0
  57. data/test/{tc_doc.rb → unit/doc_test.rb} +38 -51
  58. data/test/{tc_flag.rb → unit/flag_test.rb} +19 -25
  59. data/test/{tc_gli.rb → unit/gli_test.rb} +78 -50
  60. data/test/{tc_help.rb → unit/help_test.rb} +54 -113
  61. data/test/{tc_options.rb → unit/options_test.rb} +4 -4
  62. data/test/unit/subcommand_parsing_test.rb +263 -0
  63. data/test/unit/subcommands_test.rb +245 -0
  64. data/test/{config.yaml → unit/support/gli_test_config.yml} +1 -0
  65. data/test/unit/switch_test.rb +49 -0
  66. data/test/{tc_terminal.rb → unit/terminal_test.rb} +28 -3
  67. data/test/unit/test_helper.rb +13 -0
  68. data/test/unit/verbatim_wrapper_test.rb +24 -0
  69. metadata +85 -141
  70. data/.ruby-gemset +0 -1
  71. data/.ruby-version +0 -1
  72. data/.travis.yml +0 -12
  73. data/ObjectModel.graffle +0 -1191
  74. data/bin/report_on_rake_results +0 -10
  75. data/bin/test_all_rubies.sh +0 -6
  76. data/features/gli_executable.feature +0 -90
  77. data/features/gli_init.feature +0 -232
  78. data/features/step_definitions/gli_executable_steps.rb +0 -18
  79. data/features/step_definitions/gli_init_steps.rb +0 -11
  80. data/features/step_definitions/todo_steps.rb +0 -100
  81. data/features/support/env.rb +0 -55
  82. data/features/todo.feature +0 -546
  83. data/features/todo_legacy.feature +0 -128
  84. data/test/option_test_helper.rb +0 -13
  85. data/test/tc_compound_command.rb +0 -22
  86. data/test/tc_subcommand_parsing.rb +0 -104
  87. data/test/tc_subcommands.rb +0 -259
  88. data/test/tc_switch.rb +0 -55
  89. data/test/tc_verbatim_wrapper.rb +0 -36
  90. data/test/test_helper.rb +0 -20
  91. /data/test/{init_simplecov.rb → unit/init_simplecov.rb} +0 -0
  92. /data/test/{fake_std_out.rb → unit/support/fake_std_out.rb} +0 -0
@@ -0,0 +1,245 @@
1
+ require_relative "test_helper"
2
+ require_relative "support/fake_std_out"
3
+
4
+ class SubcommandsTest < MiniTest::Test
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
+ end
22
+
23
+ def teardown
24
+ $stdout = @original_stdout
25
+ $stderr = @original_stderr
26
+ end
27
+
28
+ def test_we_run_add_command_using_add
29
+ we_have_a_command_with_two_subcommands
30
+ run_app('remote',"add",'-f','foo','bar')
31
+ assert_command_ran_with(:add, :command_options => {:f => true}, :args => %w(foo bar))
32
+ end
33
+ def test_we_run_add_command_using_new
34
+ we_have_a_command_with_two_subcommands
35
+ run_app('remote',"new",'-f','foo','bar')
36
+ assert_command_ran_with(:add, :command_options => {:f => true}, :args => %w(foo bar))
37
+ end
38
+
39
+ def test_subcommands_not_used_on_command_line_uses_base_action
40
+ we_have_a_command_with_two_subcommands
41
+ run_app('remote','foo','bar')
42
+ assert_command_ran_with(:base, :command_options => {:f => false}, :args => %w(foo bar))
43
+ end
44
+
45
+ def test_switches_and_flags_on_subcommand_available
46
+ we_have_a_command_with_two_subcommands(:switches => [:addswitch], :flags => [:addflag])
47
+ run_app('remote','add','--addswitch','--addflag','foo','bar')
48
+ assert_command_ran_with(:add,:command_options => { :addswitch => true, :addflag => 'foo', :f => false },
49
+ :args => ['bar'])
50
+ end
51
+
52
+ def test_help_flag_works_in_normal_mode
53
+ @app.subcommand_option_handling :normal
54
+ we_have_a_command_with_two_subcommands
55
+ @app.run(["remote", "add", "--help"]) rescue nil
56
+ refute_match /^error/, @fake_stderr.to_s, "should not output an error message"
57
+ end
58
+
59
+ def test_help_flag_works_in_legacy_mode
60
+ @app.subcommand_option_handling :legacy
61
+ we_have_a_command_with_two_subcommands
62
+ @app.run(["remote", "add", "--help"]) rescue nil
63
+ refute_match /^error/, @fake_stderr.to_s, "should not output an error message"
64
+ end
65
+
66
+ def test_we_can_reopen_commands_to_add_new_subcommands
67
+ @app.command :remote do |p|
68
+ p.command :add do |c|
69
+ c.action do |global_options,command_options,args|
70
+ @ran_command = :add
71
+ end
72
+ end
73
+ end
74
+ @app.command :remote do |p|
75
+ p.command :new do |c|
76
+ c.action do |global_options,command_options,args|
77
+ @ran_command = :new
78
+ end
79
+ end
80
+ end
81
+ run_app('remote','new')
82
+ assert_equal(@ran_command, :new)
83
+ run_app('remote', 'add')
84
+ assert_equal(@ran_command, :add)
85
+ end
86
+
87
+ def test_reopening_commands_doesnt_readd_to_output
88
+ @app.command :remote do |p|
89
+ p.command(:add) { }
90
+ end
91
+ @app.command :remote do |p|
92
+ p.command(:new) { }
93
+ end
94
+ command_names = @app.instance_variable_get("@commands_declaration_order").collect { |c| c.name }
95
+ assert_equal 1, command_names.grep(:remote).size
96
+ end
97
+
98
+
99
+ def test_we_can_reopen_commands_without_causing_conflicts
100
+ @app.command :remote do |p|
101
+ p.command :add do |c|
102
+ c.action do |global_options,command_options,args|
103
+ @ran_command = :remote_add
104
+ end
105
+ end
106
+ end
107
+ @app.command :local do |p|
108
+ p.command :add do |c|
109
+ c.action do |global_options,command_options,args|
110
+ @ran_command = :local_add
111
+ end
112
+ end
113
+ end
114
+ run_app('remote','add')
115
+ assert_equal(@ran_command, :remote_add)
116
+ run_app('local', 'add')
117
+ assert_equal(@ran_command, :local_add)
118
+ end
119
+
120
+
121
+ def test_we_can_nest_subcommands_very_deep
122
+ @run_results = { :add => nil, :rename => nil, :base => nil }
123
+ @app.command :remote do |c|
124
+
125
+ c.switch :f
126
+ c.command :add do |add|
127
+ add.command :some do |some|
128
+ some.command :cmd do |cmd|
129
+ cmd.switch :s
130
+ cmd.action do |global_options,command_options,args|
131
+ @run_results[:cmd] = [global_options,command_options,args]
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end
137
+ ENV['GLI_DEBUG'] = 'true'
138
+ run_app('remote','add','some','cmd','-s','blah')
139
+ assert_command_ran_with(:cmd, :command_options => {:s => true, :f => false},:args => ['blah'])
140
+ end
141
+
142
+ def test_when_any_command_has_no_action_but_there_are_args_indicate_unknown_command
143
+ a_very_deeply_nested_command_structure
144
+ assert_raises GLI::UnknownCommand do
145
+ When run_app('remote','add','some','foo')
146
+ end
147
+ assert_match /Unknown command 'foo'/,@fake_stderr.to_s
148
+ end
149
+
150
+ def test_when_any_command_has_no_action_but_there_are_no_args_indicate_subcommand_needed
151
+ a_very_deeply_nested_command_structure
152
+ assert_raises GLI::BadCommandLine do
153
+ When run_app('remote','add','some')
154
+ end
155
+ assert_match /Command 'some' requires a subcommand/,@fake_stderr.to_s
156
+ end
157
+
158
+ private
159
+
160
+ def run_app(*args)
161
+ @exit_code = @app.run(args)
162
+ end
163
+
164
+ def a_very_deeply_nested_command_structure
165
+ @run_results = { :add => nil, :rename => nil, :base => nil }
166
+ @app.command :remote do |c|
167
+
168
+ c.switch :f
169
+ c.command :add do |add|
170
+ add.command :some do |some|
171
+ some.command :cmd do |cmd|
172
+ cmd.switch :s
173
+ cmd.action do |global_options,command_options,args|
174
+ @run_results[:cmd] = [global_options,command_options,args]
175
+ end
176
+ end
177
+ end
178
+ end
179
+ end
180
+ ENV['GLI_DEBUG'] = 'true'
181
+ end
182
+
183
+ # expected_command - name of command exepcted to have been run
184
+ # options:
185
+ # - global_options => hash of expected options
186
+ # - command_options => hash of expected command options
187
+ # - args => array of expected args
188
+ def assert_command_ran_with(expected_command,options)
189
+ global_options = options[:global_options] || { :help => false }
190
+ @run_results.each do |command,results|
191
+ if command == expected_command
192
+ assert_equal(indifferent_hash(global_options),results[0])
193
+ assert_equal(indifferent_hash(options[:command_options]),results[1])
194
+ assert_equal(options[:args],results[2])
195
+ else
196
+ assert_nil results
197
+ end
198
+ end
199
+ end
200
+
201
+ def indifferent_hash(possibly_nil_hash)
202
+ return {} if possibly_nil_hash.nil?
203
+ possibly_nil_hash.keys.each do |key|
204
+ if key.kind_of? Symbol
205
+ possibly_nil_hash[key.to_s] = possibly_nil_hash[key] unless possibly_nil_hash.has_key?(key.to_s)
206
+ elsif key.kind_of? String
207
+ possibly_nil_hash[key.to_sym] = possibly_nil_hash[key] unless possibly_nil_hash.has_key?(key.to_sym)
208
+ end
209
+ end
210
+ possibly_nil_hash
211
+ end
212
+
213
+ # options -
214
+ # :flags => flags to add to :add
215
+ # :switiches => switiches to add to :add
216
+ def we_have_a_command_with_two_subcommands(options = {})
217
+ @run_results = { :add => nil, :rename => nil, :base => nil }
218
+ @app.command :remote do |c|
219
+
220
+ c.switch :f
221
+
222
+ c.desc "add a remote"
223
+ c.command [:add,:new] do |add|
224
+
225
+ Array(options[:flags]).each { |_| add.flag _ }
226
+ Array(options[:switches]).each { |_| add.switch _ }
227
+ add.action do |global_options,command_options,args|
228
+ @run_results[:add] = [global_options,command_options,args]
229
+ end
230
+ end
231
+
232
+ c.desc "rename a remote"
233
+ c.command :rename do |rename|
234
+ rename.action do |global_options,command_options,args|
235
+ @run_results[:rename] = [global_options,command_options,args]
236
+ end
237
+ end
238
+
239
+ c.action do |global_options,command_options,args|
240
+ @run_results[:base] = [global_options,command_options,args]
241
+ end
242
+ end
243
+ ENV['GLI_DEBUG'] = 'true'
244
+ end
245
+ end
@@ -8,3 +8,4 @@ commands:
8
8
  :f: barfoo
9
9
  :f: foo
10
10
  :bleorgh: true
11
+ :t: false
@@ -0,0 +1,49 @@
1
+ require_relative "test_helper"
2
+
3
+ class SwitchTest < MiniTest::Test
4
+ include TestHelper
5
+
6
+ def test_basics_simple
7
+ switch_with_names(:filename)
8
+ attributes_should_be_set
9
+ assert_equal(:filename,@cli_option.name)
10
+ assert_nil @cli_option.aliases
11
+ end
12
+
13
+ def test_basics_kinda_complex
14
+ switch_with_names([:f])
15
+ attributes_should_be_set
16
+ assert_equal(:f,@cli_option.name)
17
+ assert_nil @cli_option.aliases
18
+ end
19
+
20
+ def test_basics_complex
21
+ switch_with_names([:f,:file,:filename])
22
+ attributes_should_be_set
23
+ assert_equal(:f,@cli_option.name)
24
+ assert_equal([:file,:filename],@cli_option.aliases)
25
+ assert_equal ["-f","--[no-]file","--[no-]filename"],@switch.arguments_for_option_parser
26
+ end
27
+
28
+ def test_includes_negatable
29
+ assert_equal '-a',GLI::Switch.name_as_string('a')
30
+ assert_equal '--[no-]foo',GLI::Switch.name_as_string('foo')
31
+ end
32
+
33
+ private
34
+
35
+ def switch_with_names(names)
36
+ @options = {
37
+ :desc => 'Filename',
38
+ :long_desc => 'The Filename',
39
+ }
40
+ @switch = GLI::Switch.new(names,@options)
41
+ @cli_option = @switch
42
+ end
43
+
44
+ def attributes_should_be_set
45
+ assert_equal(@options[:desc],@switch.description)
46
+ assert_equal(@options[:long_desc],@switch.long_description)
47
+ end
48
+
49
+ end
@@ -1,9 +1,10 @@
1
- require 'test_helper'
1
+ require_relative "test_helper"
2
2
 
3
- class TC_testTerminal < Clean::Test::TestCase
3
+ class TerminalTest < MiniTest::Test
4
4
  include TestHelper
5
5
 
6
- def test_command_exists
6
+ # TODO: Make this test not mess with the internals of the class
7
+ def xtest_command_exists
7
8
  assert GLI::Terminal.instance.command_exists?('ls')
8
9
  assert !GLI::Terminal.instance.command_exists?('asdfasfasdf')
9
10
  end
@@ -73,6 +74,30 @@ class TC_testTerminal < Clean::Test::TestCase
73
74
  assert_equal [5678,1234],terminal.size
74
75
  end
75
76
 
77
+ def test_size_using_stty_but_returns_0
78
+ terminal = GLI::Terminal.new
79
+ terminal.make_unsafe!
80
+ GLI::Terminal.instance_eval do
81
+ def run_command(command)
82
+
83
+ if RUBY_PLATFORM == 'java'
84
+ return '0' if command == 'tput cols'
85
+ return '0' if command == 'tput lines'
86
+ else
87
+ return '0 0' if command == 'stty size'
88
+ return '0 0' if command == 'stty'
89
+ end
90
+
91
+ raise "Unexpected command called: #{command} for #{RUBY_PLATFORM}"
92
+ end
93
+ def command_exists?(command); true; end
94
+ def jruby?; false; end
95
+ def solaris?; false; end
96
+ end
97
+ ENV['COLUMNS'] = 'foo'
98
+ assert_equal [80,24],terminal.size
99
+ end
100
+
76
101
  def test_size_using_default
77
102
  terminal = GLI::Terminal.new
78
103
  terminal.make_unsafe!
@@ -0,0 +1,13 @@
1
+ require "minitest/autorun"
2
+ require "gli"
3
+
4
+ module TestHelper
5
+ class CLIApp
6
+ include GLI::App
7
+
8
+ def reset
9
+ super
10
+ @subcommand_option_handling_strategy = :normal
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,24 @@
1
+ require_relative "test_helper"
2
+
3
+ class TerminalTest < MiniTest::Test
4
+ include TestHelper
5
+
6
+ def test_handles_nil
7
+ @wrapper = GLI::Commands::HelpModules::VerbatimWrapper.new(rand(100),rand(100))
8
+ @result = @wrapper.wrap(nil)
9
+ assert_equal '',@result
10
+ end
11
+
12
+ def test_does_not_touch_input
13
+ @wrapper = GLI::Commands::HelpModules::VerbatimWrapper.new(rand(100),rand(100))
14
+ @input = <<EOS
15
+ |This is|an ASCII|table|
16
+ +-------+--------+-----+
17
+ | foo | bar | baz |
18
+ +-------+--------+-----+
19
+ EOS
20
+ @result = @wrapper.wrap(@input)
21
+ assert_equal @input,@result
22
+ end
23
+
24
+ end