facets 2.0.5 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. data/WHATSNEW +11 -0
  2. data/lib/core/facets/enumerable/collect.rb +7 -2
  3. data/lib/core/facets/enumerable/permutation.rb +7 -26
  4. data/lib/core/facets/module/alias.rb +36 -12
  5. data/lib/core/facets/module/attr.rb +83 -35
  6. data/lib/core/facets/module/include.rb +10 -0
  7. data/lib/methods/facets/module/alias_accessor.rb +1 -1
  8. data/lib/methods/facets/module/alias_reader.rb +1 -0
  9. data/lib/methods/facets/module/alias_setter.rb +1 -0
  10. data/lib/methods/facets/module/alias_switcher.rb +1 -0
  11. data/lib/methods/facets/module/alias_tester.rb +1 -0
  12. data/lib/methods/facets/module/alias_toggler.rb +1 -0
  13. data/lib/methods/facets/module/alias_validator.rb +1 -0
  14. data/lib/methods/facets/module/alias_writer.rb +1 -0
  15. data/lib/methods/facets/module/attr_accessor.rb +1 -0
  16. data/lib/methods/facets/module/attr_reader.rb +1 -0
  17. data/lib/methods/facets/module/attr_switcher.rb +1 -0
  18. data/lib/methods/facets/module/attr_writer.rb +1 -0
  19. data/lib/more/facets/arguments.rb +2 -1
  20. data/lib/more/facets/command.rb +258 -395
  21. data/lib/more/facets/crypt.rb +242 -28
  22. data/lib/more/facets/ziputils.rb +1 -1
  23. data/log/changelog.txt +0 -0
  24. data/log/history.txt +22 -0
  25. data/log/release.txt +10 -0
  26. data/log/todo.txt +4 -0
  27. data/meta/{facets-2.0.5.roll → facets-2.1.0.roll} +0 -0
  28. data/meta/google_ad.html +15 -0
  29. data/meta/icli.yaml +3 -3
  30. data/meta/manifest.txt +24 -3
  31. data/task/clobber/package +10 -0
  32. data/task/config/general.yaml +21 -3
  33. data/task/isotest +2 -1
  34. data/task/loadtest +2 -0
  35. data/task/prepare +4 -2
  36. data/task/rdoc +122 -73
  37. data/task/release +12 -0
  38. data/task/special/quickopts +15 -0
  39. data/task/syntax +2 -0
  40. data/task/test +3 -1
  41. data/test/unit/enumerable/test_collect.rb +17 -0
  42. data/test/unit/enumerable/test_permutation.rb +20 -30
  43. data/test/unit/test_crypt.rb +29 -36
  44. metadata +40 -12
  45. data/RELEASE +0 -12
  46. data/test/unit/test_command.rb +0 -286
@@ -0,0 +1,11 @@
1
+ Facets 2.1.0 is in the wild!
2
+
3
+ Major changes include a new and much-improved
4
+ command.rb, a new BiCrypt class for simple two-way
5
+ crypotgraphy, as well as attr_reader!, attr_writer!
6
+ and attr_accessor! for flag attributes, plus
7
+ alias_xxx methods for all attr_xxx methods.
8
+
9
+ Enjoy!
10
+
11
+ http://facets.rubyforge.org
@@ -113,6 +113,12 @@ module Enumerable
113
113
  end
114
114
  end
115
115
 
116
+ # TODO Faster implementation? Verify equivalency.
117
+ #def injecting(res, &block)
118
+ # ([res]*length).zip(to_a).each(&block)
119
+ # res
120
+ #end
121
+
116
122
  # The #group_by method is best explained by example.
117
123
  #
118
124
  # (1..5).partition_by { |n| n % 3 }
@@ -150,8 +156,7 @@ module Enumerable
150
156
  # CREDIT Erik Veenstra
151
157
 
152
158
  def cluster_by(&b)
153
- #group_by(&b).values
154
- group_by(&b).sort.transpose.pop
159
+ group_by(&b).sort.transpose.pop || [] # group_by(&b).values ?
155
160
  end
156
161
 
157
162
  # Split on matching pattern.
@@ -6,7 +6,6 @@
6
6
  #
7
7
  # AUTHORS:
8
8
  # - Florian Gross
9
- # - Thomas Sawyer
10
9
 
11
10
  require 'facets/integer/factorial'
12
11
 
@@ -17,6 +16,8 @@ module Enumerable
17
16
  # Each is index by a permutation number. The maximum number of
18
17
  # arrangements is the factorial of the size of the array.
19
18
  #
19
+ # CREDIT Florian Gross
20
+
20
21
  def permutation(number)
21
22
  arr = to_a
22
23
  out = arr[0..0]
@@ -34,7 +35,10 @@ module Enumerable
34
35
  end
35
36
  alias :permute :permutation
36
37
 
38
+ # Calculate permutation number.
37
39
  #
