gli 1.2.5 → 1.2.6
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +1 -1
- data/bin/gli +1 -1
- data/gli.rdoc +0 -1
- data/lib/gli.rb +168 -71
- data/lib/gli/command.rb +48 -21
- data/lib/gli/command_line_token.rb +8 -7
- data/lib/gli/exceptions.rb +22 -5
- data/lib/gli/flag.rb +1 -1
- data/lib/gli/options.rb +3 -0
- data/lib/gli/switch.rb +3 -3
- data/lib/gli/terminal.rb +14 -7
- data/lib/gli_version.rb +1 -1
- data/lib/support/help.rb +8 -6
- data/lib/support/initconfig.rb +2 -3
- data/lib/support/rdoc.rb +40 -3
- data/lib/support/scaffold.rb +7 -6
- metadata +77 -8
data/README.rdoc
CHANGED
@@ -39,7 +39,7 @@ Though likely works on various other versions.
|
|
39
39
|
|
40
40
|
== Documentation
|
41
41
|
|
42
|
-
Extensive documentation is {available at the wiki}[https://github.com/davetron5000/gli/wiki]
|
42
|
+
Extensive documentation is {available at the wiki}[https://github.com/davetron5000/gli/wiki]. For API Documentation, start with the GLI module.
|
43
43
|
|
44
44
|
== Links
|
45
45
|
|
data/bin/gli
CHANGED
data/gli.rdoc
CHANGED
@@ -15,7 +15,6 @@ These options are available for any command and are specified before the name of
|
|
15
15
|
This is the directory where the projects directory will be made, so if you specify a project name foo and the root dir of ., the directory ./foo will be created
|
16
16
|
|
17
17
|
[<tt>-v</tt>] Be verbose
|
18
|
-
[<tt>--version</tt>] Show version
|
19
18
|
== Commands
|
20
19
|
[<tt>help</tt>] Shows list of commands or help for one command
|
21
20
|
[<tt>init</tt>] Create a new GLI-based project
|
data/lib/gli.rb
CHANGED
@@ -23,9 +23,15 @@ module GLI
|
|
23
23
|
@@config_file = nil
|
24
24
|
@@use_openstruct = false
|
25
25
|
@@version = nil
|
26
|
+
@@stderr = $stderr
|
26
27
|
|
27
|
-
#
|
28
|
-
def
|
28
|
+
# Override the device of stderr; exposed only for testing
|
29
|
+
def error_device=(e) #:nodoc:
|
30
|
+
@@stderr = e
|
31
|
+
end
|
32
|
+
|
33
|
+
# Reset the GLI module internal data structures; mostly useful for testing
|
34
|
+
def reset # :nodoc:
|
29
35
|
switches.clear
|
30
36
|
flags.clear
|
31
37
|
commands.clear
|
@@ -35,21 +41,51 @@ module GLI
|
|
35
41
|
clear_nexts
|
36
42
|
end
|
37
43
|
|
38
|
-
#
|
44
|
+
# Describe the next switch, flag, or command. This should be a
|
39
45
|
# short, one-line description
|
46
|
+
#
|
47
|
+
# +description+:: A String of the short descripiton of the switch, flag, or command following
|
40
48
|
def desc(description); @@next_desc = description; end
|
41
49
|
|
42
50
|
# Provide a longer, more detailed description. This
|
43
|
-
# will be reformatted and wrapped to fit in
|
51
|
+
# will be reformatted and wrapped to fit in the terminal's columns
|
52
|
+
#
|
53
|
+
# +long_desc+:: A String that is s longer description of the switch, flag, or command following.
|
44
54
|
def long_desc(long_desc); @@next_long_desc = long_desc; end
|
45
55
|
|
46
|
-
#
|
56
|
+
# Describe the argument name of the next flag. It's important to keep
|
57
|
+
# this VERY short and, ideally, without any spaces (see Example).
|
58
|
+
#
|
59
|
+
# +name+:: A String that *briefly* describes the argument given to the following command or flag.
|
60
|
+
#
|
61
|
+
# Example:
|
62
|
+
# desc 'Set the filename'
|
63
|
+
# arg_name 'file_name'
|
64
|
+
# flag [:f,:filename]
|
65
|
+
#
|
66
|
+
# Produces:
|
67
|
+
# -f, --filename=file_name Set the filename
|
47
68
|
def arg_name(name); @@next_arg_name = name; end
|
48
69
|
|
49
70
|
# set the default value of the next flag
|
71
|
+
#
|
72
|
+
# +val+:: A String reprensenting the default value to be used for the following flag if the user doesn't specify one
|
73
|
+
# and, when using a config file, the config also doesn't specify one
|
50
74
|
def default_value(val); @@next_default_value = val; end
|
51
75
|
|
52
76
|
# Create a flag, which is a switch that takes an argument
|
77
|
+
#
|
78
|
+
# +names+:: a String or Symbol, or an Array of String or Symbol that represent all the different names
|
79
|
+
# and aliases for this flag.
|
80
|
+
#
|
81
|
+
# Example:
|
82
|
+
#
|
83
|
+
# desc 'Set the filename'
|
84
|
+
# flag [:f,:filename,'file-name']
|
85
|
+
#
|
86
|
+
# Produces:
|
87
|
+
#
|
88
|
+
# -f, --filename, --file-name=arg Set the filename
|
53
89
|
def flag(*names)
|
54
90
|
names = [names].flatten
|
55
91
|
verify_unused(names,flags,switches,"in global options")
|
@@ -58,7 +94,10 @@ module GLI
|
|
58
94
|
clear_nexts
|
59
95
|
end
|
60
96
|
|
61
|
-
# Create a switch
|
97
|
+
# Create a switch, which is a command line flag that takes no arguments (thus, it _switches_ something on)
|
98
|
+
#
|
99
|
+
# +names+:: a String or Symbol, or an Array of String or Symbol that represent all the different names
|
100
|
+
# and aliases for this switch.
|
62
101
|
def switch(*names)
|
63
102
|
names = [names].flatten
|
64
103
|
verify_unused(names,flags,switches,"in global options")
|
@@ -67,8 +106,11 @@ module GLI
|
|
67
106
|
clear_nexts
|
68
107
|
end
|
69
108
|
|
70
|
-
# Sets
|
71
|
-
#
|
109
|
+
# Sets that this app uses a config file as well as the name of the config file.
|
110
|
+
#
|
111
|
+
# +filename+:: A String representing the path to the file to use for the config file. If it's an absolute
|
112
|
+
# path, this is treated as the path to the file. If it's *not*, it's treated as relative to the user's home
|
113
|
+
# directory as produced by <code>Etc.getpwuid.dir</code>.
|
72
114
|
def config_file(filename)
|
73
115
|
if filename =~ /^\//
|
74
116
|
@@config_file = filename
|
@@ -79,7 +121,11 @@ module GLI
|
|
79
121
|
@@config_file
|
80
122
|
end
|
81
123
|
|
82
|
-
# Define a command.
|
124
|
+
# Define a new command. This takes a block that will be given an instance of the Command that was created.
|
125
|
+
# You then may call methods on this object to define aspects of that Command.
|
126
|
+
#
|
127
|
+
# +names+:: a String or Symbol, or an Array of String or Symbol that represent all the different names and aliases for this command.
|
128
|
+
#
|
83
129
|
def command(*names)
|
84
130
|
command = Command.new([names].flatten,@@next_desc,@@next_arg_name,@@next_long_desc)
|
85
131
|
commands[command.name] = command
|
@@ -97,8 +143,8 @@ module GLI
|
|
97
143
|
@@pre_block = a_proc
|
98
144
|
end
|
99
145
|
|
100
|
-
# Define a block to run after command
|
101
|
-
# if there was not an error
|
146
|
+
# Define a block to run after the command was executed, <b>only
|
147
|
+
# if there was not an error</b>.
|
102
148
|
# The block will receive the global-options,command,options, and arguments
|
103
149
|
def post(&a_proc)
|
104
150
|
@@post_block = a_proc
|
@@ -106,65 +152,103 @@ module GLI
|
|
106
152
|
|
107
153
|
# Define a block to run if an error occurs.
|
108
154
|
# The block will receive any Exception that was caught.
|
109
|
-
# It should
|
110
|
-
# prints out a message)
|
155
|
+
# It should evaluate to false to avoid the built-in error handling (which basically just
|
156
|
+
# prints out a message). GLI uses a variety of exceptions that you can use to find out what
|
157
|
+
# errors might've occurred during command-line parsing:
|
158
|
+
# * GLI::CustomExit
|
159
|
+
# * GLI::UnknownCommandArgument
|
160
|
+
# * GLI::UnknownGlobalArgument
|
161
|
+
# * GLI::UnknownCommand
|
162
|
+
# * GLI::BadCommandLine
|
111
163
|
def on_error(&a_proc)
|
112
164
|
@@error_block = a_proc
|
113
165
|
end
|
114
166
|
|
115
167
|
# Indicate the version of your application
|
168
|
+
#
|
169
|
+
# +version+:: String containing the version of your application.
|
116
170
|
def version(version)
|
117
171
|
@@version = version
|
118
172
|
end
|
119
173
|
|
120
|
-
# Call this with
|
121
|
-
#
|
122
|
-
#
|
174
|
+
# Call this with +true+ will cause the +global_options+ and
|
175
|
+
# +options+ passed to your code to be wrapped in
|
176
|
+
# Options, which is a subclass of +OpenStruct+ that adds
|
123
177
|
# <tt>[]</tt> and <tt>[]=</tt> methods.
|
178
|
+
#
|
179
|
+
# +use_openstruct+:: a Boolean indicating if we should use OpenStruct instead of Hashes
|
124
180
|
def use_openstruct(use_openstruct)
|
125
181
|
@@use_openstruct = use_openstruct
|
126
182
|
end
|
127
183
|
|
128
184
|
# Runs whatever command is needed based on the arguments.
|
129
185
|
#
|
130
|
-
# args
|
186
|
+
# +args+:: the command line ARGV array
|
131
187
|
#
|
132
188
|
# Returns a number that would be a reasonable exit code
|
133
|
-
def run(args)
|
189
|
+
def run(args) #:nodoc:
|
134
190
|
rdoc = RDocCommand.new
|
135
191
|
commands[:rdoc] = rdoc if !commands[:rdoc]
|
136
192
|
commands[:help] = DefaultHelpCommand.new(@@version,rdoc) if !commands[:help]
|
193
|
+
exit_code = 0
|
137
194
|
begin
|
138
195
|
config = parse_config
|
139
196
|
global_options,command,options,arguments = parse_options(args,config)
|
140
197
|
copy_options_to_aliased_versions(global_options,command,options)
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
proceed = @@pre_block.call(global_options,command,options,arguments) if @@pre_block
|
145
|
-
if proceed
|
198
|
+
global_options = convert_to_openstruct?(global_options)
|
199
|
+
options = convert_to_openstruct?(options)
|
200
|
+
if proceed?(global_options,command,options,arguments)
|
146
201
|
command = commands[:help] if !command
|
147
202
|
command.execute(global_options,options,arguments)
|
148
203
|
@@post_block.call(global_options,command,options,arguments) if @@post_block
|
149
204
|
end
|
150
|
-
0
|
151
205
|
rescue Exception => ex
|
152
|
-
regular_error_handling = true
|
153
|
-
regular_error_handling = @@error_block.call(ex) if @@error_block
|
154
206
|
|
155
|
-
if regular_error_handling
|
156
|
-
$stderr.puts "error: #{ex.message}"
|
157
|
-
end
|
207
|
+
@@stderr.puts error_message(ex) if regular_error_handling?(ex)
|
158
208
|
|
159
209
|
raise ex if ENV['GLI_DEBUG'] == 'true'
|
160
210
|
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
else
|
211
|
+
exit_code = if ex.respond_to? :exit_code
|
212
|
+
ex.exit_code
|
213
|
+
else
|
165
214
|
-2
|
166
215
|
end
|
167
216
|
end
|
217
|
+
exit_code
|
218
|
+
end
|
219
|
+
|
220
|
+
# True if we should proceed with executing the command; this calls
|
221
|
+
# the pre block if it's defined
|
222
|
+
def proceed?(global_options,command,options,arguments) #:nodoc:
|
223
|
+
if @@pre_block
|
224
|
+
@@pre_block.call(global_options,command,options,arguments)
|
225
|
+
else
|
226
|
+
true
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
# Returns true if we should proceed with GLI's basic error handling.
|
231
|
+
# This calls the error block if the user provided one
|
232
|
+
def regular_error_handling?(ex) #:nodoc:
|
233
|
+
if @@error_block
|
234
|
+
@@error_block.call(ex)
|
235
|
+
else
|
236
|
+
true
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
# Returns a String of the error message to show the user
|
241
|
+
# +ex+:: The exception we caught that launched the error handling routines
|
242
|
+
def error_message(ex) #:nodoc:
|
243
|
+
msg = "error: #{ex.message}"
|
244
|
+
case ex
|
245
|
+
when UnknownCommand
|
246
|
+
msg += ". Use '#{program_name} help' for a list of commands"
|
247
|
+
when UnknownCommandArgument
|
248
|
+
msg += ". Use '#{program_name} help #{ex.command.name}' for a list of command options"
|
249
|
+
when UnknownGlobalArgument
|
250
|
+
msg += ". Use '#{program_name} help' for a list of global options"
|
251
|
+
end
|
168
252
|
end
|
169
253
|
|
170
254
|
# Simpler means of exiting with a custom exit code. This will
|
@@ -174,17 +258,36 @@ module GLI
|
|
174
258
|
raise CustomExit.new(message,exit_code)
|
175
259
|
end
|
176
260
|
|
261
|
+
# Set or get the name of the program, if you don't want the default (which is
|
262
|
+
# the name of the command line program). This
|
263
|
+
# is only used currently in the help and rdoc commands.
|
264
|
+
#
|
265
|
+
# +override+:: A String that represents the name of the program to use, other than the default.
|
266
|
+
#
|
267
|
+
# Returns the current program name, as a String
|
268
|
+
def program_name(override=nil)
|
269
|
+
if override
|
270
|
+
@@program_name = override
|
271
|
+
end
|
272
|
+
@@program_name
|
273
|
+
end
|
274
|
+
|
275
|
+
alias :d :desc
|
276
|
+
alias :f :flag
|
277
|
+
alias :s :switch
|
278
|
+
alias :c :command
|
279
|
+
|
177
280
|
# Possibly returns a copy of the passed-in Hash as an instance of GLI::Option.
|
178
|
-
# By default, it will *not
|
281
|
+
# By default, it will *not*. However by putting <tt>use_openstruct true</tt>
|
179
282
|
# in your CLI definition, it will
|
180
|
-
def
|
283
|
+
def convert_to_openstruct?(options) # :nodoc:
|
181
284
|
@@use_openstruct ? Options.new(options) : options
|
182
285
|
end
|
183
286
|
|
184
287
|
# Copies all options in both global_options and options to keys for the aliases of those flags.
|
185
288
|
# For example, if a flag works with either -f or --flag, this will copy the value from [:f] to [:flag]
|
186
289
|
# to allow the user to access the options by any alias
|
187
|
-
def copy_options_to_aliased_versions(global_options,command,options)
|
290
|
+
def copy_options_to_aliased_versions(global_options,command,options) # :nodoc:
|
188
291
|
copy_options_to_aliases(global_options,self)
|
189
292
|
copy_options_to_aliases(options,command)
|
190
293
|
end
|
@@ -194,7 +297,7 @@ module GLI
|
|
194
297
|
#
|
195
298
|
# options - Hash of options parsed from command line; this is an I/O param
|
196
299
|
# gli_like - Object resonding to flags and switches in the same way that GLI or a Command instance do
|
197
|
-
def copy_options_to_aliases(options,gli_like)
|
300
|
+
def copy_options_to_aliases(options,gli_like) # :nodoc:
|
198
301
|
new_options = {}
|
199
302
|
options.each do |key,value|
|
200
303
|
if gli_like.flags[key] && gli_like.flags[key].aliases
|
@@ -210,7 +313,7 @@ module GLI
|
|
210
313
|
options.merge!(new_options)
|
211
314
|
end
|
212
315
|
|
213
|
-
def parse_config
|
316
|
+
def parse_config # :nodoc:
|
214
317
|
return nil if @@config_file.nil?
|
215
318
|
require 'yaml'
|
216
319
|
if File.exist?(@@config_file)
|
@@ -220,19 +323,12 @@ module GLI
|
|
220
323
|
end
|
221
324
|
end
|
222
325
|
|
223
|
-
def program_name(override=nil)
|
224
|
-
if override
|
225
|
-
@@program_name = override
|
226
|
-
end
|
227
|
-
@@program_name
|
228
|
-
end
|
229
|
-
|
230
326
|
# Returns an array of four values:
|
231
327
|
# * global options (as a Hash)
|
232
328
|
# * Command
|
233
329
|
# * command options (as a Hash)
|
234
330
|
# * arguments (as an Array)
|
235
|
-
def parse_options(args,config=nil)
|
331
|
+
def parse_options(args,config=nil) # :nodoc:
|
236
332
|
command_configs = {}
|
237
333
|
if config.nil?
|
238
334
|
config = {}
|
@@ -247,7 +343,7 @@ module GLI
|
|
247
343
|
|
248
344
|
# Finds the index of the first non-flag
|
249
345
|
# argument or -1 if there wasn't one.
|
250
|
-
def find_non_flag_index(args)
|
346
|
+
def find_non_flag_index(args) # :nodoc:
|
251
347
|
args.each_index do |i|
|
252
348
|
return i if args[i] =~ /^[^\-]/;
|
253
349
|
return i-1 if args[i] =~ /^\-\-$/;
|
@@ -255,12 +351,7 @@ module GLI
|
|
255
351
|
-1;
|
256
352
|
end
|
257
353
|
|
258
|
-
|
259
|
-
alias :f :flag
|
260
|
-
alias :s :switch
|
261
|
-
alias :c :command
|
262
|
-
|
263
|
-
def clear_nexts
|
354
|
+
def clear_nexts # :nodoc:
|
264
355
|
@@next_desc = nil
|
265
356
|
@@next_arg_name = nil
|
266
357
|
@@next_default_value = nil
|
@@ -269,17 +360,23 @@ module GLI
|
|
269
360
|
|
270
361
|
clear_nexts
|
271
362
|
|
272
|
-
def flags
|
273
|
-
|
274
|
-
|
363
|
+
def flags # :nodoc:
|
364
|
+
@@flags ||= {}
|
365
|
+
end
|
366
|
+
def switches # :nodoc:
|
367
|
+
@@switches ||= {}
|
368
|
+
end
|
369
|
+
def commands # :nodoc:
|
370
|
+
@@commands ||= {}
|
371
|
+
end
|
275
372
|
|
276
373
|
# Recursive helper for parsing command line options
|
277
|
-
#
|
278
|
-
#
|
279
|
-
#
|
280
|
-
#
|
281
|
-
#
|
282
|
-
#
|
374
|
+
# <code>args</code>:: the arguments that have yet to be processed
|
375
|
+
# <code>global_options</code>:: the global options hash
|
376
|
+
# <code>command</code>:: the Command that has been identified (or nil if not identified yet)
|
377
|
+
# <code>command_options</code>:: options for Command
|
378
|
+
# <code>arguments</code>:: the arguments for Command
|
379
|
+
# <code>command_configs</code>:: the configuration file for all commands, used as defaults
|
283
380
|
#
|
284
381
|
# This works by finding the first non-switch/flag argument, and taking that sublist and trying to pick out
|
285
382
|
# flags and switches. After this is done, one of the following is true:
|
@@ -292,7 +389,7 @@ module GLI
|
|
292
389
|
#
|
293
390
|
# Once the command has been found, we start looking for command-specific flags and switches.
|
294
391
|
# When those have been found, we know the rest of the argument list is arguments for the command
|
295
|
-
def parse_options_helper(args,global_options,command,command_options,arguments,command_configs)
|
392
|
+
def parse_options_helper(args,global_options,command,command_options,arguments,command_configs) # :nodoc:
|
296
393
|
non_flag_i = find_non_flag_index(args)
|
297
394
|
all_flags = false
|
298
395
|
if non_flag_i == 0
|
@@ -300,7 +397,7 @@ module GLI
|
|
300
397
|
if !command
|
301
398
|
command_name = args.shift
|
302
399
|
command = find_command(command_name)
|
303
|
-
raise
|
400
|
+
raise UnknownCommand.new("Unknown command '#{command_name}'") if !command
|
304
401
|
return parse_options_helper(args,
|
305
402
|
global_options,
|
306
403
|
command,
|
@@ -366,16 +463,16 @@ module GLI
|
|
366
463
|
try_me.delete arg
|
367
464
|
break
|
368
465
|
end
|
369
|
-
raise
|
466
|
+
raise UnknownCommandArgument.new("Unknown option #{arg}",command) if arg =~ /^\-/
|
370
467
|
end
|
371
468
|
return [global_options,command,command_options,try_me + rest]
|
372
469
|
else
|
373
470
|
# Now we have our command name
|
374
471
|
command_name = try_me.shift
|
375
|
-
raise
|
472
|
+
raise UnknownGlobalArgument.new("Unknown option #{command_name}") if command_name =~ /^\-/
|
376
473
|
|
377
474
|
command = find_command(command_name)
|
378
|
-
raise
|
475
|
+
raise UnknownCommand.new("Unknown command '#{command_name}'") if !command
|
379
476
|
|
380
477
|
return parse_options_helper(rest,
|
381
478
|
global_options,
|
@@ -388,11 +485,11 @@ module GLI
|
|
388
485
|
|
389
486
|
end
|
390
487
|
|
391
|
-
def default_command_options(command,command_configs)
|
488
|
+
def default_command_options(command,command_configs) # :nodoc:
|
392
489
|
options = (command_configs && command_configs[command.name.to_sym]) || {}
|
393
490
|
end
|
394
491
|
|
395
|
-
def find_command(name)
|
492
|
+
def find_command(name) # :nodoc:
|
396
493
|
sym = name.to_sym
|
397
494
|
return commands[name.to_sym] if commands[sym]
|
398
495
|
commands.keys.each do |command_name|
|
@@ -403,7 +500,7 @@ module GLI
|
|
403
500
|
end
|
404
501
|
|
405
502
|
# Checks that the names passed in have not been used in another flag or option
|
406
|
-
def verify_unused(names,flags,switches,context)
|
503
|
+
def verify_unused(names,flags,switches,context) # :nodoc:
|
407
504
|
names.each do |name|
|
408
505
|
verify_unused_in_option(name,flags,"flag",context)
|
409
506
|
verify_unused_in_option(name,switches,"switch",context)
|
@@ -412,7 +509,7 @@ module GLI
|
|
412
509
|
|
413
510
|
private
|
414
511
|
|
415
|
-
def verify_unused_in_option(name,option_like,type,context)
|
512
|
+
def verify_unused_in_option(name,option_like,type,context) # :nodoc:
|
416
513
|
raise ArgumentError.new("#{name} has already been specified as a #{type} #{context}") if option_like[name]
|
417
514
|
option_like.each do |one_option_name,one_option|
|
418
515
|
if one_option.aliases
|
data/lib/gli/command.rb
CHANGED
@@ -1,47 +1,62 @@
|
|
1
1
|
require 'gli/command_line_token.rb'
|
2
2
|
|
3
3
|
module GLI
|
4
|
-
# A command to be run, in context of global flags and switches
|
4
|
+
# A command to be run, in context of global flags and switches. You are given an instance of this class
|
5
|
+
# to the block you use for GLI#command. You then use the methods described here to describe the
|
6
|
+
# command-specific command-line arguments, much as you use the methods in GLI to describe the global
|
7
|
+
# command-line interface
|
5
8
|
class Command < CommandLineToken
|
6
9
|
|
7
10
|
# Create a new command
|
8
11
|
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
def initialize(names,description,arguments_name=nil,long_desc=nil)
|
12
|
+
# +names+:: A String, Symbol, or Array of String or Symbol that represents the name(s) of this command.
|
13
|
+
# +description+:: short description of this command as a Strign
|
14
|
+
# +arguments_name+:: description of the arguments as a String, or nil if this command doesn't take arguments
|
15
|
+
# +long_desc+:: a longer description of the command, possibly with multiple lines and text formatting
|
16
|
+
def initialize(names,description,arguments_name=nil,long_desc=nil) # :nodoc:
|
15
17
|
super(names,description,long_desc)
|
16
18
|
@arguments_description = arguments_name || ''
|
17
19
|
clear_nexts
|
18
20
|
end
|
19
21
|
|
20
|
-
|
22
|
+
# Return the arguments description
|
23
|
+
def arguments_description #:nodoc:
|
24
|
+
@arguments_description
|
25
|
+
end
|
21
26
|
|
22
|
-
|
27
|
+
# Return the Array of the command's names
|
28
|
+
def names #:nodoc:
|
23
29
|
all_forms
|
24
30
|
end
|
25
31
|
|
26
|
-
|
32
|
+
# Get the usage string
|
33
|
+
# CR: This should probably not be here
|
34
|
+
def usage #:nodoc:
|
27
35
|
usage = name.to_s
|
28
|
-
usage += ' [options]' if !flags.empty? || !switches.empty?
|
36
|
+
usage += ' [command options]' if !flags.empty? || !switches.empty?
|
29
37
|
usage += ' ' + @arguments_description if @arguments_description
|
30
38
|
usage
|
31
39
|
end
|
32
40
|
|
33
|
-
|
34
|
-
def
|
41
|
+
# Return the flags as a Hash
|
42
|
+
def flags #:nodoc:
|
43
|
+
@flags ||= {}
|
44
|
+
end
|
45
|
+
# Return the switches as a Hash
|
46
|
+
def switches #:nodoc:
|
47
|
+
@switches ||= {}
|
48
|
+
end
|
35
49
|
|
36
|
-
# describe the next switch or flag
|
50
|
+
# describe the next switch or flag just as GLI#desc does.
|
37
51
|
def desc(description); @next_desc = description; end
|
38
|
-
# long description of this flag/switch
|
52
|
+
# set the long description of this flag/switch, just as GLI#long_desc does.
|
39
53
|
def long_desc(long_desc); @next_long_desc = long_desc; end
|
40
|
-
# describe the argument name of the next flag
|
54
|
+
# describe the argument name of the next flag, just as GLI#arg_name does.
|
41
55
|
def arg_name(name); @next_arg_name = name; end
|
42
|
-
# set the default value of the next flag
|
56
|
+
# set the default value of the next flag, just as GLI#default_value does.
|
43
57
|
def default_value(val); @next_default_value = val; end
|
44
58
|
|
59
|
+
# Create a command-specific flag, similar to GLI#flag
|
45
60
|
def flag(*names)
|
46
61
|
names = [names].flatten
|
47
62
|
GLI.verify_unused(names,flags,switches,"in command #{name}")
|
@@ -50,7 +65,7 @@ module GLI
|
|
50
65
|
clear_nexts
|
51
66
|
end
|
52
67
|
|
53
|
-
# Create a switch
|
68
|
+
# Create a command-specific switch, similar to GLI#switch
|
54
69
|
def switch(*names)
|
55
70
|
names = [names].flatten
|
56
71
|
GLI.verify_unused(names,flags,switches,"in command #{name}")
|
@@ -59,22 +74,34 @@ module GLI
|
|
59
74
|
clear_nexts
|
60
75
|
end
|
61
76
|
|
77
|
+
# Define the action to take when the user executes this command
|
78
|
+
#
|
79
|
+
# +block+:: A block of code to execute. The block will be given 3 arguments:
|
80
|
+
# +global_options+:: A Hash (or Options, see GLI#use_openstruct) of the _global_ options specified
|
81
|
+
# by the user, with defaults set and config file values used (if using a config file, see
|
82
|
+
# GLI#config_file)
|
83
|
+
# +options+:: A Hash (or Options, see GLI#use_openstruct) of the command-specific options specified by the
|
84
|
+
# user, with defaults set and config file values used (if using a config file, see GLI#config_file)
|
85
|
+
# +arguments+:: An Array of Strings representing the unparsed command line arguments
|
86
|
+
# The block's result value is not used; raise an exception or use GLI#exit_now! if you need an early exit based
|
87
|
+
# on an error condition
|
62
88
|
def action(&block)
|
63
89
|
@action = block
|
64
90
|
end
|
65
91
|
|
66
|
-
def self.name_as_string(name)
|
92
|
+
def self.name_as_string(name) #:nodoc:
|
67
93
|
name.to_s
|
68
94
|
end
|
69
95
|
|
70
|
-
def clear_nexts
|
96
|
+
def clear_nexts #:nodoc:
|
71
97
|
@next_desc = nil
|
72
98
|
@next_arg_name = nil
|
73
99
|
@next_default_value = nil
|
74
100
|
@next_long_desc = nil
|
75
101
|
end
|
76
102
|
|
77
|
-
|
103
|
+
# Executes the command
|
104
|
+
def execute(global_options,options,arguments) #:nodoc:
|
78
105
|
@action.call(global_options,options,arguments)
|
79
106
|
end
|
80
107
|
end
|
@@ -1,22 +1,23 @@
|
|
1
1
|
module GLI
|
2
|
-
#
|
2
|
+
# Abstract base class for a logical element of a command line, mostly so that subclasses can have similar
|
3
3
|
# initialization and interface
|
4
4
|
class CommandLineToken
|
5
|
-
attr_reader :name
|
6
|
-
attr_reader :aliases
|
7
|
-
attr_reader :description
|
8
|
-
attr_reader :long_description
|
5
|
+
attr_reader :name #:ndoc:
|
6
|
+
attr_reader :aliases #:ndoc:
|
7
|
+
attr_reader :description #:ndoc:
|
8
|
+
attr_reader :long_description #:ndoc:
|
9
9
|
|
10
|
-
def initialize(names,description,long_description=nil)
|
10
|
+
def initialize(names,description,long_description=nil) #:ndoc:
|
11
11
|
@description = description
|
12
12
|
@long_description = long_description
|
13
13
|
@name,@aliases,@names = parse_names(names)
|
14
14
|
end
|
15
15
|
|
16
|
-
def usage
|
16
|
+
def usage #:nodoc:
|
17
17
|
all_forms
|
18
18
|
end
|
19
19
|
|
20
|
+
# Sort based on name
|
20
21
|
def <=>(other)
|
21
22
|
self.name.to_s <=> other.name.to_s
|
22
23
|
end
|
data/lib/gli/exceptions.rb
CHANGED
@@ -1,13 +1,30 @@
|
|
1
1
|
module GLI
|
2
2
|
# Indicates that the command line invocation was bad
|
3
3
|
class BadCommandLine < Exception
|
4
|
-
def
|
4
|
+
def exit_code; -1; end
|
5
|
+
end
|
6
|
+
|
7
|
+
# Indicates the bad command line was an unknown command
|
8
|
+
class UnknownCommand < BadCommandLine
|
9
|
+
end
|
10
|
+
|
11
|
+
# Indicates the bad command line was an unknown global argument
|
12
|
+
class UnknownGlobalArgument < BadCommandLine
|
13
|
+
end
|
14
|
+
|
15
|
+
# Indicates the bad command line was an unknown command argument
|
16
|
+
class UnknownCommandArgument < BadCommandLine
|
17
|
+
attr_reader :command
|
18
|
+
# +message+:: the error message to show the user
|
19
|
+
# +command+:: the command we were using to parse command-specific options
|
20
|
+
def initialize(message,command)
|
5
21
|
super(message)
|
22
|
+
@command = command
|
6
23
|
end
|
7
24
|
end
|
8
25
|
|
9
26
|
# Raise this if you want to use an exit status that isn't the default
|
10
|
-
# provided by GLI.
|
27
|
+
# provided by GLI. Note that GLI#exit_now! might be a bit more to your liking.
|
11
28
|
#
|
12
29
|
# Example:
|
13
30
|
#
|
@@ -15,11 +32,11 @@ module GLI
|
|
15
32
|
# raise CustomExit.new("Bad SQL",-6) unless valid_sql?(args[0])
|
16
33
|
#
|
17
34
|
class CustomExit < Exception
|
18
|
-
attr_reader :exit_code
|
35
|
+
attr_reader :exit_code #:nodoc:
|
19
36
|
# Create a custom exit exception
|
20
37
|
#
|
21
|
-
# message
|
22
|
-
# exit_code
|
38
|
+
# +message+:: String containing error message to show the user
|
39
|
+
# +exit_code+:: the exit code to use (as an Int), overridding GLI's default
|
23
40
|
def initialize(message,exit_code)
|
24
41
|
super(message)
|
25
42
|
@exit_code = exit_code
|
data/lib/gli/flag.rb
CHANGED
data/lib/gli/options.rb
CHANGED
@@ -1,12 +1,15 @@
|
|
1
1
|
require 'ostruct'
|
2
2
|
|
3
3
|
module GLI
|
4
|
+
# Subclass of OpenStruct that provides hash-like methods for #[] and #[]=. Note that is is *not* a Hash.
|
4
5
|
class Options < OpenStruct
|
5
6
|
|
7
|
+
# Return the value of an attribute
|
6
8
|
def[](k)
|
7
9
|
@table[k.to_sym]
|
8
10
|
end
|
9
11
|
|
12
|
+
# Set the value of an attribute
|
10
13
|
def[]=(k, v)
|
11
14
|
@table[k.to_sym] = v
|
12
15
|
end
|
data/lib/gli/switch.rb
CHANGED
@@ -2,7 +2,7 @@ require 'gli/command_line_token.rb'
|
|
2
2
|
|
3
3
|
module GLI
|
4
4
|
# Defines a command line switch
|
5
|
-
class Switch < CommandLineToken
|
5
|
+
class Switch < CommandLineToken #:nodoc:
|
6
6
|
|
7
7
|
def initialize(names,description,long_desc=nil)
|
8
8
|
super(names,description,long_desc)
|
@@ -28,8 +28,8 @@ module GLI
|
|
28
28
|
|
29
29
|
# Finds the switch in the given arg, returning the arg to keep.
|
30
30
|
# Returns an array of size 2:
|
31
|
-
#
|
32
|
-
#
|
31
|
+
# index 0:: true or false if the arg was found
|
32
|
+
# index 1:: the remaining arg to keep in the command line or nil to remove it
|
33
33
|
def find_me(arg)
|
34
34
|
if @names[arg]
|
35
35
|
return [true,nil]
|
data/lib/gli/terminal.rb
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
module GLI
|
2
|
-
# Class to encapsulate stuff about the terminal.
|
2
|
+
# Class to encapsulate stuff about the terminal. This is useful to application developers
|
3
|
+
# as a canonical means to get information about the user's current terminal configuraiton.
|
4
|
+
# GLI uses this to determine the number of columns to use when printing to the screen.
|
5
|
+
#
|
6
|
+
# To access it, use Terminal#instance. This is a singleton mostly to facilitate testing, but
|
7
|
+
# it seems reasonable enough, since there's only one terminal in effect
|
3
8
|
#
|
4
9
|
# Example:
|
5
10
|
#
|
@@ -20,29 +25,31 @@ module GLI
|
|
20
25
|
|
21
26
|
# Set the default size of the terminal to use when we can't figure it out
|
22
27
|
#
|
23
|
-
# size
|
28
|
+
# +size+:: array of two int [cols,rows]
|
24
29
|
def self.default_size=(size)
|
25
30
|
@@default_size = size
|
26
31
|
end
|
27
32
|
|
28
|
-
# Provide access to the shared instance
|
33
|
+
# Provide access to the shared instance.
|
29
34
|
def self.instance; @@instance ||= Terminal.new; end
|
30
35
|
|
31
36
|
# Call this to cause methods to throw exceptions rather than return a sane default. You
|
32
37
|
# probably don't want to call this unless you are writing tests
|
33
|
-
def make_unsafe
|
38
|
+
def make_unsafe!
|
34
39
|
@unsafe = true
|
35
40
|
end
|
36
41
|
|
37
42
|
# Returns true if the given command exists on this system
|
38
43
|
#
|
39
|
-
# command
|
44
|
+
# +command+:: The command, as a String, to check for, without any path information.
|
40
45
|
def command_exists?(command)
|
41
46
|
ENV['PATH'].split(File::PATH_SEPARATOR).any? {|d| File.exists? File.join(d, command) }
|
42
47
|
end
|
43
48
|
|
44
|
-
#
|
45
|
-
#
|
49
|
+
# Get the size of the current terminal.
|
50
|
+
# Ripped from hirb[https://github.com/cldwalker/hirb/blob/master/lib/hirb/util.rb]
|
51
|
+
#
|
52
|
+
# Returns an Array of size two Ints representing the terminal width and height
|
46
53
|
def size
|
47
54
|
if (ENV['COLUMNS'] =~ /^\d+$/) && (ENV['LINES'] =~ /^\d+$/)
|
48
55
|
[ENV['COLUMNS'].to_i, ENV['LINES'].to_i]
|
data/lib/gli_version.rb
CHANGED
data/lib/support/help.rb
CHANGED
@@ -3,9 +3,9 @@ require 'gli/command'
|
|
3
3
|
require 'gli/terminal'
|
4
4
|
|
5
5
|
module GLI
|
6
|
-
class DefaultHelpCommand < Command
|
6
|
+
class DefaultHelpCommand < Command #:nodoc:
|
7
7
|
@@output = $stdout
|
8
|
-
# Exposed for testing
|
8
|
+
# Exposed for testing
|
9
9
|
def self.output_device=(o); @@output = o; end
|
10
10
|
|
11
11
|
def initialize(version,*omit_from_list)
|
@@ -47,18 +47,20 @@ module GLI
|
|
47
47
|
private
|
48
48
|
|
49
49
|
def list_global_flags
|
50
|
-
usage = "usage: #{GLI.program_name}
|
50
|
+
usage = "usage: #{GLI.program_name} "
|
51
51
|
all_options = GLI.switches.merge(GLI.flags)
|
52
52
|
if !all_options.empty?
|
53
|
-
|
53
|
+
usage += "[global options] "
|
54
54
|
end
|
55
|
+
usage += "command"
|
56
|
+
usage += ' [command options]'
|
55
57
|
@@output.puts usage
|
56
58
|
@@output.puts
|
57
59
|
if @version
|
58
60
|
@@output.puts "Version: #{@version}"
|
59
61
|
@@output.puts
|
60
62
|
end
|
61
|
-
@@output.puts 'Options:' if !all_options.empty?
|
63
|
+
@@output.puts 'Global Options:' if !all_options.empty?
|
62
64
|
output_command_tokens_for_help(all_options)
|
63
65
|
@@output.puts if !all_options.empty?
|
64
66
|
end
|
@@ -85,7 +87,7 @@ module GLI
|
|
85
87
|
all_options = command.switches.merge(command.flags)
|
86
88
|
if !all_options.empty?
|
87
89
|
@@output.puts
|
88
|
-
@@output.puts "Options:"
|
90
|
+
@@output.puts "Command Options:"
|
89
91
|
output_command_tokens_for_help(all_options)
|
90
92
|
end
|
91
93
|
else
|
data/lib/support/initconfig.rb
CHANGED
@@ -3,7 +3,7 @@ require 'gli/command'
|
|
3
3
|
require 'yaml'
|
4
4
|
|
5
5
|
module GLI
|
6
|
-
class InitConfig < Command
|
6
|
+
class InitConfig < Command # :nodoc:
|
7
7
|
COMMANDS_KEY = 'commands'
|
8
8
|
|
9
9
|
def initialize(config_file_name)
|
@@ -27,8 +27,7 @@ module GLI
|
|
27
27
|
YAML.dump(config,file)
|
28
28
|
end
|
29
29
|
else
|
30
|
-
|
31
|
-
puts 'Use --force to override'
|
30
|
+
raise "Not overwriting existing config file #{@filename}, use --force to override"
|
32
31
|
end
|
33
32
|
end
|
34
33
|
end
|
data/lib/support/rdoc.rb
CHANGED
@@ -2,13 +2,50 @@ require 'gli'
|
|
2
2
|
require 'fileutils'
|
3
3
|
|
4
4
|
module GLI
|
5
|
-
class RDocCommand < Command
|
5
|
+
class RDocCommand < Command # :nodoc:
|
6
6
|
|
7
7
|
def initialize
|
8
|
-
super(:rdoc,'Generates RDoc for your command line interface')
|
8
|
+
super(:rdoc,'Generates RDoc (and other types of documentation) for your command line interface')
|
9
|
+
self.desc 'Create a very basic scaffold for a cheat-style cheatsheet, in addition to rdoc'
|
10
|
+
self.switch 'cheatsheet'
|
11
|
+
self.desc 'Include a manapage suitable for gem man, in addition to rdoc'
|
12
|
+
self.switch 'manpage'
|
13
|
+
self.desc 'Do not create rdoc'
|
14
|
+
self.switch 'no-rdoc'
|
9
15
|
end
|
10
16
|
|
11
|
-
def execute(g,
|
17
|
+
def execute(g,options,a)
|
18
|
+
create_rdoc unless options[:'no-rdoc']
|
19
|
+
create_manpage if options[:manpage]
|
20
|
+
create_cheatsheet if options[:cheatsheet]
|
21
|
+
end
|
22
|
+
|
23
|
+
def create_cheatsheet
|
24
|
+
File.open("#{GLI.program_name}.cheat",'w') do |file|
|
25
|
+
file << GLI.program_name
|
26
|
+
file << "\n"
|
27
|
+
file << GLI.program_name.length.times.inject("") { |a,x| a + "=" }
|
28
|
+
file << "\n"
|
29
|
+
file << "\n"
|
30
|
+
file << "Installation:\n"
|
31
|
+
file << "$ gem install #{GLI.program_name}\n\n"
|
32
|
+
GLI.commands.values.sort.each do |command|
|
33
|
+
next if command == self
|
34
|
+
file << command.description
|
35
|
+
file << "\n"
|
36
|
+
[command.name,command.aliases].flatten.each do |name|
|
37
|
+
next unless name
|
38
|
+
file << "$ #{GLI.program_name} #{name} #{command.arguments_description}\n"
|
39
|
+
end
|
40
|
+
file << "\n"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def create_manpage
|
46
|
+
end
|
47
|
+
|
48
|
+
def create_rdoc
|
12
49
|
File.open("#{GLI.program_name}.rdoc",'w') do |file|
|
13
50
|
file << "= <tt>#{GLI.program_name}</tt>\n\n"
|
14
51
|
file << " "
|
data/lib/support/scaffold.rb
CHANGED
@@ -2,7 +2,7 @@ require 'gli'
|
|
2
2
|
require 'fileutils'
|
3
3
|
|
4
4
|
module GLI
|
5
|
-
class Scaffold
|
5
|
+
class Scaffold #:nodoc:
|
6
6
|
|
7
7
|
def self.create_scaffold(root_dir,create_test_dir,create_ext_dir,project_name,commands,force=false,dry_run=false)
|
8
8
|
dirs = [File.join(root_dir,project_name,'lib')]
|
@@ -58,6 +58,8 @@ bin/#{project_name}
|
|
58
58
|
s.rdoc_options << '--title' << '#{project_name}' << '--main' << 'README.rdoc' << '-ri'
|
59
59
|
s.bindir = 'bin'
|
60
60
|
s.executables << '#{project_name}'
|
61
|
+
s.add_development_dependency('rake')
|
62
|
+
s.add_development_dependency('rdoc')
|
61
63
|
end
|
62
64
|
EOS
|
63
65
|
end
|
@@ -137,8 +139,7 @@ EOS
|
|
137
139
|
puts "Created #{root_dir}/#{project_name}/Rakefile"
|
138
140
|
File.open("#{root_dir}/#{project_name}/Gemfile",'w') do |bundler_file|
|
139
141
|
bundler_file.puts "source :rubygems"
|
140
|
-
bundler_file.puts "
|
141
|
-
bundler_file.puts "gem: 'rdoc'"
|
142
|
+
bundler_file.puts "gemspec"
|
142
143
|
end
|
143
144
|
puts "Created #{root_dir}/#{project_name}/Gemfile"
|
144
145
|
end
|
@@ -155,7 +156,7 @@ EOS
|
|
155
156
|
# have this method, so we add it so we get resolved symlinks
|
156
157
|
# and compatibility
|
157
158
|
unless File.respond_to? :realpath
|
158
|
-
class File
|
159
|
+
class File #:nodoc:
|
159
160
|
def self.realpath path
|
160
161
|
return realpath(File.readlink(path)) if symlink?(path)
|
161
162
|
path
|
@@ -253,7 +254,7 @@ EOS
|
|
253
254
|
if !force
|
254
255
|
dirs.each do |dir|
|
255
256
|
if File.exist? dir
|
256
|
-
|
257
|
+
raise "#{dir} exists; use --force to override"
|
257
258
|
exists = true
|
258
259
|
end
|
259
260
|
end
|
@@ -262,7 +263,7 @@ EOS
|
|
262
263
|
dirs.each do |dir|
|
263
264
|
puts "Creating dir #{dir}..."
|
264
265
|
if dry_run
|
265
|
-
|
266
|
+
puts "dry-run; #{dir} not created"
|
266
267
|
else
|
267
268
|
FileUtils.mkdir_p dir
|
268
269
|
end
|
metadata
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash: 21
|
5
4
|
prerelease: false
|
6
5
|
segments:
|
7
6
|
- 1
|
8
7
|
- 2
|
9
|
-
-
|
10
|
-
version: 1.2.
|
8
|
+
- 6
|
9
|
+
version: 1.2.6
|
11
10
|
platform: ruby
|
12
11
|
authors:
|
13
12
|
- David Copeland
|
@@ -15,10 +14,82 @@ autorequire:
|
|
15
14
|
bindir: bin
|
16
15
|
cert_chain: []
|
17
16
|
|
18
|
-
date:
|
17
|
+
date: 2011-03-06 00:00:00 -05:00
|
19
18
|
default_executable:
|
20
|
-
dependencies:
|
21
|
-
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: rake
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
segments:
|
29
|
+
- 0
|
30
|
+
- 8
|
31
|
+
- 7
|
32
|
+
version: 0.8.7
|
33
|
+
type: :development
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: rcov
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
segments:
|
44
|
+
- 0
|
45
|
+
- 9
|
46
|
+
- 8
|
47
|
+
version: 0.9.8
|
48
|
+
type: :development
|
49
|
+
version_requirements: *id002
|
50
|
+
- !ruby/object:Gem::Dependency
|
51
|
+
name: rdoc
|
52
|
+
prerelease: false
|
53
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
54
|
+
none: false
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
segments:
|
59
|
+
- 2
|
60
|
+
- 4
|
61
|
+
- 3
|
62
|
+
version: 2.4.3
|
63
|
+
type: :development
|
64
|
+
version_requirements: *id003
|
65
|
+
- !ruby/object:Gem::Dependency
|
66
|
+
name: sdoc
|
67
|
+
prerelease: false
|
68
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
69
|
+
none: false
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
segments:
|
74
|
+
- 0
|
75
|
+
- 2
|
76
|
+
- 20
|
77
|
+
version: 0.2.20
|
78
|
+
type: :development
|
79
|
+
version_requirements: *id004
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: grancher
|
82
|
+
prerelease: false
|
83
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
84
|
+
none: false
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
segments:
|
89
|
+
- 0
|
90
|
+
version: "0"
|
91
|
+
type: :development
|
92
|
+
version_requirements: *id005
|
22
93
|
description: An application and API for describing command line interfaces that can be used to quickly create a shell for executing command-line tasks. The command line user interface is similar to Gits, in that it takes global options, a command, command-specific options, and arguments
|
23
94
|
email: davidcopeland@naildrivin5.com
|
24
95
|
executables:
|
@@ -64,7 +135,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
64
135
|
requirements:
|
65
136
|
- - ">="
|
66
137
|
- !ruby/object:Gem::Version
|
67
|
-
hash: 3
|
68
138
|
segments:
|
69
139
|
- 0
|
70
140
|
version: "0"
|
@@ -73,7 +143,6 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
73
143
|
requirements:
|
74
144
|
- - ">="
|
75
145
|
- !ruby/object:Gem::Version
|
76
|
-
hash: 3
|
77
146
|
segments:
|
78
147
|
- 0
|
79
148
|
version: "0"
|