delano-drydock 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE.txt +22 -0
- data/README.rdoc +57 -0
- data/bin/example +170 -0
- data/lib/drydock/exceptions.rb +24 -0
- data/lib/drydock.rb +232 -0
- metadata +64 -0
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2008 Delano Mandelbaum
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person
|
4
|
+
obtaining a copy of this software and associated documentation
|
5
|
+
files (the "Software"), to deal in the Software without
|
6
|
+
restriction, including without limitation the rights to use,
|
7
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
copies of the Software, and to permit persons to whom the
|
9
|
+
Software is furnished to do so, subject to the following
|
10
|
+
conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
17
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
19
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
20
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
21
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
= Drydock - Easy Command line apps
|
2
|
+
|
3
|
+
Inspired by "github-gem":http://github.com/defunkt/github-gem
|
4
|
+
|
5
|
+
Inspired by "bmizerany-frylock":http://github.com/bmizerany/frylock/tree
|
6
|
+
|
7
|
+
== Overview
|
8
|
+
|
9
|
+
Drydock is a DSL for command line apps.
|
10
|
+
|
11
|
+
== Install
|
12
|
+
|
13
|
+
git clone git://github.com/delano/drydock.git
|
14
|
+
|
15
|
+
|
16
|
+
== Examples
|
17
|
+
|
18
|
+
See bin/example for more.
|
19
|
+
|
20
|
+
<pre><code>
|
21
|
+
require 'rubygems'
|
22
|
+
require 'drydock'
|
23
|
+
|
24
|
+
default :welcome
|
25
|
+
|
26
|
+
before do
|
27
|
+
# You can execute a block before the requests command is executed. Instance
|
28
|
+
# variables defined here will be available to all commands.
|
29
|
+
end
|
30
|
+
|
31
|
+
command :welcome do
|
32
|
+
# Example: ruby bin/example
|
33
|
+
|
34
|
+
puts "Meatwad: Science is a mystery to man, isn't it Frylock?"
|
35
|
+
print "Frylock: At least we have some commands: "
|
36
|
+
|
37
|
+
# The commands method returns a hash of Frylock::Command objects
|
38
|
+
puts commands.keys.inject([]) { |list, command| list << command.to_s }.sort.join(', ')
|
39
|
+
end
|
40
|
+
|
41
|
+
option :f, :found, "A boolean value. Did you find the car?"
|
42
|
+
command :findcar do |options|
|
43
|
+
# +options+ is a hash containing the options defined above
|
44
|
+
# Example: ruby bin/example -f findcar
|
45
|
+
|
46
|
+
puts "Frylock: So, did they ever find your car?"
|
47
|
+
|
48
|
+
# The keys to the hash are the long string from the option definition.
|
49
|
+
# If only the short string is provided, those will be used instead (i.e. :f).
|
50
|
+
puts (!options[:found]) ? "Carl: No" :
|
51
|
+
"Carl: Oh, they found part of it, hangin' from a trestle near the turnpike."
|
52
|
+
end
|
53
|
+
</code></pre>
|
54
|
+
|
55
|
+
== License
|
56
|
+
|
57
|
+
See LICENSE.txt
|
data/bin/example
ADDED
@@ -0,0 +1,170 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
DRYDOCK_HOME = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
4
|
+
$: << File.join(DRYDOCK_HOME, 'lib')
|
5
|
+
|
6
|
+
require 'rubygems'
|
7
|
+
require 'drydock'
|
8
|
+
|
9
|
+
default :welcome
|
10
|
+
|
11
|
+
|
12
|
+
before do
|
13
|
+
# You can execute a block before the requests command is executed. Instance
|
14
|
+
# variables defined here will be available to all commands.
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
command :welcome do
|
19
|
+
# Example: ruby bin/example
|
20
|
+
|
21
|
+
puts "Meatwad: Science is a mystery to man, isn't it Frylock?"
|
22
|
+
print "Frylock: At least we have some commands: "
|
23
|
+
|
24
|
+
# The commands method returns a hash of Drydock::Command objects
|
25
|
+
puts commands.keys.inject([]) { |list, command| list << command.to_s }.sort.join(', ')
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
option :f, :found, "A boolean value. Did you find the car?"
|
30
|
+
command :findcar do |options|
|
31
|
+
# +options+ is a hash containing the options defined above
|
32
|
+
# Example: ruby bin/example -f findcar
|
33
|
+
|
34
|
+
puts "Frylock: So, did they ever find your car?"
|
35
|
+
|
36
|
+
# The keys to the hash are the long string from the option definition.
|
37
|
+
# If only the short string is provided, those will be used instead (i.e. :f).
|
38
|
+
puts (!options[:found]) ? "Carl: No" :
|
39
|
+
"Carl: Oh, they found part of it, hangin' from a trestle near the turnpike."
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
|
44
|
+
global_usage "USAGE: #{File.basename($0)} [global options] command [command options]"
|
45
|
+
global_option :s, :seconds, "Display values in seconds"
|
46
|
+
global_option :v, :verbose, "Verbosity level (i.e. -vvv is greater than -v)" do |v|
|
47
|
+
# Use instance variables to maintain values between option blocks.
|
48
|
+
# This will increment for every -v found (i.e. -vvv)
|
49
|
+
@val ||= 0
|
50
|
+
@val += 1
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
usage "ruby bin/example [--seconds] [-vv] time"
|
55
|
+
command :date do |options, argv, global_options|
|
56
|
+
# +argv+ contains the unnamed arguments
|
57
|
+
# +global_options+ contains hash of the options defined with global_options
|
58
|
+
|
59
|
+
require 'time'
|
60
|
+
now = Time.now
|
61
|
+
puts "More verbosely, the date is now: " if (global_options[:verbose] || 0) >= 2
|
62
|
+
puts (global_options[:seconds]) ? now.to_i : now.to_s
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
option :c, :check, "Check response codes for each URI"
|
67
|
+
option :d, :delim, String, "Output delimiter"
|
68
|
+
option :t, :timeout, Float, "Timeout value for HTTP request" do |v|
|
69
|
+
# You can provide an block to process the option value.
|
70
|
+
# This block must return the final value.
|
71
|
+
v = 10 if (v > 10)
|
72
|
+
v
|
73
|
+
end
|
74
|
+
|
75
|
+
usage 'echo "http://github.com/" | ruby bin/example process -c -d " " -t 15 http://solutious.com/'
|
76
|
+
command :processuris do |options, argv, global_options, stdin, cmd|
|
77
|
+
# +stdin+ is either an IO object or a custom object defined with a stdin block (see below)
|
78
|
+
# +cmd+ is the string used to evoke this command. Useful with alias_command (see below).
|
79
|
+
|
80
|
+
require 'net/http'
|
81
|
+
require 'uri'
|
82
|
+
require 'timeout'
|
83
|
+
|
84
|
+
uris = [stdin, argv].flatten # Combine the argv and stdin arrays
|
85
|
+
delim = options[:delim] || ','
|
86
|
+
timeout = options[:timeout] || 5
|
87
|
+
code = :notchecked # The default code when :check is false
|
88
|
+
|
89
|
+
if uris.empty?
|
90
|
+
puts "Frylock: You didn't provide any URIs. "
|
91
|
+
puts "Master Shake: Ya, see #{$0} #{cmd} -h"
|
92
|
+
exit 0
|
93
|
+
end
|
94
|
+
|
95
|
+
uris.each_with_index do |uri, index|
|
96
|
+
code = response_code(uri, timeout) if (options[:check])
|
97
|
+
puts [index+1, uri, code].join(delim)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
alias_command :process, :processuris
|
101
|
+
|
102
|
+
|
103
|
+
|
104
|
+
|
105
|
+
stdin do |stdin, output|
|
106
|
+
# Pre-process STDIN for all commands. This example returns an array of lines.
|
107
|
+
# The command processuris uses this array.
|
108
|
+
|
109
|
+
# We only want piped data. If this is not included
|
110
|
+
# execution will wait for input from the user.
|
111
|
+
unless stdin.tty?
|
112
|
+
|
113
|
+
while !stdin.eof? do
|
114
|
+
line = stdin.readline
|
115
|
+
line.chomp!
|
116
|
+
(output ||= []) << line
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
output
|
121
|
+
end
|
122
|
+
|
123
|
+
|
124
|
+
|
125
|
+
# response_code
|
126
|
+
#
|
127
|
+
# return the HTTP response code for the given URI
|
128
|
+
# +uri+ A valid HTTP URI
|
129
|
+
# +duration+ The timeout threshold (in seconds) for the request.
|
130
|
+
def response_code(uri_str, duration=5)
|
131
|
+
response = :unavailable
|
132
|
+
begin
|
133
|
+
uri = (uri_str.kind_of? URI::HTTP) ? uri_str : URI.parse(uri_str)
|
134
|
+
timeout(duration) do
|
135
|
+
response = Net::HTTP.get_response(uri).code
|
136
|
+
end
|
137
|
+
rescue Exception => ex
|
138
|
+
end
|
139
|
+
response
|
140
|
+
end
|
141
|
+
|
142
|
+
|
143
|
+
at_exit do
|
144
|
+
# This is an example of how to call Frylock in your script.
|
145
|
+
begin
|
146
|
+
Drydock.run!(ARGV, STDIN)
|
147
|
+
|
148
|
+
rescue Drydock::UnknownCommand => ex
|
149
|
+
STDERR.puts "Frylock: I don't know what the #{ex.name} command is. #{$/}"
|
150
|
+
STDERR.puts "Master Shake: I'll tell you what it is, friends... it's shut up and let me eat it."
|
151
|
+
|
152
|
+
rescue Drydock::NoCommandsDefined => ex
|
153
|
+
STDERR.puts "Frylock: Carl, I don't want it. And I'd appreciate it if you'd define at least one command. #{$/}"
|
154
|
+
STDERR.puts "Carl: Fryman, don't be that way! This sorta thing happens every day! People just don't... you know, talk about it this loud."
|
155
|
+
|
156
|
+
rescue Drydock::InvalidArgument => ex
|
157
|
+
STDERR.puts "Frylock: Shake, how many arguments have you not provided a value for this year? #{$/}"
|
158
|
+
STDERR.puts "Master Shake: A *lot* more than *you* have! (#{@args.join(', ')})"
|
159
|
+
|
160
|
+
rescue Drydock::MissingArgument => ex
|
161
|
+
STDERR.puts "Frylock: I don't know what #{ex.args.join(', ')} is. #{$/}"
|
162
|
+
STDERR.puts "Master Shake: I'll tell you what it is, friends... it's shut up and let me eat it."
|
163
|
+
|
164
|
+
rescue => ex
|
165
|
+
STDERR.puts "Master Shake: Okay, but when we go in, watch your step. "
|
166
|
+
STDERR.puts "Frylock: Why?"
|
167
|
+
STDERR.puts "Meatwad: [explosion] #{ex.message}"
|
168
|
+
STDERR.puts ex.backtrace
|
169
|
+
end
|
170
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Drylock
|
2
|
+
|
3
|
+
class UnknownCommand < RuntimeError
|
4
|
+
attr_reader :name
|
5
|
+
def initialize(name)
|
6
|
+
@name = name || :unknown
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class NoCommandsDefined < RuntimeError
|
11
|
+
end
|
12
|
+
|
13
|
+
class InvalidArgument < RuntimeError
|
14
|
+
attr_accessor :args
|
15
|
+
def initialize(args)
|
16
|
+
# We grab just the name of the argument
|
17
|
+
@args = args || []
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class MissingArgument < InvalidArgument
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
data/lib/drydock.rb
ADDED
@@ -0,0 +1,232 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'ostruct'
|
3
|
+
require 'pp'
|
4
|
+
|
5
|
+
require 'drydock/exceptions'
|
6
|
+
|
7
|
+
module Drydock
|
8
|
+
class Command
|
9
|
+
attr_reader :cmd, :index
|
10
|
+
def initialize(cmd, index, &b)
|
11
|
+
@cmd = (cmd.kind_of?(Symbol)) ? cmd.to_s : cmd
|
12
|
+
@index = index
|
13
|
+
@b = b
|
14
|
+
end
|
15
|
+
|
16
|
+
def call(cmd_str, argv, stdin, global_options, options)
|
17
|
+
block_args = [options, argv, global_options, stdin, cmd_str, self]
|
18
|
+
@b.call(*block_args[0..(@b.arity-1)])
|
19
|
+
end
|
20
|
+
def to_s
|
21
|
+
@cmd.to_s
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
module Drydock
|
27
|
+
extend self
|
28
|
+
|
29
|
+
FORWARDED_METHODS = %w(command before alias_command global_option global_usage usage option stdin default commands).freeze
|
30
|
+
|
31
|
+
def default(cmd)
|
32
|
+
@default_command = canonize(cmd)
|
33
|
+
end
|
34
|
+
|
35
|
+
def stdin(&b)
|
36
|
+
@stdin_block = b
|
37
|
+
end
|
38
|
+
def before(&b)
|
39
|
+
@before_block = b
|
40
|
+
end
|
41
|
+
|
42
|
+
# global_usage
|
43
|
+
# ex: usage "Usage: frylla [global options] command [command options]"
|
44
|
+
def global_usage(msg)
|
45
|
+
@global_opts_parser ||= OptionParser.new
|
46
|
+
@global_options ||= OpenStruct.new
|
47
|
+
|
48
|
+
@global_opts_parser.banner = msg
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
|
53
|
+
# process_arguments
|
54
|
+
#
|
55
|
+
# Split the +argv+ array into global args and command args and
|
56
|
+
# find the command name.
|
57
|
+
# i.e. ./script -H push -f (-H is a global arg, push is the command, -f is a command arg)
|
58
|
+
# returns [global_options, cmd, command_options, argv]
|
59
|
+
def process_arguments(argv)
|
60
|
+
global_options = command_options = {}
|
61
|
+
cmd = nil
|
62
|
+
|
63
|
+
global_parser = @global_opts_parser
|
64
|
+
|
65
|
+
global_options = global_parser.getopts(argv)
|
66
|
+
global_options = global_options.keys.inject({}) do |hash, key|
|
67
|
+
hash[key.to_sym] = global_options[key]
|
68
|
+
hash
|
69
|
+
end
|
70
|
+
|
71
|
+
cmd_name = (argv.empty?) ? @default_command : argv.shift
|
72
|
+
raise UnknownCommand.new(cmd_name) unless command?(cmd_name)
|
73
|
+
|
74
|
+
cmd = get_command(cmd_name)
|
75
|
+
command_parser = @command_opts_parser[cmd.index]
|
76
|
+
|
77
|
+
command_options = command_parser.getopts(argv) if (!argv.empty? && command_parser)
|
78
|
+
command_options = command_options.keys.inject({}) do |hash, key|
|
79
|
+
hash[key.to_sym] = command_options[key]
|
80
|
+
hash
|
81
|
+
end
|
82
|
+
|
83
|
+
[global_options, cmd_name, command_options, argv]
|
84
|
+
end
|
85
|
+
|
86
|
+
|
87
|
+
|
88
|
+
def usage(msg)
|
89
|
+
get_current_option_parser.banner = msg
|
90
|
+
end
|
91
|
+
|
92
|
+
# get_current_option_parser
|
93
|
+
#
|
94
|
+
# Grab the options parser for the current command or create it if it doesn't exist.
|
95
|
+
def get_current_option_parser
|
96
|
+
@command_opts_parser ||= []
|
97
|
+
@command_index ||= 0
|
98
|
+
(@command_opts_parser[@command_index] ||= OptionParser.new)
|
99
|
+
end
|
100
|
+
|
101
|
+
def global_option(*args, &b)
|
102
|
+
@global_opts_parser ||= OptionParser.new
|
103
|
+
args.unshift(@global_opts_parser)
|
104
|
+
option_parser(args, &b)
|
105
|
+
end
|
106
|
+
|
107
|
+
def option(*args, &b)
|
108
|
+
args.unshift(get_current_option_parser)
|
109
|
+
option_parser(args, &b)
|
110
|
+
end
|
111
|
+
|
112
|
+
# option_parser
|
113
|
+
#
|
114
|
+
# Processes calls to option and global_option. Symbols are converted into
|
115
|
+
# OptionParser style strings (:h and :help become '-h' and '--help'). If a
|
116
|
+
# class is included, it will tell OptionParser to expect a value otherwise
|
117
|
+
# it assumes a boolean value.
|
118
|
+
#
|
119
|
+
# +args+ is passed directly to OptionParser.on so it can contain anything
|
120
|
+
# that's valid to that method. Some examples:
|
121
|
+
# [:h, :help, "Displays this message"]
|
122
|
+
# [:m, :max, Integer, "Maximum threshold"]
|
123
|
+
# ['-l x,y,z', '--lang=x,y,z', Array, "Requested languages"]
|
124
|
+
def option_parser(args=[], &b)
|
125
|
+
return if args.empty?
|
126
|
+
opts_parser = args.shift
|
127
|
+
|
128
|
+
symbol_switches = []
|
129
|
+
args.each_with_index do |arg, index|
|
130
|
+
if arg.is_a? Symbol
|
131
|
+
args[index] = (arg.to_s.length == 1) ? "-#{arg.to_s}" : "--#{arg.to_s}"
|
132
|
+
symbol_switches << args[index]
|
133
|
+
elsif arg.kind_of?(Class)
|
134
|
+
symbol_switches.each do |arg|
|
135
|
+
arg << "=S"
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
if args.size == 1
|
141
|
+
opts_parser.on(args.shift)
|
142
|
+
else
|
143
|
+
opts_parser.on(*args) do |v|
|
144
|
+
block_args = [v, opts_parser]
|
145
|
+
result = (b.nil?) ? v : b.call(*block_args[0..(b.arity-1)])
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def command(*cmds, &b)
|
151
|
+
@command_index ||= 0
|
152
|
+
@command_opts_parser ||= []
|
153
|
+
cmds.each do |cmd|
|
154
|
+
c = Command.new(cmd, @command_index, &b)
|
155
|
+
(@commands ||= {})[cmd] = c
|
156
|
+
end
|
157
|
+
|
158
|
+
@command_index += 1
|
159
|
+
end
|
160
|
+
|
161
|
+
def alias_command(aliaz, cmd)
|
162
|
+
return unless @commands.has_key? cmd
|
163
|
+
@commands[aliaz] = @commands[cmd]
|
164
|
+
end
|
165
|
+
|
166
|
+
def run!(argv, stdin=nil)
|
167
|
+
raise NoCommandsDefined.new unless @commands
|
168
|
+
@global_options, cmd_name, @command_options, argv = process_arguments(argv)
|
169
|
+
|
170
|
+
cmd_name ||= @default_command
|
171
|
+
|
172
|
+
raise UnknownCommand.new(cmd_name) unless command?(cmd_name)
|
173
|
+
|
174
|
+
stdin = (defined? @stdin_block) ? @stdin_block.call(stdin, []) : stdin
|
175
|
+
@before_block.call if defined? @before_block
|
176
|
+
|
177
|
+
|
178
|
+
call_command(cmd_name, argv, stdin)
|
179
|
+
|
180
|
+
|
181
|
+
rescue OptionParser::InvalidOption => ex
|
182
|
+
raise Drydock::InvalidArgument.new(ex.args)
|
183
|
+
rescue OptionParser::MissingArgument => ex
|
184
|
+
raise Drydock::MissingArgument.new(ex.args)
|
185
|
+
end
|
186
|
+
|
187
|
+
|
188
|
+
def call_command(cmd_str, argv=[], stdin=nil)
|
189
|
+
return unless command?(cmd_str)
|
190
|
+
get_command(cmd_str).call(cmd_str, argv, stdin, @global_options, @command_options)
|
191
|
+
end
|
192
|
+
|
193
|
+
def get_command(cmd)
|
194
|
+
return unless command?(cmd)
|
195
|
+
@commands[canonize(cmd)]
|
196
|
+
end
|
197
|
+
|
198
|
+
def commands
|
199
|
+
@commands
|
200
|
+
end
|
201
|
+
|
202
|
+
def run
|
203
|
+
@run || true
|
204
|
+
end
|
205
|
+
|
206
|
+
def run=(v)
|
207
|
+
@run = v
|
208
|
+
end
|
209
|
+
|
210
|
+
def command?(cmd)
|
211
|
+
name = canonize(cmd)
|
212
|
+
(@commands || {}).has_key? name
|
213
|
+
end
|
214
|
+
def canonize(cmd)
|
215
|
+
return unless cmd
|
216
|
+
return cmd if cmd.kind_of?(Symbol)
|
217
|
+
cmd.tr('-', '_').to_sym
|
218
|
+
end
|
219
|
+
|
220
|
+
end
|
221
|
+
|
222
|
+
Drydock::FORWARDED_METHODS.each do |m|
|
223
|
+
eval(<<-end_eval, binding, "(Drydock)", __LINE__)
|
224
|
+
def #{m}(*args, &b)
|
225
|
+
Drydock.#{m}(*args, &b)
|
226
|
+
end
|
227
|
+
end_eval
|
228
|
+
end
|
229
|
+
|
230
|
+
|
231
|
+
|
232
|
+
|
metadata
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: delano-drydock
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Delano Mandelbaum
|
8
|
+
- Blake Mizerany
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2008-08-17 00:00:00 -07:00
|
14
|
+
default_executable:
|
15
|
+
dependencies: []
|
16
|
+
|
17
|
+
description: Command line apps made easy
|
18
|
+
email: delano@solutious.com
|
19
|
+
executables: []
|
20
|
+
|
21
|
+
extensions: []
|
22
|
+
|
23
|
+
extra_rdoc_files:
|
24
|
+
- README.rdoc
|
25
|
+
- LICENSE.txt
|
26
|
+
files:
|
27
|
+
- LICENSE.txt
|
28
|
+
- README.rdoc
|
29
|
+
- bin/example
|
30
|
+
- lib/drydock/exceptions.rb
|
31
|
+
- lib/drydock.rb
|
32
|
+
has_rdoc: true
|
33
|
+
homepage: http://github.com/delano/drydock
|
34
|
+
post_install_message:
|
35
|
+
rdoc_options:
|
36
|
+
- --line-numbers
|
37
|
+
- --inline-source
|
38
|
+
- --title
|
39
|
+
- "Drydock: Easy command-line apps"
|
40
|
+
- --main
|
41
|
+
- README.rdoc
|
42
|
+
require_paths:
|
43
|
+
- lib
|
44
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: "0"
|
49
|
+
version:
|
50
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: "0"
|
55
|
+
version:
|
56
|
+
requirements: []
|
57
|
+
|
58
|
+
rubyforge_project:
|
59
|
+
rubygems_version: 1.2.0
|
60
|
+
signing_key:
|
61
|
+
specification_version: 1
|
62
|
+
summary: Command line apps made easy
|
63
|
+
test_files: []
|
64
|
+
|