40
+ # CREDIT Florian Gross
41
+
38
42
  def permutation_number(original_array=self.to_a.sort)
39
43
  arr = to_a
40
44
  m = 1
@@ -62,6 +66,8 @@ module Enumerable
62
66
  # cab
63
67
  # cba
64
68
  #
69
+ # CREDIT Florian Gross
70
+
65
71
  def each_permutation()
66
72
  arr = to_a
67
73
  size = arr.size
@@ -98,28 +104,3 @@ module Enumerable
98
104
  #++
99
105
 
100
106
  end
101
-
102
-
103
- # _____ _
104
- # |_ _|__ ___| |_
105
- # | |/ _ \/ __| __|
106
- # | | __/\__ \ |_
107
- # |_|\___||___/\__|
108
- #
109
- =begin test
110
-
111
- require 'test/unit'
112
- require 'set'
113
-
114
- class TestEnumerablePermutation < Test::Unit::TestCase
115
-
116
- def test_permutation
117
- o = Set.new
118
- %w[a b c].each_permutation { |x| o << x.join('') }
119
- r = Set.new(['abc','acb','bac','bca','cab','cba'])
120
- assert_equal( r, o )
121
- end
122
-
123
- end
124
-
125
- =end
@@ -23,15 +23,6 @@ class Module
23
23
 
24
24
  private
25
25
 
26
- # Like module_funtion but makes the instance method
27
- # public rather than private. This can not work
28
- # as a sectional modifier however.
29
-
30
- def module_method *meth
31
- module_function *meth
32
- public *meth
33
- end
34
-
35
26
  # As with alias_method, but alias both reader and writer.
36
27
  #
37
28
  # attr_accessor :x
@@ -41,9 +32,42 @@ class Module
41
32
  # self.y = 2
42
33
  # x #=> 2
43
34
 
44
- def alias_accessor(name, target)
45
- alias_method(name, target)
46
- alias_method("#{name}=", "#{target}=")
35
+ def alias_accessor(*args)
36
+ orig = args.last
37
+ args = args - [orig]
38
+ args.each do |name|
39
+ alias_method(name, orig)
40
+ alias_method("#{name}=", "#{orig}=")
41
+ end
42
+ end
43
+
44
+ # As with alias_accessor, but just for the reader.
45
+
46
+ def alias_reader(*args)
47
+ orig = args.last
48
+ args = args - [orig]
49
+ args.each do |name|
50
+ alias_method(name, orig)
51
+ end
52
+ end
53
+
54
+ # As with alias_method but does the writer instead.
55
+
56
+ def alias_writer(*args)
57
+ orig = args.last
58
+ args = args - [orig]
59
+ args.each do |name|
60
+ alias_method("#{name}=", "#{orig}=")
61
+ end
62
+ end
63
+
64
+ # Like module_funtion but makes the instance method
65
+ # public rather than private. This can not work
66
+ # as a sectional modifier however.
67
+
68
+ def module_method *meth
69
+ module_function *meth
70
+ public *meth
47
71
  end
48
72
 
49
73
  # Alias a module function so that the alias is also
@@ -1,6 +1,6 @@
1
1
  # TITLE:
2
2
  #
3
- # Attributes Methods
3
+ # Extra Attributes Methods
4
4
  #
5
5
  # SUMMARY:
6
6
  #
@@ -9,9 +9,6 @@
9
9
  # AUTHORS:
10
10
  #
11
11
  # - Thomas Sawyer
12
- #
13
- # TODO:
14
- # - Need better name for attr_toggler, since it's not realy a "toggle".
15
12
 
16
13
  #
17
14
  class Module
@@ -30,7 +27,16 @@ class Module
30
27
  end
31
28
  made << "#{symbol}=".to_sym
32
29
  end
33
- return *made
30
+ made
31
+ end
32
+
33
+ def alias_validator(*args)
34
+ orig = args.last
35
+ args = args - [orig]
36
+ args.each do |name|
37
+ alias_method(name, orig)
38
+ alias_method("#{name}=", "#{orig}=")
39
+ end
34
40
  end
35
41
 
36
42
  # TODO Perhaps need to make a check against overriding annotated version.
@@ -62,31 +68,62 @@ class Module
62
68
  made << "#{a}".to_sym
63
69
  end
64
70
  module_eval code
65
- return *made
71
+ made
72
+ end
73
+
74
+ def alias_setter(*args)
75
+ args = args - [orig]
76
+ args.each do |name|
77
+ alias_method(name, orig)
78
+ end
66
79
  end
67
80
 
68
- # Create an tester attribute. This creates two methods for
69
- # each given variable name. One is used to test
70
- # the attribute and the other is used to set or toggle it.
81
+ # Create a toggle attribute. This creates two methods for
82
+ # each given name. One is a form of tester and the other
83
+ # is used to toggle the value.
71
84
  #
