executable 1.1.0 → 1.2.0
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/.ruby +61 -0
- data/.yardopts +7 -0
- data/COPYING.rdoc +35 -0
- data/DEMO.rdoc +568 -0
- data/HISTORY.rdoc +55 -0
- data/README.rdoc +101 -51
- data/Schedule.reap +17 -0
- data/demo/00_introduction.rdoc +6 -0
- data/demo/01_single_command.rdoc +44 -0
- data/demo/02_multiple_commands.rdoc +125 -0
- data/demo/03_help_text.rdoc +109 -0
- data/demo/04_manpage.rdoc +14 -0
- data/demo/05_optparse_example.rdoc +152 -0
- data/demo/06_delegate_example.rdoc +40 -0
- data/demo/07_command_methods.rdoc +36 -0
- data/demo/08_dispatach.rdoc +29 -0
- data/demo/applique/ae.rb +1 -0
- data/demo/applique/compare.rb +4 -0
- data/demo/applique/exec.rb +1 -0
- data/demo/samples/bin/hello +31 -0
- data/demo/samples/man/hello.1 +22 -0
- data/demo/samples/man/hello.1.html +102 -0
- data/demo/samples/man/hello.1.ronn +19 -0
- data/lib/executable.rb +67 -128
- data/lib/executable/core_ext.rb +102 -0
- data/lib/executable/dispatch.rb +30 -0
- data/lib/executable/domain.rb +106 -0
- data/lib/executable/errors.rb +22 -0
- data/lib/executable/help.rb +430 -0
- data/lib/executable/parser.rb +208 -0
- data/lib/executable/utils.rb +41 -0
- data/lib/executable/version.rb +23 -0
- data/meta/authors +2 -0
- data/meta/copyrights +3 -0
- data/meta/created +1 -0
- data/meta/description +6 -0
- data/meta/name +1 -0
- data/meta/organization +1 -0
- data/meta/repositories +2 -0
- data/meta/requirements +6 -0
- data/meta/resources +7 -0
- data/meta/summary +1 -0
- data/meta/version +1 -0
- data/test/test_executable.rb +40 -19
- metadata +124 -68
- data/History.rdoc +0 -35
- data/NOTICE.rdoc +0 -23
- data/Profile +0 -30
- data/Version +0 -1
- data/meta/license/Apache2.txt +0 -177
@@ -0,0 +1,208 @@
|
|
1
|
+
module Executable
|
2
|
+
|
3
|
+
# The Parser class does all the heavy lifting for Executable.
|
4
|
+
#
|
5
|
+
class Parser
|
6
|
+
|
7
|
+
#
|
8
|
+
# @param [Executable] cli_class
|
9
|
+
# An executabe class.
|
10
|
+
#
|
11
|
+
def initialize(cli_class)
|
12
|
+
@cli_class = cli_class
|
13
|
+
end
|
14
|
+
|
15
|
+
attr :cli_class
|
16
|
+
|
17
|
+
# Parse command-line.
|
18
|
+
#
|
19
|
+
# @param argv [Array,String] command-line arguments
|
20
|
+
#
|
21
|
+
def parse(argv=ARGV)
|
22
|
+
# duplicate to make sure ARGV stay intact.
|
23
|
+
argv = argv.dup
|
24
|
+
argv = parse_shellwords(argv)
|
25
|
+
|
26
|
+
cmd, argv = parse_subcommand(argv)
|
27
|
+
cli = cmd.new
|
28
|
+
args = parse_arguments(cli, argv)
|
29
|
+
|
30
|
+
return cli, args
|
31
|
+
end
|
32
|
+
|
33
|
+
# Make sure arguments are an array. If argv is a String,
|
34
|
+
# then parse using Shellwords module.
|
35
|
+
#
|
36
|
+
# @param argv [Array,String] commmand-line arguments
|
37
|
+
def parse_shellwords(argv)
|
38
|
+
if String === argv
|
39
|
+
require 'shellwords'
|
40
|
+
argv = Shellwords.shellwords(argv)
|
41
|
+
end
|
42
|
+
argv.to_a
|
43
|
+
end
|
44
|
+
|
45
|
+
#
|
46
|
+
#
|
47
|
+
#
|
48
|
+
def parse_subcommand(argv)
|
49
|
+
cmd = cli_class
|
50
|
+
arg = argv.first
|
51
|
+
|
52
|
+
while c = cmd.subcommands[arg]
|
53
|
+
cmd = c
|
54
|
+
argv.shift
|
55
|
+
arg = argv.first
|
56
|
+
end
|
57
|
+
|
58
|
+
return cmd, argv
|
59
|
+
end
|
60
|
+
|
61
|
+
#
|
62
|
+
# Parse command line options based on given object.
|
63
|
+
#
|
64
|
+
# @param obj [Object] basis for command-line parsing
|
65
|
+
# @param argv [Array,String] command-line arguments
|
66
|
+
# @param args [Array] pre-seeded arguments to add to
|
67
|
+
#
|
68
|
+
# @return [Array] parsed arguments
|
69
|
+
#
|
70
|
+
def parse_arguments(obj, argv, args=[])
|
71
|
+
case argv
|
72
|
+
when String
|
73
|
+
require 'shellwords'
|
74
|
+
argv = Shellwords.shellwords(argv)
|
75
|
+
#else
|
76
|
+
# argv = argv.dup
|
77
|
+
end
|
78
|
+
|
79
|
+
#subc = nil
|
80
|
+
#@args = [] #opts, i = {}, 0
|
81
|
+
|
82
|
+
while argv.size > 0
|
83
|
+
case arg = argv.shift
|
84
|
+
when /=/
|
85
|
+
parse_equal(obj, arg, argv, args)
|
86
|
+
when /^--/
|
87
|
+
parse_long(obj, arg, argv, args)
|
88
|
+
when /^-/
|
89
|
+
parse_flags(obj, arg, argv, args)
|
90
|
+
else
|
91
|
+
#if Executable === obj
|
92
|
+
# if cmd_class = obj.class.subcommands[arg]
|
93
|
+
# cmd = cmd_class.new(obj)
|
94
|
+
# subc = cmd
|
95
|
+
# parse(cmd, argv, args)
|
96
|
+
# else
|
97
|
+
args << arg
|
98
|
+
# end
|
99
|
+
#end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
return args
|
104
|
+
end
|
105
|
+
|
106
|
+
#
|
107
|
+
# Parse equal setting comman-line option.
|
108
|
+
#
|
109
|
+
def parse_equal(obj, opt, argv, args)
|
110
|
+
if md = /^[-]*(.*?)=(.*?)$/.match(opt)
|
111
|
+
x, v = md[1], md[2]
|
112
|
+
else
|
113
|
+
raise ArgumentError, "#{x}"
|
114
|
+
end
|
115
|
+
if obj.respond_to?("#{x}=")
|
116
|
+
v = true if v == 'true' # yes or on ?
|
117
|
+
v = false if v == 'false' # no or off ?
|
118
|
+
obj.send("#{x}=", v)
|
119
|
+
else
|
120
|
+
obj.__send__(:option_missing, x, v) # argv?
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
#
|
125
|
+
# Parse double-dash command-line option.
|
126
|
+
#
|
127
|
+
def parse_long(obj, opt, argv, args)
|
128
|
+
x = opt.sub(/^\-+/, '') # remove '--'
|
129
|
+
if obj.respond_to?("#{x}=")
|
130
|
+
m = obj.method("#{x}=")
|
131
|
+
if obj.respond_to?("#{x}?")
|
132
|
+
m.call(true)
|
133
|
+
else
|
134
|
+
invoke(obj, m, argv)
|
135
|
+
end
|
136
|
+
elsif obj.respond_to?("#{x}!")
|
137
|
+
invoke(obj, "#{x}!", argv)
|
138
|
+
else
|
139
|
+
# call even if private method
|
140
|
+
obj.__send__(:option_missing, x, argv)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
# TODO: parse_flags needs some thought concerning character
|
145
|
+
# spliting and arguments.
|
146
|
+
|
147
|
+
#
|
148
|
+
# Parse single-dash command-line option.
|
149
|
+
#
|
150
|
+
def parse_flags(obj, opt, argv, args)
|
151
|
+
x = opt[1..-1]
|
152
|
+
c = 0
|
153
|
+
x.split(//).each do |k|
|
154
|
+
if obj.respond_to?("#{k}=")
|
155
|
+
m = obj.method("#{k}=")
|
156
|
+
if obj.respond_to?("#{x}?")
|
157
|
+
m.call(true)
|
158
|
+
else
|
159
|
+
invoke(obj, m, argv) #m.call(argv.shift)
|
160
|
+
end
|
161
|
+
elsif obj.respond_to?("#{k}!")
|
162
|
+
invoke(obj, "#{k}!", argv)
|
163
|
+
else
|
164
|
+
long = find_long_option(obj, k)
|
165
|
+
if long
|
166
|
+
if long.end_with?('=') && obj.respond_to?(long.chomp('=')+'?')
|
167
|
+
invoke(obj, long, [true])
|
168
|
+
else
|
169
|
+
invoke(obj, long, argv)
|
170
|
+
end
|
171
|
+
else
|
172
|
+
obj.__send__(:option_missing, x, argv)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
#
|
179
|
+
#
|
180
|
+
# @todo Sort alphabetically?
|
181
|
+
#
|
182
|
+
def find_long_option(obj, char)
|
183
|
+
meths = obj.methods.map{ |m| m.to_s }
|
184
|
+
meths = meths.select do |m|
|
185
|
+
m.start_with?(char) and (m.end_with?('=') or m.end_with?('!'))
|
186
|
+
end
|
187
|
+
meths.first
|
188
|
+
end
|
189
|
+
|
190
|
+
#
|
191
|
+
#
|
192
|
+
def invoke(obj, meth, argv)
|
193
|
+
m = (Method === meth ? meth : obj.method(meth))
|
194
|
+
a = []
|
195
|
+
m.arity.abs.times{ a << argv.shift }
|
196
|
+
m.call(*a)
|
197
|
+
end
|
198
|
+
|
199
|
+
# Index of subcommands.
|
200
|
+
#
|
201
|
+
# @return [Hash] name mapped to subcommnd class
|
202
|
+
def subcommands
|
203
|
+
@cli_class.subcommands
|
204
|
+
end
|
205
|
+
|
206
|
+
end
|
207
|
+
|
208
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Executable
|
2
|
+
|
3
|
+
# Some handy-dandy CLI utility methods.
|
4
|
+
#
|
5
|
+
module Utils
|
6
|
+
extend self
|
7
|
+
|
8
|
+
# TODO: Maybe #ask chould serve all purposes depending on degfault?
|
9
|
+
# e.g. `ask?("ok?", default=>true)`, would be same as `yes?("ok?")`.
|
10
|
+
|
11
|
+
# Strings to interprest as boolean values.
|
12
|
+
BOOLEAN_MAP = {"y"=>true, "yes"=>true, "n"=>false, "no"=>false}
|
13
|
+
|
14
|
+
# Query the user for a yes/no answer, defaulting to yes.
|
15
|
+
def yes?(question, options={})
|
16
|
+
print "#{question} [Y/n] "
|
17
|
+
input = STDIN.readline.chomp.downcase
|
18
|
+
BOOLEAN_MAP[input] || true
|
19
|
+
end
|
20
|
+
|
21
|
+
# Query the user for a yes/no answer, defaulting to no.
|
22
|
+
def no?(question, options={})
|
23
|
+
print "#{question} [y/N] "
|
24
|
+
input = STDIN.readline.chomp.downcase
|
25
|
+
BOOLEAN_MAP[input] || false
|
26
|
+
end
|
27
|
+
|
28
|
+
# Query the user for an answer.
|
29
|
+
def ask(question, options={})
|
30
|
+
print "#{question} [default: #{options[:default]}] "
|
31
|
+
reply = STDIN.readline.chomp
|
32
|
+
if reply.empty?
|
33
|
+
options[:default]
|
34
|
+
else
|
35
|
+
reply
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Exectuable
|
2
|
+
|
3
|
+
#
|
4
|
+
DIRECTORY = File.dirname(__FILE__)
|
5
|
+
|
6
|
+
#
|
7
|
+
def self.version
|
8
|
+
@package ||= (
|
9
|
+
require 'yaml'
|
10
|
+
YAML.load(File.new(DIRECTORY + '/version.yml'))
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
#
|
15
|
+
def self.const_missing(name)
|
16
|
+
version[name.to_s.downcase] || super(name)
|
17
|
+
end
|
18
|
+
|
19
|
+
# because Ruby 1.8~ gets in the way
|
20
|
+
remove_const(:VERSION) if const_defined?(:VERSION)
|
21
|
+
|
22
|
+
end
|
23
|
+
|
data/meta/authors
ADDED
data/meta/copyrights
ADDED
data/meta/created
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2008-08-08
|
data/meta/description
ADDED
@@ -0,0 +1,6 @@
|
|
1
|
+
Think of Executable as a *COM*, a Commandline Object Mapper,
|
2
|
+
in much the same way that ActiveRecord is an ORM,
|
3
|
+
an Object Relational Mapper. A class utilizing Executable
|
4
|
+
can define a complete command line tool using nothing more
|
5
|
+
than Ruby's own method definitions.
|
6
|
+
|
data/meta/name
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
executable
|
data/meta/organization
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rubyworks
|
data/meta/repositories
ADDED
data/meta/requirements
ADDED
data/meta/resources
ADDED
data/meta/summary
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Commandline Object Mapper
|
data/meta/version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.2.0
|
data/test/test_executable.rb
CHANGED
@@ -1,38 +1,59 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__)+'/../lib')
|
2
|
+
|
3
|
+
require 'microtest'
|
4
|
+
require 'ae'
|
5
|
+
|
1
6
|
require 'executable'
|
2
7
|
|
3
|
-
class
|
8
|
+
class ExecutableTestCase < MicroTest::TestCase
|
4
9
|
|
5
|
-
class
|
10
|
+
class MyCommand
|
6
11
|
include Executable
|
7
12
|
|
8
|
-
|
13
|
+
attr_reader :size, :quiet, :file
|
9
14
|
|
10
15
|
def initialize
|
11
|
-
@
|
16
|
+
@file = 'hey.txt' # default
|
17
|
+
end
|
18
|
+
|
19
|
+
def quiet=(bool)
|
20
|
+
@quiet = bool
|
21
|
+
end
|
22
|
+
|
23
|
+
def quiet?
|
24
|
+
@quiet
|
12
25
|
end
|
13
26
|
|
14
|
-
def
|
15
|
-
@
|
27
|
+
def size=(integer)
|
28
|
+
@size = integer.to_i
|
16
29
|
end
|
17
30
|
|
18
|
-
def
|
19
|
-
@
|
31
|
+
def file=(fname)
|
32
|
+
@file = fname
|
33
|
+
end
|
34
|
+
|
35
|
+
def call(*args)
|
36
|
+
@args = args
|
20
37
|
end
|
21
38
|
end
|
22
39
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
s.execute!("jump")
|
27
|
-
assert_equal(s.result, ["jump"])
|
40
|
+
def test_boolean_optiion
|
41
|
+
mc = MyCommand.execute('--quiet')
|
42
|
+
mc.assert.quiet?
|
28
43
|
end
|
29
44
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
s.execute!("jump --output=home")
|
34
|
-
assert_equal(s.result, ['output: home', 'jump'])
|
45
|
+
def test_integer_optiion
|
46
|
+
mc = MyCommand.execute('--size=4')
|
47
|
+
mc.size.assert == 4
|
35
48
|
end
|
36
49
|
|
37
|
-
|
50
|
+
def test_default_value
|
51
|
+
mc = MyCommand.execute('')
|
52
|
+
mc.file.assert == 'hey.txt'
|
53
|
+
end
|
54
|
+
|
55
|
+
#def usage_output
|
56
|
+
# MyCommand.help.usage.assert == "{$0} [options] [subcommand]"
|
57
|
+
#end
|
38
58
|
|
59
|
+
end
|
metadata
CHANGED
@@ -1,90 +1,146 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: executable
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease:
|
6
|
-
segments:
|
7
|
-
- 1
|
8
|
-
- 1
|
9
|
-
- 0
|
10
|
-
version: 1.1.0
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.2.0
|
5
|
+
prerelease:
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
13
|
-
-
|
7
|
+
authors:
|
8
|
+
- 7rans
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
12
|
+
date: 2012-02-01 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: qed
|
16
|
+
requirement: &16160360 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
23
|
prerelease: false
|
24
|
-
|
24
|
+
version_requirements: *16160360
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: ae
|
27
|
+
requirement: &16158800 !ruby/object:Gem::Requirement
|
25
28
|
none: false
|
26
|
-
requirements:
|
27
|
-
- -
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
|
30
|
-
segments:
|
31
|
-
- 0
|
32
|
-
version: "0"
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
33
|
type: :development
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *16158800
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: detroit
|
38
|
+
requirement: &16156720 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *16156720
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: simplecov
|
49
|
+
requirement: &16155820 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *16155820
|
58
|
+
description: ! 'Think of Executable as a *COM*, a Commandline Object Mapper,
|
38
59
|
|
39
|
-
|
60
|
+
in much the same way that ActiveRecord is an ORM,
|
61
|
+
|
62
|
+
an Object Relational Mapper. A class utilizing Executable
|
63
|
+
|
64
|
+
can define a complete command line tool using nothing more
|
40
65
|
|
41
|
-
|
66
|
+
than Ruby''s own method definitions.'
|
67
|
+
email:
|
68
|
+
- transfire@gmail.com
|
69
|
+
executables: []
|
70
|
+
extensions: []
|
71
|
+
extra_rdoc_files:
|
72
|
+
- HISTORY.rdoc
|
73
|
+
- DEMO.rdoc
|
42
74
|
- README.rdoc
|
43
|
-
|
75
|
+
- COPYING.rdoc
|
76
|
+
files:
|
77
|
+
- .ruby
|
78
|
+
- .yardopts
|
79
|
+
- demo/00_introduction.rdoc
|
80
|
+
- demo/01_single_command.rdoc
|
81
|
+
- demo/02_multiple_commands.rdoc
|
82
|
+
- demo/03_help_text.rdoc
|
83
|
+
- demo/04_manpage.rdoc
|
84
|
+
- demo/05_optparse_example.rdoc
|
85
|
+
- demo/06_delegate_example.rdoc
|
86
|
+
- demo/07_command_methods.rdoc
|
87
|
+
- demo/08_dispatach.rdoc
|
88
|
+
- demo/applique/ae.rb
|
89
|
+
- demo/applique/compare.rb
|
90
|
+
- demo/applique/exec.rb
|
91
|
+
- demo/samples/bin/hello
|
92
|
+
- demo/samples/man/hello.1
|
93
|
+
- demo/samples/man/hello.1.html
|
94
|
+
- demo/samples/man/hello.1.ronn
|
95
|
+
- lib/executable/core_ext.rb
|
96
|
+
- lib/executable/dispatch.rb
|
97
|
+
- lib/executable/domain.rb
|
98
|
+
- lib/executable/errors.rb
|
99
|
+
- lib/executable/help.rb
|
100
|
+
- lib/executable/parser.rb
|
101
|
+
- lib/executable/utils.rb
|
102
|
+
- lib/executable/version.rb
|
44
103
|
- lib/executable.rb
|
45
|
-
- meta/
|
104
|
+
- meta/authors
|
105
|
+
- meta/copyrights
|
106
|
+
- meta/created
|
107
|
+
- meta/description
|
108
|
+
- meta/name
|
109
|
+
- meta/organization
|
110
|
+
- meta/repositories
|
111
|
+
- meta/requirements
|
112
|
+
- meta/resources
|
113
|
+
- meta/summary
|
114
|
+
- meta/version
|
46
115
|
- test/test_executable.rb
|
47
|
-
-
|
116
|
+
- HISTORY.rdoc
|
117
|
+
- DEMO.rdoc
|
118
|
+
- Schedule.reap
|
48
119
|
- README.rdoc
|
49
|
-
-
|
50
|
-
- Version
|
51
|
-
- NOTICE.rdoc
|
52
|
-
has_rdoc: true
|
120
|
+
- COPYING.rdoc
|
53
121
|
homepage: http://rubyworks.github.com/executable
|
54
|
-
licenses:
|
55
|
-
-
|
122
|
+
licenses:
|
123
|
+
- BSD-2-Clause
|
56
124
|
post_install_message:
|
57
|
-
rdoc_options:
|
58
|
-
|
59
|
-
- Executable API
|
60
|
-
- --main
|
61
|
-
- README.rdoc
|
62
|
-
require_paths:
|
125
|
+
rdoc_options: []
|
126
|
+
require_paths:
|
63
127
|
- lib
|
64
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
128
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
65
129
|
none: false
|
66
|
-
requirements:
|
67
|
-
- -
|
68
|
-
- !ruby/object:Gem::Version
|
69
|
-
|
70
|
-
|
71
|
-
- 0
|
72
|
-
version: "0"
|
73
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
130
|
+
requirements:
|
131
|
+
- - ! '>='
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
134
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
135
|
none: false
|
75
|
-
requirements:
|
76
|
-
- -
|
77
|
-
- !ruby/object:Gem::Version
|
78
|
-
|
79
|
-
segments:
|
80
|
-
- 0
|
81
|
-
version: "0"
|
136
|
+
requirements:
|
137
|
+
- - ! '>='
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: '0'
|
82
140
|
requirements: []
|
83
|
-
|
84
|
-
|
85
|
-
rubygems_version: 1.3.7
|
141
|
+
rubyforge_project:
|
142
|
+
rubygems_version: 1.8.11
|
86
143
|
signing_key:
|
87
144
|
specification_version: 3
|
88
|
-
summary:
|
89
|
-
test_files:
|
90
|
-
- test/test_executable.rb
|
145
|
+
summary: Commandline Object Mapper
|
146
|
+
test_files: []
|