facets 2.0.5 → 2.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.
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