clio 0.2.0 → 0.3.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/CHANGES CHANGED
@@ -1,10 +1,22 @@
1
+ == 0.3.0 / 2008-11-19
2
+
3
+ * 5 Other Enhancements
4
+
5
+ * improved usage specs (#2e805f40a05afcccdf59bad087b759d1fda60354)
6
+ * string.rb, fixed gsub (#f7449ced8d9757aefb8dedb04e65821fd174a31d)
7
+ * renamed Usage::Main to Usage::Command and Usage::Command to Usage::Subcommand (#42ccad02a7f5a68461e70c4ef775a8751facbddb)
8
+ * remove QED from end of specs (#0a820c7c44db3d1a6e7b1950152fabdaae006381)
9
+ * Merge: 0a820c7... f7449ce...
10
+ improved string spec (#b0579c898f02be2a3644e3f4bc233f9795f9a122)
11
+
12
+
1
13
  == 0.2.0 / 2008-11-15
2
14
 
3
15
  * 1 Major Enhancements
4
16
 
5
17
  * commandline now has a full parser (#251ff8fb0d6e56dd6e90d6e859e840717af004e4)
6
18
 
7
- * 46 Other Enhancements
19
+ * 52 Other Enhancements
8
20
 
9
21
  * capitialized main files (#1ac75f6de90bab8a696e657b4b33f936c969bbe2)
10
22
  * moved multicommand prototype to depot (#efe1d718e191394fa73064e4527a113374c55931)
@@ -52,6 +64,12 @@
52
64
  * clio/string.rb, fixed require (#4a519dd76be6e66454424edbe9eb790c786fc582)
53
65
  * all specs now pass (#4b90a0b08a6a97ab29453b647ef969a7384f2d5d)
54
66
  * avoid class with Clio::String and use ::String where needed (#471a0b1480207324ecf17ffe2943dac29fedba7e)
67
+ * updated reap configs (#361162622b25a25b5600a55f523ee80d2f719208)
68
+ * update README and VERSION (0.2.0) (#01d804e3789b5d58fd7e6243a11ea0ba65f96296)
69
+ * argument.rb, added splat option (#4d37a8906945c223100cc0d617a8ecbe9f25b863)
70
+ * support for argument added splat option (#8176e5cee31f2a8fa73e0f151f504a40f0a9a21a)
71
+ * added some website assets (#16e6b765fd606f5c09d43b52f6d0104aa55fc56f)
72
+ * added doc/spec to .gitignore (#1fc846f54b304da8956fecc84d9287641a5da052)
55
73
 
56
74
 
57
75
  == 0.0.1 / 2008-08-29
data/MANIFEST CHANGED
@@ -14,6 +14,7 @@ spec/commandline/scenario.rd
14
14
  spec/string
15
15
  spec/string/unit.rd
16
16
  spec/commandable
17
+ MANIFEST
17
18
  CHANGES
18
19
  RELEASE
19
20
  README
@@ -31,11 +32,11 @@ lib/clio/facets
31
32
  lib/clio/facets/kernel.rb
32
33
  lib/clio/facets/string.rb
33
34
  lib/clio/usage
34
- lib/clio/usage/main.rb
35
35
  lib/clio/usage/signature.rb
36
36
  lib/clio/usage/command.rb
37
37
  lib/clio/usage/parser.rb
38
38
  lib/clio/usage/argument.rb
39
+ lib/clio/usage/subcommand.rb
39
40
  lib/clio/usage/interface.rb
40
41
  lib/clio/usage/option.rb
41
42
  lib/clio/commandline.rb
data/README CHANGED
@@ -6,11 +6,10 @@
6
6
  == INTRODUCTION
7
7
 
8
8
  Clio is a great way to build commandline tools.
9
- It provides an advanced options parser with
10
- a variety of notations suited to almost any
11
- perfered style, and provides a very rich and
12
- and easy to use library for generating console
13
- output.
9
+ It provides an advanced options parser with a variety
10
+ of notations suited to almost any perfered style,
11
+ and provides a very rich and and easy to use library
12
+ for generating console output.
14
13
 
15
14
 
16
15
  == RELEASE NOTES
@@ -35,7 +34,7 @@ Clio .tgz package and type:
35
34
 
36
35
  == USAGE
37
36
 
38
- Please see the RDoc API.
37
+ For now please see the RDoc API.
39
38
 
40
39
 
41
40
  == LICENSE
data/RELEASE CHANGED
@@ -1,8 +1,13 @@
1
- This is the initial release of Clio. While useable,
2
- it is still very much APLHA code. The API is still
3
- in flux and needs a lot more testing before I'd
4
- put it to gereral use.
1
+ Clio is much cloer to a stable status. This release
2
+ has a fairly large set of passing specifications.
5
3
 
6
- ### 0.0.1 // 2008-08-29
4
+ ### 0.3.0 // 2008-08-29
7
5
 
6
+ 1 Major Change
7
+
8
+ * Rename Usage Main to Command and Command to Subcommand.
9
+
10
+ 1 Minor Change
11
+
12
+ * Fixed many small bugs.
8
13
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- clio 0.2.0 beta (2008-11-15)
1
+ clio 0.3.0 beta (2008-11-19)
@@ -1,4 +1,3 @@
1
- require 'clio/facets/kernel' # for deep_copy
2
1
  require 'clio/usage'
3
2
  #require 'shellwords'
4
3
 
@@ -183,7 +182,7 @@ module Clio
183
182
  #def inherited(subclass)
184
183
  #p usage.to_s
185
184
  #p subclass.usage.to_s
186
- # subclass.usage = self.usage.clone #deep_copy
185
+ # subclass.usage = self.usage.clone #deep copy?
187
186
  #p subclass.usage.to_s
188
187
  # end
189
188
 
@@ -203,12 +202,6 @@ module Clio
203
202
  @usage = u
204
203
  end
205
204
 
206
- # if ancestors[1] < Command
207
- # @usage = ancestors[0].usage.deep_copy
208
- # else
209
- # @usage = Usage.new
210
- # end
211
-
212
205
  #
213
206
  def subcommand(name, help=nil, &block)
214
207
  usage.subcommand(name, help, &block)
@@ -256,7 +249,7 @@ module Clio
256
249
  if self.class == Commandline
257
250
  @usage = Usage.new
258
251
  else
259
- @usage = self.class.usage #|| Usage.new #.deep_copy
252
+ @usage = self.class.usage #|| Usage.new
260
253
  end
261
254
  @usage.instance_eval(&block) if block
262
255
  end
@@ -32,8 +32,8 @@ module Clio
32
32
  s = text.dup
33
33
  m = marks.sort{ |a,b| b[0] <=> a[0] }
34
34
  m.each do |index, codes|
35
- codes.each do |code|
36
- s.insert(index, ANSICode.send(code))
35
+ codes.reverse_each do |code|
36
+ s.insert(index, ANSICode.__send__(code))
37
37
  end
38
38
  end
39
39
  s
@@ -41,20 +41,6 @@ module Clio
41
41
 
42
42
  def size ; text.size ; end
43
43
 
44
- ###
45
- def color!(ansicolor)
46
- marks[0] << ansicolor
47
- marks[size] << :clear
48
- end
49
-
50
- ###
51
- def color(ansicolor)
52
- m = marks.dup
53
- m[0] << ansicolor
54
- m[size] << :clear
55
- self.class.new(text, m)
56
- end
57
-
58
44
  ###
59
45
  def upcase ; self.class.new(text.upcase, marks) ; end
60
46
  def upcase! ; text.upcase! ; end
@@ -69,7 +55,8 @@ module Clio
69
55
  when String
70
56
  ntext = text + other.text
71
57
  nmarks = marks.dup
72
- other.marks.each{ |i, c| m[i] << c }
58
+ omarks = shift_marks(0, text.size, other.marks)
59
+ omarks.each{ |i, c| nmarks[i].concat(c) }
73
60
  else
74
61
  ntext = text + other.to_s
75
62
  nmarks = marks.dup
@@ -117,38 +104,110 @@ module Clio
117
104
 
118
105
  alias_method :[], :slice
119
106
 
120
- # TODO: block support and \1, \2 support.
107
+ # This is more limited than the normal String method.
108
+ # It does not yet support a block, and +replacement+
109
+ # won't substitue for \1, \2, etc.
110
+ #
111
+ # TODO: block support.
112
+ def sub!(pattern,replacement)
113
+ mark_changes = []
114
+ text = @text.sub(pattern) do |s|
115
+ index = $~.begin(0)
116
+ delta = (replacement.size - s.size)
117
+ mark_changes << [index, delta]
118
+ replacement
119
+ end
120
+ marks = @marks
121
+ mark_changes.each do |index, delta|
122
+ marks = shift_marks(index, delta, marks)
123
+ end
124
+ @text = text
125
+ @marks = marks
126
+ self
127
+ end
128
+
129
+ #
121
130
  def sub(pattern,replacement)
122
- if md = pattern.match(@text)
123
- delta = replacement.size - md.size
124
- marks2 = shift_marks(md.end, delta)
125
- text2 = text.sub(pattern,replacement)
126
- self.class.new(text2, marks2)
127
- else
128
- self.class.new(text, marks)
131
+ dup.sub!(pattern, replacement)
132
+ end
133
+
134
+ #
135
+ def gsub!(pattern,replacement)
136
+ mark_changes = []
137
+ text = @text.gsub(pattern) do |s|
138
+ index = $~.begin(0)
139
+ delta = (replacement.size - s.size)
140
+ mark_changes << [index, delta]
141
+ replacement
142
+ end
143
+ marks = @marks
144
+ mark_changes.each do |index, delta|
145
+ marks = shift_marks(index, delta, marks)
129
146
  end
147
+ @text = text
148
+ @marks = marks
149
+ self
130
150
  end
131
151
 
132
152
  #
133
- def gsub
153
+ def gsub(pattern_replacement)
154
+ dup.gsub(pattern, replacement)
155
+ end
156
+
157
+ ###
158
+ def ansi(code)
159
+ m = marks.dup
160
+ m[0] << code
161
+ m[size] << :clear
162
+ self.class.new(text, m)
134
163
  end
164
+ alias_method :color, :ansi
165
+
166
+ ###
167
+ def ansi!(code)
168
+ marks[0] << ansicolor
169
+ marks[size] << :clear
170
+ end
171
+ alias_method :color!, :ansi!
172
+
173
+ def red ; color(:red) ; end
174
+ def green ; color(:green) ; end
175
+ def blue ; color(:blue) ; end
176
+ def black ; color(:black) ; end
177
+ def magenta ; color(:magenta) ; end
178
+ def yellow ; color(:yellow) ; end
179
+ def cyan ; color(:cyan) ; end
180
+
181
+ def red! ; color!(:red) ; end
182
+ def green! ; color!(:green) ; end
183
+ def blue! ; color!(:blue) ; end
184
+ def black! ; color!(:black) ; end
185
+ def magenta! ; color!(:magenta) ; end
186
+ def yellow! ; color!(:yellow) ; end
187
+ def cyan! ; color!(:cyan) ; end
135
188
 
136
189
  private
137
190
 
138
- def shift_marks(index, delta)
191
+ #
192
+ def shift_marks(index, delta, marks=nil)
139
193
  new_marks = {}
140
- marks.each do |i, v|
194
+ (marks || @marks).each do |i, v|
141
195
  case i <=> index
142
- when 0, -1
196
+ when -1
143
197
  new_marks[i] = v
144
- when 1
198
+ when 0, 1
145
199
  new_marks[i+delta] = v
146
200
  end
147
201
  end
148
202
  new_marks
149
203
  end
150
204
 
151
- end
205
+ #
206
+ def shift_marks!(index, delta)
207
+ @marks.replace(shift_marks(index, delta))
208
+ end
209
+
210
+ end # class String
152
211
 
153
- end
212
+ end # module Clio
154
213
 
@@ -1,4 +1,4 @@
1
- require 'clio/usage/main'
1
+ require 'clio/usage/command'
2
2
  require 'clio/usage/parser'
3
3
 
4
4
  module Clio
@@ -175,7 +175,7 @@ module Clio
175
175
  module Usage
176
176
 
177
177
  def self.new(name=nil, &block)
178
- Main.new(name, &block)
178
+ Command.new(name, &block)
179
179
  end
180
180
 
181
181
  end#module Usage
@@ -4,19 +4,18 @@ module Clio
4
4
 
5
5
  # = Usage Argument
6
6
  #
7
+ # TODO: Should argument have name in addition to type?
7
8
  class Argument
8
9
  #attr :parent
9
- attr :name
10
+ #attr :name
10
11
  attr :type
11
12
  attr :help
12
13
  attr :splat
13
14
 
14
15
  # New Argument.
15
- #def initialize(name, parent=nil, &block)
16
- def initialize(name, &block)
17
- @name = name.to_s
18
- @type = name.upcase
19
- #@parent = parent
16
+ def initialize(type, &block)
17
+ @type = type
18
+ #@name = type.downcase if type.upcase != type
20
19
  @splat = false
21
20
  @help = ''
22
21
  instance_eval(&block) if block
@@ -24,15 +23,15 @@ module Clio
24
23
 
25
24
  #
26
25
  def initialize_copy(o)
27
- @name = o.name.dup
26
+ #@name = o.name.dup
28
27
  @type = o.type.dup
29
28
  @help = o.help.dup
30
29
  end
31
30
 
32
31
  # Same as +name+ but given as a symbol.
33
- def key
34
- name.to_sym
35
- end
32
+ #def key
33
+ # name.to_sym
34
+ #end
36
35
 
37
36
  # Specify the type of the argument.
38
37
  # This is an arbitrary description of the type.
@@ -47,6 +46,12 @@ module Clio
47
46
  self
48
47
  end
49
48
 
49
+ #def name(string=nil)
50
+ # return @name unless string
51
+ # @name = string.to_s
52
+ # self
53
+ #end
54
+
50
55
  #
51
56
  def splat(true_or_false=nil)
52
57
  return @splat if true_or_false.nil?
@@ -60,20 +65,17 @@ module Clio
60
65
  end
61
66
 
62
67
  def to_s
63
- if name.upcase == type
64
- s = "<#{name}"
65
- else
66
- s = "<#{name}:#{type}"
67
- end
68
+ s = "<#{type}"
68
69
  s << (splat ? "...>" : ">")
69
70
  s
70
71
  end
71
72
 
72
73
  def inspect
73
- s = "<#{name}"
74
- s << ":#{type.inspect}" if type
75
- s << ">"
76
- s
74
+ to_s
75
+ #s = "<#{name}"
76
+ #s << ":#{type.inspect}" if type
77
+ #s << ">"
78
+ #s
77
79
  end
78
80
 
79
81
  end #class Argument
@@ -1,354 +1,75 @@
1
- require 'clio/usage/option'
2
- require 'clio/usage/argument'
1
+ require 'clio/usage/subcommand'
3
2
 
4
3
  module Clio
5
4
 
6
5
  module Usage #:nodoc:
7
6
 
8
- # = Commandline Usage Command
7
+ # = Command
9
8
  #
10
- # This is the heart of usage; subclassed by Main and
11
- # containing together Options and Arguments.
9
+ # This is the toplevel "main" command.
12
10
  #
13
- # usage = Usage.new
14
- #
15
- class Command
16
-
17
- # Parent command. This is needed
18
- # to support cascading options.
19
- #--
20
- # NOTE: If it were possible to have this it would be better.
21
- #++
22
- attr :parent
23
-
24
- # Name of the command.
25
- attr :name
26
-
27
- # Array of subcommands.
28
- attr :subcommands
29
-
30
- # Array of arguments. Arguments and subcommands
31
- # are mutually exclusive, ie. either @arguments
32
- # or @subcommands will be empty.
33
- #
34
- # TODO: Could use single attribute for both subcommands
35
- # and arguments and use a flag to designate which type.
36
- attr :arguments
37
-
38
- # Array of options.
39
- attr :options
40
-
41
- # Help text.
42
- attr :help
43
-
44
- # Widely accepted alternate term for options.
45
- alias_method :switches, :options
46
-
47
- #
48
- def initialize(name, parent=nil, &block)
49
- @name = name.to_s
50
- @parent = parent
51
- @subcommands = []
52
- @options = []
53
- @arguments = []
54
- @help = ''
55
- instance_eval(&block) if block
56
- end
57
-
58
- #
59
- def initialize_copy(c)
60
- @parent = c.parent
61
- @name = c.name.dup
62
- @options = c.options.dup
63
- @arguments = c.arguments.dup
64
- @subcommands = c.subcommands.dup
65
- @help = c.help.dup
66
- end
67
-
68
- def key ; @name.to_sym ; end
69
-
70
- # METHOD MISSING
71
- #-------------------------------------------------------------
72
-
73
- def method_missing(key, *args, &blk)
74
- key = key.to_s
75
- case key
76
- when /\?$/
77
- option(key.chomp('?'), *args, &blk)
78
- else
79
- #k = full_name ? "#{full_name} #{key}" : "#{key}"
80
- c = command(key, &blk)
81
- args.each{ |a| c[a] }
82
- c
83
- end
84
- end
85
-
86
- #
87
- def help!(*args)
88
- Hash[*args].each do |key, desc|
89
- self[key, desc]
90
- end
91
- end
92
-
93
- # Define or retrieve a command.
94
- #
95
- # subcommand('remote')
96
- #
97
- # A shortcut to accessing subcommands of subcommands, the following
98
- # statements are equivalent:
99
- #
100
- # subcommand('remote').subcommand('add')
101
- #
102
- # subcommand('remote add')
103
- #
104
- def subcommand(name, help=nil, &block)
105
- name, names = *name.to_s.strip.split(/\s+/)
106
- if names
107
- names = [name, *names]
108
- cmd = names.inject(self) do |c, n|
109
- c.subcommand(n)
110
- end
111
- else
112
- cmd = subcommands.find{ |c| c === name }
113
- unless cmd
114
- cmd = Command.new(name, self)
115
- subcommands << cmd
116
- end
117
- end
118
- cmd.help(help) if help
119
- cmd.instance_eval(&block) if block
120
- cmd
121
- end
122
-
123
- alias_method :cmd, :subcommand
124
- alias_method :command, :subcommand
11
+ class Command < Subcommand
125
12
 
126
- alias_method :commands, :subcommands
127
-
128
- # Define an option.
129
- #
130
- # option(:output, :o)
13
+ # New Usage.
131
14
  #
132
- def option(name, *aliases, &block)
133
- opt = options.find{|o| o === name}
134
- if not opt
135
- opt = Option.new(name) #, self)
136
- #opt.aliases(*aliases)
137
- @options << opt
138
- end
139
- opt.aliases(*aliases) unless aliases.empty?
140
- opt.instance_eval(&block) if block
141
- opt
15
+ def initialize(name=nil, &block)
16
+ name ||= File.basename($0)
17
+ super(name, &block)
142
18
  end
143
19
 
144
- alias_method :switch, :option
145
-
146
- # Option shorthand.
20
+ # Define a command.
147
21
  #
148
- # opt('--output=FILE -o', 'output directory')
22
+ # command('remote')
23
+ # command('remote','add')
149
24
  #
150
- def opt(name, help=nil)
151
- name, *aliases = name.split(/\s+/)
152
- name, type = *name.split('=')
153
- mult = false
154
- if type && type[0,1] == '*'
155
- mult = true
156
- type = type[1..-1]
157
- end
158
- name = option_name(name).to_sym
159
- o = option(name, *aliases)
160
- o.help(help) if help
161
- o.argument(type) if type
162
- o.multiple(mult)
163
- self
164
- end
165
-
166
- alias_method :swt, :opt
167
-
168
- # A switch is like an option, but it is greedy.
169
- # When parsed it will pick-up any match subsequent
170
- # the switch's parent command. In other words,
171
- # switches are consumed by a command even if they
172
- # appear in a subcommand's arguments.
173
- #
174
- #def switch(name, *aliases, &block)
175
- # if opt = @switches.find{|o| o === name}
25
+ #def command(name, &block)
26
+ # raise "Command cannot have both arguments and subcommands (eg. #{name})." unless arguments.empty?
27
+ # key = name.to_s.strip
28
+ # if cmd = @commands.find{|c| c === key}
176
29
  # else
177
- # opt = Option.new(name, self)
178
- # opt.greedy = true
179
- # opt.aliases(*aliases)
180
- # @switches << opt
30
+ # cmd = Command.new(key, self)
31
+ # @commands << cmd
181
32
  # end
182
- # opt.instance_eval(&block) if block
183
- # opt
33
+ # cmd.instance_eval(&block) if block
34
+ # cmd
184
35
  #end
185
36
 
186
- # Switch shorthand.
187
- #
188
- # swt('--output=FILE -o', 'output directory')
189
- #
190
- #def swt(name, help=nil)
191
- # name, *aliases = name.split(/\s+/)
192
- # name, type = *name.split('=')
193
- # mult = false
194
- # if type && type[0,1] == '*'
195
- # mult = true
196
- # type = type[1..-1]
197
- # end
198
- # name = clean_name(name)
199
- # o = switch(name, *aliases)
200
- # o.help(help) if help
201
- # o.argument(type) if type
202
- # o.multiple(mult)
203
- # self
204
- #end
37
+ =begin
38
+ #alias_method :[], :command
205
39
 
206
- # Define an argument.
207
- # Takes a name, optional index and block.
208
- #
209
- # Indexing of arguments starts at 1, not 0.
210
- #
211
- # Examples
212
- #
213
- # argument(:path)
214
- # argument(1, :path)
215
- #
216
- def argument(*n_type, &block)
217
- index = Integer===n_type[0] ? n_type.shift : @arguments.size + 1
218
- type = n_type.shift
219
- help = n_type.shift
220
40
 
221
- index = index - 1
222
- type = type.to_s.sub(/^\</,'').chomp('>')
223
-
224
- if type[0,1] == '*'
225
- type.sub!('*', '')
226
- splat = true
227
- elsif type[-1,1] == '*'
228
- type.sub!(/[*]$/, '')
229
- splat = true
230
- else
231
- splat = false
232
- end
233
-
234
- raise "Command cannot have both arguments (eg. #{type}) and subcommands." unless subcommands.empty?
235
-
236
- if arg = @arguments[index]
237
- arg.type(type) if type
238
- arg.help(help) if help
239
- arg.splat(splat) if splat
240
- arg.instance_eval(&block) if block
241
- else
242
- if type || block
243
- arg = Argument.new(type, &block) #self, &block)
244
- arg.help(help) if help
245
- arg.splat(splat) if splat
246
- @arguments[index] = arg
247
- end
248
- end
249
- return arg
250
- end
251
-
252
- alias_method :arg, :argument
253
-
254
- # Argument shorthand.
255
- #
256
- # arg('PIN', 'pin number')
257
- #
258
- #def arg(type=nil, help=nil)
259
- # type = type.to_s.sub(/^\</,'').chomp('>')
260
- # argument(type).help(help)
261
- # self
262
- #end
263
-
264
- #
265
- def help(string=nil)
266
- @help.replace(string.to_s) if string
267
- @help
268
- end
269
-
270
- # SHORTHAND NOTATION
271
- #-------------------------------------------------------------
272
-
273
- # Super shorthand notation.
274
- #
275
- # cli['document']['--output=FILE -o']['<files>']
276
- #
277
- def [](*x)
278
- case x[0].to_s[0,1]
279
- when '-'
280
- opt(*x)
281
- when '<'
282
- arg(*x)
283
- else
284
- subcommand(*x)
285
- end
286
- end
287
-
288
- # QUERY METHODS
41
+ # ARRAY NOTATION
289
42
  #-------------------------------------------------------------
290
43
 
291
44
  #
292
- def completion
293
- if subcommands.empty?
294
- options.collect{|o| o.to_s.strip } +
295
- arguments.collect{|c| c.name}
296
- else
297
- options.collect{|o| o.to_s.strip } +
298
- subcommands.collect{|c| c.name}
299
- end
300
- end
301
-
302
- # Option defined?
303
- #
304
- def option?(name)
305
- opt = options.find{|o| o === name}
306
- if parent && !opt
307
- opt = parent.option?(name)
308
- end
309
- opt
310
- #return opt if opt
311
- #options.each do |o|
312
- # return o if o.aliases.include?(key)
313
- #end
314
- #nil
315
- end
316
-
317
- alias_method :switch?, :option
318
-
319
- # Greedy Option defined?
320
- #
321
- #def greedy_option?(key)
322
- # switches.find{|o| o === key}
323
- #end
324
-
325
- #
326
- def ===(other_name)
327
- name == other_name.to_s
328
- end
329
-
330
- #
331
- def inspect
332
- s = ''
333
- s << "#<#{self.class}:#{object_id} #{@name}"
334
- s << " @arguments=#{@arguments.inspect} " unless @arguments.empty?
335
- s << " @options=#{@options.inspect} " unless @options.empty?
336
- #s << "@switches=#{@switches.inspect} " unless @switches.empty?
337
- s << " @help=#{@help.inspect}" unless @help.empty?
338
- #s << "@commands=#{@commands.inspect} " unless @commands.empty?
339
- s << ">"
340
- s
341
- end
45
+ def [](*args)
46
+ res = nil
47
+ head, *tail = *args
48
+ case head.to_s
49
+ when /^-/
50
+ x = []
51
+ opts = args.map do |o|
52
+ o = o.to_s
53
+ if i = o.index('=')
54
+ x << o[i+1..-1]
55
+ o[0...i]
56
+ else
57
+ o
58
+ end
59
+ end
60
+ x = x.uniq
342
61
 
343
- # Full callable command name.
344
- def full_name
345
- if parent && parent.full_name
346
- "#{parent.full_name} #{name}"
62
+ res = opt(*opts)
347
63
  else
348
- "#{name}"
64
+ args.each do |name|
65
+ res = command(name)
66
+ end
349
67
  end
68
+ return res
350
69
  end
70
+ =end
351
71
 
72
+ =begin
352
73
  # Usage text.
353
74
  #
354
75
  def to_s
@@ -360,17 +81,17 @@ module Clio
360
81
  when 1, 2, 3
361
82
  s.concat(options.collect{ |o| "[#{o.to_s.strip}]" })
362
83
  else
363
- s << "[switches]" # switches? vs. options
84
+ s << "[switches]"
364
85
  end
365
-
86
+ # switches? vs. options
366
87
  s << arguments.join(' ') unless arguments.empty?
367
88
 
368
- case subcommands.size
89
+ case commands.size
369
90
  when 0
370
91
  when 1
371
- s << subcommands.join('')
92
+ s << commands.join('')
372
93
  when 2, 3
373
- s << '[' + subcommands.join(' | ') + ']'
94
+ s << '[' + commands.join(' | ') + ']'
374
95
  else
375
96
  s << 'command'
376
97
  end
@@ -388,10 +109,10 @@ module Clio
388
109
  end
389
110
  s << "Usage:"
390
111
  s << " " + to_s
391
- unless subcommands.empty?
112
+ unless commands.empty?
392
113
  s << ''
393
114
  s << 'Commands:'
394
- s.concat(subcommands.collect{ |x| " %-20s %s" % [x.name, x.help] }.sort)
115
+ s.concat(commands.collect{ |x| " %-20s %s" % [x.key, x.help] }.sort)
395
116
  end
396
117
  unless arguments.empty?
397
118
  s << ''
@@ -405,36 +126,40 @@ module Clio
405
126
  end
406
127
  s.flatten.join("\n")
407
128
  end
129
+ =end
408
130
 
409
- # PARSE
410
- #-------------------------------------------------------------
131
+ def parse(argv)
132
+ Parser.new(self, argv).parse #(argv)
133
+ end
411
134
 
412
- # Parse usage.
413
- def parse(argv, index=0)
414
- @parser ||= Parser.new(self, argv, index)
415
- @parser.parse
135
+ # Cache usage into a per-user cache file for reuse.
136
+ # This can be used to greatly speed up tab completion.
137
+ #
138
+ def cache
139
+ File.open(cache_file, 'w'){ |f| f << to_yaml }
416
140
  end
417
141
 
418
142
  private
419
143
 
420
- def option_key(key)
421
- name = option_name(key) #.to_s
422
- if name.size == 1
423
- "-#{name}".to_sym
424
- else
425
- "--#{name}".to_sym
426
- end
144
+ # TODO: Use XDG
145
+
146
+ def cache_file
147
+ File.join(File.expand_path('~'), '.cache', 'clio', "#{name}.yaml")
427
148
  end
428
149
 
429
- def option_name(name)
430
- name = name.to_s
431
- name = name.gsub(/^[-]+/, '')
432
- return name.chomp('?') #.to_sym
150
+ def self.cache_file
151
+ File.join(File.expand_path('~'), '.cache', 'clio', "#{name}.yaml")
152
+ end
153
+
154
+ def self.load_cache
155
+ if File.file?(cache_file)
156
+ YAML.load(File.new(cache_file))
157
+ end
433
158
  end
434
159
 
435
- end #class Command
160
+ end#class Main
436
161
 
437
- end #module Usage
162
+ end#module Usage
438
163
 
439
- end #module Clio
164
+ end#module Clio
440
165