72
- # attr_tester :a
85
+ # attr_accessor! :a
73
86
  #
74
87
  # is equivalent to
75
88
  #
76
89
  # def a?
77
- # @a ? true : @a
90
+ # @a
78
91
  # end
79
92
  #
80
- # def a!(switch=Exception)
81
- # if switch == Exception
82
- # @a = !@a
83
- # else
84
- # @a = switch ? true : @a
85
- # self
86
- # end
93
+ # def a!(value=true)
94
+ # @a = value
95
+ # self
96
+ # end
97
+
98
+ def attr_accessor!(*args)
99
+ attr_reader!(*args) + attr_writer!(*args)
100
+ end
101
+ alias_method :attr_switcher, :attr_accessor!
102
+ alias_method :attr_toggler, :attr_accessor!
103
+
104
+ def alias_accessor!(*args)
105
+ orig = args.last
106
+ args = args - [orig]
107
+ args.each do |name|
108
+ alias_method("#{name}?", "#{orig}?")
109
+ alias_method("#{name}!", "#{orig}!")
110
+ end
111
+ end
112
+ alias_method :alias_switcher, :alias_accessor!
113
+ alias_method :alias_toggler, :alias_accessor!
114
+
115
+ # Create an tester attribute. This creates a single methods
116
+ # used to test the attribute for truth.
117
+ #
118
+ # attr_reader! :a
119
+ #
120
+ # is equivalent to
121
+ #
122
+ # def a?
123
+ # @a ? true : @a
87
124
  # end
88
125
 
89
- def attr_tester(*args)
126
+ def attr_reader!(*args)
90
127
  code, made = '', []
91
128
  args.each do |a|
