delano-drydock 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGES.txt +16 -0
- data/README.rdoc +46 -33
- data/Rakefile +72 -0
- data/bin/example +32 -50
- data/drydock.gemspec +53 -0
- data/lib/drydock.rb +375 -125
- data/test/command_test.rb +40 -0
- metadata +33 -7
- data/lib/drydock/exceptions.rb +0 -24
data/CHANGES.txt
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
DRYDOCK, CHANGES
|
2
|
+
|
3
|
+
#### 0.3 (2009-02-05) ###############################
|
4
|
+
|
5
|
+
* Added support for custom Drydock::Commands objects
|
6
|
+
* Global and command-specific options are now available as
|
7
|
+
attributes of the Drydock::Commands class instance.
|
8
|
+
* Automatic execution
|
9
|
+
* Now in a single file (lib/drydock.rb)
|
10
|
+
* Started adding tests
|
11
|
+
* Improved documentation
|
12
|
+
|
13
|
+
#### 0.2 (2008-12-27) ###############################
|
14
|
+
|
15
|
+
* Initial release
|
16
|
+
* Forked from bmizerany/frylock
|
data/README.rdoc
CHANGED
@@ -1,56 +1,69 @@
|
|
1
|
-
= Drydock -
|
1
|
+
= Drydock - v0.3
|
2
2
|
|
3
|
-
Inspired by
|
4
|
-
|
5
|
-
Inspired by "bmizerany-frylock":http://github.com/bmizerany/frylock/tree
|
3
|
+
Inspired by github-gem and bmizerany-frylock.
|
6
4
|
|
7
5
|
== Overview
|
8
6
|
|
9
|
-
Drydock is a DSL for command line apps.
|
7
|
+
Drydock is a seaworthy DSL for command line apps. It is contained in a single .rb which can be copied directly into your project.
|
10
8
|
|
11
9
|
== Install
|
12
10
|
|
13
|
-
|
11
|
+
One of:
|
12
|
+
|
13
|
+
* gem install drydock
|
14
|
+
* copy lib/drydock.rb into your lib directory.
|
14
15
|
|
16
|
+
Or for GitHub fans:
|
17
|
+
|
18
|
+
* git clone git://github.com/delano/drydock.git
|
19
|
+
* gem install delano-drydock
|
15
20
|
|
16
21
|
== Examples
|
17
22
|
|
18
23
|
See bin/example for more.
|
19
24
|
|
20
|
-
|
21
|
-
require '
|
22
|
-
require 'drydock'
|
25
|
+
require 'rubygems'
|
26
|
+
require 'drydock'
|
23
27
|
|
24
|
-
default :welcome
|
28
|
+
default :welcome
|
25
29
|
|
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
|
+
before do
|
31
|
+
# You can execute a block before the requests command is executed. Instance
|
32
|
+
# variables defined here will be available to all commands.
|
33
|
+
end
|
30
34
|
|
31
|
-
command :welcome do
|
32
|
-
# Example: ruby bin/example
|
35
|
+
command :welcome do
|
36
|
+
# Example: ruby bin/example
|
33
37
|
|
34
|
-
|
35
|
-
|
38
|
+
puts "Meatwad: Science is a mystery to man, isn't it Frylock?"
|
39
|
+
print "Frylock: At least we have some commands: "
|
36
40
|
|
37
|
-
|
38
|
-
|
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
|
41
|
+
# The commands method returns a hash of Frylock::Command objects
|
42
|
+
puts commands.keys.inject([]) { |list, command| list << command.to_s }.sort.join(', ')
|
43
|
+
end
|
44
|
+
|
45
|
+
option :f, :found, "A boolean value. Did you find the car?"
|
46
|
+
command :findcar do |options|
|
47
|
+
# +options+ is a hash containing the options defined above
|
48
|
+
# Example: ruby bin/example -f findcar
|
45
49
|
|
46
|
-
|
50
|
+
puts "Frylock: So, did they ever find your car?"
|
47
51
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
end
|
53
|
-
|
52
|
+
# The keys to the hash are the long string from the option definition.
|
53
|
+
# If only the short string is provided, those will be used instead (i.e. :f).
|
54
|
+
puts (!options[:found]) ? "Carl: No" :
|
55
|
+
"Carl: Oh, they found part of it, hangin' from a trestle near the turnpike."
|
56
|
+
end
|
57
|
+
|
58
|
+
== More Information
|
59
|
+
|
60
|
+
http://www.youtube.com/watch?v=m_wFEB4Oxlo
|
61
|
+
|
62
|
+
== Credits
|
63
|
+
|
64
|
+
* Delano Mandelbaum (delano@solutious.com)
|
65
|
+
* Bernie Kopell (bernie@solutious.com)
|
66
|
+
|
54
67
|
|
55
68
|
== License
|
56
69
|
|
data/Rakefile
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake/clean'
|
3
|
+
require 'rake/gempackagetask'
|
4
|
+
require 'hanna/rdoctask'
|
5
|
+
require 'fileutils'
|
6
|
+
include FileUtils
|
7
|
+
|
8
|
+
task :default => :test
|
9
|
+
|
10
|
+
# SPECS ===============================================================
|
11
|
+
|
12
|
+
desc 'Run specs with unit test style output'
|
13
|
+
task :test do |t|
|
14
|
+
sh "ruby tests/*_test.rb"
|
15
|
+
end
|
16
|
+
|
17
|
+
# PACKAGE =============================================================
|
18
|
+
|
19
|
+
|
20
|
+
require File.dirname(__FILE__) + "/lib/drydock"
|
21
|
+
load "drydock.gemspec"
|
22
|
+
|
23
|
+
version = Drydock::VERSION.to_s
|
24
|
+
|
25
|
+
Drydock.run = false
|
26
|
+
|
27
|
+
Rake::GemPackageTask.new(@spec) do |p|
|
28
|
+
p.need_tar = true if RUBY_PLATFORM !~ /mswin/
|
29
|
+
end
|
30
|
+
|
31
|
+
task :release => [ :rdoc, :package ]
|
32
|
+
|
33
|
+
task :install => [ :rdoc, :package ] do
|
34
|
+
sh %{sudo gem install pkg/#{name}-#{version}.gem}
|
35
|
+
end
|
36
|
+
|
37
|
+
task :uninstall => [ :clean ] do
|
38
|
+
sh %{sudo gem uninstall #{name}}
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
# Rubyforge Release / Publish Tasks ==================================
|
43
|
+
|
44
|
+
desc 'Publish website to rubyforge'
|
45
|
+
task 'publish:doc' => 'doc/index.html' do
|
46
|
+
sh 'scp -rp doc/* rubyforge.org:/var/www/gforge-projects/drydock/'
|
47
|
+
end
|
48
|
+
puts "rubyforge add_release drydock drydock #{@spec.version} pkg/drydock-#{@spec.version}.gem "
|
49
|
+
task 'publish:gem' => [:package] do |t|
|
50
|
+
sh <<-end
|
51
|
+
rubyforge add_release -o Any -a CHANGES.txt -f -n README.rdoc drydock drydock #{@spec.version} pkg/drydock-#{@spec.version}.gem &&
|
52
|
+
rubyforge add_file -o Any -a CHANGES.txt -f -n README.rdoc drydock drydock #{@spec.version} pkg/drydock-#{@spec.version}.tgz
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
Rake::RDocTask.new do |t|
|
58
|
+
t.rdoc_dir = 'doc'
|
59
|
+
t.title = "Drydock, A seaworthy DSL for command-line apps."
|
60
|
+
t.options << '--line-numbers' << '--inline-source' << '-A cattr_accessor=object'
|
61
|
+
t.options << '--charset' << 'utf-8'
|
62
|
+
t.rdoc_files.include('LICENSE.txt')
|
63
|
+
t.rdoc_files.include('README.rdoc')
|
64
|
+
t.rdoc_files.include('CHANGES.txt')
|
65
|
+
t.rdoc_files.include('bin/*')
|
66
|
+
t.rdoc_files.include('lib/*.rb')
|
67
|
+
end
|
68
|
+
|
69
|
+
CLEAN.include [ 'pkg', '*.gem', '.config', 'doc' ]
|
70
|
+
|
71
|
+
|
72
|
+
|
data/bin/example
CHANGED
@@ -1,19 +1,19 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
|
4
|
-
$: << File.join(DRYDOCK_HOME, 'lib')
|
3
|
+
$:.unshift File.expand_path(File.join(File.dirname(__FILE__), '..')), 'lib'
|
5
4
|
|
6
|
-
require 'rubygems'
|
7
5
|
require 'drydock'
|
8
6
|
|
9
7
|
default :welcome
|
10
8
|
|
11
|
-
|
12
9
|
before do
|
13
10
|
# You can execute a block before the requests command is executed. Instance
|
14
11
|
# variables defined here will be available to all commands.
|
15
12
|
end
|
16
13
|
|
14
|
+
after do
|
15
|
+
# And this will be called after the command.
|
16
|
+
end
|
17
17
|
|
18
18
|
command :welcome do
|
19
19
|
# Example: ruby bin/example
|
@@ -27,15 +27,15 @@ end
|
|
27
27
|
|
28
28
|
|
29
29
|
option :f, :found, "A boolean value. Did you find the car?"
|
30
|
-
command :findcar do |
|
31
|
-
# +
|
30
|
+
command :findcar do |obj|
|
31
|
+
# +obj+ is the Drylock::Command object instance. It contains accessors for all options.
|
32
32
|
# Example: ruby bin/example -f findcar
|
33
33
|
|
34
34
|
puts "Frylock: So, did they ever find your car?"
|
35
35
|
|
36
36
|
# The keys to the hash are the long string from the option definition.
|
37
37
|
# If only the short string is provided, those will be used instead (i.e. :f).
|
38
|
-
puts (!
|
38
|
+
puts (!obj.found) ? "Carl: No" :
|
39
39
|
"Carl: Oh, they found part of it, hangin' from a trestle near the turnpike."
|
40
40
|
end
|
41
41
|
|
@@ -51,17 +51,28 @@ global_option :v, :verbose, "Verbosity level (i.e. -vvv is greater than -v)" do
|
|
51
51
|
end
|
52
52
|
|
53
53
|
|
54
|
-
usage "
|
55
|
-
command :date do |
|
56
|
-
# +argv+
|
57
|
-
# +global_options+ contains hash of the options defined with global_options
|
58
|
-
|
54
|
+
usage "#{$0} [-s] [-vv] date"
|
55
|
+
command :date do |obj, argv|
|
56
|
+
# +argv+ is an array containing the unnamed arguments
|
59
57
|
require 'time'
|
60
58
|
now = Time.now
|
61
|
-
puts "
|
62
|
-
puts
|
59
|
+
puts "(Not verbose enough. Try adding a -v.)" if (obj.verbose || 0) == 1
|
60
|
+
puts "More verbosely, the date is now: " if (obj.verbose || 0) >= 2
|
61
|
+
puts (obj.seconds) ? now.to_i : now.to_s
|
63
62
|
end
|
64
63
|
|
64
|
+
usage "#{$0} rogue"
|
65
|
+
ignore :options
|
66
|
+
command :rogue do |obj, argv|
|
67
|
+
# You can use ignore :options to tell Drydock to not process the
|
68
|
+
# command-specific options.
|
69
|
+
if argv.empty?
|
70
|
+
puts "Had you supplied some arguments, I would have ignored them."
|
71
|
+
else
|
72
|
+
puts "Hi! You supplied some arguments but I ignored them."
|
73
|
+
puts "They're all still here in this array: %s" % argv.join(', ')
|
74
|
+
end
|
75
|
+
end
|
65
76
|
|
66
77
|
option :c, :check, "Check response codes for each URI"
|
67
78
|
option :d, :delim, String, "Output delimiter"
|
@@ -73,31 +84,31 @@ option :t, :timeout, Float, "Timeout value for HTTP request" do |v|
|
|
73
84
|
end
|
74
85
|
|
75
86
|
usage 'echo "http://github.com/" | ruby bin/example process -c -d " " -t 15 http://solutious.com/'
|
76
|
-
command :
|
77
|
-
# +stdin+ is either an IO object or a custom object defined with a stdin block (see below)
|
87
|
+
command :processuri do |obj, argv, stdin|
|
78
88
|
# +cmd+ is the string used to evoke this command. Useful with alias_command (see below).
|
89
|
+
# +stdin+ is either an IO object or a custom object defined with a stdin block (see below)
|
79
90
|
|
80
91
|
require 'net/http'
|
81
92
|
require 'uri'
|
82
93
|
require 'timeout'
|
83
94
|
|
84
95
|
uris = [stdin, argv].flatten # Combine the argv and stdin arrays
|
85
|
-
delim =
|
86
|
-
timeout =
|
96
|
+
delim = obj.delim || ','
|
97
|
+
timeout = obj.timeout || 5
|
87
98
|
code = :notchecked # The default code when :check is false
|
88
99
|
|
89
100
|
if uris.empty?
|
90
101
|
puts "Frylock: You didn't provide any URIs. "
|
91
|
-
puts "Master Shake: Ya, see #{$0} #{
|
102
|
+
puts "Master Shake: Ya, see #{$0} #{obj.alias} -h"
|
92
103
|
exit 0
|
93
104
|
end
|
94
105
|
|
95
106
|
uris.each_with_index do |uri, index|
|
96
|
-
code = response_code(uri, timeout) if (
|
107
|
+
code = response_code(uri, timeout) if (obj.check)
|
97
108
|
puts [index+1, uri, code].join(delim)
|
98
109
|
end
|
99
110
|
end
|
100
|
-
alias_command :
|
111
|
+
alias_command :checkuri, :processuri
|
101
112
|
|
102
113
|
|
103
114
|
|
@@ -139,32 +150,3 @@ def response_code(uri_str, duration=5)
|
|
139
150
|
response
|
140
151
|
end
|
141
152
|
|
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
|
data/drydock.gemspec
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
@spec = Gem::Specification.new do |s|
|
2
|
+
s.name = %q{drydock}
|
3
|
+
s.version = "0.3.1"
|
4
|
+
s.specification_version = 1 if s.respond_to? :specification_version=
|
5
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
6
|
+
|
7
|
+
s.authors = ["Delano Mandelbaum"]
|
8
|
+
s.date = %q{2008-08-17}
|
9
|
+
s.description = %q{A seaworthy DSL for writing command line apps inspired by Blake Mizerany's Frylock}
|
10
|
+
s.email = %q{delano@solutious.com}
|
11
|
+
s.files = %w(
|
12
|
+
CHANGES.txt
|
13
|
+
LICENSE.txt
|
14
|
+
README.rdoc
|
15
|
+
Rakefile
|
16
|
+
bin/example
|
17
|
+
drydock.gemspec
|
18
|
+
lib/drydock.rb
|
19
|
+
test/command_test.rb
|
20
|
+
doc
|
21
|
+
doc/classes
|
22
|
+
doc/classes/Drydock
|
23
|
+
doc/classes/Drydock/Command.html
|
24
|
+
doc/classes/Drydock/InvalidArgument.html
|
25
|
+
doc/classes/Drydock/MissingArgument.html
|
26
|
+
doc/classes/Drydock/NoCommandsDefined.html
|
27
|
+
doc/classes/Drydock/UnknownCommand.html
|
28
|
+
doc/classes/Drydock.html
|
29
|
+
doc/created.rid
|
30
|
+
doc/files
|
31
|
+
doc/files/bin
|
32
|
+
doc/files/bin/example.html
|
33
|
+
doc/files/CHANGES_txt.html
|
34
|
+
doc/files/lib
|
35
|
+
doc/files/lib/drydock_rb.html
|
36
|
+
doc/files/LICENSE_txt.html
|
37
|
+
doc/files/README_rdoc.html
|
38
|
+
doc/fr_class_index.html
|
39
|
+
doc/fr_file_index.html
|
40
|
+
doc/fr_method_index.html
|
41
|
+
doc/index.html
|
42
|
+
doc/rdoc-style.css
|
43
|
+
)
|
44
|
+
s.has_rdoc = true
|
45
|
+
s.homepage = %q{http://github.com/delano/drydock}
|
46
|
+
s.extra_rdoc_files = %w[README.rdoc LICENSE.txt CHANGES.txt]
|
47
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Drydock: a seaworthy DSL for command-line apps", "--main", "README.rdoc"]
|
48
|
+
s.require_paths = ["lib"]
|
49
|
+
s.rubygems_version = %q{1.1.1}
|
50
|
+
s.summary = %q{A seaworthy DSL for writing command line apps}
|
51
|
+
|
52
|
+
s.rubyforge_project = "drydock"
|
53
|
+
end
|
data/lib/drydock.rb
CHANGED
@@ -1,133 +1,368 @@
|
|
1
1
|
require 'optparse'
|
2
2
|
require 'ostruct'
|
3
|
-
require 'pp'
|
4
|
-
|
5
|
-
require 'drydock/exceptions'
|
6
3
|
|
4
|
+
#
|
5
|
+
#
|
7
6
|
module Drydock
|
7
|
+
# The base class for all command objects. There is an instance of this class
|
8
|
+
# for every command defined. Global and command-specific options are added
|
9
|
+
# as attributes to this class dynamically.
|
10
|
+
#
|
11
|
+
# i.e. "example -v date -f yaml"
|
12
|
+
#
|
13
|
+
# global_option :v, :verbose, "I want mooooore!"
|
14
|
+
# option :f, :format, String, "Long date format"
|
15
|
+
# command :date do |obj|
|
16
|
+
# puts obj.verbose #=> true
|
17
|
+
# puts obj.format #=> "yaml"
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# You can inherit from this class to create your own: EatFood < Drydock::Command.
|
21
|
+
# And then specific your class in the command definition:
|
22
|
+
#
|
23
|
+
# command :eat => EatFood do |obj|; ...; end
|
24
|
+
#
|
8
25
|
class Command
|
9
|
-
attr_reader :cmd, :
|
10
|
-
|
11
|
-
|
12
|
-
|
26
|
+
attr_reader :cmd, :alias
|
27
|
+
# +cmd+ is the short name of this command.
|
28
|
+
# +b+ is the block associated to this command.
|
29
|
+
def initialize(cmd, &b)
|
30
|
+
@cmd = (cmd.kind_of?(Symbol)) ? cmd : cmd.to_sym
|
13
31
|
@b = b
|
14
32
|
end
|
15
33
|
|
16
|
-
|
17
|
-
|
18
|
-
|
34
|
+
# Execute the block.
|
35
|
+
#
|
36
|
+
# +cmd_str+ is the short name used to evoke this command. It will equal @cmd
|
37
|
+
# unless an alias was used used to evoke this command.
|
38
|
+
# +argv+ an array of unnamed arguments. If ignore :options was declared this
|
39
|
+
# will contain the arguments exactly as they were defined on the command-line.
|
40
|
+
# +stdin+ contains the output of stdin do; ...; end otherwise it's a STDIN IO handle.
|
41
|
+
# +global_options+ a hash of the global options specified on the command-line
|
42
|
+
# +options+ a hash of the command-specific options specific on the command-line.
|
43
|
+
def call(cmd_str=nil, argv=[], stdin=[], global_options={}, options={})
|
44
|
+
@alias = cmd_str.nil? ? @cmd : cmd_str
|
45
|
+
global_options.merge(options).each_pair do |n,v|
|
46
|
+
self.send("#{n}=", v)
|
47
|
+
end
|
48
|
+
block_args = [self, argv, stdin] # TODO: review order
|
49
|
+
@b.call(*block_args[0..(@b.arity-1)]) # send only as many args as defined
|
19
50
|
end
|
51
|
+
|
52
|
+
# The name of the command
|
20
53
|
def to_s
|
21
54
|
@cmd.to_s
|
22
55
|
end
|
23
56
|
end
|
24
57
|
end
|
25
58
|
|
59
|
+
module Drydock
|
60
|
+
class UnknownCommand < RuntimeError
|
61
|
+
attr_reader :name
|
62
|
+
def initialize(name)
|
63
|
+
@name = name || :unknown
|
64
|
+
end
|
65
|
+
def message
|
66
|
+
"Unknown command: #{@name}"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
class NoCommandsDefined < RuntimeError
|
70
|
+
def message
|
71
|
+
"No commands defined"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
class InvalidArgument < RuntimeError
|
75
|
+
attr_accessor :args
|
76
|
+
def initialize(args)
|
77
|
+
@args = args || []
|
78
|
+
end
|
79
|
+
def message
|
80
|
+
"Unknown option: #{@args.join(", ")}"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
class MissingArgument < InvalidArgument
|
84
|
+
def message
|
85
|
+
"Option requires a value: #{@args.join(", ")}"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# Drydock is a DSL for command-line apps.
|
91
|
+
# See bin/example for usage examples.
|
26
92
|
module Drydock
|
27
93
|
extend self
|
28
94
|
|
29
|
-
|
95
|
+
VERSION = 0.3
|
96
|
+
|
97
|
+
private
|
98
|
+
# Stolen from Sinatra!
|
99
|
+
def delegate(*args)
|
100
|
+
args.each do |m|
|
101
|
+
eval(<<-end_eval, binding, "(__Drydock__)", __LINE__)
|
102
|
+
def #{m}(*args, &b)
|
103
|
+
Drydock.#{m}(*args, &b)
|
104
|
+
end
|
105
|
+
end_eval
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
delegate :before, :after, :alias_command, :commands
|
110
|
+
delegate :global_option, :global_usage, :usage, :command
|
111
|
+
delegate :debug, :option, :stdin, :default, :ignore, :command_alias
|
112
|
+
|
113
|
+
@@debug = false
|
114
|
+
@@has_run = false
|
115
|
+
@@run = true
|
116
|
+
|
117
|
+
public
|
118
|
+
# Enable or disable debug output.
|
119
|
+
#
|
120
|
+
# debug :on
|
121
|
+
# debug :off
|
122
|
+
#
|
123
|
+
# Calling without :on or :off will toggle the value.
|
124
|
+
#
|
125
|
+
def debug(toggle=false)
|
126
|
+
if toggle.is_a? Symbol
|
127
|
+
@@debug = true if toggle == :on
|
128
|
+
@@debug = false if toggle == :off
|
129
|
+
else
|
130
|
+
@@debug = (!@@debug)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
# Returns true if debug output is enabled.
|
134
|
+
def debug?
|
135
|
+
@@debug
|
136
|
+
end
|
30
137
|
|
138
|
+
# Define a default command.
|
139
|
+
#
|
140
|
+
# default :task
|
141
|
+
#
|
31
142
|
def default(cmd)
|
32
|
-
|
143
|
+
@@default_command = canonize(cmd)
|
33
144
|
end
|
34
145
|
|
146
|
+
# Define a block for processing STDIN before the command is called.
|
147
|
+
# The command block receives the return value of this block in a named argument:
|
148
|
+
#
|
149
|
+
# command :task do |obj, argv, stdin|; ...; end
|
150
|
+
#
|
151
|
+
# If a stdin block isn't defined, +stdin+ above will be the STDIN IO handle.
|
35
152
|
def stdin(&b)
|
36
|
-
|
153
|
+
@@stdin_block = b
|
37
154
|
end
|
155
|
+
|
156
|
+
# Define a block to be called before the command.
|
157
|
+
# This is useful for opening database connections, etc...
|
38
158
|
def before(&b)
|
39
|
-
|
159
|
+
@@before_block = b
|
40
160
|
end
|
41
161
|
|
42
|
-
#
|
43
|
-
#
|
162
|
+
# Define a block to be called after the command.
|
163
|
+
# This is useful for stopping, closing, etc... the stuff in the before block.
|
164
|
+
def after(&b)
|
165
|
+
@@after_block = b
|
166
|
+
end
|
167
|
+
|
168
|
+
# Define the default global usage banner. This is displayed
|
169
|
+
# with "script -h".
|
44
170
|
def global_usage(msg)
|
45
|
-
|
46
|
-
|
171
|
+
@@global_options ||= OpenStruct.new
|
172
|
+
global_opts_parser.banner = "USAGE: #{msg}"
|
173
|
+
end
|
47
174
|
|
48
|
-
|
175
|
+
# Define a command-specific usage banner. This is displayed
|
176
|
+
# with "script command -h"
|
177
|
+
def usage(msg)
|
178
|
+
get_current_option_parser.banner = "USAGE: #{msg}"
|
49
179
|
end
|
50
180
|
|
51
|
-
|
181
|
+
# Grab the options parser for the current command or create it if it doesn't exist.
|
182
|
+
def get_current_option_parser
|
183
|
+
@@command_opts_parser ||= []
|
184
|
+
@@command_index ||= 0
|
185
|
+
(@@command_opts_parser[@@command_index] ||= OptionParser.new)
|
186
|
+
end
|
52
187
|
|
53
|
-
#
|
188
|
+
# Tell the Drydock parser to ignore something.
|
189
|
+
# Drydock will currently only listen to you if you tell it to "ignore :options",
|
190
|
+
# otherwise it will ignore you!
|
191
|
+
#
|
192
|
+
# +what+ the thing to ignore. When it equals :options Drydock will not parse
|
193
|
+
# the command-specific arguments. It will pass the Command object the list of
|
194
|
+
# arguments. This is useful when you want to parse the arguments in some a way
|
195
|
+
# that's too crazy, dangerous for Drydock to handle automatically.
|
196
|
+
def ignore(what=:nothing)
|
197
|
+
@@command_opts_parser[@@command_index] = :ignore if what == :options || what == :all
|
198
|
+
end
|
199
|
+
|
200
|
+
# Define a global option. See +option+ for more info.
|
201
|
+
def global_option(*args, &b)
|
202
|
+
args.unshift(global_opts_parser)
|
203
|
+
global_option_names << option_parser(args, &b)
|
204
|
+
end
|
205
|
+
|
206
|
+
# Define a command-specific option.
|
207
|
+
#
|
208
|
+
# +args+ is passed directly to OptionParser.on so it can contain anything
|
209
|
+
# that's valid to that method. Some examples:
|
210
|
+
# [:h, :help, "Displays this message"]
|
211
|
+
# [:m, :max, Integer, "Maximum threshold"]
|
212
|
+
# ['-l x,y,z', '--lang=x,y,z', Array, "Requested languages"]
|
213
|
+
# If a class is included, it will tell OptionParser to expect a value
|
214
|
+
# otherwise it assumes a boolean value.
|
54
215
|
#
|
55
|
-
#
|
56
|
-
#
|
57
|
-
#
|
58
|
-
#
|
59
|
-
|
60
|
-
|
61
|
-
|
216
|
+
# All calls to +option+ must come before the command they're associated
|
217
|
+
# to. Example:
|
218
|
+
#
|
219
|
+
# option :l, :longname, String, "Description" do; ...; end
|
220
|
+
# command :task do |obj|; ...; end
|
221
|
+
#
|
222
|
+
# When calling your script with a specific command-line option, the value
|
223
|
+
# is available via obj.longname inside the command block.
|
224
|
+
#
|
225
|
+
def option(*args, &b)
|
226
|
+
args.unshift(get_current_option_parser)
|
227
|
+
current_command_option_names << option_parser(args, &b)
|
228
|
+
end
|
229
|
+
|
230
|
+
# Define a command.
|
231
|
+
#
|
232
|
+
# command :task do
|
233
|
+
# ...
|
234
|
+
# end
|
235
|
+
#
|
236
|
+
# A custom command class can be specified using Hash syntax. The class
|
237
|
+
# must inherit from Drydock::Command (class CustomeClass < Drydock::Command)
|
238
|
+
#
|
239
|
+
# command :task => CustomCommand do
|
240
|
+
# ...
|
241
|
+
# end
|
242
|
+
#
|
243
|
+
def command(*cmds, &b)
|
244
|
+
@@command_index ||= 0
|
245
|
+
@@command_opts_parser ||= []
|
246
|
+
@@command_option_names ||= []
|
247
|
+
cmds.each do |cmd|
|
248
|
+
if cmd.is_a? Hash
|
249
|
+
c = cmd.values.first.new(cmd.keys.first, &b)
|
250
|
+
else
|
251
|
+
c = Drydock::Command.new(cmd, &b)
|
252
|
+
end
|
253
|
+
commands[c.cmd] = c
|
254
|
+
command_index_map[c.cmd] = @@command_index
|
255
|
+
@@command_index += 1
|
256
|
+
end
|
62
257
|
|
63
|
-
|
258
|
+
end
|
259
|
+
|
260
|
+
# Used to create an alias to a defined command.
|
261
|
+
# Here's an example:
|
262
|
+
#
|
263
|
+
# command :task do; ...; end
|
264
|
+
# alias_command :pointer, :task
|
265
|
+
#
|
266
|
+
# Either name can be used on the command-line:
|
267
|
+
#
|
268
|
+
# $ script task [options]
|
269
|
+
# $ script pointer [options]
|
270
|
+
#
|
271
|
+
# Inside of the command definition, you have access to the
|
272
|
+
# command name that was used via obj.alias.
|
273
|
+
def alias_command(aliaz, cmd)
|
274
|
+
return unless commands.has_key? cmd
|
275
|
+
@@commands[aliaz] = commands[cmd]
|
276
|
+
end
|
277
|
+
alias :command_alias :alias_command
|
278
|
+
|
279
|
+
# An array of the currently defined Drydock::Command objects
|
280
|
+
def commands
|
281
|
+
@@commands ||= {}
|
282
|
+
end
|
283
|
+
|
284
|
+
# Returns true if automatic execution is enabled.
|
285
|
+
def run?
|
286
|
+
@@run
|
287
|
+
end
|
288
|
+
|
289
|
+
# Disable automatic execution (enabled by default)
|
290
|
+
#
|
291
|
+
# Drydock.run = false
|
292
|
+
def run=(v)
|
293
|
+
@@run = (v == true) ? true : false
|
294
|
+
end
|
295
|
+
|
296
|
+
# Return true if a command has been executed.
|
297
|
+
def has_run?
|
298
|
+
@@has_run
|
299
|
+
end
|
300
|
+
|
301
|
+
# Execute the given command.
|
302
|
+
# By default, Drydock automatically executes itself and provides handlers for known errors.
|
303
|
+
# You can override this functionality by calling +Drydock.run!+ yourself. Drydock
|
304
|
+
# will only call +run!+ once.
|
305
|
+
def run!(argv=[], stdin=STDIN)
|
306
|
+
return if has_run?
|
307
|
+
@@has_run = true
|
308
|
+
raise NoCommandsDefined.new unless commands
|
309
|
+
@@global_options, cmd_name, @@command_options, argv = process_arguments(argv)
|
64
310
|
|
65
|
-
|
66
|
-
global_options = global_options.keys.inject({}) do |hash, key|
|
67
|
-
hash[key.to_sym] = global_options[key]
|
68
|
-
hash
|
69
|
-
end
|
311
|
+
cmd_name ||= default_command
|
70
312
|
|
71
|
-
cmd_name = (argv.empty?) ? @default_command : argv.shift
|
72
313
|
raise UnknownCommand.new(cmd_name) unless command?(cmd_name)
|
73
314
|
|
74
|
-
|
75
|
-
|
315
|
+
stdin = (defined? @@stdin_block) ? @@stdin_block.call(stdin, []) : stdin
|
316
|
+
@@before_block.call if defined? @@before_block
|
76
317
|
|
77
|
-
|
78
|
-
command_options = command_options.keys.inject({}) do |hash, key|
|
79
|
-
hash[key.to_sym] = command_options[key]
|
80
|
-
hash
|
81
|
-
end
|
318
|
+
call_command(cmd_name, argv, stdin)
|
82
319
|
|
83
|
-
|
320
|
+
@@after_block.call if defined? @@after_block
|
321
|
+
|
322
|
+
rescue OptionParser::InvalidOption => ex
|
323
|
+
raise Drydock::InvalidArgument.new(ex.args)
|
324
|
+
rescue OptionParser::MissingArgument => ex
|
325
|
+
raise Drydock::MissingArgument.new(ex.args)
|
84
326
|
end
|
85
327
|
|
86
|
-
|
328
|
+
private
|
87
329
|
|
88
|
-
|
89
|
-
|
330
|
+
# Executes the block associated to +cmd+
|
331
|
+
def call_command(cmd, argv=[], stdin=nil)
|
332
|
+
return unless command?(cmd)
|
333
|
+
get_command(cmd).call(cmd, argv, stdin, @@global_options || {}, @@command_options || {})
|
90
334
|
end
|
91
335
|
|
92
|
-
#
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
@command_index ||= 0
|
98
|
-
(@command_opts_parser[@command_index] ||= OptionParser.new)
|
99
|
-
end
|
336
|
+
# Returns the Drydock::Command object with the name +cmd+
|
337
|
+
def get_command(cmd)
|
338
|
+
return unless command?(cmd)
|
339
|
+
@@commands[canonize(cmd)]
|
340
|
+
end
|
100
341
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
342
|
+
# Returns true if a command with the name +cmd+ has been defined.
|
343
|
+
def command?(cmd)
|
344
|
+
name = canonize(cmd)
|
345
|
+
(@@commands || {}).has_key? name
|
105
346
|
end
|
106
347
|
|
107
|
-
|
108
|
-
|
109
|
-
|
348
|
+
# Canonizes a string to the symbol format for command names
|
349
|
+
def canonize(cmd)
|
350
|
+
return unless cmd
|
351
|
+
return cmd if cmd.kind_of?(Symbol)
|
352
|
+
cmd.tr('-', '_').to_sym
|
110
353
|
end
|
111
354
|
|
112
|
-
# option_parser
|
113
|
-
#
|
114
355
|
# Processes calls to option and global_option. Symbols are converted into
|
115
|
-
# OptionParser style strings (:h and :help become '-h' and '--help').
|
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"]
|
356
|
+
# OptionParser style strings (:h and :help become '-h' and '--help').
|
124
357
|
def option_parser(args=[], &b)
|
125
358
|
return if args.empty?
|
126
359
|
opts_parser = args.shift
|
127
360
|
|
361
|
+
arg_name = ''
|
128
362
|
symbol_switches = []
|
129
363
|
args.each_with_index do |arg, index|
|
130
364
|
if arg.is_a? Symbol
|
365
|
+
arg_name = arg.to_s if arg.to_s.size > arg_name.size
|
131
366
|
args[index] = (arg.to_s.length == 1) ? "-#{arg.to_s}" : "--#{arg.to_s}"
|
132
367
|
symbol_switches << args[index]
|
133
368
|
elsif arg.kind_of?(Class)
|
@@ -145,88 +380,103 @@ module Drydock
|
|
145
380
|
result = (b.nil?) ? v : b.call(*block_args[0..(b.arity-1)])
|
146
381
|
end
|
147
382
|
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
383
|
|
158
|
-
|
384
|
+
arg_name
|
159
385
|
end
|
160
386
|
|
161
|
-
def alias_command(aliaz, cmd)
|
162
|
-
return unless @commands.has_key? cmd
|
163
|
-
@commands[aliaz] = @commands[cmd]
|
164
|
-
end
|
165
387
|
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
388
|
+
# Split the +argv+ array into global args and command args and
|
389
|
+
# find the command name.
|
390
|
+
# i.e. ./script -H push -f (-H is a global arg, push is the command, -f is a command arg)
|
391
|
+
# returns [global_options, cmd, command_options, argv]
|
392
|
+
def process_arguments(argv=[])
|
393
|
+
global_options = command_options = {}
|
394
|
+
cmd = nil
|
171
395
|
|
396
|
+
global_options = global_opts_parser.getopts(argv)
|
397
|
+
|
398
|
+
cmd_name = (argv.empty?) ? @@default_command : argv.shift
|
172
399
|
raise UnknownCommand.new(cmd_name) unless command?(cmd_name)
|
173
400
|
|
174
|
-
|
175
|
-
@before_block.call if defined? @before_block
|
401
|
+
cmd = get_command(cmd_name)
|
176
402
|
|
403
|
+
command_parser = @@command_opts_parser[get_command_index(cmd_name)]
|
404
|
+
command_options = {}
|
177
405
|
|
178
|
-
|
406
|
+
# We only need to parse the options out of the arguments when
|
407
|
+
# there are args available, there is a valid parser, and
|
408
|
+
# we weren't requested to ignore the options.
|
409
|
+
if !argv.empty? && command_parser && command_parser != :ignore
|
410
|
+
command_options = command_parser.getopts(argv)
|
411
|
+
end
|
179
412
|
|
413
|
+
# Add accessors to the Drydock::Command object
|
414
|
+
# for the global and command specific options
|
415
|
+
[global_option_names, (command_option_names[get_command_index(cmd_name)] || [])].flatten.each do |n|
|
416
|
+
unless cmd.respond_to?(n)
|
417
|
+
cmd.class.send(:define_method, n) do
|
418
|
+
instance_variable_get("@#{n}")
|
419
|
+
end
|
420
|
+
end
|
421
|
+
unless cmd.respond_to?("#{n}=")
|
422
|
+
cmd.class.send(:define_method, "#{n}=") do |val|
|
423
|
+
instance_variable_set("@#{n}", val)
|
424
|
+
end
|
425
|
+
end
|
426
|
+
end
|
180
427
|
|
181
|
-
|
182
|
-
raise Drydock::InvalidArgument.new(ex.args)
|
183
|
-
rescue OptionParser::MissingArgument => ex
|
184
|
-
raise Drydock::MissingArgument.new(ex.args)
|
428
|
+
[global_options, cmd_name, command_options, argv]
|
185
429
|
end
|
186
430
|
|
187
|
-
|
188
|
-
|
189
|
-
return unless command?(cmd_str)
|
190
|
-
get_command(cmd_str).call(cmd_str, argv, stdin, @global_options, @command_options)
|
431
|
+
def global_option_names
|
432
|
+
@@global_option_names ||= []
|
191
433
|
end
|
192
434
|
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
435
|
+
# Grab the current list of command-specific option names. This is a list of the
|
436
|
+
# long names.
|
437
|
+
def current_command_option_names
|
438
|
+
@@command_option_names ||= []
|
439
|
+
@@command_index ||= 0
|
440
|
+
(@@command_option_names[@@command_index] ||= [])
|
441
|
+
end
|
197
442
|
|
198
|
-
def
|
199
|
-
|
443
|
+
def command_index_map
|
444
|
+
@@command_index_map ||= {}
|
200
445
|
end
|
201
446
|
|
202
|
-
def
|
203
|
-
|
447
|
+
def get_command_index(cmd)
|
448
|
+
command_index_map[canonize(cmd)] || -1
|
204
449
|
end
|
205
450
|
|
206
|
-
def
|
207
|
-
|
451
|
+
def command_option_names
|
452
|
+
@@command_option_names ||= []
|
208
453
|
end
|
209
454
|
|
210
|
-
def
|
211
|
-
|
212
|
-
(@commands || {}).has_key? name
|
455
|
+
def global_opts_parser
|
456
|
+
@@global_opts_parser ||= OptionParser.new
|
213
457
|
end
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
cmd.tr('-', '_').to_sym
|
458
|
+
|
459
|
+
def default_command
|
460
|
+
@@default_command ||= nil
|
218
461
|
end
|
219
462
|
|
220
463
|
end
|
221
464
|
|
222
|
-
Drydock
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
end_eval
|
465
|
+
include Drydock
|
466
|
+
|
467
|
+
trap ("SIGINT") do
|
468
|
+
puts "#{$/}Exiting..."
|
469
|
+
exit 1
|
228
470
|
end
|
229
471
|
|
230
472
|
|
473
|
+
at_exit {
|
474
|
+
begin
|
475
|
+
Drydock.run!(ARGV, STDIN) if Drydock.run? && !Drydock.has_run?
|
476
|
+
rescue => ex
|
477
|
+
STDERR.puts "ERROR: #{ex.message}"
|
478
|
+
STDERR.puts ex.backtrace if Drydock.debug?
|
479
|
+
end
|
480
|
+
}
|
231
481
|
|
232
482
|
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/../lib/drydock"
|
2
|
+
require "rubygems"
|
3
|
+
require "test/spec"
|
4
|
+
require "mocha"
|
5
|
+
|
6
|
+
class Test::Unit::TestCase
|
7
|
+
def test_command_direct(cmd, argv, &b)
|
8
|
+
Drydock::Command.new(cmd, &b).call(*argv)
|
9
|
+
end
|
10
|
+
def test_command(*args, &b)
|
11
|
+
command(*args, &b)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class JohnWestSmokedOysters < Drydock::Command; end;
|
16
|
+
|
17
|
+
Drydock.run = false
|
18
|
+
|
19
|
+
context "command" do
|
20
|
+
|
21
|
+
setup do
|
22
|
+
@mock = mock()
|
23
|
+
end
|
24
|
+
|
25
|
+
specify "should know a command alias" do
|
26
|
+
@mock.expects(:called).with(:eat_alias)
|
27
|
+
test_command_direct(:eat, [:eat_alias]) { |obj,argv|
|
28
|
+
@mock.called(obj.alias)
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
specify "should accept a custom command class" do
|
33
|
+
@mock.expects(:called).with(JohnWestSmokedOysters)
|
34
|
+
test_command(:eat => JohnWestSmokedOysters) { |obj,argv|
|
35
|
+
@mock.called(obj.class)
|
36
|
+
}
|
37
|
+
Drydock.run!(['eat'])
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
metadata
CHANGED
@@ -1,11 +1,10 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: delano-drydock
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Delano Mandelbaum
|
8
|
-
- Blake Mizerany
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
@@ -14,7 +13,7 @@ date: 2008-08-17 00:00:00 -07:00
|
|
14
13
|
default_executable:
|
15
14
|
dependencies: []
|
16
15
|
|
17
|
-
description:
|
16
|
+
description: A seaworthy DSL for writing command line apps inspired by Blake Mizerany's Frylock
|
18
17
|
email: delano@solutious.com
|
19
18
|
executables: []
|
20
19
|
|
@@ -23,12 +22,39 @@ extensions: []
|
|
23
22
|
extra_rdoc_files:
|
24
23
|
- README.rdoc
|
25
24
|
- LICENSE.txt
|
25
|
+
- CHANGES.txt
|
26
26
|
files:
|
27
|
+
- CHANGES.txt
|
27
28
|
- LICENSE.txt
|
28
29
|
- README.rdoc
|
30
|
+
- Rakefile
|
29
31
|
- bin/example
|
30
|
-
-
|
32
|
+
- drydock.gemspec
|
31
33
|
- lib/drydock.rb
|
34
|
+
- test/command_test.rb
|
35
|
+
- doc
|
36
|
+
- doc/classes
|
37
|
+
- doc/classes/Drydock
|
38
|
+
- doc/classes/Drydock/Command.html
|
39
|
+
- doc/classes/Drydock/InvalidArgument.html
|
40
|
+
- doc/classes/Drydock/MissingArgument.html
|
41
|
+
- doc/classes/Drydock/NoCommandsDefined.html
|
42
|
+
- doc/classes/Drydock/UnknownCommand.html
|
43
|
+
- doc/classes/Drydock.html
|
44
|
+
- doc/created.rid
|
45
|
+
- doc/files
|
46
|
+
- doc/files/bin
|
47
|
+
- doc/files/bin/example.html
|
48
|
+
- doc/files/CHANGES_txt.html
|
49
|
+
- doc/files/lib
|
50
|
+
- doc/files/lib/drydock_rb.html
|
51
|
+
- doc/files/LICENSE_txt.html
|
52
|
+
- doc/files/README_rdoc.html
|
53
|
+
- doc/fr_class_index.html
|
54
|
+
- doc/fr_file_index.html
|
55
|
+
- doc/fr_method_index.html
|
56
|
+
- doc/index.html
|
57
|
+
- doc/rdoc-style.css
|
32
58
|
has_rdoc: true
|
33
59
|
homepage: http://github.com/delano/drydock
|
34
60
|
post_install_message:
|
@@ -36,7 +62,7 @@ rdoc_options:
|
|
36
62
|
- --line-numbers
|
37
63
|
- --inline-source
|
38
64
|
- --title
|
39
|
-
- "Drydock:
|
65
|
+
- "Drydock: a seaworthy DSL for command-line apps"
|
40
66
|
- --main
|
41
67
|
- README.rdoc
|
42
68
|
require_paths:
|
@@ -55,10 +81,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
55
81
|
version:
|
56
82
|
requirements: []
|
57
83
|
|
58
|
-
rubyforge_project:
|
84
|
+
rubyforge_project: drydock
|
59
85
|
rubygems_version: 1.2.0
|
60
86
|
signing_key:
|
61
87
|
specification_version: 1
|
62
|
-
summary:
|
88
|
+
summary: A seaworthy DSL for writing command line apps
|
63
89
|
test_files: []
|
64
90
|
|
data/lib/drydock/exceptions.rb
DELETED
@@ -1,24 +0,0 @@
|
|
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
|