gli 1.1.3 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,14 @@
1
1
  == Changelog
2
2
 
3
+ === 1.2.0 - 11/26/2010
4
+
5
+ * Added ability to use +help+ command to list commands suitable for creating bash completion script
6
+ * <code>options</code> and <code>global_options</code> will now contain values for all aliases of each flag and switch, so if you created a flag with <code>flag [:f,:flag]</code> and the user specifies <code>-f foo</code> on the command line, both <code>options[:f]</code> and <code>options[:flag]</code> will have the value <code>foo</code>. Same behavior for <code>--flag=foo</code>.
7
+ * You may now no-longer use names that have already been used. So if you declare a switch <code>switch :foo</code> and then later declare a flag <code>flag [:f,:foo]</code>, you get an <code>ArgumentError</code>. This is only checked within relevant scope, so you can still use the same option names between commands, and you can still have the same option name once in global and once in command scope. This is really a bugfix as the behavior of GLI was not clear before.
8
+ * <tt>long_desc</tt> now shows up in generated rdoc for flags and switches
9
+ * Scaffoling now generates a usable <code>Gemfile</code> for bundler
10
+ * More direct support for version numbers in GLI-managed apps
11
+
3
12
  === 1.1.3 - 10/24/2010
4
13
 
5
14
  * Changed the way we locate <code>__FILE__</code>'s directory; if it's a symlink it would've have worked. Required adding <code>:realpath</code> method to <code>File</code> for pre 1.9.2 rubies
@@ -6,6 +6,9 @@ License:: Distributes under the Apache License, see LICENSE.txt in the source di
6
6
 
7
7
  This is a DSL you can use to create a command line interface like git, gem or svn, in that the first argument is a command, and there are global and command specific flags.
8
8
 
