executable 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
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