gli 2.0.0.rc5 → 2.0.0.rc6

Sign up to get free protection for your applications and to get access to all the features.
@@ -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