9
+ * {Source on Github}[http://github.com/davetron5000/gli]
10
+ * RDoc[http://davetron5000.github.com/gli]
11
+
9
12
  == Use
10
13
 
11
14
  Install if you need to:
@@ -37,27 +40,32 @@ Though likely works on various other versions
37
40
 
38
41
  This example demonstrates most of the features of GLI.
39
42
 
40
- This sets you up to use the DSL that GLI defines:
43
+ The following sets you up to use the DSL that GLI defines:
41
44
 
42
45
  #!/usr/bin/ruby
43
46
  $: << File.expand_path(File.dirname(File.realpath(__FILE__)) + '/../lib')
44
47
 
45
48
  require 'gli'
49
+ require 'gli_version'
46
50
 
47
51
  include GLI
48
52
 
49
- This sets a description of your program. This can be as long as you want.
53
+ The following sets the version of your application for exposure in the default <tt>help</tt> subcommand (the VERSION constant was created by the scaffolding):
54
+
55
+ version GLI::VERSION
56
+
57
+ The following sets a description of your program. This can be as long as you want.
50
58
 
51
59
  program_description 'Support program for bootstrapping GLI-based programs'
52
60
 
53
- This sets a config file for your program. The config file can be used to store default values for command
61
+ The following sets a config file for your program. The config file can be used to store default values for command
54
62
  line options and command-specific options on a per-user (or per-site) basis. The format is YAML-based.
55
63
  Using an absolute path will result in the configuraiton file being located there. Without an absolute path,
56
64
  the file will be located relative to the current user's home directory (which is what is being done here).
57
65
 
58
66
  config_file '.glirc'
59
67
 
60
- This describes a command line switch "-n" that is global to all commands and specified before
68
+ The following describes a command line switch "-n" that is global to all commands and specified before
61
69
  the command name on the command line.
62
70
 
63
71
  desc 'Dry run; don\'t change the disk'
@@ -95,7 +103,9 @@ Next, while we are still inside the <tt>command</tt> block,
95
103
  we specify the actual code to execute when the command is chosen by the user. We define a block that
96
104
  will be given the global options (as a Hash), the command-specific options (as a Hash) and the command
97
105
  line arguments. The hashes keys are symbols based upon the switches and flags. For a switch or
98
- flag named "-r", we would use <tt>:r</tt>.
106
+ flag named "-r", we would use <tt>:r</tt>. Note that if you gave multiple values for one flag, e.g. <tt>flag [:f,:force]</tt>
107
+ then both <tt>:f</tt> and <tt>:force</tt> would be set to the same value; this lets you use more readable
108
+ keynames in your code when parsing options, but still provide terse flags to the user.
99
109
 
100
110
  c.action do |global_options,options,args|
101
111
  if args.length < 1
@@ -106,7 +116,7 @@ flag named "-r", we would use <tt>:r</tt>.
106
116
  options[:e],
107
117
  args[0],
108
118
  args[1..-1],
109
- ooptions[:force],
119
+ options[:force],
110
120
  global_options[:n])
111
121
  end
112
122
  end
@@ -143,7 +153,7 @@ What this gives you:
143
153
  * Error handling when an unknown command is specified
144
154
  * Default values for flags if they are not specified by the user (switches all default to false)
145
155
  * An easy way to allow user or site-specific defaults for options via a config file for your app
146
- * Nice RDoc describing how to use your application (you can see an example in the rdoc version of this file for the <tt>gli</tt> command)
156
+ * Nice RDoc describing how to use your application (you can see an example in the {rdoc version of this file}[http://davetron5000.github.com/gli] for the <tt>gli</tt> command)
147
157
 
148
158
  What this doesn't give you:
149
159
 
@@ -199,21 +209,45 @@ used.
199
209
  If your application has a <tt>README.rdoc</tt> already, you can simply add <tt>:include:yourapp.rdoc</tt> to the bottom and it will
200
210
  be included when you generate and publish your rdoc (note that it will *not* show up on github).
201
211
 
212
+ == Bash Completion
213
+
214
+ <i>Not available in current release yet</i>
215
+
216
+ The +help+ command takes an optional switch, +-c+, that will list all the commands (including aliases) in sorted order suitable for use in a bash completion script. When +-c+ is specified, the argument can be a partial command, and +help+ will only list the commands matching. Put this in your +.bashrc+:
217
+
218
+ complete -F get_myapp_targets myapp
219
+ function get_myapp_targets()
220
+ {
221
+ if [ -z $2 ] ; then
222
+ COMPREPLY=(`myapp help -c`)
223
+ else
224
+ COMPREPLY=(`myapp help -c $2`)
225
+ fi
226
+ }
227
+
228
+ Now, suppose your app takes the commands +list+, +ls+, +rm+, +add+, and +init+:
229
+
230
+ > myapp <TAB>
231
+ add init list ls rm
232
+ > myapp l<TAB>
233
+ list ls
234
+
202
235
  == Reference
203
236
 
204
237
 
205
238
  [+action+] Specify the action to take when a command is executed from the command line. This is only usable in a command block on the command object (e.g. <tt>c.action</tt>). This takes a block that yields three parameters: a hash of global options specified on the commandline, a hash of command-specific options specified on the command line, and an array of arguments parsed after the options were set on the command line. So, a command like <tt>git --git-dir=/tmp commit -a -m 'Foo bar' foo.c bar.c</tt> would result in the global hash containing <tt>:'git-dir' => '/tmp'</tt>, the options hash containing <tt>:a => true, :m => 'Foo bar'</tt> and the arguments array being <tt>['foo.c', 'bar.c']</tt>
206
239
  [+arg_name+] Describe the name of the argument to the next flag or command. This can be used at the global level or inside a command block on the command object (e.g. <tt>c.arg_name</tt>)
207
240
  [+config_file+] Name the configuration file for your applicaiton. This can either be an absolute path to where the applicaiton will find the configuration file, or a relative path, that will be interpretted as relative to the user's home directory. Default is +nil+, which means no configuration file will be used. Declaring this creates a special +initconfig+ command that can bootstrap this configuration file for your users.
208
- [+command+] Declare a command. This takes a symbol or array of symbols and a block. The block yields one argument, the command itself.
241
+ [+command+] Declare a command. This takes a symbol, String or array of symbols/Strings and a block. The block yields one argument, the command itself.
209
242
  [+default_value+] Indicate the default value of the next flag. This can be used at the global level or inside a command block on the command object (e.g. <tt>c.default_value</tt>)
210
243
  [+desc+] Describe the next flag, switch, or command you will declare. This can be used at the global level or inside a command block on the command object (e.g. <tt>c.desc</tt>)
211
- [+flag+] Declare a flag, which is a command line switch that takes an argument. This takes either a symbol or an array of symbols. The first symbol decared is used in your program to determine the flag's value at runtime. This can be used at the global level or inside a command block on the command object (e.g. <tt>c.flag</tt>)
244
+ [+flag+] Declare a flag, which is a command line switch that takes an argument. This takes either a symbol, String, or an array of symbols/Strings. The first symbol decared is used in your program to determine the flag's value at runtime. This can be used at the global level or inside a command block on the command object (e.g. <tt>c.flag</tt>)
212
245
  [+long_desc+] Provide a more lengthy description of the next flag, switch, or command you will declare. This will appear in command line output for commands when you get help for a command. For flags and switches, this will only appear in the generated rdoc and *not* on the command line. This can be used at the global level or inside a command block on the command object (e.g. <tt>c.long_desc</tt>)
213
246
  [+on_error+] Declare an error handling routine that will be called if any command (or other GLI processing) encouters an exception. This is a block that will receive the exception that was caught. All exceptions are routed through this block. If the block evaluates to true, the built-in error handling will be called after, otherwise, nothing will happen.
214
247
  [+post+] Declare code to run after every command that didn't experience an error. This is not available inside a command block. This takes a block that will receive four arguments: the global argument hash (as in <tt>action</tt>), the command (instance of Command), the command-specific options (as in <tt>action</tt>, and the parsed command line arguments (as in <tt>action</tt>).
215
248
  [+pre+] Declare code to run before every command. This is not available inside a command block. This takes a block that will receive four arguments: the global argument hash (as in <tt>action</tt>), the command (instance of Command), the command-specific options (as in <tt>action</tt>, and the parsed command line arguments (as in <tt>action</tt>). If this block evaluates to false, the command will not be executed and the program will stop.
216
- [+switch+] Declare a switch, which is a command-line switch taking no argument that indicates a boolean "true" when specified on the command line. This takes either a symbol or array of symbols. The first symbol declared is used in your program to determine if the switch was set. This can be used at the global level or inside a command block on the command object (e.g. <tt>c.switch</tt>)
249
+ [+switch+] Declare a switch, which is a command-line switch taking no argument that indicates a boolean "true" when specified on the command line. This takes either a symbol, String or array of symbols/Strings. The first symbol declared is used in your program to determine if the switch was set. This can be used at the global level or inside a command block on the command object (e.g. <tt>c.switch</tt>)
250
+ [+version+] Indicate the verison of your application/library. This is used by the default <tt>help</tt> command to allow users to see the version of your application.
217
251
 
218
252
  == Interface Generated
219
253
 
@@ -253,6 +287,16 @@ they start with a "--"
253
287
  :include:gli.rdoc
254
288
 
255
289
  :include:CHANGELOG.rdoc
290
+
291
+ == Developing
292
+
293
+ gem install bundler
294
+ bundle install
295
+ rake test
296
+ rake rcov
297
+
298
+ GLI currently has 100% test coverage, and I'd like to keep it that way. If you submit patches, please have a test, that makes it easier for me to know if anything's broken.
299
+
256
300
  == Links
257
301
 
258
302
  * [http://davetron5000.github.com/gli] - RubyDoc
data/bin/gli CHANGED
@@ -15,15 +15,14 @@ $: << File.expand_path(File.dirname(File.realpath(__FILE__)) + '/../lib')
15
15
 
16
16
  require 'gli'
17
17
  require 'support/scaffold'
18
+ require 'gli_version'
18
19
 
19
20
  include GLI
20
21
 
22
+ version GLI::VERSION
21
23
  desc 'Be verbose'
22
24
  switch :v
23
25
 
24
- desc 'Show version'
25
- switch :version
26
-
27
26
  desc 'Dry run; don''t change the disk'
28
27
  switch :n
29
28
 
@@ -60,13 +59,8 @@ command [:init,:scaffold] do |c|
60
59
  end
61
60
 
62
61
  pre do |global,command,options,args|
63
- if (!command || command.name == :help) && global[:version]
64
- puts "#{$0} v#{GLI::VERSION}"
65
- false
66
- else
67
- puts "Executing #{command.name}" if global[:v]
68
- true
69
- end
62
+ puts "Executing #{command.name}" if global[:v]
63
+ true
70
64
  end
71
65
 
72
66
  post do |global,command,options,args|
data/gli.rdoc CHANGED
@@ -24,6 +24,12 @@ These options are available for any command and are specified before the name of
24
24
 
25
25
  Shows list of commands or help for one command
26
26
 
27
+ Gets help for the application or its commands. Can also list the commands in a way helpful to creating a bash-style completion function
28
+
29
+ ==== Options
30
+ These options are specified *after* the command.
31
+
32
+ [<tt>-c, --completion</tt>] List all commands one line at a time, for use with shell completion ([command] argument is partial command to match)
27
33
  === <tt>init project_name [command[ command]*]</tt>
28
34
 
29
35
  Create a new GLI-based project
data/lib/gli.rb CHANGED
@@ -26,6 +26,7 @@ module GLI
26
26
  switches.clear
27
27
  flags.clear
28
28
  commands.clear
29
+ @@version = nil
29
30
  @@config_file = nil
30
31
  clear_nexts
31
32
  end
@@ -46,14 +47,18 @@ module GLI
46
47
 
47
48
  # Create a flag, which is a switch that takes an argument
48
49
  def flag(*names)
49
- flag = Flag.new([names].flatten,@@next_desc,@@next_arg_name,@@next_default_value,@@next_long_desc)
50
+ names = [names].flatten
51
+ verify_unused(names,flags,switches,"in global options")
52
+ flag = Flag.new(names,@@next_desc,@@next_arg_name,@@next_default_value,@@next_long_desc)
50
53
  flags[flag.name] = flag
51
54
  clear_nexts
52
55
  end
53
56
 
54
57
  # Create a switch
55
58
  def switch(*names)
56
- switch = Switch.new([names].flatten,@@next_desc,@@next_long_desc)
59
+ names = [names].flatten
60
+ verify_unused(names,flags,switches,"in global options")
61
+ switch = Switch.new(names,@@next_desc,@@next_long_desc)
57
62
  switches[switch.name] = switch
58
63
  clear_nexts
59
64
  end
@@ -103,14 +108,20 @@ module GLI
103
108
  @@error_block = a_proc
104
109
  end
105
110
 
111
+ # Indicate the version of your application
112
+ def version(version)
113
+ @@version = version
114
+ end
115
+
106
116
  # Runs whatever command is needed based on the arguments.
107
117
  def run(args)
108
118
  rdoc = RDocCommand.new
109
119
  commands[:rdoc] = rdoc if !commands[:rdoc]
110
- commands[:help] = DefaultHelpCommand.new(rdoc) if !commands[:help]
120
+ commands[:help] = DefaultHelpCommand.new(@@version,rdoc) if !commands[:help]
111
121
  begin
112
122
  config = parse_config
113
123
  global_options,command,options,arguments = parse_options(args,config)
124
+ copy_options_to_aliased_versions(global_options,command,options)
114
125
  proceed = true
115
126
  proceed = @@pre_block.call(global_options,command,options,arguments) if @@pre_block
116
127
  if proceed
@@ -123,9 +134,38 @@ module GLI
123
134
  regular_error_handling = @@error_block.call(ex) if @@error_block
124
135
 
125
136
  if regular_error_handling
126
- puts "error: #{ex.message}"
137
+ $stderr.puts "error: #{ex.message}"
138
+ end
139
+ end
140
+ end
141
+
142
+ # Copies all options in both global_options and options to keys for the aliases of those flags.
143
+ # For example, if a flag works with either -f or --flag, this will copy the value from [:f] to [:flag]
144
+ # to allow the user to access the options by any alias
145
+ def copy_options_to_aliased_versions(global_options,command,options)
146
+ copy_options_to_aliases(global_options,self)
147
+ copy_options_to_aliases(options,command)
148
+ end
149
+
150
+ # For each option in options, copies its value to keys for the aliases of the flags or
151
+ # switches in gli_like
152
+ #
153
+ # options - Hash of options parsed from command line; this is an I/O param
154
+ # gli_like - Object resonding to flags and switches in the same way that GLI or a Command instance do
155
+ def copy_options_to_aliases(options,gli_like)
156
+ new_options = {}
157
+ options.each do |key,value|
158
+ if gli_like.flags[key] && gli_like.flags[key].aliases
159
+ gli_like.flags[key].aliases.each do |alias_name|
160
+ new_options[alias_name] = value
161
+ end
162
+ elsif gli_like.switches[key] && gli_like.switches[key].aliases
163
+ gli_like.switches[key].aliases.each do |alias_name|
164
+ new_options[alias_name] = value
165
+ end
127
166
  end
128
167
  end
168
+ options.merge!(new_options)
129
169
  end
130
170
 
131
171
  def parse_config
@@ -320,4 +360,22 @@ module GLI
320
360
  nil
321
361
  end
322
362
 
363
+ # Checks that the names passed in have not been used in another flag or option
364
+ def verify_unused(names,flags,switches,context)
365
+ names.each do |name|
366
+ verify_unused_in_option(name,flags,"flag",context)
367
+ verify_unused_in_option(name,switches,"switch",context)
368
+ end
369
+ end
370
+
371
+ private
372
+
373
+ def verify_unused_in_option(name,option_like,type,context)
374
+ raise ArgumentError.new("#{name} has already been specified as a #{type} #{context}") if option_like[name]
375
+ option_like.each do |one_option_name,one_option|
376
+ if one_option.aliases
377
+ raise ArgumentError.new("#{name} has already been specified as an alias of #{type} #{one_option_name} #{context}") if one_option.aliases.include? name
378
+ end
379
+ end
380
+ end
323
381
  end
@@ -35,20 +35,26 @@ module GLI
35
35
 
36
36
  # describe the next switch or flag
37
37
  def desc(description); @next_desc = description; end
38
+ # long description of this flag/switch
39
+ def long_desc(long_desc); @next_long_desc = long_desc; end
38
40
  # describe the argument name of the next flag
39
41
  def arg_name(name); @next_arg_name = name; end
40
42
  # set the default value of the next flag
41
43
  def default_value(val); @next_default_value = val; end
42
44
 
43
45
  def flag(*names)
44
- flag = Flag.new([names].flatten,@next_desc,@next_arg_name,@next_default_value)
46
+ names = [names].flatten
47
+ GLI.verify_unused(names,flags,switches,"in command #{name}")
48
+ flag = Flag.new(names,@next_desc,@next_arg_name,@next_default_value,@next_long_desc)
45
49
  flags[flag.name] = flag
46
50
  clear_nexts
47
51
  end
48
52
 
49
53
  # Create a switch
50
54
  def switch(*names)
51
- switch = Switch.new([names].flatten,@next_desc)
55
+ names = [names].flatten
56
+ GLI.verify_unused(names,flags,switches,"in command #{name}")
57
+ switch = Switch.new(names,@next_desc,@next_long_desc)
52
58
  switches[switch.name] = switch
53
59
  clear_nexts
54
60
  end
@@ -65,6 +71,7 @@ module GLI
65
71
  @next_desc = nil
66
72
  @next_arg_name = nil
67
73
  @next_default_value = nil
74
+ @next_long_desc = nil
68
75
  end
69
76
 
70
77
  def execute(global_options,options,arguments)
@@ -34,9 +34,13 @@ module GLI
34
34
  # Handles dealing with the "names" param, parsing
35
35
  # it into the primary name and aliases list
36
36
  def parse_names(names)
37
+ # Allow strings; convert to symbols
38
+ names = [names].flatten.map(&:to_sym)
37
39
  names_hash = Hash.new
38
- names = names.is_a?(Array) ? names : [names]
39
- names.each { |n| names_hash[self.class.name_as_string(n)] = true }
40
+ names.each do |n|
41
+ raise ArgumentError.new("#{n} has spaces; they are not allowed") if n.to_s =~ /\s/
42
+ names_hash[self.class.name_as_string(n)] = true
43
+ end
40
44
  name = names.shift
41
45
  aliases = names.length > 0 ? names : nil
42
46
  [name,aliases,names_hash]
@@ -1,3 +1,3 @@
1
1
  module GLI
2
- VERSION = '1.1.3'
2
+ VERSION = '1.2.0'
3
3
  end
@@ -3,17 +3,43 @@ require 'gli/command'
3
3
 
4
4
  module GLI
5
5
  class DefaultHelpCommand < Command
6
- def initialize(*omit_from_list)
6
+ @@output = $stdout
7
+ # Exposed for testing :nodoc:
8
+ def self.output_device=(o); @@output = o; end
9
+
10
+ def initialize(version,*omit_from_list)
7
11
  @omit_from_list = omit_from_list
8
- super(:help,'Shows list of commands or help for one command','[command]')
12
+ @version = version
13
+ super(:help,
14
+ 'Shows list of commands or help for one command',
15
+ '[command]',
16
+ 'Gets help for the application or its commands. Can also list the commands in a way helpful to creating a bash-style completion function')
17
+ self.desc 'List all commands one line at a time, for use with shell completion ([command] argument is partial command to match)'
18
+ self.switch [:c,:completion]
9
19
  end
10
20
 
11
21
  def execute(global_options,options,arguments)
12
- if arguments.empty?
13
- list_global_flags
14
- list_commands
22
+ if options[:c]
23
+ names = commands_to_show.reduce([]) do |memo,obj|
24
+ memo << obj[0]
25
+ memo << obj[1].aliases
26
+ memo = memo.flatten
27
+ end
28
+ names.map!(&:to_s)
29
+ if arguments && arguments.size > 0
30
+ names = names.select { |name| name =~ /^#{arguments[0]}/ }
31
+ end
32
+ names.sort.each do |command|
33
+ next if command.empty?
34
+ @@output.puts command
35
+ end
15
36
  else
16
- list_one_command_help(arguments[0])
37
+ if arguments.empty?
38
+ list_global_flags
39
+ list_commands
40
+ else
41
+ list_one_command_help(arguments[0])
42
+ end
17
43
  end
18
44
  end
19
45
 
@@ -25,37 +51,44 @@ module GLI
25
51
  if !all_options.empty?
26
52
  usage += ' [options]'
27
53
  end
28
- puts usage
29
- puts
30
- puts 'Options:' if !all_options.empty?
54
+ @@output.puts usage
55
+ @@output.puts
56
+ if @version
57
+ @@output.puts "Version: #{@version}"
58
+ @@output.puts
59
+ end
60
+ @@output.puts 'Options:' if !all_options.empty?
31
61
  output_command_tokens_for_help(all_options)
32
- puts if !all_options.empty?
62
+ @@output.puts if !all_options.empty?
33
63
  end
34
64
 
35
65
  def list_commands
36
- puts 'Commands:'
37
- commands_to_show = GLI.commands.reject{ |name,c| @omit_from_list.include?(c) }
66
+ @@output.puts 'Commands:'
38
67
  output_command_tokens_for_help(commands_to_show,:names)
39
68
  end
40
69
 
70
+ def commands_to_show
71
+ GLI.commands.reject{ |name,c| @omit_from_list.include?(c) }
72
+ end
73
+
41
74
  def list_one_command_help(command_name)
42
75
  command = GLI.find_command(command_name)
43
76
  if command
44
- puts command.usage
77
+ @@output.puts command.usage
45
78
  description = wrap(command.description,4)
46
- puts " #{description}"
79
+ @@output.puts " #{description}"
47
80
  if command.long_description
48
- puts
49
- puts " #{wrap(command.long_description,4)}"
81
+ @@output.puts
82
+ @@output.puts " #{wrap(command.long_description,4)}"
50
83
  end
51
84
  all_options = command.switches.merge(command.flags)
52
85
  if !all_options.empty?
53
- puts
54
- puts "Options:"
86
+ @@output.puts
87
+ @@output.puts "Options:"
55
88
  output_command_tokens_for_help(all_options)
56
89
  end
57
90
  else
58
- puts "No such command #{command_name}"
91
+ @@output.puts "No such command #{command_name}"
59
92
  end
60
93
  end
61
94
 
@@ -75,7 +108,8 @@ module GLI
75
108
  description += " (default: #{token.default_value})" if token.default_value
76
109
  end
77
110
  description = wrap(description,max+7)
78
- printf " %-#{max}s - %s\n",token.send(usage_name),description
111
+ string = sprintf " %-#{max}s - %s",token.send(usage_name),description
112
+ @@output.puts string
79
113
  end
80
114
  end
81
115
  end
@@ -49,8 +49,8 @@ module GLI
49
49
  file << "\n"
50
50
  end
51
51
  all_options = command.switches.merge(command.flags)
52
+ file << "#{command.long_description}\n\n" if command.long_description
52
53
  if (all_options && all_options.length > 0)
53
- file << "#{command.long_description}\n\n"
54
54
  file << "==== Options\n"
55
55
  file << "These options are specified *after* the command.\n\n"
56
56
  output_flags(file,all_options)
@@ -68,7 +68,7 @@ module GLI
68
68
  file << "\n"
69
69
  if flag.long_description
70
70
  file << "\n"
71
- # 12 is 4 for tt, 5 for /tt, 2 for the brackets and 1 for spacing
71
+ # 12 is: 4 for tt, 5 for /tt, 2 for the brackets and 1 for spacing
72
72
  (flag.usage.length + 12).times { file << " " }
73
73
  file << "#{flag.long_description}\n\n"
74
74
  end
@@ -15,6 +15,7 @@ module GLI
15
15
  mk_readme(root_dir,dry_run,project_name)
16
16
  mk_gemspec(root_dir,dry_run,project_name)
17
17
  mk_rakefile(root_dir,dry_run,project_name,create_test_dir)
18
+ mk_version(root_dir,dry_run,project_name)
18
19
  end
19
20
  end
20
21
 
@@ -25,19 +26,23 @@ module GLI
25
26
  file << "Describe your project here\n\n"
26
27
  file << ":include:#{project_name}.rdoc\n\n"
27
28
  end
29
+ puts "Created #{root_dir}/#{project_name}/README.rdoc"
28
30
  File.open("#{root_dir}/#{project_name}/#{project_name}.rdoc",'w') do |file|
29
31
  file << "= #{project_name}\n\n"
30
32
  file << "Generate this with\n #{project_name} rdoc\nAfter you have described your command line interface"
31
33
  end
34
+ puts "Created #{root_dir}/#{project_name}/#{project_name}.rdoc"
32
35
  end
33
36
 
34
37
  def self.mk_gemspec(root_dir,dry_run,project_name)
35
38
  return if dry_run
36
39
  File.open("#{root_dir}/#{project_name}/#{project_name}.gemspec",'w') do |file|
37
40
  file.puts <<EOS
41
+ # Ensure we require the local version and not one we might have installed already
42
+ require File.join([File.dirname(__FILE__),'lib','#{project_name}_version.rb'])
38
43
  spec = Gem::Specification.new do |s|
39
44
  s.name = '#{project_name}'
40
- s.version = '0.0.01'
45
+ s.version = #{project_name_as_module_name(project_name)}::VERSION
41
46
  s.author = 'Your Name Here'
42
47
  s.email = 'your@email.address.com'
43
48
  s.homepage = 'http://your.website.com'
@@ -50,14 +55,30 @@ bin/#{project_name}
50
55
  s.require_paths << 'lib'
51
56
  s.has_rdoc = true
52
57
  s.extra_rdoc_files = ['README.rdoc','#{project_name}.rdoc']
53
- s.rdoc_options << '--title' << 'Git Like Interface' << '--main' << 'README.rdoc' << '-ri'
58
+ s.rdoc_options << '--title' << '#{project_name}' << '--main' << 'README.rdoc' << '-ri'
54
59
  s.bindir = 'bin'
55
60
  s.executables << '#{project_name}'
56
61
  end
57
62
  EOS
58
63
  end
64
+ puts "Created #{root_dir}/#{project_name}/#{project_name}.gemspec"
59
65
  end
60
66
 
67
+ def self.project_name_as_module_name(project_name)
68
+ project_name.split(/_/).map { |part| part[0..0].upcase + part[1..-1] }.join('')
69
+ end
70
+
71
+ def self.mk_version(root_dir,dry_run,project_name)
72
+ return if dry_run
73
+ File.open("#{root_dir}/#{project_name}/lib/#{project_name}_version.rb",'w') do |file|
74
+ file.puts <<EOS
75
+ module #{project_name_as_module_name(project_name)}
76
+ VERSION = '0.0.1'
77
+ end
78
+ EOS
79
+ end
80
+ puts "Created #{root_dir}/#{project_name}/lib/#{project_name}_version.rb"
81
+ end
61
82
  def self.mk_rakefile(root_dir,dry_run,project_name,create_test_dir)
62
83
  return if dry_run
63
84
  File.open("#{root_dir}/#{project_name}/Rakefile",'w') do |file|
@@ -108,10 +129,18 @@ class TC_testNothing < Test::Unit::TestCase
108
129
  end
109
130
  EOS
110
131
  end
132
+ puts "Created #{root_dir}/#{project_name}/test/tc_nothing.rb"
111
133
  else
112
134
  file.puts "task :default => :package\n"
113
135
  end
114
136
  end
137
+ puts "Created #{root_dir}/#{project_name}/Rakefile"
138
+ File.open("#{root_dir}/#{project_name}/Gemfile",'w') do |bundler_file|
139
+ bundler_file.puts "source :rubygems"
140
+ bundler_file.puts "gem: 'rake'"
141
+ bundler_file.puts "gem: 'rdoc'"
142
+ end
143
+ puts "Created #{root_dir}/#{project_name}/Gemfile"
115
144
  end
116
145
 
117
146
  def self.mk_binfile(root_dir,create_ext_dir,force,dry_run,project_name,commands)
@@ -139,9 +168,12 @@ EOS
139
168
  file.puts <<EOS
140
169
  require 'rubygems'
141
170
  require 'gli'
171
+ require '#{project_name}_version'
142
172
 
143
173
  include GLI
144
174
 
175
+ version #{project_name_as_module_name(project_name)}::VERSION
176
+
145
177
  desc 'Describe some switch here'
146
178
  switch [:s,:switch]
147
179
 
@@ -165,7 +197,7 @@ command :#{command} do |c|
165
197
 
166
198
  c.desc 'Describe a flag to #{command}'
167
199
  c.default_value 'default'
168
- c.flag :s
200
+ c.flag :f
169
201
  c.action do |global_options,options,args|
170
202
 
171
203
  # Your command logic here
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gli
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 31
4
5
  prerelease: false
5
6
  segments:
6
7
  - 1
7
- - 1
8
- - 3
9
- version: 1.1.3
8
+ - 2
9
+ - 0
10
+ version: 1.2.0
10
11
  platform: ruby
11
12
  authors:
12
13
  - David Copeland
@@ -14,7 +15,7 @@ autorequire:
14
15
  bindir: bin
15
16
  cert_chain: []
16
17
 
17
- date: 2010-10-24 00:00:00 -04:00
18
+ date: 2010-11-26 00:00:00 -05:00
18
19
  default_executable:
19
20
  dependencies: []
20
21
 
@@ -63,6 +64,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
63
64
  requirements:
64
65
  - - ">="
65
66
  - !ruby/object:Gem::Version
67
+ hash: 3
66
68
  segments:
67
69
  - 0
68
70
  version: "0"
@@ -71,6 +73,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
71
73
  requirements:
72
74
  - - ">="
73
75
  - !ruby/object:Gem::Version
76
+ hash: 3
74
77
  segments:
75
78
  - 0
76
79
  version: "0"