gli 2.0.0.rc5 → 2.0.0.rc6

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.
@@ -11,24 +11,26 @@ module GLI
11
11
  @filename = config_file_name
12
12
  super(:names => :initconfig,
13
13
  :description => "Initialize the config file using current global options",
14
- :long_desc => 'Initializes a configuration file where you can set default options for command line flags, both globally and on a per-command basis. These defaults override the built-in defaults and allow you to omit commonly-used command line flags when invoking this program')
14
+ :long_desc => 'Initializes a configuration file where you can set default options for command line flags, both globally and on a per-command basis. These defaults override the built-in defaults and allow you to omit commonly-used command line flags when invoking this program',
15
+ :skips_pre => true,:skips_post => true, :skips_around => true)
16
+
17
+ @app_commands = commands
18
+ @app_flags = flags
19
+ @app_switches = switches
15
20
 
16
21
  self.desc 'force overwrite of existing config file'
17
22
  self.switch :force
18
23
 
19
- @commands = commands
20
- @flags = flags
21
- @switches = switches
22
- end
23
-
24
- def execute(global_options,options,arguments)
25
- if options[:force] || !File.exist?(@filename)
26
- create_config(global_options,options,arguments)
27
- else
28
- raise "Not overwriting existing config file #{@filename}, use --force to override"
24
+ action do |global_options,options,arguments|
25
+ if options[:force] || !File.exist?(@filename)
26
+ create_config(global_options,options,arguments)
27
+ else
28
+ raise "Not overwriting existing config file #{@filename}, use --force to override"
29
+ end
29
30
  end
30
31
  end
31
32
 
33
+
32
34
  private
33
35
 
34
36
  def create_config(global_options,options,arguments)
@@ -40,10 +42,10 @@ module GLI
40
42
  end
41
43
  }]
42
44
  config[COMMANDS_KEY] = {}
43
- @commands.each do |name,command|
45
+ @app_commands.each do |name,command|
44
46
  if (command != self) && (name != :rdoc) && (name != :help)
45
47
  if command != self
46
- config[COMMANDS_KEY][name.to_sym] = config_for_command(@commands,name.to_sym)
48
+ config[COMMANDS_KEY][name.to_sym] = config_for_command(@app_commands,name.to_sym)
47
49
  end
48
50
  end
49
51
  end
@@ -0,0 +1,112 @@
1
+ require 'stringio'
2
+ module GLI
3
+ module Commands
4
+ class RdocDocumentListener
5
+
6
+ def initialize(global_options,options,arguments)
7
+ @io = File.new(File.basename($0) + ".rdoc",'w')
8
+ @nest = ''
9
+ end
10
+
11
+ def beginning
12
+ end
13
+
14
+ # Called when processing has completed
15
+ def ending
16
+ @io.close
17
+ end
18
+
19
+ # Gives you the program description
20
+ def program_desc(desc)
21
+ @io.puts "== #{File.basename($0)} - #{desc}"
22
+ @io.puts
23
+ end
24
+
25
+ # Gives you the program version
26
+ def version(version)
27
+ @io.puts "v#{version}"
28
+ @io.puts
29
+ end
30
+
31
+ def options
32
+ if @nest.size == 0
33
+ @io.puts "=== Global Options"
34
+ else
35
+ @io.puts "#{@nest}=== Options"
36
+ end
37
+ end
38
+
39
+ # Gives you a flag in the current context
40
+ def flag(name,aliases,desc,long_desc,default_value,arg_name,must_match,type)
41
+ usage = "#{add_dashes(name)} #{arg_name || 'arg'}"
42
+ @io.puts "#{@nest}=== #{usage}"
43
+ @io.puts
44
+ @io.puts String(desc).strip
45
+ @io.puts
46
+ @io.puts "[Aliases] #{aliases.map { |_| add_dashes(_) }.join(',')}" unless aliases.empty?
47
+ @io.puts "[Default Value] #{default_value || 'None'}"
48
+ @io.puts "[Must Match] #{must_match.to_s}" unless must_match.nil?
49
+ @io.puts String(long_desc).strip
50
+ @io.puts
51
+ end
52
+
53
+ # Gives you a switch in the current context
54
+ def switch(name,aliases,desc,long_desc,negetable)
55
+ if negetable
56
+ name = "[no-]#{name}" if name.length > 1
57
+ aliases = aliases.map { |_| _.length > 1 ? "[no-]#{_}" : _ }
58
+ end
59
+ @io.puts "#{@nest}=== #{add_dashes(name)}"
60
+ @io.puts String(desc).strip
61
+ @io.puts
62
+ @io.puts "[Aliases] #{aliases.map { |_| add_dashes(_) }.join(',')}\n" unless aliases.empty?
63
+ @io.puts
64
+ @io.puts String(long_desc).strip
65
+ @io.puts
66
+ end
67
+
68
+ def end_options
69
+ end
70
+
71
+ def commands
72
+ @io.puts "#{@nest}=== Commands"
73
+ @nest = "#{@nest}="
74
+ end
75
+
76
+ # Gives you a command in the current context and creates a new context of this command
77
+ def command(name,aliases,desc,long_desc,arg_name)
78
+ @io.puts "#{@nest}=== #{name} #{arg_name}"
79
+ @io.puts String(desc).strip
80
+ @io.puts
81
+ @io.puts "[Aliases] #{aliases.join(',')}\n" unless aliases.empty?
82
+ @io.puts
83
+ @io.puts String(long_desc).strip
84
+ @nest = "#{@nest}="
85
+ end
86
+
87
+ # Ends a command, and "pops" you back up one context
88
+ def end_command(name)
89
+ @nest.gsub!(/=$/,'')
90
+ end
91
+
92
+ # Gives you the name of the current command in the current context
93
+ def default_command(name)
94
+ @io.puts "[Default Command] #{name}" unless name.nil?
95
+ end
96
+
97
+ def end_commands
98
+ @nest.gsub!(/=$/,'')
99
+ end
100
+
101
+ private
102
+
103
+ def add_dashes(name)
104
+ name = "-#{name}"
105
+ name = "-#{name}" if name.length > 2
106
+ name
107
+ end
108
+
109
+
110
+ end
111
+ end
112
+ end
@@ -273,7 +273,6 @@ EOS
273
273
  file.chmod(0755)
