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 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
+
File without changes
@@ -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 writters become CLI options.
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
- ["BREAD", quiet, *args]
43
+ ["bread", quiet, size, *args]
38
44
  end
45
+
39
46
  def butter(*args)
40
- ["BUTTER", quiet, *args]
47
+ ["butter", quiet, size, *args]
41
48
  end
42
49
  end
43
50
 
44
51
  x = X.new
45
52
 
46
- x.execute_command("butter yum")
47
- => ["BUTTER", nil, "yum"]
53
+ x.execute!("butter yum")
54
+ => ["butter", nil, nil, "yum"]
48
55
 
49
- x.execute_command("bread --quiet")
50
- => ["BREAD", true]
56
+ x.execute!("bread --quiet --size=big")
57
+ => ["bread", true, "big"]
51
58
 
52
- See RDocs for more information.
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
- $ sudo gem install executable
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
- # way to make almost any class usable via a command
5
- # line interface. It simply uses writer methods as
6
- # option setters, and the first command line argument
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 (besides the weak
11
- # control of the process) is that required options must
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 X
11
+ # class Example
15
12
  # include Executable
16
13
  #
17
14
  # attr_accessor :quiet
18
15
  #
19
16
  # def bread(*args)
20
- # ["BREAD", quiet, *args]
17
+ # ["bread", quiet, *args]
21
18
  # end
22
19
  #
23
20
  # def butter(*args)
24
- # ["BUTTER", quiet, *args]
21
+ # ["butter", quiet, *args]
25
22
  # end
26
23
  # end
27
24
  #
28
- # x = X.new
25
+ # ex = Example.new
29
26
  #
30
- # x.execute_command("butter yum")
31
- # => ["BUTTER", nil, "yum"]
27
+ # ex.execute!("butter yum")
28
+ # => ["butter", nil, "yum"]
32
29
  #
33
- # x.execute_command("bread --quiet")
34
- # => ["BUTTER", true]
30
+ # ex.execute!("bread --quiet")
31
+ # => ["butter", true]
35
32
  #
36
- # Executable also defines #command_missing and #option_missing,
37
- # which you can override to provide suitable results.
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
- class NoCommandError < NameError
44
- end
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
- # This is the fallback subcommand. Override this to provide
55
- # a fallback when no command is given on the commandline.
56
- def command_missing
57
- raise NoCommandError
58
- end
59
-
60
- # Override option_missing if needed.
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
- def run(obj, argv=ARGV)
72
- args = parse(obj, argv)
73
- subcmd = args.shift
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(subcmd, *args)
59
+ obj.send(*args)
76
60
  else
77
- obj.command_missing
61
+ obj.method_missing(*args)
78
62
  end
79
63
  end
80
64
 
81
- #def run(obj)
82
- # methname, args = *parse(obj)
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 obj.respond_to?("#{x}=")
122
- # TODO: to_b if 'true' or 'false' ?
123
- obj.send("#{x}=",v)
124
- else
125
- obj.option_missing(x, v) # argv?
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[2..-1]
132
- if obj.respond_to?("#{x}=")
133
- obj.send("#{x}=",true)
134
- else
135
- obj.option_missing(x, argv)
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[1..-1]
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
- obj.option_missing(x, argv)
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
-
@@ -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.execute_command("jump")
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.execute_command("jump --output=home")
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: 23
5
- prerelease:
4
+ hash: 19
5
+ prerelease: false
6
6
  segments:
7
7
  - 1
8
+ - 1
8
9
  - 0
9
- - 0
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-15 00:00:00 Z
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
- - Rakefile
46
- - PROFILE
47
- - LICENSE
48
- - README
49
- - HISTORY
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.2
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
@@ -1,11 +0,0 @@
1
- = HISTORY
2
-
3
- == 1.0.0 / 2009-06-25
4
-
5
- This is the initialize release of Cliable (as a stand alone project).
6
- Cliable is a mixin that can turn any class into an commandline interface.
7
-
8
- * 1 Major Enhancement
9
-
10
- * Birthday!
11
-
data/Rakefile DELETED
@@ -1,11 +0,0 @@
1
- task :default => [:test]
2
-
3
- desc "run tests"
4
- task :test do
5
- sh "ruby -rtest/unit -Ilib test/*.rb"
6
- end
7
-
8
- desc "run tests with turn"
9
- task :turn do
10
- sh "turn -T -Ilib test/*.rb"
11
- end