gli 1.2.2 → 1.2.5
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +2 -1
- data/lib/gli.rb +27 -5
- data/lib/gli/exceptions.rb +28 -0
- data/lib/gli/flag.rb +2 -2
- data/lib/gli/terminal.rb +72 -0
- data/lib/gli_version.rb +1 -1
- data/lib/support/help.rb +5 -1
- data/lib/support/scaffold.rb +1 -1
- metadata +8 -5
- data/CHANGELOG.rdoc +0 -25
data/README.rdoc
CHANGED
@@ -13,7 +13,7 @@ This is a DSL you can use to create a command line interface like git, gem or sv
|
|
13
13
|
|
14
14
|
Install if you need to:
|
15
15
|
|
16
|
-
|
16
|
+
gem install gli
|
17
17
|
|
18
18
|
The simplest way to get started is to create a scaffold project
|
19
19
|
|
@@ -46,5 +46,6 @@ Extensive documentation is {available at the wiki}[https://github.com/davetron50
|
|
46
46
|
* [http://davetron5000.github.com/gli] - RubyDoc
|
47
47
|
* [http://www.github.com/davetron5000/gli] - Source on GitHub
|
48
48
|
* [http://www.github.com/davetron5000/gli/wiki] - Documentation Wiki
|
49
|
+
* [http://www.github.com/davetron5000/gli/wiki/Changelog] - Changelog
|
49
50
|
|
50
51
|
:include:gli.rdoc
|
data/lib/gli.rb
CHANGED
@@ -3,6 +3,7 @@ require 'gli/command.rb'
|
|
3
3
|
require 'gli/switch.rb'
|
4
4
|
require 'gli/flag.rb'
|
5
5
|
require 'gli/options.rb'
|
6
|
+
require 'gli/exceptions.rb'
|
6
7
|
require 'gli_version.rb'
|
7
8
|
require 'support/help.rb'
|
8
9
|
require 'support/rdoc.rb'
|
@@ -124,7 +125,11 @@ module GLI
|
|
124
125
|
@@use_openstruct = use_openstruct
|
125
126
|
end
|
126
127
|
|
127
|
-
# Runs whatever command is needed based on the arguments.
|
128
|
+
# Runs whatever command is needed based on the arguments.
|
129
|
+
#
|
130
|
+
# args - the command line ARGV array
|
131
|
+
#
|
132
|
+
# Returns a number that would be a reasonable exit code
|
128
133
|
def run(args)
|
129
134
|
rdoc = RDocCommand.new
|
130
135
|
commands[:rdoc] = rdoc if !commands[:rdoc]
|
@@ -142,6 +147,7 @@ module GLI
|
|
142
147
|
command.execute(global_options,options,arguments)
|
143
148
|
@@post_block.call(global_options,command,options,arguments) if @@post_block
|
144
149
|
end
|
150
|
+
0
|
145
151
|
rescue Exception => ex
|
146
152
|
regular_error_handling = true
|
147
153
|
regular_error_handling = @@error_block.call(ex) if @@error_block
|
@@ -149,9 +155,25 @@ module GLI
|
|
149
155
|
if regular_error_handling
|
150
156
|
$stderr.puts "error: #{ex.message}"
|
151
157
|
end
|
158
|
+
|
159
|
+
raise ex if ENV['GLI_DEBUG'] == 'true'
|
160
|
+
|
161
|
+
case ex
|
162
|
+
when BadCommandLine then -1
|
163
|
+
when CustomExit then ex.exit_code
|
164
|
+
else
|
165
|
+
-2
|
166
|
+
end
|
152
167
|
end
|
153
168
|
end
|
154
169
|
|
170
|
+
# Simpler means of exiting with a custom exit code. This will
|
171
|
+
# raise a CustomExit with the given message and exit code, which will ultimatley
|
172
|
+
# cause your application to exit with the given exit_code as its exit status
|
173
|
+
def exit_now!(message,exit_code)
|
174
|
+
raise CustomExit.new(message,exit_code)
|
175
|
+
end
|
176
|
+
|
155
177
|
# Possibly returns a copy of the passed-in Hash as an instance of GLI::Option.
|
156
178
|
# By default, it will *not*, however by putting <tt>use_openstruct true</tt>
|
157
179
|
# in your CLI definition, it will
|
@@ -278,7 +300,7 @@ module GLI
|
|
278
300
|
if !command
|
279
301
|
command_name = args.shift
|
280
302
|
command = find_command(command_name)
|
281
|
-
raise "Unknown command '#{command_name}'" if !command
|
303
|
+
raise BadCommandLine.new("Unknown command '#{command_name}'") if !command
|
282
304
|
return parse_options_helper(args,
|
283
305
|
global_options,
|
284
306
|
command,
|
@@ -344,16 +366,16 @@ module GLI
|
|
344
366
|
try_me.delete arg
|
345
367
|
break
|
346
368
|
end
|
347
|
-
raise "Unknown argument #{arg}" if arg =~ /^\-/
|
369
|
+
raise BadCommandLine.new("Unknown argument #{arg}") if arg =~ /^\-/
|
348
370
|
end
|
349
371
|
return [global_options,command,command_options,try_me + rest]
|
350
372
|
else
|
351
373
|
# Now we have our command name
|
352
374
|
command_name = try_me.shift
|
353
|
-
raise "Unknown argument #{command_name}" if command_name =~ /^\-/
|
375
|
+
raise BadCommandLine.new("Unknown argument #{command_name}") if command_name =~ /^\-/
|
354
376
|
|
355
377
|
command = find_command(command_name)
|
356
|
-
raise "Unknown command '#{command_name}'" if !command
|
378
|
+
raise BadCommandLine.new("Unknown command '#{command_name}'") if !command
|
357
379
|
|
358
380
|
return parse_options_helper(rest,
|
359
381
|
global_options,
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module GLI
|
2
|
+
# Indicates that the command line invocation was bad
|
3
|
+
class BadCommandLine < Exception
|
4
|
+
def initialize(message)
|
5
|
+
super(message)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
# Raise this if you want to use an exit status that isn't the default
|
10
|
+
# provided by GLI.
|
11
|
+
#
|
12
|
+
# Example:
|
13
|
+
#
|
14
|
+
# raise CustomExit.new("Not connected to DB",-5) unless connected?
|
15
|
+
# raise CustomExit.new("Bad SQL",-6) unless valid_sql?(args[0])
|
16
|
+
#
|
17
|
+
class CustomExit < Exception
|
18
|
+
attr_reader :exit_code
|
19
|
+
# Create a custom exit exception
|
20
|
+
#
|
21
|
+
# message - String containing error message to show the user
|
22
|
+
# exit_code - the exit code to use, overridding GLI's default
|
23
|
+
def initialize(message,exit_code)
|
24
|
+
super(message)
|
25
|
+
@exit_code = exit_code
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/gli/flag.rb
CHANGED
@@ -24,7 +24,7 @@ module GLI
|
|
24
24
|
args.delete_at index
|
25
25
|
return value
|
26
26
|
else
|
27
|
-
raise "#{matched} requires an argument"
|
27
|
+
raise BadCommandLine.new("#{matched} requires an argument")
|
28
28
|
end
|
29
29
|
else
|
30
30
|
return value
|
@@ -38,7 +38,7 @@ module GLI
|
|
38
38
|
if @names[arg]
|
39
39
|
return [true,arg,nil] if arg.length == 2
|
40
40
|
# This means we matched the long-form, but there's no argument
|
41
|
-
raise "#{arg} requires an argument via #{arg}=argument"
|
41
|
+
raise BadCommandLine.new("#{arg} requires an argument via #{arg}=argument")
|
42
42
|
end
|
43
43
|
@names.keys.each() do |name|
|
44
44
|
match_string = "^#{name}=(.*)$"
|
data/lib/gli/terminal.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
module GLI
|
2
|
+
# Class to encapsulate stuff about the terminal. This is a singleton, mostly to facilitate testing.
|
3
|
+
#
|
4
|
+
# Example:
|
5
|
+
#
|
6
|
+
# Terminal.instance.size[0] # => columns in the terminal
|
7
|
+
# Terminal.default_size = [128,24] # => change default when we can't figure it out
|
8
|
+
# raise "no ls?!?!?" unless Terminal.instance.command_exists?("ls")
|
9
|
+
#
|
10
|
+
class Terminal
|
11
|
+
|
12
|
+
@@default_size = [80,24]
|
13
|
+
|
14
|
+
# Get the default size of the terminal when we can't figure it out
|
15
|
+
#
|
16
|
+
# Returns an array of int [cols,rows]
|
17
|
+
def self.default_size
|
18
|
+
@@default_size
|
19
|
+
end
|
20
|
+
|
21
|
+
# Set the default size of the terminal to use when we can't figure it out
|
22
|
+
#
|
23
|
+
# size - array of two int [cols,rows]
|
24
|
+
def self.default_size=(size)
|
25
|
+
@@default_size = size
|
26
|
+
end
|
27
|
+
|
28
|
+
# Provide access to the shared instance
|
29
|
+
def self.instance; @@instance ||= Terminal.new; end
|
30
|
+
|
31
|
+
# Call this to cause methods to throw exceptions rather than return a sane default. You
|
32
|
+
# probably don't want to call this unless you are writing tests
|
33
|
+
def make_unsafe!;
|
34
|
+
@unsafe = true
|
35
|
+
end
|
36
|
+
|
37
|
+
# Returns true if the given command exists on this system
|
38
|
+
#
|
39
|
+
# command - The command to check for
|
40
|
+
def command_exists?(command)
|
41
|
+
ENV['PATH'].split(File::PATH_SEPARATOR).any? {|d| File.exists? File.join(d, command) }
|
42
|
+
end
|
43
|
+
|
44
|
+
# Ripped from hirb https://github.com/cldwalker/hirb/blob/master/lib/hirb/util.rb
|
45
|
+
# Returns an array of size two ints representing the terminal width and height
|
46
|
+
def size
|
47
|
+
if (ENV['COLUMNS'] =~ /^\d+$/) && (ENV['LINES'] =~ /^\d+$/)
|
48
|
+
[ENV['COLUMNS'].to_i, ENV['LINES'].to_i]
|
49
|
+
elsif (jruby? || (!STDIN.tty? && ENV['TERM'])) && command_exists?('tput')
|
50
|
+
[run_command('tput cols').to_i, run_command('tput lines').to_i]
|
51
|
+
elsif STDIN.tty? && command_exists?('stty')
|
52
|
+
run_command('stty size').scan(/\d+/).map { |s| s.to_i }.reverse
|
53
|
+
else
|
54
|
+
Terminal.default_size
|
55
|
+
end
|
56
|
+
rescue Exception => ex
|
57
|
+
raise ex if @unsafe
|
58
|
+
Terminal.default_size
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
# Runs a command using backticks. Extracted to allow for testing
|
64
|
+
def run_command(command)
|
65
|
+
`#{command}`
|
66
|
+
end
|
67
|
+
|
68
|
+
# True if we are JRuby; exposed to allow for testing
|
69
|
+
def jruby?; RUBY_PLATFORM =~ /java/; end
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
data/lib/gli_version.rb
CHANGED
data/lib/support/help.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'gli'
|
2
2
|
require 'gli/command'
|
3
|
+
require 'gli/terminal'
|
3
4
|
|
4
5
|
module GLI
|
5
6
|
class DefaultHelpCommand < Command
|
@@ -119,7 +120,10 @@ module GLI
|
|
119
120
|
# Wraps the line at the given column length, using the given line padding.
|
120
121
|
# Assumes that the first line doesn't need the padding, as its filled
|
121
122
|
# up with other stuff
|
122
|
-
def wrap(line,pad_length=0,line_length=
|
123
|
+
def wrap(line,pad_length=0,line_length=nil)
|
124
|
+
if line_length.nil?
|
125
|
+
line_length = Terminal.instance.size[0]
|
126
|
+
end
|
123
127
|
line_padding = sprintf("%#{pad_length}s",'')
|
124
128
|
words = line.split(/\s+/)
|
125
129
|
return line if !words || words.empty?
|
data/lib/support/scaffold.rb
CHANGED
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: 21
|
4
5
|
prerelease: false
|
5
6
|
segments:
|
6
7
|
- 1
|
7
8
|
- 2
|
8
|
-
-
|
9
|
-
version: 1.2.
|
9
|
+
- 5
|
10
|
+
version: 1.2.5
|
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-12-
|
18
|
+
date: 2010-12-12 00:00:00 -05:00
|
18
19
|
default_executable:
|
19
20
|
dependencies: []
|
20
21
|
|
@@ -27,13 +28,14 @@ extensions: []
|
|
27
28
|
extra_rdoc_files:
|
28
29
|
- README.rdoc
|
29
30
|
- gli.rdoc
|
30
|
-
- CHANGELOG.rdoc
|
31
31
|
files:
|
32
32
|
- lib/gli/command.rb
|
33
33
|
- lib/gli/command_line_token.rb
|
34
34
|
- lib/gli/flag.rb
|
35
35
|
- lib/gli/switch.rb
|
36
36
|
- lib/gli/options.rb
|
37
|
+
- lib/gli/exceptions.rb
|
38
|
+
- lib/gli/terminal.rb
|
37
39
|
- lib/gli.rb
|
38
40
|
- lib/gli_version.rb
|
39
41
|
- lib/support/help.rb
|
@@ -43,7 +45,6 @@ files:
|
|
43
45
|
- bin/gli
|
44
46
|
- README.rdoc
|
45
47
|
- gli.rdoc
|
46
|
-
- CHANGELOG.rdoc
|
47
48
|
has_rdoc: true
|
48
49
|
homepage: http://davetron5000.github.com/gli
|
49
50
|
licenses: []
|
@@ -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"
|
data/CHANGELOG.rdoc
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
== Changelog
|
2
|
-
=== 1.2.2 - 12/11/2010
|
3
|
-
|
4
|
-
* Changed uses of <code>map(&:symbol)</code> to older form, since this doesn't work on 100% of Ruby 1.8.7s.
|
5
|
-
|
6
|
-
=== 1.2.1 - 11/26/2010
|
7
|
-
|
8
|
-
* Changed default data structure of options *back* to a <tt>Hash</tt>. If you want to use the <tt>OpenStruct</tt> subclass <tt>Options</tt>, simply put <tt>use_openstruct true</tt> in your command line definition.
|
9
|
-
|
10
|
-
=== 1.2.0 - 11/26/2010
|
11
|
-
|
12
|
-
* Added ability to use +help+ command to list commands suitable for creating bash completion script
|
13
|
-
* <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>.
|
14
|
-
* 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.
|
15
|
-
* <tt>long_desc</tt> now shows up in generated rdoc for flags and switches
|
16
|
-
* Scaffoling now generates a usable <code>Gemfile</code> for bundler
|
17
|
-
* More direct support for version numbers in GLI-managed apps
|
18
|
-
|
19
|
-
=== 1.1.3 - 10/24/2010
|
20
|
-
|
21
|
-
* 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
|
22
|
-
|
23
|
-
=== 0.0 - 1.1.2
|
24
|
-
|
25
|
-
No changelog tracking was done for these versions :(
|