92
129
  code << %{
@@ -97,43 +134,54 @@ class Module
97
134
  made << "#{a}?".to_sym
98
135
  end
99
136
  module_eval code
100
- return *made
137
+ made
101
138
  end
139
+ alias_method :attr_reader?, :attr_reader!
140
+ alias_method :attr_tester, :attr_reader!
102
141
 
103
- # Create a toggle attribute. This creates two methods for
104
- # each given name. One is a form of tester and the other
105
- # is used to toggle the value.
142
+ def alias_reader!(*args)
143
+ orig = args.last
144
+ args = args - [orig]
145
+ args.each do |name|
146
+ alias_method("#{name}?", "#{orig}?")
147
+ end
148
+ end
149
+ alias_method :alias_reader?, :alias_reader!
150
+ alias_method :alias_tester, :alias_reader!
151
+
152
+ # Create a flaggable attribute. This creates a single methods
153
+ # used to set an attribute to "true".
106
154
  #
107
- # attr_toggler :a
155
+ # attr_writer! :a
108
156
  #
109
157
  # is equivalent to
110
158
  #
111
- # def a?
112
- # @a
113
- # end
114
- #
115
159
  # def a!(value=true)
116
160
  # @a = value
117
161
  # self
118
162
  # end
119
163
 
120
- def attr_toggler(*args)
164
+ def attr_writer!(*args)
121
165
  code, made = '', []
122
166
  args.each do |a|
123
167
  code << %{
124
168
  def #{a}!(value=true)
125
- @a = value
169
+ @#{a} = value
126
170
  self
127
171
  end
128
- def #{a}?
129
- @#{a}
130
- end
131
172
  }
132
173
  made << "#{a}!".to_sym
133
- made << "#{a}?".to_sym
134
174
  end
135
175
  module_eval code
136
- return *made
176
+ made
177
+ end
178
+
179
+ def alias_writer!(*args)
180
+ orig = args.last
181
+ args = args - [orig]
182
+ args.each do |name|
183
+ alias_method("#{name}!", "#{orig}!")
184
+ end
137
185
  end
138
186
 
139
187
  end
@@ -10,6 +10,16 @@ class Module
10
10
  #
11
11
  alias_method :is, :include
12
12
 
13
+ # TODO
14
+ # def is(*mods)
15
+ # mods.each do |mod|
16
+ # if mod.const_defined?(:Self)
17
+ # extend mod.const_get(:Self)
18
+ # end
19
+ # end
20
+ # include(*mods)
21
+ # end
22
+
13
23
  # Expirmental idea for #is.
14
24
  #
15
25
  # If the module has #append_function_function
@@ -1 +1 @@
1
- require 'facets/module/alias.rb'
1
+ require 'facets/module/attr.rb'
@@ -0,0 +1 @@
1
+ require 'facets/module/attr.rb'
@@ -0,0 +1 @@
1
+ require 'facets/module/attr.rb'
@@ -0,0 +1 @@
1
+ require 'facets/module/attr.rb'
@@ -0,0 +1 @@
1
+ require 'facets/module/attr.rb'
@@ -0,0 +1 @@
1
+ require 'facets/module/attr.rb'
@@ -0,0 +1 @@
1
+ require 'facets/module/attr.rb'
@@ -0,0 +1 @@
1
+ require 'facets/module/attr.rb'
@@ -0,0 +1 @@
1
+ require 'facets/module/attr.rb'
@@ -0,0 +1 @@
1
+ require 'facets/module/attr.rb'
@@ -0,0 +1 @@
1
+ require 'facets/module/attr.rb'
@@ -0,0 +1 @@
1
+ require 'facets/module/attr.rb'
@@ -58,7 +58,7 @@ class Console::Arguments
58
58
  # Takes the command line string (or array) and options.
59
59
  # Options have flags and end with a hash of option arity.
60
60
  #
61
- def initialize( line=nil, arity=nil )
61
+ def initialize(line=nil, arity=nil)
62
62
  @line, @argv = parse_line(line)
63
63
  @arity = parse_arity(arity||{})
64
64
  parse
@@ -237,6 +237,7 @@ class Console::Arguments
237
237
  key, val = key.split('=')
238
238
  elsif a = arity[key]
239
239
  val = args.slice!(0,a)
240
+ val = val.first if a == 1
240
241
  else
241
242
  val = true
242
243
  end
@@ -20,182 +20,323 @@
20
20
  #
21
21
  # AUTHORS:
22
22
  #
23
- # - 7rans
24
- # - Tyler Rick
23
+ # - Trans
25
24
  #
26
- # TODOs:
25
+ # TODO:
27
26
  #
28
- # - Add help/documentation features.
29
- # - Problem with exit -1 when testing. See IMPORTANT!!! remark below.
30
- #
31
- # LOG:
32
- #
33
- # - 2007.10.31 TRANS
34
- # Re-added support for __option notation.
27
+ # - Add global options to master command, or "all are master options" flag?
28
+ # - Add usage/help/documentation/man features.
35
29
 
36
- require 'shellwords'
37
30
  #require 'facets/annotations' # for help ?
31
+ #require 'facets/module/attr'
32
+ #require 'facets/kernel/constant'
33
+ #require 'shellwords'
34
+ require 'facets/arguments'
38
35
 
39
36
  module Console
40
37
 
41
- # Base command class.
42
- #
43
- # class MyCommand < Command
44
- #
45
- # class JumpOptions < Command::Options
46
- # attr_accessor :height
47
- # end
48
- #
49
- # help :jump, "this is the jump command"
38
+ # For CommandOptions, but defined external to it, so
39
+ # that it is easy to access from user defined commands.
40
+ # (This lookup issue should be fixed in Ruby 1.9+, and then
41
+ # the class can be moved back into Command namespace.)
42
+
43
+ class NoOptionError < NoMethodError
44
+ def initialize(name, *arg)
45
+ super("unknown option -- #{name}", name, *args)
46
+ end
47
+ end
48
+
49
+ class NoCommandError < NoMethodError
50
+ def initialize(name, *arg)
51
+ super("unknown subcommand -- #{name}", name, *args)
52
+ end
53
+ end
54
+
55
+ # Here is an example of usage:
50
56
  #
51
- # opts :jump, JumpOptions
57
+ # # General Options
52
58
  #
53
- # def jump
54
- # puts "jump #{options.height} feet!"
55
- # end
59
+ # module GeneralOptions
60
+ # attr_accessor :dryrun ; alias_accessor :n, :noharm, :dryrun
61
+ # attr_accessor :quiet ; alias_accessor :q, :quiet
62
+ # attr_accessor :force
63
+ # attr_accessor :trace
56
64
  # end
57
65
  #
58
- # A little more conveniently:
66
+ # # Build Subcommand
59
67
  #
60
- # class MyCommand < Command
68
+ # class BuildCommand < Console::Command
69
+ # include GeneralOptions
61
70
  #
62
- # help :jump, "this is the jump command"
71
+ # # metadata files
72
+ # attr_accessor :file ; alias_accessor :f, :file
73
+ # attr_accessor :manifest ; alias_accessor :m, :manifest
63
74
  #
64
- # opts :jump do
65
- # attr_accessor :height
75
+ # def call
76
+ # # do stuf here
66
77
  # end
78
+ # end
67
79
  #
68
- # def jump
69
- # puts "jump #{options.height} feet!"
70
- # end
80
+ # # Box Master Command
81
+ #
82
+ # class BoxCommand < Console::MasterCommand
83
+ # subcommand :build, BuildCommand
71
84
  # end
72
85
  #
86
+ # BoxCommand.start
73
87
 
74
- class Command
88
+ class MasterCommand
89
+
90
+ #
75
91
 
76
- # Command Syntax DSL
92
+ module UniversalOptions
93
+ end
77
94
 
78
- module Syntax
95
+ #
79
96
 
80
- # Starts the command execution.
81
- def execute(*args)
82
- cmd = new()
83
- #cmd.instance_variable_set("@global_options",global_options)
84
- cmd.execute(*args)
97
+ def self.option_arity(arity_hash=nil)
98
+ if arity_hash
99
+ (@option_arity ||= {}).merge!(arity_hash)
85
100
  end
86
- alias_method :start, :execute
101
+ @option_arity
102
+ end
103
+
104
+ #
87
105
 
88
- # Change the option mode.
89
- def global_option( *names )
90
- names.each{ |name| global_options << name.to_sym }
106
+ def self.start(line=nil)
107
+ cargs = Console::Arguments.new(line || ARGV, option_arity)
108
+ pre = cargs.preoptions
109
+ cmd, argv = *cargs.subcommand
110
+ args, opts = *argv
111
+ if is_a?(UniversalOptions)
112
+ new(pre, opts).call(cmd, args, opts)
113
+ else
114
+ new(pre).call(cmd, args, opts)
91
115
  end
92
- alias_method :global_options, :global_option
116
+ end
93
117
 
94
- # Define a set of options. This can be a Command::Options subclass,
95
- # or a block whihc will be used to create an Command::Options subclass.
118
+ #
96
119
 
97
- def options(name, klass=nil, &block)
98
- raise ArgumentError if klass && block
99
- if block
100
- command_options[name.to_sym] = Class.new(Options, &block)
101
- else
102
- command_options[name.to_sym] = klass
103
- end
120
+ def self.subcommand(name, command_class, options=nil)
121
+ options ||= {}
122
+ if options[:no_merge]
123
+ file, line = __FILE__, __LINE__+1
124
+ code = %{
125
+ def #{name}(args, opts)
126
+ #{command_class}.new(args, opts).call
127
+ end
128
+ }
129
+ else
130
+ file, line = __FILE__, __LINE__+1
131
+ code = %{
132
+ def #{name}(args, opts)
133
+ opts.merge(master_options)
134
+ #{command_class}.new(args, opts).call
135
+ end
136
+ }
104
137
  end
105
- alias_method :opts, :options
106
- alias_method :opt, :options
138
+ class_eval(code, file, line)
139
+ end
140
+
141
+ private
107
142
 
108
- #
143
+ attr :master_options
109
144
 
110
- def command_options
111
- @_command_options ||= {}
145
+ #
146
+
147
+ def initialize(*options)
148
+ initialize_options(*options)
149
+ end
150
+
151
+ #
152
+
153
+ def initialize_options(*options)
154
+ options = options.inject{ |h,o| h.merge(o) }
155
+ begin
156
+ opt, val = nil, nil
157
+ options.each do |opt, val|
158
+ send("#{opt}=", val)
159
+ end
160
+ rescue NoMethodError
161
+ option_missing(opt, val)
112
162
  end
163
+ @master_options = options
164
+ end
165
+
166
+ public
113
167
 
114
- #
168
+ #
115
169
 
116
- def global_options
117
- @_global_options ||= []
170
+ def call(cmd, args, opts)
171
+ cmd = :default if cmd.nil?
172
+ begin
173
+ subcommand = method(cmd)
174
+ parameters = [args, opts]
175
+ rescue NameError
176
+ subcommand = method(:subcommand_missing)
177
+ parameters = [cmd, args, opts]
178
+ end
179
+ if subcommand.arity < 0
180
+ subcommand.call(*parameters[0..subcommand.arity])
181
+ else
182
+ subcommand.call(*parameters[0,subcommand.arity])
118
183
  end
119
184
  end
120
185
 
121
- extend Syntax
186
+ #
187
+
188
+ def help; end
122
189
 
123
- #def initialize #(global_options=nil)
124
- # #@global_options = global_options || []
125
- #end
190
+ def default ; help ; end
191
+
192
+ private
126
193
 
127
194
  #
128
195
 
129
- def execute(line=ARGV)
130
- argv = line
196
+ def subcommand_missing(cmd, args, opt)
197
+ help
198
+ #raise NoCommandError.new(cmd, args << opt)
199
+ end
131
200
 
132
- g_opts = Command::Options.new(self)
133
- g_keys = self.class.global_options
201
+ #
134
202
 
135
- # Deal with global options.
136
- if g_keys && ! g_keys.empty?
137
- argv = g_opts.parse(argv, :only => g_keys)
138
- end
203
+ def option_missing(opt, arg=nil)
204
+ raise NoOptionError.new(opt)
205
+ end
139
206
 
140
- # Sole main command or has subcommands?
141
- if respond_to?(:main)
142
- argv = g_opts.parse(argv, :pass => true)
143
- cmd = :main
144
- else
145
- argv = g_opts.parse(argv, :stop => true)
146
- cmd = argv.find{ |s| s !~ /^-/ }
147
- argv.delete_at(argv.index(cmd)) if cmd
148
- cmd = :default unless cmd
149
- cmd = cmd.to_sym
150
- end
207
+ end
208
+
209
+ # = Command base class
210
+ #
211
+ # See MasterCommand for example.
151
212
 
152
- keys = self.class.command_options
213
+ class Command
153
214
 
154
- if keys.key?(cmd)
155
- opts = keys[cmd].new
156
- argv = opts.parse(argv)
157
- end
215
+ def self.start(line=nil)
216
+ cargs = Console::Argument.new(line || ARGV)
217
+ pre = cargs.preoptions
218
+ args, opts = *cargs.parameters
219
+ new(args, opts).call
220
+ end
158
221
 
159
- argv = g_opts.parse_missing(argv)
222
+ attr :arguments
223
+ attr :options
160
224
 
161
- call(cmd, argv, opts)
225
+ #
226
+
227
+ def call
228
+ puts "Not implemented yet."
162
229
  end
163
230
 
231
+ private
232
+
164
233
  #
165
234
 
166
- def call(subcmd, argv, opts)
167
- @options = opts # should we use this it fill in instance vars?
235
+ def initialize(arguments, options=nil)
236
+ initialize_arguments(*arguments)
237
+ initialize_options(options)
238
+ end
168
239
 
169
- # This is a little tricky. The method has to be defined by a subclass.
170
- if self.respond_to?(subcmd) and not Console::Command.public_instance_methods.include?(subcmd.to_s)
171
- puts "# call: #{subcmd}(*#{argv.inspect})" if $debug
172
- __send__(subcmd, *argv)
173
- else
174
- begin
175
- puts "# call: method_missing(#{subcmd.inspect}, #{argv.inspect})" if $debug
176
- method_missing(subcmd.to_sym, *argv)
177
- rescue NoMethodError => e
178
- #if self.private_methods.include?( "no_command_error" )
179
- # no_command_error( *args )
180
- #else
181
- $stderr << "Unrecognized subcommand -- #{subcmd}\n"
182
- exit -1
183
- #end
240
+ #
241
+
242
+ def initialize_arguments(*arguments)
243
+ @arguments = arguments
244
+ end
245
+
246
+ #
247
+
248
+ def initialize_options(options)
249
+ options = options || {}
250
+ begin
251
+ opt, val = nil, nil
252
+ options.each do |opt, val|
253
+ send("#{opt}=", val)
184
254
  end
255
+ rescue NoMethodError
256
+ option_missing(opt, val)
185
257
  end
258
+ @options = options
186
259
  end
187
260
 
188
- #def global_options
189
- # self.class.global_options
190
- #end
261
+ #
191
262
 
192
263
  def option_missing(opt, arg=nil)
193
- raise InvalidOptionError.new(opt)
264
+ raise NoOptionError.new(opt)
265
+ end
266
+
267
+ end
268
+
269
+ end
270
+
271
+
272
+ class Array
273
+
274
+ # Not empty?
275
+
276
+ def not_empty?
277
+ !empty?
278
+ end
279
+
280
+ # Convert an array into command line parameters.
281
+ # The array is accepted in the format of Ruby
282
+ # method arguments --ie. [arg1, arg2, ..., hash]
283
+
284
+ def to_console
285
+ flags = (Hash===last ? pop : {})
286
+ flags = flags.to_console
287
+ flags + ' ' + join(" ")
288
+ end
289
+
290
+ end
291
+
292
+
293
+ class Hash
294
+
295
+ # Convert an array into command line parameters.
296
+ # The array is accepted in the format of Ruby
297
+ # method arguments --ie. [arg1, arg2, ..., hash]
298
+
299
+ def to_console
300
+ flags = collect do |f,v|
301
+ m = f.to_s.size == 1 ? '-' : '--'
302
+ case v
303
+ when Array
304
+ v.collect{ |e| "#{m}#{f}='#{e}'" }.join(' ')
305
+ when true
306
+ "#{m}#{f}"
307
+ when false, nil
308
+ ''
309
+ else
310
+ "#{m}#{f}='#{v}'"
311
+ end
194
312
  end
313
+ flags.join(" ")
314
+ end
195
315
 
316
+ # Turn a hash into arguments.
317
+ #
318
+ # h = { :list => [1,2], :base => "HI" }
319
+ # h.argumentize #=> [ [], { :list => [1,2], :base => "HI" } ]
320
+ # h.argumentize(:list) #=> [ [1,2], { :base => "HI" } ]
321
+ #
322
+ def argumentize(args_field=nil)
323
+ config = dup
324
+ if args_field
325
+ args = [config.delete(args_field)].flatten.compact
326
+ else
327
+ args = []
328
+ end
329
+ args << config
330
+ return args
196
331
  end
197
332
 
333
+ end
334
+
335
+
336
+ # SCRAP CODE FOR REFERENCE TO POSSIBLE ADD FUTURE FEATURES
337
+
198
338
  =begin
339
+
199
340
  # We include a module here so you can define your own help
200
341
  # command and call #super to utilize this one.
201
342
 
@@ -264,248 +405,12 @@ module Console
264
405
 
265
406
  include Help
266
407
  extend Help::ClassMethods
267
- =end
268
-
269
-
270
- # = Command::Options
271
- #
272
- # CommandOptions provides the basis for Command to Object Mapping (COM).
273
- # It is an commandline options parser that uses method definitions
274
- # as means of interprting command arguments.
275
- #
276
- # == Synopsis
277
- #
278
- # Let's make an executable called 'mycmd'.
279
- #
280
- # #!/usr/bin/env ruby
281
- #
282
- # require 'facets/command_options'
283
- #
284
- # class MyOptions < CommandOptions
285
- # attr_accessor :file
286
- #
287
- # def v!
288
- # @verbose = true
289
- # end
290
- # end
291
- #
292
- # opts = MyOptions.parse("-v --file hello.rb")
293
- #
294
- # opts.verbose #=> true
295
- # opts.file #=> "hello.rb"
296
- #
297
- #--
298
- # == Global Options
299
- #
300
- # You can define <i>global options</i> which are options that will be
301
- # processed no matter where they occur in the command line. In the above
302
- # examples only the options occuring before the subcommand are processed
303
- # globally. Anything occuring after the subcommand belonds strictly to
304
- # the subcommand. For instance, if we had added the following to the above
305
- # example:
306
- #
307
- # global_option :_v
308
- #
309
- # Then -v could appear anywhere in the command line, even on the end,
310
- # and still work as expected.
311
- #
312
- # % mycmd jump -h 3 -v
313
- #++
314
- #
315
- # == Missing Options
316
- #
317
- # You can use #option_missing to catch any options that are not explicility
318
- # defined.
319
- #
320
- # The method signature should look like:
321
- #
322
- # option_missing(option_name, args)
323
- #
324
- # Example:
325
- # def option_missing(option_name, args)
326
- # p args if $debug
327
- # case option_name
328
- # when 'p'
329
- # @a = args[0].to_i
330
- # @b = args[1].to_i
331
- # 2
332
- # else
333
- # raise InvalidOptionError(option_name, args)
334
- # end
335
- # end
336
- #
337
- # Its return value should be the effective "arity" of that options -- that is,
338
- # how many arguments it consumed ("-p a b", for example, would consume 2 args:
339
- # "a" and "b"). An arity of 1 is assumed if nil or false is returned.
340
-
341
- class Command::Options
342
-
343
- def self.parse(*line_and_options)
344
- o = new
345
- o.parse(*line_and_options)
346
- o
347
- end
348
-
349
- def initialize(delegate=nil)
350
- @__self__ = delegate || self
351
- end
352
-
353
- # Parse line for options in the context self.
354
- #
355
- # Options:
356
- #
357
- # :pass => true || false
358
- #
359
- # Setting this to true prevents the parse_missing routine from running.
360
- #
361
- # :only => [ global options, ... ]
362
- #
363
- # When processing global options, we only want to parse selected options.
364
- # This also set +pass+ to true.
365
- #
366
- # :stop => true || false
367
- #
368
- # If we are parsing options for the *main* command and we are allowing
369
- # subcommands, then we want to stop as soon as we get to the first non-option,
370
- # because that non-option will be the name of our subcommand and all options that
371
- # follow should be parsed later when we handle the subcommand.
372
- # This also set +pass+ to true.
373
-
374
- def parse(*line_and_options)
375
- __self__ = @__self__
376
-
377
- if Hash === line_and_options.last
378
- options = line_and_options.pop
379
- line = line_and_options.first
380
- else
381
- options = {}
382
- line = line_and_options.first
383
- end
384
408
 
385
- case line
386
- when String
387
- argv = Shellwords.shellwords(line)
388
- when Array
389
- argv = line.dup
390
- else
391
- argv = ARGV.dup
392
- end
393
-
394
- only = options[:only] # only parse these options
395
- stop = options[:stop] # stop at first non-option
396
- pass = options[:pass] || only || stop # don't run options_missing
397
-
398
- if $debug
399
- puts(only ? "\nGlobal parsing..." : "\nParsing...")
400
- end
401
-
402
- puts "# line: #{argv.inspect}" if $debug
403
-
404
- # Split single letter option groupings into separate options.
405
- # ie. -xyz => -x -y -z
406
- argv = argv.collect { |arg|
407
- if md = /^-(\w{2,})/.match( arg )
408
- md[1].split(//).collect { |c| "-#{c}" }
409
- else
410
- arg
411
- end
412
- }.flatten
413
-
414
- index = 0
415
-
416
- until index >= argv.size
417
- arg = argv.at(index)
418
- break if arg == '--' # POSIX compliance
419
- if arg[0,1] == '-'
420
- puts "# option: #{arg}" if $debug
421
- cnt = (arg[0,2] == '--' ? 2 : 1)
422
- #opt = Option.new(arg)
423
- #name = opt.methodize
424
- name = arg.sub(/^-{1,2}/,'')
425
- skip = only && only.include?(name)
426
- unam = ('__'*cnt)+name
427
- if __self__.respond_to?(unam)
428
- puts "# method: #{uname}" if $debug
429
- meth = method(unam)
430
- arity = meth.arity
431
- if arity < 0
432
- meth.call(*argv.slice(index+1..-1)) unless skip
433
- arity[index..-1] = nil # Get rid of the *name* and values
434
- elsif arity == 0
435
- meth.call unless skip
436
- argv.delete_at(index) # Get rid of the *name* of the option
437
- else
438
- meth.call(*argv.slice(index+1, arity)) unless skip
439
- #argv.delete_at(index) # Get rid of the *name* of the option
440
- #arity.times{ argv.delete_at(index) } # Get rid of the *value* of the option
441
- arity[index,arity] = nil
442
- end
443
- elsif __self__.respond_to?(name+'=')
444
- puts "# method: #{name}=" if $debug
445
- __self__.send(name+'=', *argv.slice(index+1, 1)) unless skip
446
- argv.delete_at(index) # Get rid of the *name* of the option
447
- argv.delete_at(index) # Get rid of the *value* of the option
448
- elsif __self__.respond_to?(name+'!')
449
- puts "# method: #{name}!" if $debug
450
- __self__.send(name+'!') unless skip
451
- argv.delete_at(index) # Get rid of the *name* of the option
452
- else
453
- index += 1
454
- end
455
- else
456
- index += 1
457
- break if stop
458
- end
459
- end
460
- # parse missing ?
461
- argv = parse_missing(argv) unless pass
462
- # return the remaining argv
463
- puts "# return: #{argv.inspect}" if $debug
464
- return argv
465
- end
466
-
467
- #
468
-
469
- def parse_missing(argv)
470
- argv.each_with_index do |a,i|
471
- if a =~ /^-/
472
- #raise InvalidOptionError.new(a) unless @__self__.respond_to?(:option_missing)
473
- kept = @__self__.option_missing(a, *argv[i+1,1])
474
- argv.delete_at(i) if kept # delete if value kept
475
- argv.delete_at(i) # delete option
476
- end
477
- end
478
- return argv
479
- end
480
-
481
- #
482
-
483
- def option_missing(opt, arg=nil)
484
- raise InvalidOptionError.new(opt)
485
- # #$stderr << "Unknown option '#{arg}'.\n"
486
- # #exit -1
487
- end
488
-
489
- #
490
-
491
- def to_h
492
- opts = @__self__.public_methods(true).select{ |m| m =~ /^[A-Za-z0-9]+[=!]$/ || m =~ /^[_][A-Za-z0-9]+$/ }
493
- #opts.reject!{ |k| k =~ /_$/ }
494
- opts.collect!{ |m| m.chomp('=').chomp('!') }
495
- opts.inject({}) do |h, m|
496
- k = m.sub(/^_+/, '')
497
- v = @__self__.send(m)
498
- h[k] = v if v
499
- h
500
- end
409
+ =end
501
410
 
502
- #@__self__.instance_variables.inject({}) do |h, v|
503
- # next h if v == "@__self__"
504
- # h[v[1..-1]] = @__self__.instance_variable_get(v); h
505
- #end
506
- end
411
+ =begin
507
412
 
508
- # Provides a very basic usage help string.
413
+ # Provides a very basic usage help string.
509
414
  #
510
415
  # TODO Add support for __options.
511
416
  def usage
@@ -559,48 +464,6 @@ module Console
559
464
  return c
560
465
  end
561
466
 
562
- # # Single Option
563
- #
564
- # class Option < String
565
- #
566
- # def initialize(option)
567
- # @flag = option
568
- # @long = (/^--/ =~ option)
569
- # super(option.sub(/^-{1,2}/,''))
570
- # end
571
- #
572
- # def long?
573
- # @long
574
- # end
575
- #
576
- # def short?
577
- # !@long
578
- # end
579
- #
580
- # #def demethodize
581
- # # sub('__','--').sub('_','-')
582
- # #end
583
- #
584
- # def methodize
585
- # @flag.sub(/^-{1,2}/,'')
586
- # end
587
- #
588
- # end
589
-
590
- end
591
-
592
- # For CommandOptions, but defined external to it, so
593
- # that it is easy to access from user defined commands.
594
- # (This lookup issue should be fixed in Ruby 1.9+, and then
595
- # the class can be moved back into Command namespace.)
596
-
597
- class InvalidOptionError < StandardError
598
- def initialize(option_name)
599
- @option_name = option_name
600
- end
601
- def message
602
- "Unknown option '#{@option_name}'."
603
- end
604
467
  end
605
468
 
606
- end
469
+ =end