gli 1.1.3 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +9 -0
- data/README.rdoc +54 -10
- data/bin/gli +4 -10
- data/gli.rdoc +6 -0
- data/lib/gli.rb +62 -4
- data/lib/gli/command.rb +9 -2
- data/lib/gli/command_line_token.rb +6 -2
- data/lib/gli_version.rb +1 -1
- data/lib/support/help.rb +54 -20
- data/lib/support/rdoc.rb +2 -2
- data/lib/support/scaffold.rb +35 -3
- metadata +7 -4
data/CHANGELOG.rdoc
CHANGED
@@ -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
|
data/README.rdoc
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
64
|
-
|
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
|
-
|
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
|
-
|
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
|
data/lib/gli/command.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
39
|
-
|
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]
|
data/lib/gli_version.rb
CHANGED
data/lib/support/help.rb
CHANGED
@@ -3,17 +3,43 @@ require 'gli/command'
|
|
3
3
|
|
4
4
|
module GLI
|
5
5
|
class DefaultHelpCommand < Command
|
6
|
-
|
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
|
-
|
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
|
13
|
-
|
14
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
111
|
+
string = sprintf " %-#{max}s - %s",token.send(usage_name),description
|
112
|
+
@@output.puts string
|
79
113
|
end
|
80
114
|
end
|
81
115
|
end
|
data/lib/support/rdoc.rb
CHANGED
@@ -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
|
data/lib/support/scaffold.rb
CHANGED
@@ -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 =
|
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' << '
|
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 :
|
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
|
-
-
|
8
|
-
-
|
9
|
-
version: 1.
|
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-
|
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"
|