274
274
  file.puts '#!/usr/bin/env ruby'
275
275
  file.puts <<EOS
276
- require 'rubygems'
277
276
  require 'gli'
278
277
  begin # XXX: Remove this begin/rescue before distributing your app
279
278
  require '#{project_name}'
@@ -15,6 +15,9 @@ module GLI
15
15
  @table[k.to_sym] = v
16
16
  end
17
17
 
18
+ def map(&block)
19
+ @table.map(&block)
20
+ end
18
21
  end
19
22
  end
20
23
 
@@ -5,6 +5,7 @@ module GLI
5
5
  class Switch < CommandLineOption #:nodoc:
6
6
 
7
7
  attr_accessor :default_value
8
+ attr_reader :negatable
8
9
 
9
10
  # Creates a new switch
10
11
  #
@@ -1,5 +1,5 @@
1
1
  module GLI
2
2
  unless const_defined? :VERSION
3
- VERSION = '2.0.0.rc5' #:nodoc:
3
+ VERSION = '2.0.0.rc6' #:nodoc:
4
4
  end
5
5
  end
@@ -15,4 +15,4 @@ MethodNameCheck:
15
15
  ModuleNameCheck:
16
16
  pattern: !ruby/regexp /^[A-Z][a-zA-Z0-9]*$/
17
17
  ParameterNumberCheck:
