executable 1.0.0 → 1.1.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/History.rdoc +35 -0
- data/NOTICE.rdoc +23 -0
- data/{PROFILE → Profile} +0 -0
- data/{README → README.rdoc} +30 -13
- data/Version +1 -0
- data/lib/executable.rb +65 -116
- data/{LICENSE → meta/license/Apache2.txt} +1 -28
- data/test/test_executable.rb +2 -2
- metadata +16 -13
- data/HISTORY +0 -11
- data/Rakefile +0 -11
data/History.rdoc
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
= RELEASE HISTORY
|
2
|
+
|
3
|
+
== 1.1.0 / 2011-04-21
|
4
|
+
|
5
|
+
This release simplifies Exectuable, removing the #option_missing method
|
6
|
+
and using the standard #method_missing callback instead. Along with this
|
7
|
+
the special error class, +NoOptionError+, has been removed. This release
|
8
|
+
also fixes an issue with inconsistant arguments being passed to the callback.
|
9
|
+
Finally it renames the #execute_command method to simple #execute!.
|
10
|
+
|
11
|
+
Changes:
|
12
|
+
|
13
|
+
* Name Changes
|
14
|
+
|
15
|
+
* Renamed `#execute_command` method to `#execute!`.
|
16
|
+
|
17
|
+
* Deprecations
|
18
|
+
|
19
|
+
* Rely on #method_missing callback instead of special #option_missing method.
|
20
|
+
* The +NoOptionError+ exceotion class is no longer needed because of above.
|
21
|
+
|
22
|
+
* Bug Fixes
|
23
|
+
|
24
|
+
* The #method_missing callback takes the value of the option being set.
|
25
|
+
|
26
|
+
|
27
|
+
== 1.0.0 / 2011-04-15
|
28
|
+
|
29
|
+
This is the initialize release of Executable (as a stand alone project).
|
30
|
+
Executable is a mixin that can turn any class into an commandline interface.
|
31
|
+
|
32
|
+
* 1 Major Enhancement
|
33
|
+
|
34
|
+
* Birthday!
|
35
|
+
|
data/NOTICE.rdoc
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
= COPYRIGHT NOTICES
|
2
|
+
|
3
|
+
== Executable
|
4
|
+
|
5
|
+
Copyright (c) 2009 Thomas Sawyer
|
6
|
+
|
7
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
you may not use this program except in compliance with the License.
|
9
|
+
You may obtain a copy of the License at
|
10
|
+
|
11
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
|
13
|
+
Unless required by applicable law or agreed to in writing, software
|
14
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
See the License for the specific language governing permissions and
|
17
|
+
limitations under the License.
|
18
|
+
|
19
|
+
---
|
20
|
+
|
21
|
+
You can find the full text of all cited licenses in the `meta/license`
|
22
|
+
directory distributed with this program.
|
23
|
+
|
data/{PROFILE → Profile}
RENAMED
File without changes
|
data/{README → README.rdoc}
RENAMED
@@ -1,9 +1,5 @@
|
|
1
1
|
= Executable
|
2
2
|
|
3
|
-
* http://rubyworks.github.com/executable
|
4
|
-
* http://github.com/rubyworks/executable
|
5
|
-
|
6
|
-
|
7
3
|
== DESCRIPTION
|
8
4
|
|
9
5
|
The Executable mixin is a very quick and and easy
|
@@ -17,10 +13,16 @@ passed to the method.
|
|
17
13
|
== FEATURES
|
18
14
|
|
19
15
|
* Super easy to use, just mixin.
|
20
|
-
* Public
|
16
|
+
* Public writers become options.
|
21
17
|
* Public methods become subcommands.
|
22
18
|
|
23
19
|
|
20
|
+
== RESOURCES
|
21
|
+
|
22
|
+
* http://rubyworks.github.com/executable
|
23
|
+
* http://github.com/rubyworks/executable
|
24
|
+
|
25
|
+
|
24
26
|
== RELEASE NOTES
|
25
27
|
|
26
28
|
Please see HISTORY file.
|
@@ -32,29 +34,44 @@ Simply mixin Executable, then call #execute_command.
|
|
32
34
|
|
33
35
|
class X
|
34
36
|
include Executable
|
37
|
+
|
35
38
|
attr_accessor :quiet
|
39
|
+
|
40
|
+
attr_accessor :size
|
41
|
+
|
36
42
|
def bread(*args)
|
37
|
-
["
|
43
|
+
["bread", quiet, size, *args]
|
38
44
|
end
|
45
|
+
|
39
46
|
def butter(*args)
|
40
|
-
["
|
47
|
+
["butter", quiet, size, *args]
|
41
48
|
end
|
42
49
|
end
|
43
50
|
|
44
51
|
x = X.new
|
45
52
|
|
46
|
-
x.
|
47
|
-
=> ["
|
53
|
+
x.execute!("butter yum")
|
54
|
+
=> ["butter", nil, nil, "yum"]
|
48
55
|
|
49
|
-
x.
|
50
|
-
=> ["
|
56
|
+
x.execute!("bread --quiet --size=big")
|
57
|
+
=> ["bread", true, "big"]
|
51
58
|
|
52
|
-
|
59
|
+
|
60
|
+
Notice that Executable requires an equal-sign (<code>=</code>) be used
|
61
|
+
when specifying values for non-boolean attributes.
|
62
|
+
|
63
|
+
To make the command available on the command line, add an executable
|
64
|
+
to your project passing ARGV to the #execute_command method.
|
65
|
+
|
66
|
+
#!usr/bin/env ruby
|
67
|
+
require 'x'
|
68
|
+
x = X.new
|
69
|
+
x.execute_command(ARGV)
|
53
70
|
|
54
71
|
|
55
72
|
== INSTALL
|
56
73
|
|
57
|
-
$
|
74
|
+
$ gem install executable
|
58
75
|
|
59
76
|
|
60
77
|
== LEGAL
|
data/Version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.1.0
|
data/lib/executable.rb
CHANGED
@@ -1,90 +1,71 @@
|
|
1
1
|
# = Executable Mixin
|
2
2
|
#
|
3
|
-
# The Executable mixin is a very quick and and easy
|
4
|
-
#
|
5
|
-
#
|
6
|
-
#
|
7
|
-
# as the method to call, with the subsequent arguments
|
8
|
-
# passed to the method.
|
3
|
+
# The Executable mixin is a very quick and and easy way to make almost
|
4
|
+
# any class usable via a command line interface. It simply uses writer
|
5
|
+
# methods as option setters, and the first command line argument as a
|
6
|
+
# method to call with the subsequent arguments passed to the method.
|
9
7
|
#
|
10
|
-
# The only limitation of this approach
|
11
|
-
#
|
12
|
-
# be specified with the key=value notation.
|
8
|
+
# The only limitation of this approach is that non-boolean options must
|
9
|
+
# be specified with `key=value` notation.
|
13
10
|
#
|
14
|
-
# class
|
11
|
+
# class Example
|
15
12
|
# include Executable
|
16
13
|
#
|
17
14
|
# attr_accessor :quiet
|
18
15
|
#
|
19
16
|
# def bread(*args)
|
20
|
-
# ["
|
17
|
+
# ["bread", quiet, *args]
|
21
18
|
# end
|
22
19
|
#
|
23
20
|
# def butter(*args)
|
24
|
-
# ["
|
21
|
+
# ["butter", quiet, *args]
|
25
22
|
# end
|
26
23
|
# end
|
27
24
|
#
|
28
|
-
#
|
25
|
+
# ex = Example.new
|
29
26
|
#
|
30
|
-
#
|
31
|
-
# => ["
|
27
|
+
# ex.execute!("butter yum")
|
28
|
+
# => ["butter", nil, "yum"]
|
32
29
|
#
|
33
|
-
#
|
34
|
-
# => ["
|
30
|
+
# ex.execute!("bread --quiet")
|
31
|
+
# => ["butter", true]
|
35
32
|
#
|
36
|
-
# Executable also
|
37
|
-
#
|
38
|
-
#
|
39
|
-
# TODO: Maybe command_missing is redundant, and method_missing would suffice?
|
33
|
+
# Executable also provides #option_missing, which you can overriden to provide
|
34
|
+
# suitable results when a given command line option has no corresponding
|
35
|
+
# writer method.
|
40
36
|
#
|
41
37
|
module Executable
|
42
38
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
class NoOptionError < ArgumentError
|
47
|
-
end
|
48
|
-
|
49
|
-
# Used to invoke the command.
|
50
|
-
def execute_command(argv=ARGV)
|
51
|
-
Executable.run(self, argv)
|
39
|
+
# Used the #excute! method to invoke the command.
|
40
|
+
def execute!(argv=ARGV)
|
41
|
+
Executable.execute(self, argv)
|
52
42
|
end
|
53
43
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
#
|
61
|
-
# This receives the name of the option and
|
62
|
-
# the remaining arguments list. It must consume
|
63
|
-
# any argument it uses from the (begining of)
|
64
|
-
# the list.
|
65
|
-
def option_missing(opt, *argv)
|
66
|
-
raise NoOptionError, opt
|
67
|
-
end
|
44
|
+
## When no attribute write exists for an option that has been given on
|
45
|
+
## the command line #option_missing is called. Override #option_missing
|
46
|
+
## to handle these cases, if needed. Otherwise a NoMethodArgument will be
|
47
|
+
## raised. This callback method receives the name and value of the option.
|
48
|
+
#def option_missing(opt, arg)
|
49
|
+
# raise NoMethodError, "undefined option `#{opt}=' for #{self}"
|
50
|
+
#end
|
68
51
|
|
69
52
|
class << self
|
70
53
|
|
71
|
-
|
72
|
-
|
73
|
-
|
54
|
+
# Process the arguments as an exectuable against the given object.
|
55
|
+
def execute(obj, argv=ARGV)
|
56
|
+
args = parse(obj, argv)
|
57
|
+
subcmd = args.first
|
74
58
|
if subcmd && !obj.respond_to?("#{subcmd}=")
|
75
|
-
obj.send(
|
59
|
+
obj.send(*args)
|
76
60
|
else
|
77
|
-
obj.
|
61
|
+
obj.method_missing(*args)
|
78
62
|
end
|
79
63
|
end
|
80
64
|
|
81
|
-
#
|
82
|
-
|
83
|
-
# meth = obj.method(methname)
|
84
|
-
# meth.call(*args)
|
85
|
-
#end
|
65
|
+
# The original name for #execute.
|
66
|
+
alias_method :run, :execute
|
86
67
|
|
87
|
-
#
|
68
|
+
# Parse command line with respect to +obj+.
|
88
69
|
def parse(obj, argv)
|
89
70
|
case argv
|
90
71
|
when String
|
@@ -111,84 +92,52 @@ module Executable
|
|
111
92
|
return args
|
112
93
|
end
|
113
94
|
|
114
|
-
#
|
95
|
+
# Parse a setting option.
|
115
96
|
def parse_equal(obj, opt, argv)
|
116
97
|
if md = /^[-]*(.*?)=(.*?)$/.match(opt)
|
117
98
|
x, v = md[1], md[2]
|
118
99
|
else
|
119
100
|
raise ArgumentError, "#{x}"
|
120
101
|
end
|
121
|
-
if
|
122
|
-
|
123
|
-
obj.send("#{x}=",v)
|
124
|
-
else
|
125
|
-
|
126
|
-
end
|
102
|
+
# TODO: to_b if 'true' or 'false' ?
|
103
|
+
#if obj.respond_to?("#{x}=")
|
104
|
+
obj.send("#{x}=", v)
|
105
|
+
#else
|
106
|
+
# obj.option_missing(x, v)
|
107
|
+
#end
|
127
108
|
end
|
128
109
|
|
129
|
-
#
|
110
|
+
# Parse a named boolean option.
|
130
111
|
def parse_option(obj, opt, argv)
|
131
|
-
x = opt
|
132
|
-
if obj.respond_to?("#{x}=")
|
133
|
-
obj.send("#{x}=",true)
|
134
|
-
else
|
135
|
-
|
136
|
-
end
|
112
|
+
x = opt.sub(/^--/, '')
|
113
|
+
#if obj.respond_to?("#{x}=")
|
114
|
+
obj.send("#{x}=", true)
|
115
|
+
#else
|
116
|
+
# obj.option_missing(x, true)
|
117
|
+
#end
|
137
118
|
end
|
138
119
|
|
120
|
+
# Parse flags. Each character of a flag set is treated as a separate option.
|
121
|
+
# For example:
|
122
|
+
#
|
123
|
+
# $ foo -abc
|
124
|
+
#
|
125
|
+
# Would be parsed the same as:
|
126
|
+
#
|
127
|
+
# $ foo -a -b -c
|
139
128
|
#
|
140
129
|
def parse_flags(obj, opt, args)
|
141
|
-
x = opt
|
142
|
-
c = 0
|
130
|
+
x = opt.sub(/^-/, '')
|
131
|
+
#c = 0
|
143
132
|
x.split(//).each do |k|
|
144
|
-
if obj.respond_to?("#{k}=")
|
145
|
-
obj.send("#{k}=",true)
|
146
|
-
else
|
147
|
-
|
148
|
-
end
|
133
|
+
#if obj.respond_to?("#{k}=")
|
134
|
+
obj.send("#{k}=", true)
|
135
|
+
#else
|
136
|
+
# obj.option_missing(x, true)
|
137
|
+
#end
|
149
138
|
end
|
150
139
|
end
|
151
140
|
|
152
141
|
end #class << self
|
153
142
|
|
154
143
|
end
|
155
|
-
|
156
|
-
|
157
|
-
=begin SPEC
|
158
|
-
|
159
|
-
class X
|
160
|
-
include Executable
|
161
|
-
|
162
|
-
attr_accessor :file
|
163
|
-
attr_accessor :quiet
|
164
|
-
|
165
|
-
attr :cmd
|
166
|
-
|
167
|
-
#
|
168
|
-
def bread(*args)
|
169
|
-
@cmd = "BREAD"
|
170
|
-
end
|
171
|
-
|
172
|
-
#
|
173
|
-
def butter(*args)
|
174
|
-
@cmd = "BUTTER"
|
175
|
-
end
|
176
|
-
end
|
177
|
-
|
178
|
-
Respect.spec "Executable" do
|
179
|
-
|
180
|
-
it "first command runs" do
|
181
|
-
x = X.new
|
182
|
-
x.execute_command("bread")
|
183
|
-
x.cmd.assert == "BREAD"
|
184
|
-
end
|
185
|
-
|
186
|
-
it "second command runs" do
|
187
|
-
x = X.new
|
188
|
-
x.execute_command("butter")
|
189
|
-
x.cmd.assert == "BUTTER"
|
190
|
-
end
|
191
|
-
end
|
192
|
-
|
193
|
-
=end
|
194
|
-
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
|
2
2
|
Apache License
|
3
3
|
Version 2.0, January 2004
|
4
4
|
http://www.apache.org/licenses/
|
@@ -175,30 +175,3 @@
|
|
175
175
|
of your accepting any such warranty or additional liability.
|
176
176
|
|
177
177
|
END OF TERMS AND CONDITIONS
|
178
|
-
|
179
|
-
APPENDIX: How to apply the Apache License to your work.
|
180
|
-
|
181
|
-
To apply the Apache License to your work, attach the following
|
182
|
-
boilerplate notice, with the fields enclosed by brackets "[]"
|
183
|
-
replaced with your own identifying information. (Don't include
|
184
|
-
the brackets!) The text should be enclosed in the appropriate
|
185
|
-
comment syntax for the file format. We also recommend that a
|
186
|
-
file or class name and description of purpose be included on the
|
187
|
-
same "printed page" as the copyright notice for easier
|
188
|
-
identification within third-party archives.
|
189
|
-
|
190
|
-
Copyright [yyyy] [name of copyright owner]
|
191
|
-
|
192
|
-
Licensed under the Apache License, Version 2.0 (the "License");
|
193
|
-
you may not use this file except in compliance with the License.
|
194
|
-
You may obtain a copy of the License at
|
195
|
-
|
196
|
-
http://www.apache.org/licenses/LICENSE-2.0
|
197
|
-
|
198
|
-
Unless required by applicable law or agreed to in writing, software
|
199
|
-
distributed under the License is distributed on an "AS IS" BASIS,
|
200
|
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
201
|
-
See the License for the specific language governing permissions and
|
202
|
-
limitations under the License.
|
203
|
-
|
204
|
-
|
data/test/test_executable.rb
CHANGED
@@ -23,14 +23,14 @@ class TestExecutable < Test::Unit::TestCase
|
|
23
23
|
#
|
24
24
|
def test_parse_without_option
|
25
25
|
s = SampleCli.new
|
26
|
-
s.
|
26
|
+
s.execute!("jump")
|
27
27
|
assert_equal(s.result, ["jump"])
|
28
28
|
end
|
29
29
|
|
30
30
|
#
|
31
31
|
def test_parse_with_option
|
32
32
|
s = SampleCli.new
|
33
|
-
s.
|
33
|
+
s.execute!("jump --output=home")
|
34
34
|
assert_equal(s.result, ['output: home', 'jump'])
|
35
35
|
end
|
36
36
|
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: executable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
5
|
-
prerelease:
|
4
|
+
hash: 19
|
5
|
+
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 1
|
8
|
+
- 1
|
8
9
|
- 0
|
9
|
-
|
10
|
-
version: 1.0.0
|
10
|
+
version: 1.1.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Thomas Sawyer
|
@@ -15,7 +15,8 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-04-
|
18
|
+
date: 2011-04-21 00:00:00 -04:00
|
19
|
+
default_executable:
|
19
20
|
dependencies:
|
20
21
|
- !ruby/object:Gem::Dependency
|
21
22
|
name: turn
|
@@ -38,15 +39,17 @@ executables: []
|
|
38
39
|
extensions: []
|
39
40
|
|
40
41
|
extra_rdoc_files:
|
41
|
-
- README
|
42
|
+
- README.rdoc
|
42
43
|
files:
|
43
44
|
- lib/executable.rb
|
45
|
+
- meta/license/Apache2.txt
|
44
46
|
- test/test_executable.rb
|
45
|
-
-
|
46
|
-
-
|
47
|
-
-
|
48
|
-
-
|
49
|
-
-
|
47
|
+
- Profile
|
48
|
+
- README.rdoc
|
49
|
+
- History.rdoc
|
50
|
+
- Version
|
51
|
+
- NOTICE.rdoc
|
52
|
+
has_rdoc: true
|
50
53
|
homepage: http://rubyworks.github.com/executable
|
51
54
|
licenses:
|
52
55
|
- Apache 2.0
|
@@ -55,7 +58,7 @@ rdoc_options:
|
|
55
58
|
- --title
|
56
59
|
- Executable API
|
57
60
|
- --main
|
58
|
-
- README
|
61
|
+
- README.rdoc
|
59
62
|
require_paths:
|
60
63
|
- lib
|
61
64
|
required_ruby_version: !ruby/object:Gem::Requirement
|
@@ -79,7 +82,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
79
82
|
requirements: []
|
80
83
|
|
81
84
|
rubyforge_project: executable
|
82
|
-
rubygems_version: 1.7
|
85
|
+
rubygems_version: 1.3.7
|
83
86
|
signing_key:
|
84
87
|
specification_version: 3
|
85
88
|
summary: Any class, a command-line interface.
|
data/HISTORY
DELETED