18
- parameter_count: 5
18
+ parameter_count: 8
@@ -0,0 +1,315 @@
1
+ require 'test_helper'
2
+ require 'pp'
3
+
4
+ class String
5
+ def blank?
6
+ self.strip.length == 0
7
+ end
8
+ end
9
+
10
+ class NilClass
11
+ def blank?
12
+ true
13
+ end
14
+ end
15
+
16
+ class Object
17
+ def blank?
18
+ false
19
+ end
20
+ end
21
+
22
+ class TC_testDoc < Clean::Test::TestCase
23
+ include TestHelper
24
+
25
+ class TestApp
26
+ include GLI::App
27
+ end
28
+
29
+ class TestListener
30
+ @@last = nil
31
+ def self.last
32
+ @@last
33
+ end
34
+ def initialize(*ignored)
35
+ @stringio = StringIO.new
36
+ @indent = ''
37
+ @@last = self
38
+ end
39
+ def options
40
+ end
41
+ def end_options
42
+ end
43
+ def commands
44
+ end
45
+ def end_commands
46
+ end
47
+ def beginning
48
+ @stringio << 'BEGIN' << "\n"
49
+ end
50
+
51
+ def ending
52
+ @stringio << 'END' << "\n"
53
+ end
54
+
55
+ def program_desc(desc)
56
+ @stringio << desc << "\n"
57
+ end
58
+
59
+ def version(version)
60
+ @stringio << version << "\n"
61
+ end
62
+
63
+ def default_command(name)
64
+ @stringio << @indent << "default_command: " << name << "\n"
65
+ end
66
+
67
+ def flag(name,aliases,desc,long_desc,default_value,arg_name,must_match,type)
68
+ @stringio << @indent << "flag: " << name << "\n"
69
+ @indent += ' '
70
+ @stringio << @indent << "aliases: " << aliases.join(',') << "\n" unless aliases.empty?
71
+ @stringio << @indent << "desc: " << desc << "\n" unless desc.blank?
72
+ @stringio << @indent << "long_desc: " << long_desc << "\n" unless long_desc.blank?
73
+ @stringio << @indent << "default_value: " << default_value << "\n" unless default_value.blank?
74
+ @stringio << @indent << "arg_name: " << arg_name << "\n" unless arg_name.blank?
75
+ @indent.gsub!(/ $/,'')
76
+ end
77
+
78
+ def switch(name,aliases,desc,long_desc,negatable)
79
+ @stringio << @indent << "switch: " << name << "\n"
80
+ @indent += ' '
81
+ @stringio << @indent << "aliases: " << aliases.join(',') << "\n" unless aliases.empty?
82
+ @stringio << @indent << "desc: " << desc << "\n" unless desc.blank?
83
+ @stringio << @indent << "long_desc: " << long_desc << "\n" unless long_desc.blank?
84
+ @stringio << @indent << "negatable: " << negatable << "\n" unless negatable.blank?
85
+ @indent.gsub!(/ $/,'')
86
+ end
87
+
88
+ def command(name,aliases,desc,long_desc,arg_name)
89
+ @stringio << @indent << "command: " << name << "\n"
90
+ @indent += ' '
91
+ @stringio << @indent << "aliases: " << aliases.join(',') << "\n" unless aliases.empty?
92
+ @stringio << @indent << "desc: " << desc << "\n" unless desc.blank?
93
+ @stringio << @indent << "long_desc: " << long_desc << "\n" unless long_desc.blank?
94
+ @stringio << @indent << "arg_name: " << arg_name << "\n" unless arg_name.blank?
95
+ end
96
+
97
+ def end_command(name)
98
+ @indent.gsub!(/ $/,'')
99
+ @stringio << @indent << "end #{name}" << "\n"
100
+ end
101
+
102
+ def to_s
103
+ @stringio.string
104
+ end
105
+ end
106
+
107
+ def setup
108
+ @@counter = -1 # we pre-increment so this makes 0 first
109
+ end
110
+
111
+ test_that "a GLI app with documentation gets the callbacks for each element" do
112
+ Given :the_test_app
113
+ And :the_expected_output
114
+ And {
115
+ @documenter = GLI::Commands::Doc.new(@app)
116
+ @listener = TestListener.new
117
+ }
118
+ When {
119
+ @documenter.document(@listener)
120
+ }
121
+ Then {
122
+ lines_expected = @string.split(/\n/)
123
+ lines_got = @listener.to_s.split(/\n/)
124
+ lines_expected.zip(lines_got).each_with_index do |(expected,got),index|
125
+ assert_equal expected,got,"At index #{index}"
126
+ end
127
+ }
128
+ end
129
+
130
+ test_that "the doc command works as a GLI command" do
131
+ Given :the_test_app
132
+ And :the_expected_output
133
+ And {
134
+ @documenter = GLI::Commands::Doc.new(@app)
135
+ @listener = TestListener.new
136
+ }
137
+ When {
138
+ @documenter.execute({},{:format => "TC_testDoc::TestListener"},[])
139
+ }
140
+ Then {
141
+ lines_expected = @string.split(/\n/)
142
+ lines_got = TestListener.last.to_s.split(/\n/)
143
+ lines_expected.zip(lines_got).each_with_index do |(expected,got),index|
144
+ assert_equal expected,got,"At index #{index}"
145
+ end
146
+ }
147
+ end
148
+
149
+ private
150
+
151
+ @@counter = 1
152
+ def self.counter
153
+ @@counter += 1
154
+ @@counter
155
+ end
156
+
157
+ def the_test_app
158
+ @app = TestApp.new
159
+ @app.instance_eval do
160
+ program_desc "program desc"
161
+ version "1.3.4"
162
+
163
+ TC_testDoc.flag_with_everything_specified(self)
164
+ TC_testDoc.flag_with_everything_omitted(self)
165
+ TC_testDoc.switch_with_everything_specified(self)
166
+ TC_testDoc.switch_with_everything_omitted(self)
167
+
168
+ desc "command desc"
169
+ long_desc "command long desc"
170
+ arg_name "cmd_arg_name"
171
+ command [:command1,:com1] do |c|
172
+ TC_testDoc.flag_with_everything_specified(c)
173
+ TC_testDoc.flag_with_everything_omitted(c)
174
+ TC_testDoc.switch_with_everything_specified(c)
175
+ TC_testDoc.switch_with_everything_omitted(c)
176
+
177
+ c.desc "subcommand desc"
178
+ c.long_desc "subcommand long desc"
179
+ c.arg_name "subcmd_arg_name"
180
+ c.action { |g,o,a| }
181
+ c.command [:sub,:subcommand] do |sub|
182
+ TC_testDoc.flag_with_everything_specified(sub,:subflag)
183
+ TC_testDoc.flag_with_everything_omitted(sub,:subflag2)
184
+ TC_testDoc.switch_with_everything_specified(sub,:subswitch)
185
+ TC_testDoc.switch_with_everything_omitted(sub,:subswitch2)
186
+ sub.action { |g,o,a| }
187
+ end
188
+ c.command [:default] do |sub|
189
+ sub.action { |g,o,a| }
190
+ end
191
+ c.default_command :default
192
+ end
193
+
194
+ command [:command2,:com2] do |c|
195
+ c.action { |g,o,a| }
196
+ c.command [:sub2,:subcommand2] do |sub|
197
+ sub.action { |g,o,a| }
198
+ end
199
+ end
200
+ end
201
+ end
202
+
203
+ def self.flag_with_everything_specified(on,name=[:f,:flag])
204
+ on.flag name,:desc => "flag desc #{counter}",
205
+ :long_desc => "flag long_desc #{counter}",
206
+ :default_value => "flag default_value #{counter}",
207
+ :arg_name => "flag_arg_name_#{counter}",
208
+ :must_match => /foo.*bar/,
209
+ :type => Array
210
+ end
211
+
212
+ def self.flag_with_everything_omitted(on,name=[:F,:flag2])
213
+ on.flag name
214
+ end
215
+
216
+ def self.switch_with_everything_specified(on,name=[:s,:switch])
217
+ on.switch name, :desc => "switch desc #{counter}",
218
+ :long_desc => "switch long_desc #{counter}",
219
+ :negatable => false
220
+ end
221
+
222
+ def self.switch_with_everything_omitted(on,name=[:S,:switch2])
223
+ on.switch name
224
+ end
225
+ def the_expected_output
226
+ # Oh yeah. Creating a string representing the structure of the calls.
227
+ @string =<<EOS
228
+ BEGIN
229
+ program desc
230
+ 1.3.4
231
+ flag: F
232
+ aliases: flag2
233
+ arg_name: arg
234
+ flag: f
235
+ aliases: flag
236
+ desc: flag desc 0
237
+ long_desc: flag long_desc 1
238
+ default_value: flag default_value 2
239
+ arg_name: flag_arg_name_3
240
+ switch: S
241
+ aliases: switch2
242
+ negatable: true
243
+ switch: s
244
+ aliases: switch
245
+ desc: switch desc 4
246
+ long_desc: switch long_desc 5
247
+ negatable: false
248
+ switch: version
249
+ negatable: false
250
+ command: command1
251
+ aliases: com1
252
+ desc: command desc
253
+ long_desc: command long desc
254
+ arg_name: cmd_arg_name
255
+ flag: F
256
+ aliases: flag2
257
+ arg_name: arg
258
+ flag: f
259
+ aliases: flag
260
+ desc: flag desc 6
261
+ long_desc: flag long_desc 7
262
+ default_value: flag default_value 8
263
+ arg_name: flag_arg_name_9
264
+ switch: S
265
+ aliases: switch2
266
+ negatable: true
267
+ switch: s
268
+ aliases: switch
269
+ desc: switch desc 10
270
+ long_desc: switch long_desc 11
271
+ negatable: false
272
+ command: default
273
+ default_command:
274
+ end default
275
+ command: sub
276
+ aliases: subcommand
277
+ desc: subcommand desc
278
+ long_desc: subcommand long desc
279
+ arg_name: subcmd_arg_name
280
+ flag: subflag
281
+ desc: flag desc 12
282
+ long_desc: flag long_desc 13
283
+ default_value: flag default_value 14
284
+ arg_name: flag_arg_name_15
285
+ flag: subflag2
286
+ arg_name: arg
287
+ switch: subswitch
288
+ desc: switch desc 16
289
+ long_desc: switch long_desc 17
290
+ negatable: false
291
+ switch: subswitch2
292
+ negatable: true
293
+ default_command:
294
+ end sub
295
+ default_command: default
296
+ end command1
297
+ command: command2
298
+ aliases: com2
299
+ command: sub2
300
+ aliases: subcommand2
301
+ default_command:
302
+ end sub2
303
+ default_command:
304
+ end command2
305
+ command: help
306
+ desc: Shows a list of commands or help for one command
307
+ long_desc: Gets help for the application or its commands. Can also list the commands in a way helpful to creating a bash-style completion function
308
+ arg_name: command
309
+ default_command:
310
+ end help
311
+ default_command:
312
+ END
313
+ EOS
314
+ end
315
+ end